1 /* 2 * Copyright (C) 2013 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 <SkCanvas.h> 18 #include <algorithm> 19 20 #include <utils/Trace.h> 21 22 #include "DamageAccumulator.h" 23 #include "Debug.h" 24 #include "DisplayList.h" 25 #include "OpDumper.h" 26 #include "RecordedOp.h" 27 #include "RenderNode.h" 28 #include "VectorDrawable.h" 29 #include "renderthread/CanvasContext.h" 30 31 namespace android { 32 namespace uirenderer { 33 34 DisplayList::DisplayList() 35 : projectionReceiveIndex(-1) 36 , stdAllocator(allocator) 37 , chunks(stdAllocator) 38 , ops(stdAllocator) 39 , children(stdAllocator) 40 , bitmapResources(stdAllocator) 41 , pathResources(stdAllocator) 42 , patchResources(stdAllocator) 43 , paints(stdAllocator) 44 , regions(stdAllocator) 45 , referenceHolders(stdAllocator) 46 , functors(stdAllocator) 47 , vectorDrawables(stdAllocator) {} 48 49 DisplayList::~DisplayList() { 50 cleanupResources(); 51 } 52 53 void DisplayList::cleanupResources() { 54 if (CC_UNLIKELY(patchResources.size())) { 55 ResourceCache& resourceCache = ResourceCache::getInstance(); 56 resourceCache.lock(); 57 58 for (size_t i = 0; i < patchResources.size(); i++) { 59 resourceCache.decrementRefcountLocked(patchResources[i]); 60 } 61 62 resourceCache.unlock(); 63 } 64 65 for (size_t i = 0; i < pathResources.size(); i++) { 66 const SkPath* path = pathResources[i]; 67 if (path->unique() && Caches::hasInstance()) { 68 Caches::getInstance().pathCache.removeDeferred(path); 69 } 70 delete path; 71 } 72 73 for (auto& iter : functors) { 74 if (iter.listener) { 75 iter.listener->onGlFunctorReleased(iter.functor); 76 } 77 } 78 79 patchResources.clear(); 80 pathResources.clear(); 81 paints.clear(); 82 regions.clear(); 83 } 84 85 size_t DisplayList::addChild(NodeOpType* op) { 86 referenceHolders.push_back(op->renderNode); 87 size_t index = children.size(); 88 children.push_back(op); 89 return index; 90 } 91 92 void DisplayList::syncContents() { 93 for (auto& iter : functors) { 94 (*iter.functor)(DrawGlInfo::kModeSync, nullptr); 95 } 96 for (auto& vectorDrawable : vectorDrawables) { 97 vectorDrawable->syncProperties(); 98 } 99 } 100 101 void DisplayList::updateChildren(std::function<void(RenderNode*)> updateFn) { 102 for (auto&& child : children) { 103 updateFn(child->renderNode); 104 } 105 } 106 107 bool DisplayList::prepareListAndChildren( 108 TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer, 109 std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) { 110 info.prepareTextures = info.canvasContext.pinImages(bitmapResources); 111 112 for (auto&& op : children) { 113 RenderNode* childNode = op->renderNode; 114 info.damageAccumulator->pushTransform(&op->localMatrix); 115 bool childFunctorsNeedLayer = 116 functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip; 117 childFn(childNode, observer, info, childFunctorsNeedLayer); 118 info.damageAccumulator->popTransform(); 119 } 120 121 bool isDirty = false; 122 for (auto& vectorDrawable : vectorDrawables) { 123 // If any vector drawable in the display list needs update, damage the node. 124 if (vectorDrawable->isDirty()) { 125 isDirty = true; 126 } 127 vectorDrawable->setPropertyChangeWillBeConsumed(true); 128 } 129 return isDirty; 130 } 131 132 void DisplayList::output(std::ostream& output, uint32_t level) { 133 for (auto&& op : getOps()) { 134 OpDumper::dump(*op, output, level + 1); 135 if (op->opId == RecordedOpId::RenderNodeOp) { 136 auto rnOp = reinterpret_cast<const RenderNodeOp*>(op); 137 rnOp->renderNode->output(output, level + 1); 138 } else { 139 output << std::endl; 140 } 141 } 142 } 143 144 }; // namespace uirenderer 145 }; // namespace android 146