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