xref: /aosp_15_r20/frameworks/base/libs/hwui/RenderNode.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #pragma once
18*d57664e9SAndroid Build Coastguard Worker 
19*d57664e9SAndroid Build Coastguard Worker #include <SkMatrix.h>
20*d57664e9SAndroid Build Coastguard Worker 
21*d57664e9SAndroid Build Coastguard Worker #include <utils/LinearAllocator.h>
22*d57664e9SAndroid Build Coastguard Worker #include <utils/RefBase.h>
23*d57664e9SAndroid Build Coastguard Worker #include <utils/String8.h>
24*d57664e9SAndroid Build Coastguard Worker 
25*d57664e9SAndroid Build Coastguard Worker #include <cutils/compiler.h>
26*d57664e9SAndroid Build Coastguard Worker 
27*d57664e9SAndroid Build Coastguard Worker #include <androidfw/ResourceTypes.h>
28*d57664e9SAndroid Build Coastguard Worker 
29*d57664e9SAndroid Build Coastguard Worker #include <ui/FatVector.h>
30*d57664e9SAndroid Build Coastguard Worker 
31*d57664e9SAndroid Build Coastguard Worker #include "AnimatorManager.h"
32*d57664e9SAndroid Build Coastguard Worker #include "CanvasTransform.h"
33*d57664e9SAndroid Build Coastguard Worker #include "Debug.h"
34*d57664e9SAndroid Build Coastguard Worker #include "DisplayList.h"
35*d57664e9SAndroid Build Coastguard Worker #include "Matrix.h"
36*d57664e9SAndroid Build Coastguard Worker #include "RenderProperties.h"
37*d57664e9SAndroid Build Coastguard Worker #include "pipeline/skia/HolePunch.h"
38*d57664e9SAndroid Build Coastguard Worker #include "pipeline/skia/SkiaDisplayList.h"
39*d57664e9SAndroid Build Coastguard Worker #include "pipeline/skia/SkiaLayer.h"
40*d57664e9SAndroid Build Coastguard Worker 
41*d57664e9SAndroid Build Coastguard Worker #include <vector>
42*d57664e9SAndroid Build Coastguard Worker #include <pipeline/skia/StretchMask.h>
43*d57664e9SAndroid Build Coastguard Worker 
44*d57664e9SAndroid Build Coastguard Worker class SkBitmap;
45*d57664e9SAndroid Build Coastguard Worker class SkPaint;
46*d57664e9SAndroid Build Coastguard Worker class SkPath;
47*d57664e9SAndroid Build Coastguard Worker class SkRegion;
48*d57664e9SAndroid Build Coastguard Worker class SkSurface;
49*d57664e9SAndroid Build Coastguard Worker 
50*d57664e9SAndroid Build Coastguard Worker namespace android {
51*d57664e9SAndroid Build Coastguard Worker namespace uirenderer {
52*d57664e9SAndroid Build Coastguard Worker 
53*d57664e9SAndroid Build Coastguard Worker class CanvasState;
54*d57664e9SAndroid Build Coastguard Worker class Rect;
55*d57664e9SAndroid Build Coastguard Worker class SkiaShader;
56*d57664e9SAndroid Build Coastguard Worker struct RenderNodeOp;
57*d57664e9SAndroid Build Coastguard Worker 
58*d57664e9SAndroid Build Coastguard Worker class TreeInfo;
59*d57664e9SAndroid Build Coastguard Worker class TreeObserver;
60*d57664e9SAndroid Build Coastguard Worker 
61*d57664e9SAndroid Build Coastguard Worker namespace proto {
62*d57664e9SAndroid Build Coastguard Worker class RenderNode;
63*d57664e9SAndroid Build Coastguard Worker }
64*d57664e9SAndroid Build Coastguard Worker 
65*d57664e9SAndroid Build Coastguard Worker /**
66*d57664e9SAndroid Build Coastguard Worker  * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display
67*d57664e9SAndroid Build Coastguard Worker  * properties.
68*d57664e9SAndroid Build Coastguard Worker  *
69*d57664e9SAndroid Build Coastguard Worker  * Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording
70*d57664e9SAndroid Build Coastguard Worker  * functionality is split between RecordingCanvas (which manages the recording), DisplayList
71*d57664e9SAndroid Build Coastguard Worker  * (which holds the actual data), and RenderNode (which holds properties used for render playback).
72*d57664e9SAndroid Build Coastguard Worker  *
73*d57664e9SAndroid Build Coastguard Worker  * Note that DisplayList is swapped out from beneath an individual RenderNode when a view's
74*d57664e9SAndroid Build Coastguard Worker  * recorded stream of canvas operations is refreshed. The RenderNode (and its properties) stay
75*d57664e9SAndroid Build Coastguard Worker  * attached.
76*d57664e9SAndroid Build Coastguard Worker  */
77*d57664e9SAndroid Build Coastguard Worker class RenderNode : public VirtualLightRefBase {
78*d57664e9SAndroid Build Coastguard Worker     friend class TestUtils;  // allow TestUtils to access syncDisplayList / syncProperties
79*d57664e9SAndroid Build Coastguard Worker 
80*d57664e9SAndroid Build Coastguard Worker public:
81*d57664e9SAndroid Build Coastguard Worker     enum DirtyPropertyMask {
82*d57664e9SAndroid Build Coastguard Worker         GENERIC = 1 << 1,
83*d57664e9SAndroid Build Coastguard Worker         TRANSLATION_X = 1 << 2,
84*d57664e9SAndroid Build Coastguard Worker         TRANSLATION_Y = 1 << 3,
85*d57664e9SAndroid Build Coastguard Worker         TRANSLATION_Z = 1 << 4,
86*d57664e9SAndroid Build Coastguard Worker         SCALE_X = 1 << 5,
87*d57664e9SAndroid Build Coastguard Worker         SCALE_Y = 1 << 6,
88*d57664e9SAndroid Build Coastguard Worker         ROTATION = 1 << 7,
89*d57664e9SAndroid Build Coastguard Worker         ROTATION_X = 1 << 8,
90*d57664e9SAndroid Build Coastguard Worker         ROTATION_Y = 1 << 9,
91*d57664e9SAndroid Build Coastguard Worker         X = 1 << 10,
92*d57664e9SAndroid Build Coastguard Worker         Y = 1 << 11,
93*d57664e9SAndroid Build Coastguard Worker         Z = 1 << 12,
94*d57664e9SAndroid Build Coastguard Worker         ALPHA = 1 << 13,
95*d57664e9SAndroid Build Coastguard Worker         DISPLAY_LIST = 1 << 14,
96*d57664e9SAndroid Build Coastguard Worker     };
97*d57664e9SAndroid Build Coastguard Worker 
98*d57664e9SAndroid Build Coastguard Worker     RenderNode();
99*d57664e9SAndroid Build Coastguard Worker     virtual ~RenderNode();
100*d57664e9SAndroid Build Coastguard Worker 
101*d57664e9SAndroid Build Coastguard Worker     // See flags defined in DisplayList.java
102*d57664e9SAndroid Build Coastguard Worker     enum ReplayFlag { kReplayFlag_ClipChildren = 0x1 };
103*d57664e9SAndroid Build Coastguard Worker 
104*d57664e9SAndroid Build Coastguard Worker     void setStagingDisplayList(DisplayList&& newData);
105*d57664e9SAndroid Build Coastguard Worker     void discardStagingDisplayList();
106*d57664e9SAndroid Build Coastguard Worker 
107*d57664e9SAndroid Build Coastguard Worker     void output();
108*d57664e9SAndroid Build Coastguard Worker     int getUsageSize();
109*d57664e9SAndroid Build Coastguard Worker     int getAllocatedSize();
110*d57664e9SAndroid Build Coastguard Worker 
isRenderable()111*d57664e9SAndroid Build Coastguard Worker     bool isRenderable() const { return mDisplayList.hasContent(); }
112*d57664e9SAndroid Build Coastguard Worker 
hasProjectionReceiver()113*d57664e9SAndroid Build Coastguard Worker     bool hasProjectionReceiver() const {
114*d57664e9SAndroid Build Coastguard Worker         return mDisplayList.containsProjectionReceiver();
115*d57664e9SAndroid Build Coastguard Worker     }
116*d57664e9SAndroid Build Coastguard Worker 
getName()117*d57664e9SAndroid Build Coastguard Worker     const char* getName() const { return mName.c_str(); }
118*d57664e9SAndroid Build Coastguard Worker 
setName(const char * name)119*d57664e9SAndroid Build Coastguard Worker     void setName(const char* name) {
120*d57664e9SAndroid Build Coastguard Worker         if (name) {
121*d57664e9SAndroid Build Coastguard Worker             const char* lastPeriod = strrchr(name, '.');
122*d57664e9SAndroid Build Coastguard Worker             if (lastPeriod) {
123*d57664e9SAndroid Build Coastguard Worker                 mName = (lastPeriod + 1);
124*d57664e9SAndroid Build Coastguard Worker             } else {
125*d57664e9SAndroid Build Coastguard Worker                 mName = name;
126*d57664e9SAndroid Build Coastguard Worker             }
127*d57664e9SAndroid Build Coastguard Worker         }
128*d57664e9SAndroid Build Coastguard Worker     }
129*d57664e9SAndroid Build Coastguard Worker 
getStretchMask()130*d57664e9SAndroid Build Coastguard Worker     StretchMask& getStretchMask() { return mStretchMask; }
131*d57664e9SAndroid Build Coastguard Worker 
isPropertyFieldDirty(DirtyPropertyMask field)132*d57664e9SAndroid Build Coastguard Worker     bool isPropertyFieldDirty(DirtyPropertyMask field) const {
133*d57664e9SAndroid Build Coastguard Worker         return mDirtyPropertyFields & field;
134*d57664e9SAndroid Build Coastguard Worker     }
135*d57664e9SAndroid Build Coastguard Worker 
setPropertyFieldsDirty(uint32_t fields)136*d57664e9SAndroid Build Coastguard Worker     void setPropertyFieldsDirty(uint32_t fields) { mDirtyPropertyFields |= fields; }
137*d57664e9SAndroid Build Coastguard Worker 
properties()138*d57664e9SAndroid Build Coastguard Worker     const RenderProperties& properties() const { return mProperties; }
139*d57664e9SAndroid Build Coastguard Worker 
animatorProperties()140*d57664e9SAndroid Build Coastguard Worker     RenderProperties& animatorProperties() { return mProperties; }
141*d57664e9SAndroid Build Coastguard Worker 
stagingProperties()142*d57664e9SAndroid Build Coastguard Worker     const RenderProperties& stagingProperties() { return mStagingProperties; }
143*d57664e9SAndroid Build Coastguard Worker 
mutateStagingProperties()144*d57664e9SAndroid Build Coastguard Worker     RenderProperties& mutateStagingProperties() { return mStagingProperties; }
145*d57664e9SAndroid Build Coastguard Worker 
isValid()146*d57664e9SAndroid Build Coastguard Worker     bool isValid() { return mValid; }
147*d57664e9SAndroid Build Coastguard Worker 
getWidth()148*d57664e9SAndroid Build Coastguard Worker     int getWidth() const { return properties().getWidth(); }
149*d57664e9SAndroid Build Coastguard Worker 
getHeight()150*d57664e9SAndroid Build Coastguard Worker     int getHeight() const { return properties().getHeight(); }
151*d57664e9SAndroid Build Coastguard Worker 
152*d57664e9SAndroid Build Coastguard Worker     virtual void prepareTree(TreeInfo& info);
153*d57664e9SAndroid Build Coastguard Worker     void destroyHardwareResources(TreeInfo* info = nullptr);
154*d57664e9SAndroid Build Coastguard Worker     void destroyLayers();
155*d57664e9SAndroid Build Coastguard Worker 
156*d57664e9SAndroid Build Coastguard Worker     // UI thread only!
157*d57664e9SAndroid Build Coastguard Worker     void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
158*d57664e9SAndroid Build Coastguard Worker     void removeAnimator(const sp<BaseRenderNodeAnimator>& animator);
159*d57664e9SAndroid Build Coastguard Worker 
160*d57664e9SAndroid Build Coastguard Worker     // This can only happen during pushStaging()
onAnimatorTargetChanged(BaseRenderNodeAnimator * animator)161*d57664e9SAndroid Build Coastguard Worker     void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
162*d57664e9SAndroid Build Coastguard Worker         mAnimatorManager.onAnimatorTargetChanged(animator);
163*d57664e9SAndroid Build Coastguard Worker     }
164*d57664e9SAndroid Build Coastguard Worker 
animators()165*d57664e9SAndroid Build Coastguard Worker     AnimatorManager& animators() { return mAnimatorManager; }
166*d57664e9SAndroid Build Coastguard Worker 
167*d57664e9SAndroid Build Coastguard Worker     void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;
168*d57664e9SAndroid Build Coastguard Worker 
nothingToDraw()169*d57664e9SAndroid Build Coastguard Worker     bool nothingToDraw() const {
170*d57664e9SAndroid Build Coastguard Worker         const Outline& outline = properties().getOutline();
171*d57664e9SAndroid Build Coastguard Worker         return !mDisplayList.isValid() || properties().getAlpha() <= 0 ||
172*d57664e9SAndroid Build Coastguard Worker                (outline.getShouldClip() && outline.isEmpty()) || properties().getScaleX() == 0 ||
173*d57664e9SAndroid Build Coastguard Worker                properties().getScaleY() == 0;
174*d57664e9SAndroid Build Coastguard Worker     }
175*d57664e9SAndroid Build Coastguard Worker 
getDisplayList()176*d57664e9SAndroid Build Coastguard Worker     const DisplayList& getDisplayList() const { return mDisplayList; }
177*d57664e9SAndroid Build Coastguard Worker     // TODO: can this be cleaned up?
getDisplayList()178*d57664e9SAndroid Build Coastguard Worker     DisplayList& getDisplayList() { return mDisplayList; }
179*d57664e9SAndroid Build Coastguard Worker 
180*d57664e9SAndroid Build Coastguard Worker     // Note: The position callbacks are relying on the listener using
181*d57664e9SAndroid Build Coastguard Worker     // the frameNumber to appropriately batch/synchronize these transactions.
182*d57664e9SAndroid Build Coastguard Worker     // There is no other filtering/batching to ensure that only the "final"
183*d57664e9SAndroid Build Coastguard Worker     // state called once per frame.
184*d57664e9SAndroid Build Coastguard Worker     class PositionListener : public VirtualLightRefBase {
185*d57664e9SAndroid Build Coastguard Worker     public:
~PositionListener()186*d57664e9SAndroid Build Coastguard Worker         virtual ~PositionListener() {}
187*d57664e9SAndroid Build Coastguard Worker         // Called when the RenderNode's position changes
188*d57664e9SAndroid Build Coastguard Worker         virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
189*d57664e9SAndroid Build Coastguard Worker         // Called when the RenderNode no longer has a position. As in, it's
190*d57664e9SAndroid Build Coastguard Worker         // no longer being drawn.
191*d57664e9SAndroid Build Coastguard Worker         // Note, tree info might be null
192*d57664e9SAndroid Build Coastguard Worker         virtual void onPositionLost(RenderNode& node, const TreeInfo* info) = 0;
193*d57664e9SAndroid Build Coastguard Worker     };
194*d57664e9SAndroid Build Coastguard Worker 
setPositionListener(PositionListener * listener)195*d57664e9SAndroid Build Coastguard Worker     void setPositionListener(PositionListener* listener) {
196*d57664e9SAndroid Build Coastguard Worker         mStagingPositionListener = listener;
197*d57664e9SAndroid Build Coastguard Worker         mPositionListenerDirty = true;
198*d57664e9SAndroid Build Coastguard Worker     }
199*d57664e9SAndroid Build Coastguard Worker 
200*d57664e9SAndroid Build Coastguard Worker     // This is only modified in MODE_FULL, so it can be safely accessed
201*d57664e9SAndroid Build Coastguard Worker     // on the UI thread.
hasParents()202*d57664e9SAndroid Build Coastguard Worker     bool hasParents() { return mParentCount; }
203*d57664e9SAndroid Build Coastguard Worker 
204*d57664e9SAndroid Build Coastguard Worker     void onRemovedFromTree(TreeInfo* info);
205*d57664e9SAndroid Build Coastguard Worker 
206*d57664e9SAndroid Build Coastguard Worker     // Called by CanvasContext to promote a RenderNode to be a root node
makeRoot()207*d57664e9SAndroid Build Coastguard Worker     void makeRoot() { incParentRefCount(); }
208*d57664e9SAndroid Build Coastguard Worker 
209*d57664e9SAndroid Build Coastguard Worker     // Called by CanvasContext when it drops a RenderNode from being a root node
210*d57664e9SAndroid Build Coastguard Worker     void clearRoot();
211*d57664e9SAndroid Build Coastguard Worker 
212*d57664e9SAndroid Build Coastguard Worker     void output(std::ostream& output, uint32_t level);
213*d57664e9SAndroid Build Coastguard Worker 
214*d57664e9SAndroid Build Coastguard Worker     void visit(std::function<void(const RenderNode&)>) const;
215*d57664e9SAndroid Build Coastguard Worker 
setUsageHint(UsageHint usageHint)216*d57664e9SAndroid Build Coastguard Worker     void setUsageHint(UsageHint usageHint) { mUsageHint = usageHint; }
217*d57664e9SAndroid Build Coastguard Worker 
usageHint()218*d57664e9SAndroid Build Coastguard Worker     UsageHint usageHint() const { return mUsageHint; }
219*d57664e9SAndroid Build Coastguard Worker 
uniqueId()220*d57664e9SAndroid Build Coastguard Worker     int64_t uniqueId() const { return mUniqueId; }
221*d57664e9SAndroid Build Coastguard Worker 
setIsTextureView()222*d57664e9SAndroid Build Coastguard Worker     void setIsTextureView() { mIsTextureView = true; }
isTextureView()223*d57664e9SAndroid Build Coastguard Worker     bool isTextureView() const { return mIsTextureView; }
224*d57664e9SAndroid Build Coastguard Worker 
225*d57664e9SAndroid Build Coastguard Worker     void markDrawStart(SkCanvas& canvas);
226*d57664e9SAndroid Build Coastguard Worker     void markDrawEnd(SkCanvas& canvas);
227*d57664e9SAndroid Build Coastguard Worker 
228*d57664e9SAndroid Build Coastguard Worker private:
229*d57664e9SAndroid Build Coastguard Worker     void computeOrderingImpl(RenderNodeOp* opState,
230*d57664e9SAndroid Build Coastguard Worker                              std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
231*d57664e9SAndroid Build Coastguard Worker                              const mat4* transformFromProjectionSurface);
232*d57664e9SAndroid Build Coastguard Worker 
233*d57664e9SAndroid Build Coastguard Worker     void syncProperties();
234*d57664e9SAndroid Build Coastguard Worker     void syncDisplayList(TreeObserver& observer, TreeInfo* info);
235*d57664e9SAndroid Build Coastguard Worker     void handleForceDark(TreeInfo* info);
236*d57664e9SAndroid Build Coastguard Worker     bool shouldEnableForceDark(TreeInfo* info);
237*d57664e9SAndroid Build Coastguard Worker     bool isForceInvertDark(TreeInfo& info);
238*d57664e9SAndroid Build Coastguard Worker 
239*d57664e9SAndroid Build Coastguard Worker     void prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer);
240*d57664e9SAndroid Build Coastguard Worker     void pushStagingPropertiesChanges(TreeInfo& info);
241*d57664e9SAndroid Build Coastguard Worker     void pushStagingDisplayListChanges(TreeObserver& observer, TreeInfo& info);
242*d57664e9SAndroid Build Coastguard Worker     void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
243*d57664e9SAndroid Build Coastguard Worker     void pushLayerUpdate(TreeInfo& info);
244*d57664e9SAndroid Build Coastguard Worker     void deleteDisplayList(TreeObserver& observer, TreeInfo* info = nullptr);
245*d57664e9SAndroid Build Coastguard Worker     void damageSelf(TreeInfo& info);
246*d57664e9SAndroid Build Coastguard Worker 
incParentRefCount()247*d57664e9SAndroid Build Coastguard Worker     void incParentRefCount() { mParentCount++; }
248*d57664e9SAndroid Build Coastguard Worker     void decParentRefCount(TreeObserver& observer, TreeInfo* info = nullptr);
249*d57664e9SAndroid Build Coastguard Worker 
250*d57664e9SAndroid Build Coastguard Worker     const int64_t mUniqueId;
251*d57664e9SAndroid Build Coastguard Worker     String8 mName;
252*d57664e9SAndroid Build Coastguard Worker 
253*d57664e9SAndroid Build Coastguard Worker     uint32_t mDirtyPropertyFields;
254*d57664e9SAndroid Build Coastguard Worker     RenderProperties mProperties;
255*d57664e9SAndroid Build Coastguard Worker     RenderProperties mStagingProperties;
256*d57664e9SAndroid Build Coastguard Worker 
257*d57664e9SAndroid Build Coastguard Worker     // Owned by UI. Set when DL is set, cleared when DL cleared or when node detached
258*d57664e9SAndroid Build Coastguard Worker     // (likely by parent re-record/removal)
259*d57664e9SAndroid Build Coastguard Worker     bool mValid = false;
260*d57664e9SAndroid Build Coastguard Worker 
261*d57664e9SAndroid Build Coastguard Worker     bool mNeedsDisplayListSync;
262*d57664e9SAndroid Build Coastguard Worker     // WARNING: Do not delete this directly, you must go through deleteDisplayList()!
263*d57664e9SAndroid Build Coastguard Worker     DisplayList mDisplayList;
264*d57664e9SAndroid Build Coastguard Worker     DisplayList mStagingDisplayList;
265*d57664e9SAndroid Build Coastguard Worker 
266*d57664e9SAndroid Build Coastguard Worker     int64_t mDamageGenerationId = 0;
267*d57664e9SAndroid Build Coastguard Worker 
268*d57664e9SAndroid Build Coastguard Worker     friend class AnimatorManager;
269*d57664e9SAndroid Build Coastguard Worker     AnimatorManager mAnimatorManager;
270*d57664e9SAndroid Build Coastguard Worker 
271*d57664e9SAndroid Build Coastguard Worker     /**
272*d57664e9SAndroid Build Coastguard Worker      * Draw time state - these properties are only set and used during rendering
273*d57664e9SAndroid Build Coastguard Worker      */
274*d57664e9SAndroid Build Coastguard Worker 
275*d57664e9SAndroid Build Coastguard Worker     // for projection surfaces, contains a list of all children items
276*d57664e9SAndroid Build Coastguard Worker     std::vector<RenderNodeOp*> mProjectedNodes;
277*d57664e9SAndroid Build Coastguard Worker 
278*d57664e9SAndroid Build Coastguard Worker     // How many references our parent(s) have to us. Typically this should alternate
279*d57664e9SAndroid Build Coastguard Worker     // between 2 and 1 (when a staging push happens we inc first then dec)
280*d57664e9SAndroid Build Coastguard Worker     // When this hits 0 we are no longer in the tree, so any hardware resources
281*d57664e9SAndroid Build Coastguard Worker     // (specifically Layers) should be released.
282*d57664e9SAndroid Build Coastguard Worker     // This is *NOT* thread-safe, and should therefore only be tracking
283*d57664e9SAndroid Build Coastguard Worker     // mDisplayList, not mStagingDisplayList.
284*d57664e9SAndroid Build Coastguard Worker     uint32_t mParentCount;
285*d57664e9SAndroid Build Coastguard Worker 
286*d57664e9SAndroid Build Coastguard Worker     bool mPositionListenerDirty = false;
287*d57664e9SAndroid Build Coastguard Worker     sp<PositionListener> mStagingPositionListener;
288*d57664e9SAndroid Build Coastguard Worker     sp<PositionListener> mPositionListener;
289*d57664e9SAndroid Build Coastguard Worker 
290*d57664e9SAndroid Build Coastguard Worker     UsageHint mUsageHint = UsageHint::Unknown;
291*d57664e9SAndroid Build Coastguard Worker 
292*d57664e9SAndroid Build Coastguard Worker     bool mHasHolePunches;
293*d57664e9SAndroid Build Coastguard Worker     StretchMask mStretchMask;
294*d57664e9SAndroid Build Coastguard Worker 
295*d57664e9SAndroid Build Coastguard Worker     bool mIsTextureView = false;
296*d57664e9SAndroid Build Coastguard Worker 
297*d57664e9SAndroid Build Coastguard Worker     // METHODS & FIELDS ONLY USED BY THE SKIA RENDERER
298*d57664e9SAndroid Build Coastguard Worker public:
299*d57664e9SAndroid Build Coastguard Worker     /**
300*d57664e9SAndroid Build Coastguard Worker      * Detach and transfer ownership of an already allocated displayList for use
301*d57664e9SAndroid Build Coastguard Worker      * in recording updated content for this renderNode
302*d57664e9SAndroid Build Coastguard Worker      */
detachAvailableList()303*d57664e9SAndroid Build Coastguard Worker     std::unique_ptr<skiapipeline::SkiaDisplayList> detachAvailableList() {
304*d57664e9SAndroid Build Coastguard Worker         return std::move(mAvailableDisplayList);
305*d57664e9SAndroid Build Coastguard Worker     }
306*d57664e9SAndroid Build Coastguard Worker 
hasHolePunches()307*d57664e9SAndroid Build Coastguard Worker     bool hasHolePunches() { return mHasHolePunches; }
308*d57664e9SAndroid Build Coastguard Worker 
309*d57664e9SAndroid Build Coastguard Worker     /**
310*d57664e9SAndroid Build Coastguard Worker      * Attach unused displayList to this node for potential future reuse.
311*d57664e9SAndroid Build Coastguard Worker      */
attachAvailableList(skiapipeline::SkiaDisplayList * skiaDisplayList)312*d57664e9SAndroid Build Coastguard Worker     void attachAvailableList(skiapipeline::SkiaDisplayList* skiaDisplayList) {
313*d57664e9SAndroid Build Coastguard Worker         mAvailableDisplayList.reset(skiaDisplayList);
314*d57664e9SAndroid Build Coastguard Worker     }
315*d57664e9SAndroid Build Coastguard Worker 
316*d57664e9SAndroid Build Coastguard Worker     /**
317*d57664e9SAndroid Build Coastguard Worker      * Returns true if an offscreen layer from any renderPipeline is attached
318*d57664e9SAndroid Build Coastguard Worker      * to this node.
319*d57664e9SAndroid Build Coastguard Worker      */
hasLayer()320*d57664e9SAndroid Build Coastguard Worker     bool hasLayer() const { return mSkiaLayer.get(); }
321*d57664e9SAndroid Build Coastguard Worker 
322*d57664e9SAndroid Build Coastguard Worker     /**
323*d57664e9SAndroid Build Coastguard Worker      * Used by the RenderPipeline to attach an offscreen surface to the RenderNode.
324*d57664e9SAndroid Build Coastguard Worker      * The surface is then will be used to store the contents of a layer.
325*d57664e9SAndroid Build Coastguard Worker      */
setLayerSurface(sk_sp<SkSurface> layer)326*d57664e9SAndroid Build Coastguard Worker     void setLayerSurface(sk_sp<SkSurface> layer) {
327*d57664e9SAndroid Build Coastguard Worker         if (layer.get()) {
328*d57664e9SAndroid Build Coastguard Worker             if (!mSkiaLayer.get()) {
329*d57664e9SAndroid Build Coastguard Worker                 mSkiaLayer = std::make_unique<skiapipeline::SkiaLayer>();
330*d57664e9SAndroid Build Coastguard Worker             }
331*d57664e9SAndroid Build Coastguard Worker             mSkiaLayer->layerSurface = std::move(layer);
332*d57664e9SAndroid Build Coastguard Worker             mSkiaLayer->inverseTransformInWindow.loadIdentity();
333*d57664e9SAndroid Build Coastguard Worker         } else {
334*d57664e9SAndroid Build Coastguard Worker             mSkiaLayer.reset();
335*d57664e9SAndroid Build Coastguard Worker         }
336*d57664e9SAndroid Build Coastguard Worker 
337*d57664e9SAndroid Build Coastguard Worker         mProperties.mutateLayerProperties().mutableStretchEffect().clear();
338*d57664e9SAndroid Build Coastguard Worker         mStretchMask.clear();
339*d57664e9SAndroid Build Coastguard Worker         // Clear out the previous snapshot and the image filter the previous
340*d57664e9SAndroid Build Coastguard Worker         // snapshot was created with whenever the layer changes.
341*d57664e9SAndroid Build Coastguard Worker         mSnapshotResult.snapshot = nullptr;
342*d57664e9SAndroid Build Coastguard Worker         mTargetImageFilter = nullptr;
343*d57664e9SAndroid Build Coastguard Worker     }
344*d57664e9SAndroid Build Coastguard Worker 
345*d57664e9SAndroid Build Coastguard Worker     /**
346*d57664e9SAndroid Build Coastguard Worker      * If the RenderNode is of type LayerType::RenderLayer then this method will
347*d57664e9SAndroid Build Coastguard Worker      * return the an offscreen rendering surface that is used to both render into
348*d57664e9SAndroid Build Coastguard Worker      * the layer and composite the layer into its parent.  If the type is not
349*d57664e9SAndroid Build Coastguard Worker      * LayerType::RenderLayer then it will return a nullptr.
350*d57664e9SAndroid Build Coastguard Worker      *
351*d57664e9SAndroid Build Coastguard Worker      * NOTE: this function is only guaranteed to return accurate results after
352*d57664e9SAndroid Build Coastguard Worker      *       prepareTree has been run for this RenderNode
353*d57664e9SAndroid Build Coastguard Worker      */
getLayerSurface()354*d57664e9SAndroid Build Coastguard Worker     SkSurface* getLayerSurface() const {
355*d57664e9SAndroid Build Coastguard Worker         return mSkiaLayer.get() ? mSkiaLayer->layerSurface.get() : nullptr;
356*d57664e9SAndroid Build Coastguard Worker     }
357*d57664e9SAndroid Build Coastguard Worker 
358*d57664e9SAndroid Build Coastguard Worker     struct SnapshotResult {
359*d57664e9SAndroid Build Coastguard Worker         sk_sp<SkImage> snapshot;
360*d57664e9SAndroid Build Coastguard Worker         SkIRect outSubset;
361*d57664e9SAndroid Build Coastguard Worker         SkIPoint outOffset;
362*d57664e9SAndroid Build Coastguard Worker     };
363*d57664e9SAndroid Build Coastguard Worker 
364*d57664e9SAndroid Build Coastguard Worker     std::optional<SnapshotResult> updateSnapshotIfRequired(GrRecordingContext* context,
365*d57664e9SAndroid Build Coastguard Worker                                             const SkImageFilter* imageFilter,
366*d57664e9SAndroid Build Coastguard Worker                                             const SkIRect& clipBounds);
367*d57664e9SAndroid Build Coastguard Worker 
getSkiaLayer()368*d57664e9SAndroid Build Coastguard Worker     skiapipeline::SkiaLayer* getSkiaLayer() const { return mSkiaLayer.get(); }
369*d57664e9SAndroid Build Coastguard Worker 
370*d57664e9SAndroid Build Coastguard Worker     /**
371*d57664e9SAndroid Build Coastguard Worker      * Returns the path that represents the outline of RenderNode intersected with
372*d57664e9SAndroid Build Coastguard Worker      * the provided rect.  This call will internally cache the resulting path in
373*d57664e9SAndroid Build Coastguard Worker      * order to potentially return that path for subsequent calls to this method.
374*d57664e9SAndroid Build Coastguard Worker      * By reusing the same path we get better performance on the GPU backends since
375*d57664e9SAndroid Build Coastguard Worker      * those resources are cached in the hardware based on the path's genID.
376*d57664e9SAndroid Build Coastguard Worker      *
377*d57664e9SAndroid Build Coastguard Worker      * The returned path is only guaranteed to be valid until this function is called
378*d57664e9SAndroid Build Coastguard Worker      * again or the RenderNode's outline is mutated.
379*d57664e9SAndroid Build Coastguard Worker      */
380*d57664e9SAndroid Build Coastguard Worker     const SkPath* getClippedOutline(const SkRect& clipRect) const;
381*d57664e9SAndroid Build Coastguard Worker 
382*d57664e9SAndroid Build Coastguard Worker private:
383*d57664e9SAndroid Build Coastguard Worker     /**
384*d57664e9SAndroid Build Coastguard Worker      * If this RenderNode has been used in a previous frame then the SkiaDisplayList
385*d57664e9SAndroid Build Coastguard Worker      * from that frame is cached here until one of the following conditions is met:
386*d57664e9SAndroid Build Coastguard Worker      *  1) The RenderNode is deleted (causing this to be deleted)
387*d57664e9SAndroid Build Coastguard Worker      *  2) It is replaced with the displayList from the next completed frame
388*d57664e9SAndroid Build Coastguard Worker      *  3) It is detached and used to to record a new displayList for a later frame
389*d57664e9SAndroid Build Coastguard Worker      */
390*d57664e9SAndroid Build Coastguard Worker     std::unique_ptr<skiapipeline::SkiaDisplayList> mAvailableDisplayList;
391*d57664e9SAndroid Build Coastguard Worker 
392*d57664e9SAndroid Build Coastguard Worker     /**
393*d57664e9SAndroid Build Coastguard Worker      * An offscreen rendering target used to contain the contents this RenderNode
394*d57664e9SAndroid Build Coastguard Worker      * when it has been set to draw as a LayerType::RenderLayer.
395*d57664e9SAndroid Build Coastguard Worker      */
396*d57664e9SAndroid Build Coastguard Worker     std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer;
397*d57664e9SAndroid Build Coastguard Worker 
398*d57664e9SAndroid Build Coastguard Worker     /**
399*d57664e9SAndroid Build Coastguard Worker      * SkImageFilter used to create the mSnapshotResult
400*d57664e9SAndroid Build Coastguard Worker      */
401*d57664e9SAndroid Build Coastguard Worker     sk_sp<SkImageFilter> mTargetImageFilter;
402*d57664e9SAndroid Build Coastguard Worker     uint32_t mTargetImageFilterLayerSurfaceGenerationId = 0;
403*d57664e9SAndroid Build Coastguard Worker 
404*d57664e9SAndroid Build Coastguard Worker     /**
405*d57664e9SAndroid Build Coastguard Worker      * Clip bounds used to create the mSnapshotResult
406*d57664e9SAndroid Build Coastguard Worker      */
407*d57664e9SAndroid Build Coastguard Worker     SkIRect mImageFilterClipBounds;
408*d57664e9SAndroid Build Coastguard Worker 
409*d57664e9SAndroid Build Coastguard Worker     /**
410*d57664e9SAndroid Build Coastguard Worker      * Result of the most recent snapshot with additional metadata used to
411*d57664e9SAndroid Build Coastguard Worker      * determine how to draw the contents
412*d57664e9SAndroid Build Coastguard Worker      */
413*d57664e9SAndroid Build Coastguard Worker     SnapshotResult mSnapshotResult;
414*d57664e9SAndroid Build Coastguard Worker 
415*d57664e9SAndroid Build Coastguard Worker     struct ClippedOutlineCache {
416*d57664e9SAndroid Build Coastguard Worker         // keys
417*d57664e9SAndroid Build Coastguard Worker         uint32_t outlineID = 0;
418*d57664e9SAndroid Build Coastguard Worker         SkRect clipRect;
419*d57664e9SAndroid Build Coastguard Worker 
420*d57664e9SAndroid Build Coastguard Worker         // value
421*d57664e9SAndroid Build Coastguard Worker         SkPath clippedOutline;
422*d57664e9SAndroid Build Coastguard Worker     };
423*d57664e9SAndroid Build Coastguard Worker     mutable ClippedOutlineCache mClippedOutlineCache;
424*d57664e9SAndroid Build Coastguard Worker };  // class RenderNode
425*d57664e9SAndroid Build Coastguard Worker 
426*d57664e9SAndroid Build Coastguard Worker class MarkAndSweepRemoved : public TreeObserver {
427*d57664e9SAndroid Build Coastguard Worker     PREVENT_COPY_AND_ASSIGN(MarkAndSweepRemoved);
428*d57664e9SAndroid Build Coastguard Worker 
429*d57664e9SAndroid Build Coastguard Worker public:
MarkAndSweepRemoved(TreeInfo * info)430*d57664e9SAndroid Build Coastguard Worker     explicit MarkAndSweepRemoved(TreeInfo* info) : mTreeInfo(info) {}
431*d57664e9SAndroid Build Coastguard Worker 
onMaybeRemovedFromTree(RenderNode * node)432*d57664e9SAndroid Build Coastguard Worker     void onMaybeRemovedFromTree(RenderNode* node) override { mMarked.emplace_back(node); }
433*d57664e9SAndroid Build Coastguard Worker 
~MarkAndSweepRemoved()434*d57664e9SAndroid Build Coastguard Worker     ~MarkAndSweepRemoved() {
435*d57664e9SAndroid Build Coastguard Worker         for (auto& node : mMarked) {
436*d57664e9SAndroid Build Coastguard Worker             if (!node->hasParents()) {
437*d57664e9SAndroid Build Coastguard Worker                 node->onRemovedFromTree(mTreeInfo);
438*d57664e9SAndroid Build Coastguard Worker             }
439*d57664e9SAndroid Build Coastguard Worker         }
440*d57664e9SAndroid Build Coastguard Worker     }
441*d57664e9SAndroid Build Coastguard Worker 
442*d57664e9SAndroid Build Coastguard Worker private:
443*d57664e9SAndroid Build Coastguard Worker     FatVector<sp<RenderNode>, 10> mMarked;
444*d57664e9SAndroid Build Coastguard Worker     TreeInfo* mTreeInfo;
445*d57664e9SAndroid Build Coastguard Worker };
446*d57664e9SAndroid Build Coastguard Worker 
447*d57664e9SAndroid Build Coastguard Worker } /* namespace uirenderer */
448*d57664e9SAndroid Build Coastguard Worker } /* namespace android */
449