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