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 50 DisplayList::~DisplayList() { 51 cleanupResources(); 52 } 53 54 void DisplayList::cleanupResources() { 55 if (CC_UNLIKELY(patchResources.size())) { 56 ResourceCache& resourceCache = ResourceCache::getInstance(); 57 resourceCache.lock(); 58 59 for (size_t i = 0; i < patchResources.size(); i++) { 60 resourceCache.decrementRefcountLocked(patchResources[i]); 61 } 62 63 resourceCache.unlock(); 64 } 65 66 for (size_t i = 0; i < pathResources.size(); i++) { 67 const SkPath* path = pathResources[i]; 68 if (path->unique() && Caches::hasInstance()) { 69 Caches::getInstance().pathCache.removeDeferred(path); 70 } 71 delete path; 72 } 73 74 for (auto& iter : functors) { 75 if (iter.listener) { 76 iter.listener->onGlFunctorReleased(iter.functor); 77 } 78 } 79 80 patchResources.clear(); 81 pathResources.clear(); 82 paints.clear(); 83 regions.clear(); 84 } 85 86 size_t DisplayList::addChild(NodeOpType* op) { 87 referenceHolders.push_back(op->renderNode); 88 size_t index = children.size(); 89 children.push_back(op); 90 return index; 91 } 92 93 void DisplayList::syncContents() { 94 for (auto& iter : functors) { 95 (*iter.functor)(DrawGlInfo::kModeSync, nullptr); 96 } 97 for (auto& vectorDrawable : vectorDrawables) { 98 vectorDrawable->syncProperties(); 99 } 100 } 101 102 void DisplayList::updateChildren(std::function<void(RenderNode*)> updateFn) { 103 for (auto&& child : children) { 104 updateFn(child->renderNode); 105 } 106 } 107 108 bool DisplayList::prepareListAndChildren(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 = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip; 116 childFn(childNode, observer, info, childFunctorsNeedLayer); 117 info.damageAccumulator->popTransform(); 118 } 119 120 bool isDirty = false; 121 for (auto& vectorDrawable : vectorDrawables) { 122 // If any vector drawable in the display list needs update, damage the node. 123 if (vectorDrawable->isDirty()) { 124 isDirty = true; 125 } 126 vectorDrawable->setPropertyChangeWillBeConsumed(true); 127 } 128 return isDirty; 129 } 130 131 void DisplayList::output(std::ostream& output, uint32_t level) { 132 for (auto&& op : getOps()) { 133 OpDumper::dump(*op, output, level + 1); 134 if (op->opId == RecordedOpId::RenderNodeOp) { 135 auto rnOp = reinterpret_cast<const RenderNodeOp*>(op); 136 rnOp->renderNode->output(output, level + 1); 137 } else { 138 output << std::endl; 139 } 140 } 141 } 142 143 }; // namespace uirenderer 144 }; // namespace android 145