• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <SkCamera.h>
20 #include <SkMatrix.h>
21 
22 #include <utils/LinearAllocator.h>
23 #include <utils/RefBase.h>
24 #include <utils/String8.h>
25 
26 #include <cutils/compiler.h>
27 
28 #include <androidfw/ResourceTypes.h>
29 
30 #include "AnimatorManager.h"
31 #include "Debug.h"
32 #include "DisplayList.h"
33 #include "Matrix.h"
34 #include "RenderProperties.h"
35 #include "pipeline/skia/SkiaDisplayList.h"
36 #include "pipeline/skia/SkiaLayer.h"
37 #include "utils/FatVector.h"
38 
39 #include <vector>
40 
41 class SkBitmap;
42 class SkPaint;
43 class SkPath;
44 class SkRegion;
45 class SkSurface;
46 
47 namespace android {
48 namespace uirenderer {
49 
50 class CanvasState;
51 class DisplayListOp;
52 class FrameBuilder;
53 class OffscreenBuffer;
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 properties.
67  *
68  * Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording
69  * functionality is split between RecordingCanvas (which manages the recording), DisplayList
70  * (which holds the actual data), and RenderNode (which holds properties used for render playback).
71  *
72  * Note that DisplayList is swapped out from beneath an individual RenderNode when a view's
73  * recorded stream of canvas operations is refreshed. The RenderNode (and its properties) stay
74  * attached.
75  */
76 class RenderNode : public VirtualLightRefBase {
77 friend class TestUtils; // allow TestUtils to access syncDisplayList / syncProperties
78 friend class FrameBuilder;
79 public:
80     enum DirtyPropertyMask {
81         GENERIC         = 1 << 1,
82         TRANSLATION_X   = 1 << 2,
83         TRANSLATION_Y   = 1 << 3,
84         TRANSLATION_Z   = 1 << 4,
85         SCALE_X         = 1 << 5,
86         SCALE_Y         = 1 << 6,
87         ROTATION        = 1 << 7,
88         ROTATION_X      = 1 << 8,
89         ROTATION_Y      = 1 << 9,
90         X               = 1 << 10,
91         Y               = 1 << 11,
92         Z               = 1 << 12,
93         ALPHA           = 1 << 13,
94         DISPLAY_LIST    = 1 << 14,
95     };
96 
97     ANDROID_API RenderNode();
98     ANDROID_API virtual ~RenderNode();
99 
100     // See flags defined in DisplayList.java
101     enum ReplayFlag {
102         kReplayFlag_ClipChildren = 0x1
103     };
104 
105     ANDROID_API void setStagingDisplayList(DisplayList* newData);
106 
107     void computeOrdering();
108 
109     ANDROID_API void output();
110     ANDROID_API int getDebugSize();
111     void copyTo(proto::RenderNode* node);
112 
isRenderable()113     bool isRenderable() const {
114         return mDisplayList && !mDisplayList->isEmpty();
115     }
116 
hasProjectionReceiver()117     bool hasProjectionReceiver() const {
118         return mDisplayList && mDisplayList->projectionReceiveIndex >= 0;
119     }
120 
getName()121     const char* getName() const {
122         return mName.string();
123     }
124 
setName(const char * name)125     void setName(const char* name) {
126         if (name) {
127             const char* lastPeriod = strrchr(name, '.');
128             if (lastPeriod) {
129                 mName.setTo(lastPeriod + 1);
130             } else {
131                 mName.setTo(name);
132             }
133         }
134     }
135 
getUserContext()136     VirtualLightRefBase* getUserContext() const {
137         return mUserContext.get();
138     }
139 
setUserContext(VirtualLightRefBase * context)140     void setUserContext(VirtualLightRefBase* context) {
141         mUserContext = context;
142     }
143 
isPropertyFieldDirty(DirtyPropertyMask field)144     bool isPropertyFieldDirty(DirtyPropertyMask field) const {
145         return mDirtyPropertyFields & field;
146     }
147 
setPropertyFieldsDirty(uint32_t fields)148     void setPropertyFieldsDirty(uint32_t fields) {
149         mDirtyPropertyFields |= fields;
150     }
151 
properties()152     const RenderProperties& properties() const {
153         return mProperties;
154     }
155 
animatorProperties()156     RenderProperties& animatorProperties() {
157         return mProperties;
158     }
159 
stagingProperties()160     const RenderProperties& stagingProperties() {
161         return mStagingProperties;
162     }
163 
mutateStagingProperties()164     RenderProperties& mutateStagingProperties() {
165         return mStagingProperties;
166     }
167 
isValid()168     bool isValid() {
169         return mValid;
170     }
171 
getWidth()172     int getWidth() const {
173         return properties().getWidth();
174     }
175 
getHeight()176     int getHeight() const {
177         return properties().getHeight();
178     }
179 
180     ANDROID_API virtual void prepareTree(TreeInfo& info);
181     void destroyHardwareResources(TreeInfo* info = nullptr);
182     void destroyLayers();
183 
184     // UI thread only!
185     ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
186     void removeAnimator(const sp<BaseRenderNodeAnimator>& animator);
187 
188     // This can only happen during pushStaging()
onAnimatorTargetChanged(BaseRenderNodeAnimator * animator)189     void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
190         mAnimatorManager.onAnimatorTargetChanged(animator);
191     }
192 
animators()193     AnimatorManager& animators() { return mAnimatorManager; }
194 
195     void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;
196 
nothingToDraw()197     bool nothingToDraw() const {
198         const Outline& outline = properties().getOutline();
199         return mDisplayList == nullptr
200                 || properties().getAlpha() <= 0
201                 || (outline.getShouldClip() && outline.isEmpty())
202                 || properties().getScaleX() == 0
203                 || properties().getScaleY() == 0;
204     }
205 
getDisplayList()206     const DisplayList* getDisplayList() const {
207         return mDisplayList;
208     }
getLayer()209     OffscreenBuffer* getLayer() const { return mLayer; }
getLayerHandle()210     OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
setLayer(OffscreenBuffer * layer)211     void setLayer(OffscreenBuffer* layer) { mLayer = layer; }
212 
213     // Note: The position callbacks are relying on the listener using
214     // the frameNumber to appropriately batch/synchronize these transactions.
215     // There is no other filtering/batching to ensure that only the "final"
216     // state called once per frame.
217     class ANDROID_API PositionListener : public VirtualLightRefBase {
218     public:
~PositionListener()219         virtual ~PositionListener() {}
220         // Called when the RenderNode's position changes
221         virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
222         // Called when the RenderNode no longer has a position. As in, it's
223         // no longer being drawn.
224         // Note, tree info might be null
225         virtual void onPositionLost(RenderNode& node, const TreeInfo* info) = 0;
226     };
227 
228     // Note this is not thread safe, this needs to be called
229     // before the RenderNode is used for drawing.
230     // RenderNode takes ownership of the pointer
setPositionListener(PositionListener * listener)231     ANDROID_API void setPositionListener(PositionListener* listener) {
232         mPositionListener = listener;
233     }
234 
235     // This is only modified in MODE_FULL, so it can be safely accessed
236     // on the UI thread.
hasParents()237     ANDROID_API bool hasParents() {
238         return mParentCount;
239     }
240 
241     void onRemovedFromTree(TreeInfo* info);
242 
243     // Called by CanvasContext to promote a RenderNode to be a root node
makeRoot()244     void makeRoot() {
245         incParentRefCount();
246     }
247 
248     // Called by CanvasContext when it drops a RenderNode from being a root node
249     void clearRoot();
250 
251     void output(std::ostream& output, uint32_t level);
252 
253 private:
254     void computeOrderingImpl(RenderNodeOp* opState,
255             std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
256             const mat4* transformFromProjectionSurface);
257 
258     void syncProperties();
259     void syncDisplayList(TreeObserver& observer, TreeInfo* info);
260 
261     void prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer);
262     void pushStagingPropertiesChanges(TreeInfo& info);
263     void pushStagingDisplayListChanges(TreeObserver& observer, TreeInfo& info);
264     void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
265     void pushLayerUpdate(TreeInfo& info);
266     void deleteDisplayList(TreeObserver& observer, TreeInfo* info = nullptr);
267     void damageSelf(TreeInfo& info);
268 
incParentRefCount()269     void incParentRefCount() { mParentCount++; }
270     void decParentRefCount(TreeObserver& observer, TreeInfo* info = nullptr);
271 
272     String8 mName;
273     sp<VirtualLightRefBase> mUserContext;
274 
275     uint32_t mDirtyPropertyFields;
276     RenderProperties mProperties;
277     RenderProperties mStagingProperties;
278 
279     // Owned by UI. Set when DL is set, cleared when DL cleared or when node detached
280     // (likely by parent re-record/removal)
281     bool mValid = false;
282 
283     bool mNeedsDisplayListSync;
284     // WARNING: Do not delete this directly, you must go through deleteDisplayList()!
285     DisplayList* mDisplayList;
286     DisplayList* mStagingDisplayList;
287 
288     friend class AnimatorManager;
289     AnimatorManager mAnimatorManager;
290 
291     // Owned by RT. Lifecycle is managed by prepareTree(), with the exception
292     // being in ~RenderNode() which may happen on any thread.
293     OffscreenBuffer* mLayer = nullptr;
294 
295     /**
296      * Draw time state - these properties are only set and used during rendering
297      */
298 
299     // for projection surfaces, contains a list of all children items
300     std::vector<RenderNodeOp*> mProjectedNodes;
301 
302     // How many references our parent(s) have to us. Typically this should alternate
303     // between 2 and 1 (when a staging push happens we inc first then dec)
304     // When this hits 0 we are no longer in the tree, so any hardware resources
305     // (specifically Layers) should be released.
306     // This is *NOT* thread-safe, and should therefore only be tracking
307     // mDisplayList, not mStagingDisplayList.
308     uint32_t mParentCount;
309 
310     sp<PositionListener> mPositionListener;
311 
312 // METHODS & FIELDS ONLY USED BY THE SKIA RENDERER
313 public:
314     /**
315      * Detach and transfer ownership of an already allocated displayList for use
316      * in recording updated content for this renderNode
317      */
detachAvailableList()318     std::unique_ptr<skiapipeline::SkiaDisplayList> detachAvailableList() {
319         return std::move(mAvailableDisplayList);
320     }
321 
322     /**
323      * Attach unused displayList to this node for potential future reuse.
324      */
attachAvailableList(skiapipeline::SkiaDisplayList * skiaDisplayList)325     void attachAvailableList(skiapipeline::SkiaDisplayList* skiaDisplayList) {
326         mAvailableDisplayList.reset(skiaDisplayList);
327     }
328 
329     /**
330      * Returns true if an offscreen layer from any renderPipeline is attached
331      * to this node.
332      */
hasLayer()333     bool hasLayer() const { return mLayer || mSkiaLayer.get(); }
334 
335     /**
336      * Used by the RenderPipeline to attach an offscreen surface to the RenderNode.
337      * The surface is then will be used to store the contents of a layer.
338      */
setLayerSurface(sk_sp<SkSurface> layer)339     void setLayerSurface(sk_sp<SkSurface> layer) {
340         if (layer.get()) {
341             if (!mSkiaLayer.get()) {
342                 mSkiaLayer = std::make_unique<skiapipeline::SkiaLayer>();
343             }
344             mSkiaLayer->layerSurface = std::move(layer);
345             mSkiaLayer->inverseTransformInWindow.loadIdentity();
346         } else {
347             mSkiaLayer.reset();
348         }
349     }
350 
351     /**
352      * If the RenderNode is of type LayerType::RenderLayer then this method will
353      * return the an offscreen rendering surface that is used to both render into
354      * the layer and composite the layer into its parent.  If the type is not
355      * LayerType::RenderLayer then it will return a nullptr.
356      *
357      * NOTE: this function is only guaranteed to return accurate results after
358      *       prepareTree has been run for this RenderNode
359      */
getLayerSurface()360     SkSurface* getLayerSurface() const {
361         return mSkiaLayer.get() ? mSkiaLayer->layerSurface.get() : nullptr;
362     }
363 
getSkiaLayer()364     skiapipeline::SkiaLayer* getSkiaLayer() const {
365         return mSkiaLayer.get();
366     }
367 
368 private:
369     /**
370      * If this RenderNode has been used in a previous frame then the SkiaDisplayList
371      * from that frame is cached here until one of the following conditions is met:
372      *  1) The RenderNode is deleted (causing this to be deleted)
373      *  2) It is replaced with the displayList from the next completed frame
374      *  3) It is detached and used to to record a new displayList for a later frame
375      */
376     std::unique_ptr<skiapipeline::SkiaDisplayList> mAvailableDisplayList;
377 
378     /**
379      * An offscreen rendering target used to contain the contents this RenderNode
380      * when it has been set to draw as a LayerType::RenderLayer.
381      */
382     std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer;
383 }; // class RenderNode
384 
385 class MarkAndSweepRemoved : public TreeObserver {
386 PREVENT_COPY_AND_ASSIGN(MarkAndSweepRemoved);
387 
388 public:
MarkAndSweepRemoved(TreeInfo * info)389     explicit MarkAndSweepRemoved(TreeInfo* info) : mTreeInfo(info) {}
390 
onMaybeRemovedFromTree(RenderNode * node)391     void onMaybeRemovedFromTree(RenderNode* node) override {
392         mMarked.emplace_back(node);
393     }
394 
~MarkAndSweepRemoved()395     ~MarkAndSweepRemoved() {
396         for (auto& node : mMarked) {
397             if (!node->hasParents()) {
398                 node->onRemovedFromTree(mTreeInfo);
399             }
400         }
401     }
402 
403 private:
404     FatVector<sp<RenderNode>, 10> mMarked;
405     TreeInfo* mTreeInfo;
406 };
407 
408 } /* namespace uirenderer */
409 } /* namespace android */
410