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