• 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 "DisplayList.h"
20 #include "GLFunctorDrawable.h"
21 #include "RenderNodeDrawable.h"
22 
23 #include <deque>
24 #include <SkLiteDL.h>
25 #include <SkLiteRecorder.h>
26 
27 namespace android {
28 namespace uirenderer {
29 
30 class Outline;
31 
32 namespace skiapipeline {
33 
34 /**
35  * This class is intended to be self contained, but still subclasses from
36  * DisplayList to make it easier to support switching between the two at
37  * runtime.  The downside of this inheritance is that we pay for the overhead
38  * of the parent class construction/destruction without any real benefit.
39  */
40 class SkiaDisplayList : public DisplayList {
41 public:
SkiaDisplayList()42     SkiaDisplayList() { SkASSERT(projectionReceiveIndex == -1); }
~SkiaDisplayList()43     virtual ~SkiaDisplayList() {
44         /* Given that we are using a LinearStdAllocator to store some of the
45          * SkDrawable contents we must ensure that any other object that is
46          * holding a reference to those drawables is destroyed prior to their
47          * deletion.
48          */
49         mDisplayList.reset();
50     }
51 
52     /**
53      * This resets the DisplayList so that it behaves as if the object were newly
54      * constructed.  The reuse avoids any overhead associated with destroying
55      * the SkLiteDL as well as the deques and vectors.
56      */
57     void reset();
58 
59     /**
60      * Use the linear allocator to create any SkDrawables needed by the display
61      * list. This could be dangerous as these objects are ref-counted, so we
62      * need to monitor that they don't extend beyond the lifetime of the class
63      * that creates them. Allocator dtor invokes all SkDrawable dtors.
64      */
65     template<class T, typename... Params>
allocateDrawable(Params &&...params)66     SkDrawable* allocateDrawable(Params&&... params) {
67         return allocator.create<T>(std::forward<Params>(params)...);
68     }
69 
isSkiaDL()70     bool isSkiaDL() const override { return true; }
71 
72     /**
73      * Returns true if the DisplayList does not have any recorded content
74      */
isEmpty()75     bool isEmpty() const override { return mDisplayList.empty(); }
76 
77     /**
78      * Returns true if this list directly contains a GLFunctor drawing command.
79      */
hasFunctor()80     bool hasFunctor() const override { return !mChildFunctors.empty(); }
81 
82     /**
83      * Returns true if this list directly contains a VectorDrawable drawing command.
84      */
hasVectorDrawables()85     bool hasVectorDrawables() const override { return !mVectorDrawables.empty(); }
86 
87     /**
88      * Attempts to reset and reuse this DisplayList.
89      *
90      * @return true if the displayList will be reused and therefore should not be deleted
91      */
92     bool reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) override;
93 
94     /**
95      * ONLY to be called by RenderNode::syncDisplayList so that we can notify any
96      * contained VectorDrawables or GLFunctors to sync their state.
97      *
98      * NOTE: This function can be folded into RenderNode when we no longer need
99      *       to subclass from DisplayList
100      */
101     void syncContents() override;
102 
103     /**
104      * ONLY to be called by RenderNode::prepareTree in order to prepare this
105      * list while the UI thread is blocked.  Here we can upload mutable bitmaps
106      * and notify our parent if any of our content has been invalidated and in
107      * need of a redraw.  If the renderNode has any children then they are also
108      * call in order to prepare them.
109      *
110      * @return true if any content change requires the node to be invalidated
111      *
112      * NOTE: This function can be folded into RenderNode when we no longer need
113      *       to subclass from DisplayList
114      */
115 
116     bool prepareListAndChildren(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
117             std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) override;
118 
119     /**
120      *  Calls the provided function once for each child of this DisplayList
121      */
122     void updateChildren(std::function<void(RenderNode*)> updateFn) override;
123 
124     /**
125      *  Returns true if there is a child render node that is a projection receiver.
126      */
containsProjectionReceiver()127     inline bool containsProjectionReceiver() const { return mProjectionReceiver; }
128 
attachRecorder(SkLiteRecorder * recorder,const SkIRect & bounds)129     void attachRecorder(SkLiteRecorder* recorder, const SkIRect& bounds) {
130         recorder->reset(&mDisplayList, bounds);
131     }
132 
draw(SkCanvas * canvas)133     void draw(SkCanvas* canvas) { mDisplayList.draw(canvas); }
134 
135     void output(std::ostream& output, uint32_t level) override;
136 
137     /**
138      * We use std::deque here because (1) we need to iterate through these
139      * elements and (2) mDisplayList holds pointers to the elements, so they
140      * cannot relocate.
141      */
142     std::deque<RenderNodeDrawable> mChildNodes;
143     std::deque<GLFunctorDrawable> mChildFunctors;
144     std::vector<SkImage*> mMutableImages;
145     std::vector<VectorDrawableRoot*> mVectorDrawables;
146     SkLiteDL mDisplayList;
147 
148     //mProjectionReceiver points to a child node (stored in mChildNodes) that is as a projection
149     //receiver. It is set at record time and used at both prepare and draw tree traversals to
150     //make sure backward projected nodes are found and drawn immediately after mProjectionReceiver.
151     RenderNodeDrawable* mProjectionReceiver = nullptr;
152 
153     //mProjectedOutline is valid only when render node tree is traversed during the draw pass.
154     //Render nodes that have a child receiver node, will store a pointer to their outline in
155     //mProjectedOutline. Child receiver node will apply the clip before any backward projected
156     //node is drawn.
157     const Outline* mProjectedOutline = nullptr;
158 
159     //mProjectedReceiverParentMatrix is valid when render node tree is traversed during the draw
160     //pass. Render nodes that have a child receiver node, will store their matrix in
161     //mProjectedReceiverParentMatrix. Child receiver node will set the matrix and then clip with the
162     //outline of their parent.
163     SkMatrix mProjectedReceiverParentMatrix;
164 };
165 
166 }; // namespace skiapipeline
167 }; // namespace uirenderer
168 }; // namespace android
169