• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "FrontEnd/LayerCreationArgs.h"
20 #include "FrontEnd/LayerLifecycleManager.h"
21 #include "RequestedLayerState.h"
22 #include "ftl/small_vector.h"
23 
24 namespace android::surfaceflinger::frontend {
25 class LayerHierarchyBuilder;
26 
27 // LayerHierarchy allows us to navigate the layer hierarchy in z-order, or depth first traversal.
28 // The hierarchy is created from a set of RequestedLayerStates. The hierarchy itself does not
29 // contain additional states. Instead, it is a representation of RequestedLayerStates as a graph.
30 //
31 // Each node in the hierarchy can be visited by multiple parents (making this a graph). While
32 // traversing the hierarchy, a new concept called Variant can be used to understand the
33 // relationship of the layer to its parent. The following variants are possible:
34 // Attached - child of the parent
35 // Detached - child of the parent but currently relative parented to another layer
36 // Relative - relative child of the parent
37 // Mirror - mirrored from another layer
38 // Detached_Mirror - mirrored from another layer, ignoring local transform
39 //
40 // By representing the hierarchy as a graph, we can represent mirrored layer hierarchies without
41 // cloning the layer requested state. The mirrored hierarchy and its corresponding
42 // RequestedLayerStates are kept in sync because the mirrored hierarchy does not clone any
43 // states.
44 class LayerHierarchy {
45 public:
46     enum Variant : uint32_t {
47         Attached,        // child of the parent
48         Detached,        // child of the parent but currently relative parented to another layer
49         Relative,        // relative child of the parent
50         Mirror,          // mirrored from another layer
51         Detached_Mirror, // mirrored from another layer, ignoring local transform
52         ftl_first = Attached,
53         ftl_last = Detached_Mirror,
54     };
isMirror(Variant variant)55     static inline bool isMirror(Variant variant) {
56         return ((variant == Mirror) || (variant == Detached_Mirror));
57     }
58 
59     // Represents a unique path to a node.
60     // The layer hierarchy is represented as a graph. Each node can be visited by multiple parents.
61     // This allows us to represent mirroring in an efficient way. See the example below:
62     // root
63     // ├─ A {Traversal path id = 1}
64     // ├─ B {Traversal path id = 2}
65     // │  ├─ C {Traversal path id = 3}
66     // │  ├─ D {Traversal path id = 4}
67     // │  └─ E (Mirrors C) {Traversal path id = 5}
68     // └─ F (Mirrors B) {Traversal path id = 6}
69     //
70     // C can be traversed via B or E or F and or via F then E.
71     // Depending on how the node is reached, its properties such as geometry or visibility might be
72     // different. And we can uniquely identify the node by keeping track of the nodes leading up to
73     // it. But to be more efficient we only need to track the nodes id and the top mirror root path.
74     // So C for example, would have the following unique traversal paths:
75     //  - {Traversal path id = 3}
76     //  - {Traversal path id = 3, mirrorRootIds = 5}
77     //  - {Traversal path id = 3, mirrorRootIds = 6}
78     //  - {Traversal path id = 3, mirrorRootIds = 6, 5}
79 
80     struct TraversalPath {
81         uint32_t id;
82         LayerHierarchy::Variant variant;
83         // Mirrored layers can have a different geometry than their parents so we need to track
84         // the mirror roots in the traversal.
85         ftl::SmallVector<uint32_t, 5> mirrorRootIds;
86         // Relative layers can be visited twice, once by their parent and then once again by
87         // their relative parent. We keep track of the roots here to detect any loops in the
88         // hierarchy. If a relative root already exists in the list while building the
89         // TraversalPath, it means that somewhere in the hierarchy two layers are relatively
90         // parented to each other.
91         ftl::SmallVector<uint32_t, 5> relativeRootIds;
92         // First duplicate relative root id found. If this is a valid layer id that means we are
93         // in a loop.
94         uint32_t invalidRelativeRootId = UNASSIGNED_LAYER_ID;
95         // See isAttached()
96         bool detached = false;
hasRelZLoopTraversalPath97         bool hasRelZLoop() const { return invalidRelativeRootId != UNASSIGNED_LAYER_ID; }
98         // Returns true if this node is reached via one or more relative parents.
isRelativeTraversalPath99         bool isRelative() const { return !relativeRootIds.empty(); }
100         // Returns true if the node or its parents are not Detached.
isAttachedTraversalPath101         bool isAttached() const { return !detached; }
102         // Returns true if the node is a clone.
isCloneTraversalPath103         bool isClone() const { return !mirrorRootIds.empty(); }
104 
getClonedFromTraversalPath105         TraversalPath getClonedFrom() const { return {.id = id, .variant = variant}; }
106 
107         TraversalPath makeChild(uint32_t layerId, LayerHierarchy::Variant variant) const;
108 
109         bool operator==(const TraversalPath& other) const {
110             return id == other.id && mirrorRootIds == other.mirrorRootIds;
111         }
112         std::string toString() const;
113 
114         static const TraversalPath ROOT;
115     };
116 
117     struct TraversalPathHash {
operatorTraversalPathHash118         std::size_t operator()(const LayerHierarchy::TraversalPath& key) const {
119             uint32_t hashCode = key.id * 31;
120             for (uint32_t mirrorRootId : key.mirrorRootIds) {
121                 hashCode += mirrorRootId * 31;
122             }
123             return std::hash<size_t>{}(hashCode);
124         }
125     };
126 
127     LayerHierarchy(RequestedLayerState* layer);
128 
129     // Visitor function that provides the hierarchy node and a traversal id which uniquely
130     // identifies how was visited. The hierarchy contains a pointer to the RequestedLayerState.
131     // Return false to stop traversing down the hierarchy.
132     typedef std::function<bool(const LayerHierarchy& hierarchy,
133                                const LayerHierarchy::TraversalPath& traversalPath)>
134             Visitor;
135 
136     // Traverse the hierarchy and visit all child variants.
traverse(const Visitor & visitor)137     void traverse(const Visitor& visitor) const {
138         TraversalPath root = TraversalPath::ROOT;
139         if (mLayer) {
140             root.id = mLayer->id;
141         }
142         traverse(visitor, root, /*depth=*/0);
143     }
144 
145     // Traverse the hierarchy in z-order, skipping children that have relative parents.
traverseInZOrder(const Visitor & visitor)146     void traverseInZOrder(const Visitor& visitor) const {
147         TraversalPath root = TraversalPath::ROOT;
148         if (mLayer) {
149             root.id = mLayer->id;
150         }
151         traverseInZOrder(visitor, root);
152     }
153 
154     const RequestedLayerState* getLayer() const;
155     const LayerHierarchy* getRelativeParent() const;
156     const LayerHierarchy* getParent() const;
157     friend std::ostream& operator<<(std::ostream& os, const LayerHierarchy& obj) {
158         std::string prefix = " ";
159         obj.dump(os, prefix, LayerHierarchy::Variant::Attached, /*isLastChild=*/false,
160                  /*includeMirroredHierarchy*/ false);
161         return os;
162     }
dump()163     std::string dump() const {
164         std::string prefix = " ";
165         std::ostringstream os;
166         dump(os, prefix, LayerHierarchy::Variant::Attached, /*isLastChild=*/false,
167              /*includeMirroredHierarchy*/ true);
168         return os.str();
169     }
170 
171     std::string getDebugStringShort() const;
172     // Traverse the hierarchy and return true if loops are found. The outInvalidRelativeRoot
173     // will contain the first relative root that was visited twice in a traversal.
174     bool hasRelZLoop(uint32_t& outInvalidRelativeRoot) const;
175     std::vector<std::pair<LayerHierarchy*, Variant>> mChildren;
176 
177 private:
178     friend LayerHierarchyBuilder;
179     LayerHierarchy(const LayerHierarchy& hierarchy, bool childrenOnly);
180     void addChild(LayerHierarchy*, LayerHierarchy::Variant);
181     void removeChild(LayerHierarchy*);
182     void sortChildrenByZOrder();
183     void updateChild(LayerHierarchy*, LayerHierarchy::Variant);
184     void traverseInZOrder(const Visitor& visitor,
185                           const LayerHierarchy::TraversalPath& parent) const;
186     void traverse(const Visitor& visitor, const LayerHierarchy::TraversalPath& parent,
187                   uint32_t depth = 0) const;
188     void dump(std::ostream& out, const std::string& prefix, LayerHierarchy::Variant variant,
189               bool isLastChild, bool includeMirroredHierarchy) const;
190 
191     const RequestedLayerState* mLayer;
192     LayerHierarchy* mParent = nullptr;
193     LayerHierarchy* mRelativeParent = nullptr;
194 };
195 
196 // Given a list of RequestedLayerState, this class will build a root hierarchy and an
197 // offscreen hierarchy. The builder also has an update method which can update an existing
198 // hierarchy from a list of RequestedLayerState and associated change flags.
199 class LayerHierarchyBuilder {
200 public:
201     LayerHierarchyBuilder() = default;
202     void update(LayerLifecycleManager& layerLifecycleManager);
203     LayerHierarchy getPartialHierarchy(uint32_t, bool childrenOnly) const;
204     const LayerHierarchy& getHierarchy() const;
205     const LayerHierarchy& getOffscreenHierarchy() const;
206     std::string getDebugString(uint32_t layerId, uint32_t depth = 0) const;
207     void dumpLayerSample(const LayerHierarchy& layerHierarchy) const;
208 
209 private:
210     void logSampledChildren(const LayerHierarchy& hierarchy) const;
211 
212     void onLayerAdded(RequestedLayerState* layer);
213     void attachToParent(LayerHierarchy*);
214     void detachFromParent(LayerHierarchy*);
215     void attachToRelativeParent(LayerHierarchy*);
216     void detachFromRelativeParent(LayerHierarchy*);
217     std::vector<LayerHierarchy*> getDescendants(LayerHierarchy*);
218     void attachHierarchyToRelativeParent(LayerHierarchy*);
219     void detachHierarchyFromRelativeParent(LayerHierarchy*);
220     void init(const std::vector<std::unique_ptr<RequestedLayerState>>&);
221     void doUpdate(const std::vector<std::unique_ptr<RequestedLayerState>>& layers,
222                   const std::vector<std::unique_ptr<RequestedLayerState>>& destroyedLayers);
223     void onLayerDestroyed(RequestedLayerState* layer);
224     void updateMirrorLayer(RequestedLayerState* layer);
225     LayerHierarchy* getHierarchyFromId(uint32_t layerId, bool crashOnFailure = true);
226 
227     std::unordered_map<uint32_t, LayerHierarchy*> mLayerIdToHierarchy;
228     std::vector<std::unique_ptr<LayerHierarchy>> mHierarchies;
229     LayerHierarchy mRoot{nullptr};
230     LayerHierarchy mOffscreenRoot{nullptr};
231     bool mInitialized = false;
232 };
233 
234 } // namespace android::surfaceflinger::frontend
235