This is part of a bigger change that will facilitate us
to act on this `RasterStatus`. The specific case is where
after pre-roll we might decide to want to merge the threads
and re-submit the frame -- `RasterStatus::kResubmit` can then
let us achieve this result.
* Make pipeline hold a deque so we can push_front
- Also assert that all the DoDraw tasks are executed
on the GPU thread.
* Add tests for pipeline
* Add support for pipeline to push resources to the front
Using it, a Flutter app can monitor missing frames in the release mode, and a custom Flutter runner (e.g., Fuchsia) can add a custom FrameRasterizedCallback.
Related issues:
https://github.com/flutter/flutter/issues/26154https://github.com/flutter/flutter/issues/31444https://github.com/flutter/flutter/issues/32447
Need review as soon as possible so we can merge this before the end of May to catch the milestone.
Tests added:
* NoNeedToReportTimingsByDefault
* NeedsReportTimingsIsSetWithCallback
* ReportTimingsIsCalled
* FrameRasterizedCallbackIsCalled
* FrameTimingSetsAndGetsProperly
* onReportTimings preserves callback zone
* FrameTiming.toString has the correct format
This will need a manual engine roll as the TestWindow defined in the framework needs to implement onReportTimings.
At a quick glance, one could easily think of the "engine_time" as the
GPU thread time and the "frame_time" as the UI thread time because the
GPU thread time is mainly spent on the engine while the UI thread time
is mainly spent on the Dart framework to generate the frame.
But it's actually the other way. The "engine_time" is UI thread time and
the "frame_time" is the GPU thread time.
To avoid the confusion, rename them to "ui_time" and "raster_time"
respectively. I avoided the "gpu_time" because the rasterization may be
purely on a CPU backed software Skia backend.
Some components in the Flutter engine were derived from the forked blink codebase. While the forked components have either been removed or rewritten, the use of the blink namespace has mostly (and inconsistently) remained. This renames the blink namesapce to flutter for consistency. There are no functional changes in this patch.
Allow Flutter to automatically dump the skp that triggers new shader compilations. This is useful for writing custom ShaderWarmUp to reduce jank. By default, it's not enabled to reduce the overhead. This is only available in profile or debug build.
Later, we can add service protocol support to pull the skp from the client to the host. Currently, it works fine for Android-based devices (including our urgent internal clients) where we can `adb shell` into the cache directory.
Behavior (visual) changes should be very minor. Things that are to be expected:
* A few things were not color managed correctly by the transform canvas (color emoji, some color filters). Those will be handled correctly with the tagged surfaces (although we're always transforming to sRGB, so nothing should change until we target a wider gamut).
* Image filtering will happen in the source color space, rather than the destination. Very minor.
* The transform canvas did caching of images in the destination color space. Now, the conversion happens at draw time. If there are performance issues, images can be pre-converted to the destination with makeColorSpace().
Right now we do it whenever the platform views preview flag is on.
This is less efficient, filed
https://github.com/flutter/flutter/issues/24133 to only do this when
there's a platform view in the tree.
Moved the frame buffer specific logic from IOSGLContext to IOSGLRenderTarget.
use recording canvases for overlays
Support platform view overlays with gl rendering.
This also changes the overlay canvases (for both software and gl
rendering) be recording canvases, and only rasterize them after
finishing the paint traversal.
Handing a UIView refererence directly to the engine makes it challenging
for plugin authors to retain a controller for that UIView (e.g the
controller that talks over the platform channel) for as long as the
embedded view is needed.
We instead make the factory return a FlutterPlatformView which is a
wrapper around the UIView that the engine retains as long as the
platform view instance is needed. This allows plugin authors to keep
their control logic in the FlutterPlatformView and know that the engine
is responsible for retaining the reference.
When we visit a PlatformViewLayer during the paint traversal it replaces
the PaintContext's canvas with a new one that is painted ontop of the
embedded view.
We need to make sure that operations applied by parent layers are also
applied to the new canvas.
To achieve this we collect all the canvases in a SkNWayCanvas and use
this canvas by non leaf nodes. Leaf nodes still paint only to the "current"
canvas.
This PR moves the overlay canvas creation from the paint phase to the
preroll phase, collects them into a SkNWayCanvas and set it in
PaintContext.
To keep this PR focused, I only used the internal_nodes_canvas in the
tranform_layer.
Will followup with a PR that changes all internal layers to use the
internal_nodes_canvas.
When the flag is true, we currently use a single thread configuration,
and disabled the raster cache for opacity layers.
The flag's name is 'io.flutter_embedded_views_preview'.
The platform views embedding is still WIP, and until we dynamically
merge the gpu and platform threads based on the presence of an embedded
view in the scene fetching the view embedder is not thread safe.
This PR essentially disables iOS platform views embedding, we will
re-enable once dynamic thread merging is supported.
For flow to manipulate the embedded UIViews during the paint traversal
it needs some hook in PaintContext.
This PR introduces a ViewEmbeder interface that is implemented by the
iOS PlatformViewsController and plumbs it into PaintContext.
The ViewEmbedder interface is mainly a place holder at this point, as
this PR is focused on just the plumbing.
TL;DR: Offscreen surface is created on the render thread and device to host
transfer performed there before task completion on the UI thread.
While attempting to snapshot layer trees, the engine was attempting to use the
IO thread context. The reasoning was that this would be safe to do because any
textures uploaded to the GPU as a result of async texture upload would have
originated from this context and hence the handles would be valid in either
context. As it turns out, while the handles are valid, Skia does not support
this use-case because cross-context images transfer ownership of the image from
one context to another. So, when we made the hop from the UI thread to the IO
thread (for snapshotting), if either the UI or GPU threads released the last
reference to the texture backed image, the image would be invalid. This led to
such images being absent from the layer tree snapshot.
Simply referencing the images as they are being used on the IO thread is not
sufficient because accessing images on one context after their ownership has
already been transferred to another is not safe behavior (from Skia's
perspective, the handles are still valid in the sharegroup).
To work around these issues, it was decided that an offscreen render target
would be created on the render thread. The color attachment of this render
target could then be transferred as a cross context image to the IO thread for
the device to host tranfer.
Again, this is currently not quite possible because the only way to create
cross context images is from encoded data. Till Skia exposes the functionality
to create cross-context images from textures in one context, we do a device to
host transfer on the GPU thread. The side effect of this is that this is now
part of the frame workload (image compression, which dominate the wall time,
is still done of the IO thread).
A minor side effect of this patch is that the GPU latch needs to be waited on
before the UI thread tasks can be completed before shell initialization.