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