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 #ifndef RENDERNODE_H
17 #define RENDERNODE_H
18 
19 #ifndef LOG_TAG
20     #define LOG_TAG "OpenGLRenderer"
21 #endif
22 
23 #include <SkCamera.h>
24 #include <SkMatrix.h>
25 
26 #include <utils/LinearAllocator.h>
27 #include <utils/RefBase.h>
28 #include <utils/String8.h>
29 #include <utils/Vector.h>
30 
31 #include <cutils/compiler.h>
32 
33 #include <androidfw/ResourceTypes.h>
34 
35 #include "AnimatorManager.h"
36 #include "Debug.h"
37 #include "Matrix.h"
38 #include "DisplayList.h"
39 #include "RenderProperties.h"
40 
41 class SkBitmap;
42 class SkPaint;
43 class SkPath;
44 class SkRegion;
45 
46 namespace android {
47 namespace uirenderer {
48 
49 class DisplayListOp;
50 class DisplayListCanvas;
51 class OpenGLRenderer;
52 class Rect;
53 class Layer;
54 class SkiaShader;
55 
56 class ClipRectOp;
57 class SaveLayerOp;
58 class SaveOp;
59 class RestoreToCountOp;
60 class DrawRenderNodeOp;
61 class TreeInfo;
62 
63 /**
64  * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties.
65  *
66  * Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording
67  * functionality is split between DisplayListCanvas (which manages the recording), DisplayListData
68  * (which holds the actual data), and DisplayList (which holds properties and performs playback onto
69  * a renderer).
70  *
71  * Note that DisplayListData is swapped out from beneath an individual DisplayList when a view's
72  * recorded stream of canvas operations is refreshed. The DisplayList (and its properties) stay
73  * attached.
74  */
75 class RenderNode : public VirtualLightRefBase {
76 public:
77     enum DirtyPropertyMask {
78         GENERIC         = 1 << 1,
79         TRANSLATION_X   = 1 << 2,
80         TRANSLATION_Y   = 1 << 3,
81         TRANSLATION_Z   = 1 << 4,
82         SCALE_X         = 1 << 5,
83         SCALE_Y         = 1 << 6,
84         ROTATION        = 1 << 7,
85         ROTATION_X      = 1 << 8,
86         ROTATION_Y      = 1 << 9,
87         X               = 1 << 10,
88         Y               = 1 << 11,
89         Z               = 1 << 12,
90         ALPHA           = 1 << 13,
91         DISPLAY_LIST    = 1 << 14,
92     };
93 
94     ANDROID_API RenderNode();
95     ANDROID_API virtual ~RenderNode();
96 
97     // See flags defined in DisplayList.java
98     enum ReplayFlag {
99         kReplayFlag_ClipChildren = 0x1
100     };
101 
102     static void outputLogBuffer(int fd);
103     void debugDumpLayers(const char* prefix);
104 
105     ANDROID_API void setStagingDisplayList(DisplayListData* newData);
106 
107     void computeOrdering();
108 
109     void defer(DeferStateStruct& deferStruct, const int level);
110     void replay(ReplayStateStruct& replayStruct, const int level);
111 
112     ANDROID_API void output(uint32_t level = 1);
113     ANDROID_API int getDebugSize();
114 
isRenderable()115     bool isRenderable() const {
116         return mDisplayListData && !mDisplayListData->isEmpty();
117     }
118 
hasProjectionReceiver()119     bool hasProjectionReceiver() const {
120         return mDisplayListData && mDisplayListData->projectionReceiveIndex >= 0;
121     }
122 
getName()123     const char* getName() const {
124         return mName.string();
125     }
126 
setName(const char * name)127     void setName(const char* name) {
128         if (name) {
129             char* lastPeriod = strrchr(name, '.');
130             if (lastPeriod) {
131                 mName.setTo(lastPeriod + 1);
132             } else {
133                 mName.setTo(name);
134             }
135         }
136     }
137 
isPropertyFieldDirty(DirtyPropertyMask field)138     bool isPropertyFieldDirty(DirtyPropertyMask field) const {
139         return mDirtyPropertyFields & field;
140     }
141 
setPropertyFieldsDirty(uint32_t fields)142     void setPropertyFieldsDirty(uint32_t fields) {
143         mDirtyPropertyFields |= fields;
144     }
145 
properties()146     const RenderProperties& properties() const {
147         return mProperties;
148     }
149 
animatorProperties()150     RenderProperties& animatorProperties() {
151         return mProperties;
152     }
153 
stagingProperties()154     const RenderProperties& stagingProperties() {
155         return mStagingProperties;
156     }
157 
mutateStagingProperties()158     RenderProperties& mutateStagingProperties() {
159         return mStagingProperties;
160     }
161 
getWidth()162     int getWidth() {
163         return properties().getWidth();
164     }
165 
getHeight()166     int getHeight() {
167         return properties().getHeight();
168     }
169 
170     ANDROID_API virtual void prepareTree(TreeInfo& info);
171     void destroyHardwareResources();
172 
173     // UI thread only!
174     ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
175 
animators()176     AnimatorManager& animators() { return mAnimatorManager; }
177 
178     void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;
179 
180 private:
181     typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
182 
findNonNegativeIndex(const Vector<ZDrawRenderNodeOpPair> & nodes)183     static size_t findNonNegativeIndex(const Vector<ZDrawRenderNodeOpPair>& nodes) {
184         for (size_t i = 0; i < nodes.size(); i++) {
185             if (nodes[i].key >= 0.0f) return i;
186         }
187         return nodes.size();
188     }
189 
190     enum ChildrenSelectMode {
191         kNegativeZChildren,
192         kPositiveZChildren
193     };
194 
195     void computeOrderingImpl(DrawRenderNodeOp* opState,
196             const SkPath* outlineOfProjectionSurface,
197             Vector<DrawRenderNodeOp*>* compositedChildrenOfProjectionSurface,
198             const mat4* transformFromProjectionSurface);
199 
200     template <class T>
201     inline void setViewProperties(OpenGLRenderer& renderer, T& handler);
202 
203     void buildZSortedChildList(const DisplayListData::Chunk& chunk,
204             Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes);
205 
206     template<class T>
207     inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
208 
209     template <class T>
210     inline void issueOperationsOf3dChildren(ChildrenSelectMode mode,
211             const Matrix4& initialTransform, const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
212             OpenGLRenderer& renderer, T& handler);
213 
214     template <class T>
215     inline void issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler);
216 
217     /**
218      * Issue the RenderNode's operations into a handler, recursing for subtrees through
219      * DrawRenderNodeOp's defer() or replay() methods
220      */
221     template <class T>
222     inline void issueOperations(OpenGLRenderer& renderer, T& handler);
223 
224     class TextContainer {
225     public:
length()226         size_t length() const {
227             return mByteLength;
228         }
229 
text()230         const char* text() const {
231             return (const char*) mText;
232         }
233 
234         size_t mByteLength;
235         const char* mText;
236     };
237 
238     void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer);
239     void pushStagingPropertiesChanges(TreeInfo& info);
240     void pushStagingDisplayListChanges(TreeInfo& info);
241     void prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayListData* subtree);
242     void applyLayerPropertiesToLayer(TreeInfo& info);
243     void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
244     void pushLayerUpdate(TreeInfo& info);
245     void deleteDisplayListData();
246     void damageSelf(TreeInfo& info);
247 
incParentRefCount()248     void incParentRefCount() { mParentCount++; }
249     void decParentRefCount();
250 
251     String8 mName;
252 
253     uint32_t mDirtyPropertyFields;
254     RenderProperties mProperties;
255     RenderProperties mStagingProperties;
256 
257     bool mNeedsDisplayListDataSync;
258     // WARNING: Do not delete this directly, you must go through deleteDisplayListData()!
259     DisplayListData* mDisplayListData;
260     DisplayListData* mStagingDisplayListData;
261 
262     friend class AnimatorManager;
263     AnimatorManager mAnimatorManager;
264 
265     // Owned by RT. Lifecycle is managed by prepareTree(), with the exception
266     // being in ~RenderNode() which may happen on any thread.
267     Layer* mLayer;
268 
269     /**
270      * Draw time state - these properties are only set and used during rendering
271      */
272 
273     // for projection surfaces, contains a list of all children items
274     Vector<DrawRenderNodeOp*> mProjectedNodes;
275 
276     // How many references our parent(s) have to us. Typically this should alternate
277     // between 2 and 1 (when a staging push happens we inc first then dec)
278     // When this hits 0 we are no longer in the tree, so any hardware resources
279     // (specifically Layers) should be released.
280     // This is *NOT* thread-safe, and should therefore only be tracking
281     // mDisplayListData, not mStagingDisplayListData.
282     uint32_t mParentCount;
283 }; // class RenderNode
284 
285 } /* namespace uirenderer */
286 } /* namespace android */
287 
288 #endif /* RENDERNODE_H */
289