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