1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef FLUTTER_FLOW_LAYERS_CONTAINER_LAYER_H_ |
6 | #define FLUTTER_FLOW_LAYERS_CONTAINER_LAYER_H_ |
7 | |
8 | #include <vector> |
9 | #include "flutter/flow/layers/layer.h" |
10 | |
11 | namespace flutter { |
12 | |
13 | class ContainerLayer : public Layer { |
14 | public: |
15 | ContainerLayer(); |
16 | |
17 | virtual void Add(std::shared_ptr<Layer> layer); |
18 | |
19 | void Preroll(PrerollContext* context, const SkMatrix& matrix) override; |
20 | void Paint(PaintContext& context) const override; |
21 | #if defined(LEGACY_FUCHSIA_EMBEDDER) |
22 | void CheckForChildLayerBelow(PrerollContext* context) override; |
23 | void UpdateScene(SceneUpdateContext& context) override; |
24 | #endif |
25 | |
26 | const std::vector<std::shared_ptr<Layer>>& layers() const { return layers_; } |
27 | |
28 | protected: |
29 | void PrerollChildren(PrerollContext* context, |
30 | const SkMatrix& child_matrix, |
31 | SkRect* child_paint_bounds); |
32 | void PaintChildren(PaintContext& context) const; |
33 | |
34 | #if defined(LEGACY_FUCHSIA_EMBEDDER) |
35 | void UpdateSceneChildren(SceneUpdateContext& context); |
36 | #endif |
37 | |
38 | // Try to prepare the raster cache for a given layer. |
39 | // |
40 | // The raster cache would fail if either of the followings is true: |
41 | // 1. The context has a platform view. |
42 | // 2. The context does not have a valid raster cache. |
43 | // 3. The layer's paint bounds does not intersect with the cull rect. |
44 | // |
45 | // We make this a static function instead of a member function that directy |
46 | // uses the "this" pointer as the layer because we sometimes need to raster |
47 | // cache a child layer and one can't access its child's protected method. |
48 | static void TryToPrepareRasterCache(PrerollContext* context, |
49 | Layer* layer, |
50 | const SkMatrix& matrix); |
51 | |
52 | private: |
53 | std::vector<std::shared_ptr<Layer>> layers_; |
54 | |
55 | FML_DISALLOW_COPY_AND_ASSIGN(ContainerLayer); |
56 | }; |
57 | |
58 | //------------------------------------------------------------------------------ |
59 | /// Some ContainerLayer objects perform a rendering operation or filter on |
60 | /// the rendered output of their children. Often that operation is changed |
61 | /// slightly from frame to frame as part of an animation. During such an |
62 | /// animation, the children can be cached if they are stable to avoid having |
63 | /// to render them on every frame. Even if the children are not stable, |
64 | /// rendering them into the raster cache during a Preroll operation will save |
65 | /// an extra change of rendering surface during the Paint phase as compared |
66 | /// to using the SaveLayer that would otherwise be needed with no caching. |
67 | /// |
68 | /// Typically the Flutter Widget objects that lead to the creation of these |
69 | /// layers will try to enforce only a single child Widget by their design. |
70 | /// Unfortunately, the process of turning Widgets eventually into engine |
71 | /// layers is not a 1:1 process so this layer might end up with multiple |
72 | /// child layers even if the Widget only had a single child Widget. |
73 | /// |
74 | /// When such a layer goes to cache the output of its children, it will |
75 | /// need to supply a single layer to the cache mechanism since the raster |
76 | /// cache uses a layer unique_id() as part of the cache key. If this layer |
77 | /// ended up with multiple children, then it must first collect them into |
78 | /// one layer for the cache mechanism. In order to provide a single layer |
79 | /// for all of the children, this utility class will implicitly collect |
80 | /// the children into a secondary ContainerLayer called the child container. |
81 | /// |
82 | /// A by-product of creating a hidden child container, though, is that the |
83 | /// child container is created new every time this layer is created with |
84 | /// different properties, such as during an animation. In that scenario, |
85 | /// it would be best to cache the single real child of this layer if it |
86 | /// is unique and if it is stable from frame to frame. To facilitate this |
87 | /// optimal caching strategy, this class implements two accessor methods |
88 | /// to be used for different purposes: |
89 | /// |
90 | /// When the layer needs to recurse to perform some operation on its children, |
91 | /// it can call GetChildContainer() to return the hidden container containing |
92 | /// all of the real children. |
93 | /// |
94 | /// When the layer wants to cache the rendered contents of its children, it |
95 | /// should call GetCacheableChild() for best performance. This method may |
96 | /// end up returning the same layer as GetChildContainer(), but only if the |
97 | /// conditions for optimal caching of a single child are not met. |
98 | /// |
99 | class MergedContainerLayer : public ContainerLayer { |
100 | public: |
101 | MergedContainerLayer(); |
102 | |
103 | void Add(std::shared_ptr<Layer> layer) override; |
104 | |
105 | protected: |
106 | /** |
107 | * @brief Returns the ContainerLayer used to hold all of the children of the |
108 | * MergedContainerLayer. Note that this may not be the best layer to use |
109 | * for caching the children. |
110 | * |
111 | * @see GetCacheableChild() |
112 | * @return the ContainerLayer child used to hold the children |
113 | */ |
114 | ContainerLayer* GetChildContainer() const; |
115 | |
116 | /** |
117 | * @brief Returns the best choice for a Layer object that can be used |
118 | * in RasterCache operations to cache the children. |
119 | * |
120 | * The returned Layer must represent all children and try to remain stable |
121 | * if the MergedContainerLayer is reconstructed in subsequent frames of |
122 | * the scene. |
123 | * |
124 | * @see GetChildContainer() |
125 | * @return the best candidate Layer for caching the children |
126 | */ |
127 | Layer* GetCacheableChild() const; |
128 | |
129 | private: |
130 | FML_DISALLOW_COPY_AND_ASSIGN(MergedContainerLayer); |
131 | }; |
132 | |
133 | } // namespace flutter |
134 | |
135 | #endif // FLUTTER_FLOW_LAYERS_CONTAINER_LAYER_H_ |
136 | |