|
19 | 19 |
|
20 | 20 | namespace flutter {
|
21 | 21 |
|
22 |
| -/// Takes |LayerTree|s and draws its contents. |
| 22 | +//------------------------------------------------------------------------------ |
| 23 | +/// The rasterizer is a component owned by the shell that resides on the GPU |
| 24 | +/// task runner. Each shell owns exactly one instance of a rasterizer. The |
| 25 | +/// rasterizer may only be created, used and collected on the GPU task runner. |
| 26 | +/// |
| 27 | +/// The rasterizer owns the instance of the currently active on-screen render |
| 28 | +/// surface. On this surface, it renders the contents of layer trees submitted |
| 29 | +/// to it by the `Engine` (which lives on the UI task runner). |
| 30 | +/// |
| 31 | +/// The primary components owned by the rasterizer are the compositor context |
| 32 | +/// and the on-screen render surface. The compositor context has all the GPU |
| 33 | +/// state necessary to render frames to the render surface. |
| 34 | +/// |
23 | 35 | class Rasterizer final {
|
24 | 36 | public:
|
| 37 | + //---------------------------------------------------------------------------- |
| 38 | + /// @brief Used to forward events from the rasterizer to interested |
| 39 | + /// subsystems. Currently, the shell sets itself up as the |
| 40 | + /// rasterizer delegate to listen for frame rasterization events. |
| 41 | + /// It can then forward these events to the engine. |
| 42 | + /// |
| 43 | + /// Like all rasterizer operation, the rasterizer delegate call |
| 44 | + /// are made on the GPU task runner. Any delegate must ensure that |
| 45 | + /// they can handle the threading implications. |
| 46 | + /// |
25 | 47 | class Delegate {
|
26 | 48 | public:
|
27 |
| - virtual void OnFrameRasterized(const FrameTiming&) = 0; |
| 49 | + //-------------------------------------------------------------------------- |
| 50 | + /// @brief Notifies the delegate that a frame has been rendered. The |
| 51 | + /// rasterizer collects profiling information for each part of |
| 52 | + /// the frame workload. This profiling information is made |
| 53 | + /// available to the delegate for forwarding to subsystems |
| 54 | + /// interested in collecting such profiles. Currently, the shell |
| 55 | + /// (the delegate) forwards this to the engine where Dart code |
| 56 | + /// can react to this information. |
| 57 | + /// |
| 58 | + /// @see `FrameTiming` |
| 59 | + /// |
| 60 | + /// @param[in] frame_timing Instrumentation information for each phase of |
| 61 | + /// the frame workload. |
| 62 | + /// |
| 63 | + virtual void OnFrameRasterized(const FrameTiming& frame_timing) = 0; |
28 | 64 | };
|
| 65 | + |
29 | 66 | // TODO(dnfield): remove once embedders have caught up.
|
30 | 67 | class DummyDelegate : public Delegate {
|
31 | 68 | void OnFrameRasterized(const FrameTiming&) override {}
|
32 | 69 | };
|
| 70 | + |
| 71 | + //---------------------------------------------------------------------------- |
| 72 | + /// @brief Creates a new instance of a rasterizer. Rasterizers may only |
| 73 | + /// be created on the GPU task runner. Rasterizers are currently |
| 74 | + /// only created by the shell. Usually, the shell also sets itself |
| 75 | + /// up as the rasterizer delegate. But, this constructor sets up a |
| 76 | + /// dummy rasterizer delegate. |
| 77 | + /// |
| 78 | + // TODO(chinmaygarde): The rasterizer does not use the task runners for |
| 79 | + // anything other than thread checks. Remove the same as an argument. |
| 80 | + /// |
| 81 | + /// @param[in] task_runners The task runners used by the shell. |
| 82 | + /// @param[in] compositor_context The compositor context used to hold all |
| 83 | + /// the GPU state used by the rasterizer. |
| 84 | + /// |
33 | 85 | Rasterizer(TaskRunners task_runners,
|
34 | 86 | std::unique_ptr<flutter::CompositorContext> compositor_context);
|
35 | 87 |
|
| 88 | + //---------------------------------------------------------------------------- |
| 89 | + /// @brief Creates a new instance of a rasterizer. Rasterizers may only |
| 90 | + /// be created on the GPU task runner. Rasterizers are currently |
| 91 | + /// only created by the shell (which also sets itself up as the |
| 92 | + /// rasterizer delegate). |
| 93 | + /// |
| 94 | + // TODO(chinmaygarde): The rasterizer does not use the task runners for |
| 95 | + // anything other than thread checks. Remove the same as an argument. |
| 96 | + /// |
| 97 | + /// @param[in] delegate The rasterizer delegate. |
| 98 | + /// @param[in] task_runners The task runners used by the shell. |
| 99 | + /// |
36 | 100 | Rasterizer(Delegate& delegate, TaskRunners task_runners);
|
37 | 101 |
|
| 102 | + //---------------------------------------------------------------------------- |
| 103 | + /// @brief Creates a new instance of a rasterizer. Rasterizers may only |
| 104 | + /// be created on the GPU task runner. Rasterizers are currently |
| 105 | + /// only created by the shell (which also sets itself up as the |
| 106 | + /// rasterizer delegate). |
| 107 | + /// |
| 108 | + // TODO(chinmaygarde): The rasterizer does not use the task runners for |
| 109 | + // anything other than thread checks. Remove the same as an argument. |
| 110 | + /// |
| 111 | + /// @param[in] delegate The rasterizer delegate. |
| 112 | + /// @param[in] task_runners The task runners used by the shell. |
| 113 | + /// @param[in] compositor_context The compositor context used to hold all |
| 114 | + /// the GPU state used by the rasterizer. |
| 115 | + /// |
38 | 116 | Rasterizer(Delegate& delegate,
|
39 | 117 | TaskRunners task_runners,
|
40 | 118 | std::unique_ptr<flutter::CompositorContext> compositor_context);
|
41 | 119 |
|
| 120 | + //---------------------------------------------------------------------------- |
| 121 | + /// @brief Destroys the rasterizer. This must happen on the GPU task |
| 122 | + /// runner. All GPU resources are collected before this call |
| 123 | + /// returns. Any context setup by the embedder to hold these |
| 124 | + /// resources can be immediately collected as well. |
| 125 | + /// |
42 | 126 | ~Rasterizer();
|
43 | 127 |
|
| 128 | + //---------------------------------------------------------------------------- |
| 129 | + /// @brief Rasterizers may be created well before an on-screen surface is |
| 130 | + /// available for rendering. Shells usually create a rasterizer in |
| 131 | + /// their constructors. Once an on-screen surface is available |
| 132 | + /// however, one may be provided to the rasterizer using this |
| 133 | + /// call. No rendering may occur before this call. The surface is |
| 134 | + /// held till the balancing call to `Rasterizer::Teardown` is |
| 135 | + /// made. Calling a setup before tearing down the previous surface |
| 136 | + /// (if this is not the first time the surface has been setup) is |
| 137 | + /// user error. |
| 138 | + /// |
| 139 | + /// @see `Rasterizer::Teardown` |
| 140 | + /// |
| 141 | + /// @param[in] surface The on-screen render surface. |
| 142 | + /// |
44 | 143 | void Setup(std::unique_ptr<Surface> surface);
|
45 | 144 |
|
| 145 | + //---------------------------------------------------------------------------- |
| 146 | + /// @brief Releases the previously setup on-screen render surface and |
| 147 | + /// collects associated resources. No more rendering may occur |
| 148 | + /// till the next call to `Rasterizer::Setup` with a new render |
| 149 | + /// surface. Calling a teardown without a setup is user error. |
| 150 | + /// |
46 | 151 | void Teardown();
|
47 | 152 |
|
48 |
| - // Frees up Skia GPU resources. |
49 |
| - // |
50 |
| - // This method must be called from the GPU task runner. |
| 153 | + //---------------------------------------------------------------------------- |
| 154 | + /// @brief Notifies the rasterizer that there is a low memory situation |
| 155 | + /// and it must purge as many unnecessary resources as possible. |
| 156 | + /// Currently, the Skia context associated with onscreen rendering |
| 157 | + /// is told to free GPU resources. |
| 158 | + /// |
51 | 159 | void NotifyLowMemoryWarning() const;
|
52 | 160 |
|
| 161 | + //---------------------------------------------------------------------------- |
| 162 | + /// @brief Gets a weak pointer to the rasterizer. The rasterizer may only |
| 163 | + /// be accessed on the GPU task runner. |
| 164 | + /// |
| 165 | + /// @return The weak pointer to the rasterizer. |
| 166 | + /// |
53 | 167 | fml::WeakPtr<Rasterizer> GetWeakPtr() const;
|
54 | 168 |
|
| 169 | + //---------------------------------------------------------------------------- |
| 170 | + /// @brief Sometimes, it may be necessary to render the same frame again |
| 171 | + /// without having to wait for the framework to build a whole new |
| 172 | + /// layer tree describing the same contents. One such case is when |
| 173 | + /// external textures (video or camera streams for example) are |
| 174 | + /// updated in an otherwise static layer tree. To support this use |
| 175 | + /// case, the rasterizer holds onto the last rendered layer tree. |
| 176 | + /// |
| 177 | + /// @bug https://github.com/flutter/flutter/issues/33939 |
| 178 | + /// |
| 179 | + /// @return A pointer to the last layer or `nullptr` if this rasterizer |
| 180 | + /// has never rendered a frame. |
| 181 | + /// |
55 | 182 | flutter::LayerTree* GetLastLayerTree();
|
56 | 183 |
|
| 184 | + //---------------------------------------------------------------------------- |
| 185 | + /// @brief Draws a last layer tree to the render surface. This may seem |
| 186 | + /// entirely redundant at first glance. After all, on surface loss |
| 187 | + /// and re-acquisition, the framework generates a new layer tree. |
| 188 | + /// Otherwise, why render the same contents to the screen again? |
| 189 | + /// This is used as an optimization in cases where there are |
| 190 | + /// external textures (video or camera streams for example) in |
| 191 | + /// referenced in the layer tree. These textures may be updated at |
| 192 | + /// a cadence different from that of the the Flutter application. |
| 193 | + /// Flutter can re-render the layer tree with just the updated |
| 194 | + /// textures instead of waiting for the framework to do the work |
| 195 | + /// to generate the layer tree describing the same contents. |
| 196 | + /// |
57 | 197 | void DrawLastLayerTree();
|
58 | 198 |
|
| 199 | + //---------------------------------------------------------------------------- |
| 200 | + /// @brief Gets the registry of external textures currently in use by the |
| 201 | + /// rasterizer. These textures may be updated at a cadence |
| 202 | + /// different from that of the Flutter application. When an |
| 203 | + /// external texture is referenced in the Flutter layer tree, that |
| 204 | + /// texture is composited within the Flutter layer tree. |
| 205 | + /// |
| 206 | + /// @return A pointer to the external texture registry. |
| 207 | + /// |
59 | 208 | flutter::TextureRegistry* GetTextureRegistry();
|
60 | 209 |
|
| 210 | + //---------------------------------------------------------------------------- |
| 211 | + /// @brief Takes the next item from the layer tree pipeline and executes |
| 212 | + /// the GPU thread frame workload for that pipeline item to render |
| 213 | + /// a frame on the on-screen surface. |
| 214 | + /// |
| 215 | + /// Why does the draw call take a layer tree pipeline and not the |
| 216 | + /// layer tree directly? |
| 217 | + /// |
| 218 | + /// The pipeline is the way book-keeping of frame workloads |
| 219 | + /// distributed across the multiple threads is managed. The |
| 220 | + /// rasterizer deals with the pipelines directly (instead of layer |
| 221 | + /// trees which is what it actually renders) because the pipeline |
| 222 | + /// consumer's workload must be accounted for within the pipeline |
| 223 | + /// itself. If the rasterizer took the layer tree directly, it |
| 224 | + /// would have to be taken out of the pipeline. That would signal |
| 225 | + /// the end of the frame workload and the pipeline would be ready |
| 226 | + /// for new frames. But the last frame has not been rendered by |
| 227 | + /// the frame yet! On the other hand, the pipeline must own the |
| 228 | + /// layer tree it renders because it keeps a reference to the last |
| 229 | + /// layer tree around till a new frame is rendered. So a simple |
| 230 | + /// reference wont work either. The `Rasterizer::DoDraw` method |
| 231 | + /// actually performs the GPU operations within the layer tree |
| 232 | + /// pipeline. |
| 233 | + /// |
| 234 | + /// @see `Rasterizer::DoDraw` |
| 235 | + /// |
| 236 | + /// @param[in] pipeline The layer tree pipeline to take the next layer tree |
| 237 | + /// to render from. |
| 238 | + /// |
61 | 239 | void Draw(fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline);
|
62 | 240 |
|
| 241 | + //---------------------------------------------------------------------------- |
| 242 | + /// @brief The type of the screenshot to obtain of the previously |
| 243 | + /// rendered layer tree. |
| 244 | + /// |
63 | 245 | enum class ScreenshotType {
|
| 246 | + //-------------------------------------------------------------------------- |
| 247 | + /// A format used to denote a Skia picture. A Skia picture is a serialized |
| 248 | + /// representation of an `SkPicture` that can be used to introspect the |
| 249 | + /// series of commands used to draw that picture. |
| 250 | + /// |
| 251 | + /// Skia pictures are typically stored as files with the .skp extension on |
| 252 | + /// disk. These files may be viewed in an interactive debugger available at |
| 253 | + /// https://debugger.skia.org/ |
| 254 | + /// |
64 | 255 | SkiaPicture,
|
65 |
| - UncompressedImage, // In kN32_SkColorType format |
| 256 | + |
| 257 | + //-------------------------------------------------------------------------- |
| 258 | + /// A format used to denote uncompressed image data. This format |
| 259 | + /// is 32 bits per pixel, 8 bits per component and |
| 260 | + /// denoted by the `kN32_SkColorType ` Skia color type. |
| 261 | + /// |
| 262 | + UncompressedImage, |
| 263 | + |
| 264 | + //-------------------------------------------------------------------------- |
| 265 | + /// A format used to denote compressed image data. The PNG compressed |
| 266 | + /// container is used. |
| 267 | + /// |
66 | 268 | CompressedImage,
|
67 | 269 | };
|
68 | 270 |
|
| 271 | + //---------------------------------------------------------------------------- |
| 272 | + /// @brief A POD type used to return the screenshot data along with the |
| 273 | + /// size of the frame. |
| 274 | + /// |
69 | 275 | struct Screenshot {
|
| 276 | + //-------------------------------------------------------------------------- |
| 277 | + /// The data used to describe the screenshot. The data format depends on the |
| 278 | + /// type of screenshot taken and any further encoding done to the same. |
| 279 | + /// |
| 280 | + /// @see `ScreenshotType` |
| 281 | + /// |
70 | 282 | sk_sp<SkData> data;
|
| 283 | + |
| 284 | + //-------------------------------------------------------------------------- |
| 285 | + /// The size of the screenshot in texels. |
| 286 | + /// |
71 | 287 | SkISize frame_size = SkISize::MakeEmpty();
|
72 | 288 |
|
| 289 | + //-------------------------------------------------------------------------- |
| 290 | + /// @brief Creates an empty screenshot |
| 291 | + /// |
73 | 292 | Screenshot();
|
74 | 293 |
|
| 294 | + //-------------------------------------------------------------------------- |
| 295 | + /// @brief Creates a screenshot with the specified data and size. |
| 296 | + /// |
| 297 | + /// @param[in] p_data The screenshot data |
| 298 | + /// @param[in] p_size The screenshot size. |
| 299 | + /// |
75 | 300 | Screenshot(sk_sp<SkData> p_data, SkISize p_size);
|
76 | 301 |
|
| 302 | + //-------------------------------------------------------------------------- |
| 303 | + /// @brief The copy constructor for a screenshot. |
| 304 | + /// |
| 305 | + /// @param[in] other The screenshot to copy from. |
| 306 | + /// |
77 | 307 | Screenshot(const Screenshot& other);
|
78 | 308 |
|
| 309 | + //-------------------------------------------------------------------------- |
| 310 | + /// @brief Destroys the screenshot object and releases underlying data. |
| 311 | + /// |
79 | 312 | ~Screenshot();
|
80 | 313 | };
|
81 | 314 |
|
| 315 | + //---------------------------------------------------------------------------- |
| 316 | + /// @brief Screenshots the last layer tree to one of the supported |
| 317 | + /// screenshot types and optionally Base 64 encodes that data for |
| 318 | + /// easier transmission and packaging (usually over the service |
| 319 | + /// protocol for instrumentation tools running on the host). |
| 320 | + /// |
| 321 | + /// @param[in] type The type of the screenshot to gather. |
| 322 | + /// @param[in] base64_encode Whether Base 64 encoding must be applied to the |
| 323 | + /// data after a screenshot has been captured. |
| 324 | + /// |
| 325 | + /// @return A non-empty screenshot if one could be captured. A screenshot |
| 326 | + /// capture may fail if there were no layer trees previously |
| 327 | + /// rendered by this rasterizer, or, due to an unspecified |
| 328 | + /// internal error. Internal error will be logged to the console. |
| 329 | + /// |
82 | 330 | Screenshot ScreenshotLastLayerTree(ScreenshotType type, bool base64_encode);
|
83 | 331 |
|
84 |
| - // Sets a callback that will be executed after the next frame is submitted to |
85 |
| - // the surface on the GPU task runner. |
| 332 | + //---------------------------------------------------------------------------- |
| 333 | + /// @brief Sets a callback that will be executed when the next layer tree |
| 334 | + /// in rendered to the on-screen surface. This is used by |
| 335 | + /// embedders to listen for one time operations like listening for |
| 336 | + /// when the first frame is rendered so that they may hide splash |
| 337 | + /// screens. |
| 338 | + /// |
| 339 | + /// The callback is only executed once and dropped on the GPU |
| 340 | + /// thread when executed (lambda captures must be able to deal |
| 341 | + /// with the threading repercussions of this behavior). |
| 342 | + /// |
| 343 | + /// @param[in] callback The callback to execute when the next layer tree is |
| 344 | + /// rendered on-screen. |
| 345 | + /// |
86 | 346 | void SetNextFrameCallback(fml::closure callback);
|
87 | 347 |
|
| 348 | + //---------------------------------------------------------------------------- |
| 349 | + /// @brief Returns a pointer to the compositor context used by this |
| 350 | + /// rasterizer. This pointer will never be `nullptr`. |
| 351 | + /// |
| 352 | + /// @return The compositor context used by this rasterizer. |
| 353 | + /// |
88 | 354 | flutter::CompositorContext* compositor_context() {
|
89 | 355 | return compositor_context_.get();
|
90 | 356 | }
|
91 | 357 |
|
| 358 | + //---------------------------------------------------------------------------- |
| 359 | + /// @brief Skia has no notion of time. To work around the performance |
| 360 | + /// implications of this, it may cache GPU resources to reference |
| 361 | + /// them from one frame to the next. Using this call, embedders |
| 362 | + /// may set the maximum bytes cached by Skia in its caches |
| 363 | + /// dedicated to on-screen rendering. |
| 364 | + /// |
| 365 | + /// @attention This cache setting will be invalidated when the surface is |
| 366 | + /// torn down via `Rasterizer::Teardown`. This call must be made |
| 367 | + /// again with new limits after surface re-acquisition. |
| 368 | + /// |
| 369 | + /// @attention This cache does not describe the entirety of GPU resources |
| 370 | + /// that may be cached. The `RasterCache` also holds very large |
| 371 | + /// GPU resources. |
| 372 | + /// |
| 373 | + /// @see `RasterCache` |
| 374 | + /// |
| 375 | + /// @param[in] max_bytes The maximum byte size of resource that may be |
| 376 | + /// cached for GPU rendering. |
| 377 | + /// |
92 | 378 | void SetResourceCacheMaxBytes(int max_bytes);
|
93 | 379 |
|
94 | 380 | private:
|
|
0 commit comments