• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 <deque>
20 #include <memory>
21 
22 #include "Mesh.h"
23 #include "RecordingCanvas.h"
24 #include "RenderNodeDrawable.h"
25 #include "TreeInfo.h"
26 #include "hwui/AnimatedImageDrawable.h"
27 #include "utils/LinearAllocator.h"
28 #include "utils/Pair.h"
29 
30 namespace android {
31 namespace uirenderer {
32 
33 namespace renderthread {
34 class CanvasContext;
35 }
36 
37 class Outline;
38 struct WebViewSyncData;
39 
40 namespace VectorDrawable {
41 class Tree;
42 }
43 typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
44 
45 namespace skiapipeline {
46 
47 class FunctorDrawable;
48 
49 class SkiaDisplayList {
50 public:
getUsedSize()51     size_t getUsedSize() const { return allocator.usedSize() + mDisplayList.usedSize(); }
getAllocatedSize()52     size_t getAllocatedSize() const {
53         return allocator.allocatedSize() + mDisplayList.allocatedSize();
54     }
55 
~SkiaDisplayList()56     ~SkiaDisplayList() {
57         /* Given that we are using a LinearStdAllocator to store some of the
58          * SkDrawable contents we must ensure that any other object that is
59          * holding a reference to those drawables is destroyed prior to their
60          * deletion.
61          */
62         mDisplayList.reset();
63     }
64 
65     /**
66      * This resets the DisplayList so that it behaves as if the object were newly
67      * constructed.  The reuse avoids any overhead associated with destroying
68      * the SkLiteDL as well as the deques and vectors.
69      */
70     void reset();
71 
72     /**
73      * Use the linear allocator to create any SkDrawables needed by the display
74      * list. This could be dangerous as these objects are ref-counted, so we
75      * need to monitor that they don't extend beyond the lifetime of the class
76      * that creates them. Allocator dtor invokes all SkDrawable dtors.
77      */
78     template <class T, typename... Params>
allocateDrawable(Params &&...params)79     T* allocateDrawable(Params&&... params) {
80         return allocator.create<T>(std::forward<Params>(params)...);
81     }
82 
83     /**
84      * Returns true if the DisplayList does not have any recorded content
85      */
isEmpty()86     bool isEmpty() const { return mDisplayList.empty(); }
87 
88     /**
89      * Returns true if this list directly contains a GLFunctor drawing command.
90      */
hasFunctor()91     bool hasFunctor() const { return !mChildFunctors.empty(); }
92 
93     /**
94      * Returns true if this list directly contains a VectorDrawable drawing command.
95      */
hasVectorDrawables()96     bool hasVectorDrawables() const { return !mVectorDrawables.empty(); }
97 
hasText()98     bool hasText() const { return mDisplayList.hasText(); }
99 
hasFill()100     bool hasFill() const { return mDisplayList.hasFill(); }
101 
102     /**
103      * Attempts to reset and reuse this DisplayList.
104      *
105      * @return true if the displayList will be reused and therefore should not be deleted
106      */
107     bool reuseDisplayList(RenderNode* node);
108 
109     /**
110      * ONLY to be called by RenderNode::syncDisplayList so that we can notify any
111      * contained VectorDrawables or GLFunctors to sync their state.
112      *
113      * NOTE: This function can be folded into RenderNode when we no longer need
114      *       to subclass from DisplayList
115      */
116     void syncContents(const WebViewSyncData& data);
117 
118     /**
119      * ONLY to be called by RenderNode::onRemovedFromTree so that we can notify any
120      * contained VectorDrawables or GLFunctors.
121      *
122      */
123     void onRemovedFromTree();
124 
applyColorTransform(ColorTransform transform)125     void applyColorTransform(ColorTransform transform) {
126         mDisplayList.applyColorTransform(transform);
127     }
128 
129     /**
130      * ONLY to be called by RenderNode::prepareTree in order to prepare this
131      * list while the UI thread is blocked.  Here we can upload mutable bitmaps
132      * and notify our parent if any of our content has been invalidated and in
133      * need of a redraw.  If the renderNode has any children then they are also
134      * call in order to prepare them.
135      *
136      * @return true if any content change requires the node to be invalidated
137      *
138      * NOTE: This function can be folded into RenderNode when we no longer need
139      *       to subclass from DisplayList
140      */
141 
142     bool prepareListAndChildren(
143             TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
144             std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn);
145 
146     /**
147      *  Calls the provided function once for each child of this DisplayList
148      */
149     void updateChildren(std::function<void(RenderNode*)> updateFn);
150 
151     void visit(std::function<void(const RenderNode&)> func) const;
152 
153     /**
154      *  Returns true if there is a child render node that is a projection receiver.
155      */
containsProjectionReceiver()156     inline bool containsProjectionReceiver() const { return mProjectionReceiver; }
157 
attachRecorder(RecordingCanvas * recorder,const SkIRect & bounds)158     void attachRecorder(RecordingCanvas* recorder, const SkIRect& bounds) {
159         recorder->reset(&mDisplayList, bounds);
160     }
161 
draw(SkCanvas * canvas)162     void draw(SkCanvas* canvas) { mDisplayList.draw(canvas); }
163 
164     void output(std::ostream& output, uint32_t level) const;
165 
166     LinearAllocator allocator;
167 
168     /**
169      * We use std::deque here because (1) we need to iterate through these
170      * elements and (2) mDisplayList holds pointers to the elements, so they
171      * cannot relocate.
172      */
173     std::deque<RenderNodeDrawable> mChildNodes;
174     std::deque<FunctorDrawable*> mChildFunctors;
175     std::vector<SkImage*> mMutableImages;
176     std::vector<std::shared_ptr<const MeshBufferData>> mMeshBufferData;
177 
178 private:
179     std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables;
180     bool mHasHolePunches;
181 public:
appendVD(VectorDrawableRoot * r)182     void appendVD(VectorDrawableRoot* r) { appendVD(r, SkMatrix::I()); }
183 
appendVD(VectorDrawableRoot * r,const SkMatrix & mat)184     void appendVD(VectorDrawableRoot* r, const SkMatrix& mat) {
185         mVectorDrawables.push_back(Pair<VectorDrawableRoot*, SkMatrix>(r, mat));
186     }
187 
setHasHolePunches(bool hasHolePunches)188     void setHasHolePunches(bool hasHolePunches) {
189         mHasHolePunches = hasHolePunches;
190     }
191 
hasHolePunches()192     bool hasHolePunches() {
193         return mHasHolePunches;
194     }
195 
196     std::vector<AnimatedImageDrawable*> mAnimatedImages;
197     DisplayListData mDisplayList;
198 
199     // mProjectionReceiver points to a child node (stored in mChildNodes) that is as a projection
200     // receiver. It is set at record time and used at both prepare and draw tree traversals to
201     // make sure backward projected nodes are found and drawn immediately after mProjectionReceiver.
202     RenderNodeDrawable* mProjectionReceiver = nullptr;
203 
204     // mProjectedOutline is valid only when render node tree is traversed during the draw pass.
205     // Render nodes that have a child receiver node, will store a pointer to their outline in
206     // mProjectedOutline. Child receiver node will apply the clip before any backward projected
207     // node is drawn.
208     const Outline* mProjectedOutline = nullptr;
209 
210     // mParentMatrix is set and valid when render node tree is traversed during the draw
211     // pass. Render nodes, which draw in a order different than recording order (e.g. nodes with a
212     // child receiver node or Z elevation), can use mParentMatrix to calculate the final transform
213     // without replaying the matrix transform OPs from the display list.
214     // Child receiver node will set the matrix and then clip with the outline of their parent.
215     SkMatrix mParentMatrix;
216 };
217 
218 }  // namespace skiapipeline
219 }  // namespace uirenderer
220 }  // namespace android
221