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