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