SkiaDisplayList.cpp revision 021693b967a2c5556dddd183eb0247df4079e1ad
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
22#include <SkImagePriv.h>
23#include <SkMutex.h>
24
25namespace android {
26namespace uirenderer {
27namespace skiapipeline {
28
29SkiaDisplayList::SkiaDisplayList(SkRect bounds) : mDrawable(SkLiteDL::New(bounds)) {
30    SkASSERT(projectionReceiveIndex == -1);
31}
32
33void SkiaDisplayList::syncContents() {
34    for (auto& functor : mChildFunctors) {
35        functor.syncFunctor();
36    }
37    for (auto& vectorDrawable : mVectorDrawables) {
38        vectorDrawable->syncProperties();
39    }
40}
41
42bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) {
43    reset(context ? context->getGrContext() : nullptr, SkRect::MakeEmpty());
44    node->attachAvailableList(this);
45    return true;
46}
47
48void SkiaDisplayList::updateChildren(std::function<void(RenderNode*)> updateFn) {
49    for (auto& child : mChildNodes) {
50        updateFn(child.getRenderNode());
51    }
52}
53
54bool SkiaDisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
55        std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
56    // force all mutable images to be pinned in the GPU cache for the duration
57    // of this frame
58    pinImages(info.canvasContext.getGrContext());
59
60    for (auto& child : mChildNodes) {
61        RenderNode* childNode = child.getRenderNode();
62        Matrix4 mat4(child.getRecordedMatrix());
63        info.damageAccumulator->pushTransform(&mat4);
64        // TODO: a layer is needed if the canvas is rotated or has a non-rect clip
65        bool childFunctorsNeedLayer = functorsNeedLayer;
66        childFn(childNode, info, childFunctorsNeedLayer);
67        info.damageAccumulator->popTransform();
68    }
69
70    bool isDirty = false;
71    for (auto& vectorDrawable : mVectorDrawables) {
72        // If any vector drawable in the display list needs update, damage the node.
73        if (vectorDrawable->isDirty()) {
74            isDirty = true;
75        }
76        vectorDrawable->setPropertyChangeWillBeConsumed(true);
77    }
78    return isDirty;
79}
80
81static std::vector<sk_sp<SkImage>> gPinnedImages;
82static SkBaseMutex gLock;
83
84void SkiaDisplayList::pinImages(GrContext* context) {
85    if (mPinnedImages) return;
86    for (SkImage* image : mMutableImages) {
87        SkImage_pinAsTexture(image, context);
88    }
89    mPinnedImages = true;
90}
91
92void SkiaDisplayList::unpinImages(GrContext* context) {
93    if (!mPinnedImages) return;
94    if (context) {
95        for (SkImage* image : mMutableImages) {
96            SkImage_unpinAsTexture(image, context);
97        }
98    } else {
99        gLock.acquire();
100        for (SkImage* image : mMutableImages) {
101            gPinnedImages.emplace_back(sk_ref_sp(image));
102        }
103        gLock.release();
104    }
105    mPinnedImages = false;
106}
107
108void SkiaDisplayList::cleanupImages(GrContext* context) {
109    gLock.acquire();
110    for (auto& image : gPinnedImages) {
111        SkImage_unpinAsTexture(image.get(), context);
112    }
113    gPinnedImages.clear();
114    gLock.release();
115}
116
117void SkiaDisplayList::reset(GrContext* context, SkRect bounds) {
118    unpinImages(context);
119    SkASSERT(!mPinnedImages);
120    mIsProjectionReceiver = false;
121
122    mDrawable->reset(bounds);
123
124    mMutableImages.clear();
125    mVectorDrawables.clear();
126    mChildFunctors.clear();
127    mChildNodes.clear();
128
129    projectionReceiveIndex = -1;
130    allocator.~LinearAllocator();
131    new (&allocator) LinearAllocator();
132}
133
134}; // namespace skiapipeline
135}; // namespace uirenderer
136}; // namespace android
137