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