Document //flutter/shell/common/rasterizer (flutter/engine#9809)
This commit is contained in:
@@ -19,76 +19,362 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
/// Takes |LayerTree|s and draws its contents.
|
||||
//------------------------------------------------------------------------------
|
||||
/// The rasterizer is a component owned by the shell that resides on the GPU
|
||||
/// task runner. Each shell owns exactly one instance of a rasterizer. The
|
||||
/// rasterizer may only be created, used and collected on the GPU task runner.
|
||||
///
|
||||
/// The rasterizer owns the instance of the currently active on-screen render
|
||||
/// surface. On this surface, it renders the contents of layer trees submitted
|
||||
/// to it by the `Engine` (which lives on the UI task runner).
|
||||
///
|
||||
/// The primary components owned by the rasterizer are the compositor context
|
||||
/// and the on-screen render surface. The compositor context has all the GPU
|
||||
/// state necessary to render frames to the render surface.
|
||||
///
|
||||
class Rasterizer final {
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Used to forward events from the rasterizer to interested
|
||||
/// subsystems. Currently, the shell sets itself up as the
|
||||
/// rasterizer delegate to listen for frame rasterization events.
|
||||
/// It can then forward these events to the engine.
|
||||
///
|
||||
/// Like all rasterizer operation, the rasterizer delegate call
|
||||
/// are made on the GPU task runner. Any delegate must ensure that
|
||||
/// they can handle the threading implications.
|
||||
///
|
||||
class Delegate {
|
||||
public:
|
||||
virtual void OnFrameRasterized(const FrameTiming&) = 0;
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Notifies the delegate that a frame has been rendered. The
|
||||
/// rasterizer collects profiling information for each part of
|
||||
/// the frame workload. This profiling information is made
|
||||
/// available to the delegate for forwarding to subsystems
|
||||
/// interested in collecting such profiles. Currently, the shell
|
||||
/// (the delegate) forwards this to the engine where Dart code
|
||||
/// can react to this information.
|
||||
///
|
||||
/// @see `FrameTiming`
|
||||
///
|
||||
/// @param[in] frame_timing Instrumentation information for each phase of
|
||||
/// the frame workload.
|
||||
///
|
||||
virtual void OnFrameRasterized(const FrameTiming& frame_timing) = 0;
|
||||
};
|
||||
|
||||
// TODO(dnfield): remove once embedders have caught up.
|
||||
class DummyDelegate : public Delegate {
|
||||
void OnFrameRasterized(const FrameTiming&) override {}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Creates a new instance of a rasterizer. Rasterizers may only
|
||||
/// be created on the GPU task runner. Rasterizers are currently
|
||||
/// only created by the shell. Usually, the shell also sets itself
|
||||
/// up as the rasterizer delegate. But, this constructor sets up a
|
||||
/// dummy rasterizer delegate.
|
||||
///
|
||||
// TODO(chinmaygarde): The rasterizer does not use the task runners for
|
||||
// anything other than thread checks. Remove the same as an argument.
|
||||
///
|
||||
/// @param[in] task_runners The task runners used by the shell.
|
||||
/// @param[in] compositor_context The compositor context used to hold all
|
||||
/// the GPU state used by the rasterizer.
|
||||
///
|
||||
Rasterizer(TaskRunners task_runners,
|
||||
std::unique_ptr<flutter::CompositorContext> compositor_context);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Creates a new instance of a rasterizer. Rasterizers may only
|
||||
/// be created on the GPU task runner. Rasterizers are currently
|
||||
/// only created by the shell (which also sets itself up as the
|
||||
/// rasterizer delegate).
|
||||
///
|
||||
// TODO(chinmaygarde): The rasterizer does not use the task runners for
|
||||
// anything other than thread checks. Remove the same as an argument.
|
||||
///
|
||||
/// @param[in] delegate The rasterizer delegate.
|
||||
/// @param[in] task_runners The task runners used by the shell.
|
||||
///
|
||||
Rasterizer(Delegate& delegate, TaskRunners task_runners);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Creates a new instance of a rasterizer. Rasterizers may only
|
||||
/// be created on the GPU task runner. Rasterizers are currently
|
||||
/// only created by the shell (which also sets itself up as the
|
||||
/// rasterizer delegate).
|
||||
///
|
||||
// TODO(chinmaygarde): The rasterizer does not use the task runners for
|
||||
// anything other than thread checks. Remove the same as an argument.
|
||||
///
|
||||
/// @param[in] delegate The rasterizer delegate.
|
||||
/// @param[in] task_runners The task runners used by the shell.
|
||||
/// @param[in] compositor_context The compositor context used to hold all
|
||||
/// the GPU state used by the rasterizer.
|
||||
///
|
||||
Rasterizer(Delegate& delegate,
|
||||
TaskRunners task_runners,
|
||||
std::unique_ptr<flutter::CompositorContext> compositor_context);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Destroys the rasterizer. This must happen on the GPU task
|
||||
/// runner. All GPU resources are collected before this call
|
||||
/// returns. Any context setup by the embedder to hold these
|
||||
/// resources can be immediately collected as well.
|
||||
///
|
||||
~Rasterizer();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Rasterizers may be created well before an on-screen surface is
|
||||
/// available for rendering. Shells usually create a rasterizer in
|
||||
/// their constructors. Once an on-screen surface is available
|
||||
/// however, one may be provided to the rasterizer using this
|
||||
/// call. No rendering may occur before this call. The surface is
|
||||
/// held till the balancing call to `Rasterizer::Teardown` is
|
||||
/// made. Calling a setup before tearing down the previous surface
|
||||
/// (if this is not the first time the surface has been setup) is
|
||||
/// user error.
|
||||
///
|
||||
/// @see `Rasterizer::Teardown`
|
||||
///
|
||||
/// @param[in] surface The on-screen render surface.
|
||||
///
|
||||
void Setup(std::unique_ptr<Surface> surface);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Releases the previously setup on-screen render surface and
|
||||
/// collects associated resources. No more rendering may occur
|
||||
/// till the next call to `Rasterizer::Setup` with a new render
|
||||
/// surface. Calling a teardown without a setup is user error.
|
||||
///
|
||||
void Teardown();
|
||||
|
||||
// Frees up Skia GPU resources.
|
||||
//
|
||||
// This method must be called from the GPU task runner.
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Notifies the rasterizer that there is a low memory situation
|
||||
/// and it must purge as many unnecessary resources as possible.
|
||||
/// Currently, the Skia context associated with onscreen rendering
|
||||
/// is told to free GPU resources.
|
||||
///
|
||||
void NotifyLowMemoryWarning() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Gets a weak pointer to the rasterizer. The rasterizer may only
|
||||
/// be accessed on the GPU task runner.
|
||||
///
|
||||
/// @return The weak pointer to the rasterizer.
|
||||
///
|
||||
fml::WeakPtr<Rasterizer> GetWeakPtr() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Sometimes, it may be necessary to render the same frame again
|
||||
/// without having to wait for the framework to build a whole new
|
||||
/// layer tree describing the same contents. One such case is when
|
||||
/// external textures (video or camera streams for example) are
|
||||
/// updated in an otherwise static layer tree. To support this use
|
||||
/// case, the rasterizer holds onto the last rendered layer tree.
|
||||
///
|
||||
/// @bug https://github.com/flutter/flutter/issues/33939
|
||||
///
|
||||
/// @return A pointer to the last layer or `nullptr` if this rasterizer
|
||||
/// has never rendered a frame.
|
||||
///
|
||||
flutter::LayerTree* GetLastLayerTree();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Draws a last layer tree to the render surface. This may seem
|
||||
/// entirely redundant at first glance. After all, on surface loss
|
||||
/// and re-acquisition, the framework generates a new layer tree.
|
||||
/// Otherwise, why render the same contents to the screen again?
|
||||
/// This is used as an optimization in cases where there are
|
||||
/// external textures (video or camera streams for example) in
|
||||
/// referenced in the layer tree. These textures may be updated at
|
||||
/// a cadence different from that of the the Flutter application.
|
||||
/// Flutter can re-render the layer tree with just the updated
|
||||
/// textures instead of waiting for the framework to do the work
|
||||
/// to generate the layer tree describing the same contents.
|
||||
///
|
||||
void DrawLastLayerTree();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Gets the registry of external textures currently in use by the
|
||||
/// rasterizer. These textures may be updated at a cadence
|
||||
/// different from that of the Flutter application. When an
|
||||
/// external texture is referenced in the Flutter layer tree, that
|
||||
/// texture is composited within the Flutter layer tree.
|
||||
///
|
||||
/// @return A pointer to the external texture registry.
|
||||
///
|
||||
flutter::TextureRegistry* GetTextureRegistry();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Takes the next item from the layer tree pipeline and executes
|
||||
/// the GPU thread frame workload for that pipeline item to render
|
||||
/// a frame on the on-screen surface.
|
||||
///
|
||||
/// Why does the draw call take a layer tree pipeline and not the
|
||||
/// layer tree directly?
|
||||
///
|
||||
/// The pipeline is the way book-keeping of frame workloads
|
||||
/// distributed across the multiple threads is managed. The
|
||||
/// rasterizer deals with the pipelines directly (instead of layer
|
||||
/// trees which is what it actually renders) because the pipeline
|
||||
/// consumer's workload must be accounted for within the pipeline
|
||||
/// itself. If the rasterizer took the layer tree directly, it
|
||||
/// would have to be taken out of the pipeline. That would signal
|
||||
/// the end of the frame workload and the pipeline would be ready
|
||||
/// for new frames. But the last frame has not been rendered by
|
||||
/// the frame yet! On the other hand, the pipeline must own the
|
||||
/// layer tree it renders because it keeps a reference to the last
|
||||
/// layer tree around till a new frame is rendered. So a simple
|
||||
/// reference wont work either. The `Rasterizer::DoDraw` method
|
||||
/// actually performs the GPU operations within the layer tree
|
||||
/// pipeline.
|
||||
///
|
||||
/// @see `Rasterizer::DoDraw`
|
||||
///
|
||||
/// @param[in] pipeline The layer tree pipeline to take the next layer tree
|
||||
/// to render from.
|
||||
///
|
||||
void Draw(fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief The type of the screenshot to obtain of the previously
|
||||
/// rendered layer tree.
|
||||
///
|
||||
enum class ScreenshotType {
|
||||
//--------------------------------------------------------------------------
|
||||
/// A format used to denote a Skia picture. A Skia picture is a serialized
|
||||
/// representation of an `SkPicture` that can be used to introspect the
|
||||
/// series of commands used to draw that picture.
|
||||
///
|
||||
/// Skia pictures are typically stored as files with the .skp extension on
|
||||
/// disk. These files may be viewed in an interactive debugger available at
|
||||
/// https://debugger.skia.org/
|
||||
///
|
||||
SkiaPicture,
|
||||
UncompressedImage, // In kN32_SkColorType format
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// A format used to denote uncompressed image data. This format
|
||||
/// is 32 bits per pixel, 8 bits per component and
|
||||
/// denoted by the `kN32_SkColorType ` Skia color type.
|
||||
///
|
||||
UncompressedImage,
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// A format used to denote compressed image data. The PNG compressed
|
||||
/// container is used.
|
||||
///
|
||||
CompressedImage,
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief A POD type used to return the screenshot data along with the
|
||||
/// size of the frame.
|
||||
///
|
||||
struct Screenshot {
|
||||
//--------------------------------------------------------------------------
|
||||
/// The data used to describe the screenshot. The data format depends on the
|
||||
/// type of screenshot taken and any further encoding done to the same.
|
||||
///
|
||||
/// @see `ScreenshotType`
|
||||
///
|
||||
sk_sp<SkData> data;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// The size of the screenshot in texels.
|
||||
///
|
||||
SkISize frame_size = SkISize::MakeEmpty();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Creates an empty screenshot
|
||||
///
|
||||
Screenshot();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Creates a screenshot with the specified data and size.
|
||||
///
|
||||
/// @param[in] p_data The screenshot data
|
||||
/// @param[in] p_size The screenshot size.
|
||||
///
|
||||
Screenshot(sk_sp<SkData> p_data, SkISize p_size);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief The copy constructor for a screenshot.
|
||||
///
|
||||
/// @param[in] other The screenshot to copy from.
|
||||
///
|
||||
Screenshot(const Screenshot& other);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Destroys the screenshot object and releases underlying data.
|
||||
///
|
||||
~Screenshot();
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Screenshots the last layer tree to one of the supported
|
||||
/// screenshot types and optionally Base 64 encodes that data for
|
||||
/// easier transmission and packaging (usually over the service
|
||||
/// protocol for instrumentation tools running on the host).
|
||||
///
|
||||
/// @param[in] type The type of the screenshot to gather.
|
||||
/// @param[in] base64_encode Whether Base 64 encoding must be applied to the
|
||||
/// data after a screenshot has been captured.
|
||||
///
|
||||
/// @return A non-empty screenshot if one could be captured. A screenshot
|
||||
/// capture may fail if there were no layer trees previously
|
||||
/// rendered by this rasterizer, or, due to an unspecified
|
||||
/// internal error. Internal error will be logged to the console.
|
||||
///
|
||||
Screenshot ScreenshotLastLayerTree(ScreenshotType type, bool base64_encode);
|
||||
|
||||
// Sets a callback that will be executed after the next frame is submitted to
|
||||
// the surface on the GPU task runner.
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Sets a callback that will be executed when the next layer tree
|
||||
/// in rendered to the on-screen surface. This is used by
|
||||
/// embedders to listen for one time operations like listening for
|
||||
/// when the first frame is rendered so that they may hide splash
|
||||
/// screens.
|
||||
///
|
||||
/// The callback is only executed once and dropped on the GPU
|
||||
/// thread when executed (lambda captures must be able to deal
|
||||
/// with the threading repercussions of this behavior).
|
||||
///
|
||||
/// @param[in] callback The callback to execute when the next layer tree is
|
||||
/// rendered on-screen.
|
||||
///
|
||||
void SetNextFrameCallback(fml::closure callback);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Returns a pointer to the compositor context used by this
|
||||
/// rasterizer. This pointer will never be `nullptr`.
|
||||
///
|
||||
/// @return The compositor context used by this rasterizer.
|
||||
///
|
||||
flutter::CompositorContext* compositor_context() {
|
||||
return compositor_context_.get();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Skia has no notion of time. To work around the performance
|
||||
/// implications of this, it may cache GPU resources to reference
|
||||
/// them from one frame to the next. Using this call, embedders
|
||||
/// may set the maximum bytes cached by Skia in its caches
|
||||
/// dedicated to on-screen rendering.
|
||||
///
|
||||
/// @attention This cache setting will be invalidated when the surface is
|
||||
/// torn down via `Rasterizer::Teardown`. This call must be made
|
||||
/// again with new limits after surface re-acquisition.
|
||||
///
|
||||
/// @attention This cache does not describe the entirety of GPU resources
|
||||
/// that may be cached. The `RasterCache` also holds very large
|
||||
/// GPU resources.
|
||||
///
|
||||
/// @see `RasterCache`
|
||||
///
|
||||
/// @param[in] max_bytes The maximum byte size of resource that may be
|
||||
/// cached for GPU rendering.
|
||||
///
|
||||
void SetResourceCacheMaxBytes(int max_bytes);
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user