SkiaDisplayList.cpp revision d21723704571dba7e69947d92856f22989d53dbf
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#include "SkiaDisplayList.h" 18 19#include "renderthread/CanvasContext.h" 20#include "VectorDrawable.h" 21#include "DumpOpsCanvas.h" 22 23#include <SkImagePriv.h> 24 25 26namespace android { 27namespace uirenderer { 28namespace skiapipeline { 29 30SkiaDisplayList::SkiaDisplayList(SkRect bounds) : mDrawable(SkLiteDL::New(bounds)) { 31 SkASSERT(projectionReceiveIndex == -1); 32} 33 34void SkiaDisplayList::syncContents() { 35 for (auto& functor : mChildFunctors) { 36 functor.syncFunctor(); 37 } 38 for (auto& vectorDrawable : mVectorDrawables) { 39 vectorDrawable->syncProperties(); 40 } 41} 42 43bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) { 44 reset(SkRect::MakeEmpty()); 45 node->attachAvailableList(this); 46 return true; 47} 48 49void SkiaDisplayList::updateChildren(std::function<void(RenderNode*)> updateFn) { 50 for (auto& child : mChildNodes) { 51 updateFn(child.getRenderNode()); 52 } 53} 54 55bool SkiaDisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& info, 56 bool functorsNeedLayer, 57 std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) { 58 // If the prepare tree is triggered by the UI thread and no previous call to 59 // pinImages has failed then we must pin all mutable images in the GPU cache 60 // until the next UI thread draw. 61 if (info.prepareTextures && !info.canvasContext.pinImages(mMutableImages)) { 62 // In the event that pinning failed we prevent future pinImage calls for the 63 // remainder of this tree traversal and also unpin any currently pinned images 64 // to free up GPU resources. 65 info.prepareTextures = false; 66 info.canvasContext.unpinImages(); 67 } 68 69 bool hasBackwardProjectedNodesHere = false; 70 bool hasBackwardProjectedNodesSubtree= false; 71 72 for (auto& child : mChildNodes) { 73 hasBackwardProjectedNodesHere |= child.getNodeProperties().getProjectBackwards(); 74 RenderNode* childNode = child.getRenderNode(); 75 Matrix4 mat4(child.getRecordedMatrix()); 76 info.damageAccumulator->pushTransform(&mat4); 77 // TODO: a layer is needed if the canvas is rotated or has a non-rect clip 78 info.hasBackwardProjectedNodes = false; 79 childFn(childNode, observer, info, functorsNeedLayer); 80 hasBackwardProjectedNodesSubtree |= info.hasBackwardProjectedNodes; 81 info.damageAccumulator->popTransform(); 82 } 83 84 //The purpose of next block of code is to reset projected display list if there are no 85 //backward projected nodes. This speeds up drawing, by avoiding an extra walk of the tree 86 if (mProjectionReceiver) { 87 mProjectionReceiver->setProjectedDisplayList(hasBackwardProjectedNodesSubtree ? this : nullptr); 88 info.hasBackwardProjectedNodes = hasBackwardProjectedNodesHere; 89 } else { 90 info.hasBackwardProjectedNodes = hasBackwardProjectedNodesSubtree 91 || hasBackwardProjectedNodesHere; 92 } 93 94 bool isDirty = false; 95 for (auto& vectorDrawable : mVectorDrawables) { 96 // If any vector drawable in the display list needs update, damage the node. 97 if (vectorDrawable->isDirty()) { 98 isDirty = true; 99 } 100 vectorDrawable->setPropertyChangeWillBeConsumed(true); 101 } 102 return isDirty; 103} 104 105void SkiaDisplayList::reset(SkRect bounds) { 106 mProjectionReceiver = nullptr; 107 108 mDrawable->reset(bounds); 109 110 mMutableImages.clear(); 111 mVectorDrawables.clear(); 112 mChildFunctors.clear(); 113 mChildNodes.clear(); 114 115 projectionReceiveIndex = -1; 116 allocator.~LinearAllocator(); 117 new (&allocator) LinearAllocator(); 118} 119 120void SkiaDisplayList::output(std::ostream& output, uint32_t level) { 121 DumpOpsCanvas canvas(output, level, *this); 122 mDrawable->draw(&canvas, nullptr); 123} 124 125}; // namespace skiapipeline 126}; // namespace uirenderer 127}; // namespace android 128