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