RenderNode.h revision c3849aa786db65dbda254b90b7db3b13efd98e65
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
36#include <vector>
37
38class SkBitmap;
39class SkPaint;
40class SkPath;
41class SkRegion;
42
43namespace android {
44namespace uirenderer {
45
46class CanvasState;
47class DisplayListOp;
48class FrameBuilder;
49class OffscreenBuffer;
50class Rect;
51class SkiaShader;
52struct RenderNodeOp;
53
54class TreeInfo;
55class TreeObserver;
56
57namespace proto {
58class RenderNode;
59}
60
61/**
62 * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties.
63 *
64 * Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording
65 * functionality is split between RecordingCanvas (which manages the recording), DisplayList
66 * (which holds the actual data), and RenderNode (which holds properties used for render playback).
67 *
68 * Note that DisplayList is swapped out from beneath an individual RenderNode when a view's
69 * recorded stream of canvas operations is refreshed. The RenderNode (and its properties) stay
70 * attached.
71 */
72class RenderNode : public VirtualLightRefBase {
73friend class TestUtils; // allow TestUtils to access syncDisplayList / syncProperties
74friend class FrameBuilder;
75public:
76    enum DirtyPropertyMask {
77        GENERIC         = 1 << 1,
78        TRANSLATION_X   = 1 << 2,
79        TRANSLATION_Y   = 1 << 3,
80        TRANSLATION_Z   = 1 << 4,
81        SCALE_X         = 1 << 5,
82        SCALE_Y         = 1 << 6,
83        ROTATION        = 1 << 7,
84        ROTATION_X      = 1 << 8,
85        ROTATION_Y      = 1 << 9,
86        X               = 1 << 10,
87        Y               = 1 << 11,
88        Z               = 1 << 12,
89        ALPHA           = 1 << 13,
90        DISPLAY_LIST    = 1 << 14,
91    };
92
93    ANDROID_API RenderNode();
94    ANDROID_API virtual ~RenderNode();
95
96    // See flags defined in DisplayList.java
97    enum ReplayFlag {
98        kReplayFlag_ClipChildren = 0x1
99    };
100
101    ANDROID_API void setStagingDisplayList(DisplayList* newData, TreeObserver* observer);
102
103    void computeOrdering();
104
105    ANDROID_API void output();
106    ANDROID_API int getDebugSize();
107    void copyTo(proto::RenderNode* node);
108
109    bool isRenderable() const {
110        return mDisplayList && !mDisplayList->isEmpty();
111    }
112
113    bool hasProjectionReceiver() const {
114        return mDisplayList && mDisplayList->projectionReceiveIndex >= 0;
115    }
116
117    const char* getName() const {
118        return mName.string();
119    }
120
121    void setName(const char* name) {
122        if (name) {
123            const char* lastPeriod = strrchr(name, '.');
124            if (lastPeriod) {
125                mName.setTo(lastPeriod + 1);
126            } else {
127                mName.setTo(name);
128            }
129        }
130    }
131
132    VirtualLightRefBase* getUserContext() const {
133        return mUserContext.get();
134    }
135
136    void setUserContext(VirtualLightRefBase* context) {
137        mUserContext = context;
138    }
139
140    bool isPropertyFieldDirty(DirtyPropertyMask field) const {
141        return mDirtyPropertyFields & field;
142    }
143
144    void setPropertyFieldsDirty(uint32_t fields) {
145        mDirtyPropertyFields |= fields;
146    }
147
148    const RenderProperties& properties() const {
149        return mProperties;
150    }
151
152    RenderProperties& animatorProperties() {
153        return mProperties;
154    }
155
156    const RenderProperties& stagingProperties() {
157        return mStagingProperties;
158    }
159
160    RenderProperties& mutateStagingProperties() {
161        return mStagingProperties;
162    }
163
164    int getWidth() const {
165        return properties().getWidth();
166    }
167
168    int getHeight() const {
169        return properties().getHeight();
170    }
171
172    ANDROID_API virtual void prepareTree(TreeInfo& info);
173    void destroyHardwareResources(TreeObserver* observer, TreeInfo* info = nullptr);
174
175    // UI thread only!
176    ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
177    void removeAnimator(const sp<BaseRenderNodeAnimator>& animator);
178
179    // This can only happen during pushStaging()
180    void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
181        mAnimatorManager.onAnimatorTargetChanged(animator);
182    }
183
184    AnimatorManager& animators() { return mAnimatorManager; }
185
186    void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;
187
188    bool nothingToDraw() const {
189        const Outline& outline = properties().getOutline();
190        return mDisplayList == nullptr
191                || properties().getAlpha() <= 0
192                || (outline.getShouldClip() && outline.isEmpty())
193                || properties().getScaleX() == 0
194                || properties().getScaleY() == 0;
195    }
196
197    const DisplayList* getDisplayList() const {
198        return mDisplayList;
199    }
200    OffscreenBuffer* getLayer() const { return mLayer; }
201    OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
202
203    // Note: The position callbacks are relying on the listener using
204    // the frameNumber to appropriately batch/synchronize these transactions.
205    // There is no other filtering/batching to ensure that only the "final"
206    // state called once per frame.
207    class ANDROID_API PositionListener : public VirtualLightRefBase {
208    public:
209        virtual ~PositionListener() {}
210        // Called when the RenderNode's position changes
211        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
212        // Called when the RenderNode no longer has a position. As in, it's
213        // no longer being drawn.
214        // Note, tree info might be null
215        virtual void onPositionLost(RenderNode& node, const TreeInfo* info) = 0;
216    };
217
218    // Note this is not thread safe, this needs to be called
219    // before the RenderNode is used for drawing.
220    // RenderNode takes ownership of the pointer
221    ANDROID_API void setPositionListener(PositionListener* listener) {
222        mPositionListener = listener;
223    }
224
225    // This is only modified in MODE_FULL, so it can be safely accessed
226    // on the UI thread.
227    ANDROID_API bool hasParents() {
228        return mParentCount;
229    }
230
231private:
232    void computeOrderingImpl(RenderNodeOp* opState,
233            std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
234            const mat4* transformFromProjectionSurface);
235
236    void syncProperties();
237    void syncDisplayList(TreeInfo* info);
238
239    void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer);
240    void pushStagingPropertiesChanges(TreeInfo& info);
241    void pushStagingDisplayListChanges(TreeInfo& info);
242    void prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayList* subtree);
243    void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
244    void pushLayerUpdate(TreeInfo& info);
245    void deleteDisplayList(TreeObserver* observer, TreeInfo* info = nullptr);
246    void damageSelf(TreeInfo& info);
247
248    void incParentRefCount() { mParentCount++; }
249    void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr);
250    void output(std::ostream& output, uint32_t level);
251
252    String8 mName;
253    sp<VirtualLightRefBase> mUserContext;
254
255    uint32_t mDirtyPropertyFields;
256    RenderProperties mProperties;
257    RenderProperties mStagingProperties;
258
259    bool mNeedsDisplayListSync;
260    // WARNING: Do not delete this directly, you must go through deleteDisplayList()!
261    DisplayList* mDisplayList;
262    DisplayList* mStagingDisplayList;
263
264    friend class AnimatorManager;
265    AnimatorManager mAnimatorManager;
266
267    // Owned by RT. Lifecycle is managed by prepareTree(), with the exception
268    // being in ~RenderNode() which may happen on any thread.
269    OffscreenBuffer* mLayer = nullptr;
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    sp<PositionListener> mPositionListener;
287}; // class RenderNode
288
289} /* namespace uirenderer */
290} /* namespace android */
291