• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #pragma once
18 
19 #include "pipeline/skia/SkiaDisplayList.h"
20 #include "canvas/CanvasOpBuffer.h"
21 
22 #include <memory>
23 #include <variant>
24 
25 namespace android {
26 namespace uirenderer {
27 
28 namespace VectorDrawable {
29 class Tree;
30 };
31 typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
32 
33 class SkiaDisplayListWrapper {
34 public:
35     // Constructs an empty (invalid) DisplayList
SkiaDisplayListWrapper()36     explicit SkiaDisplayListWrapper() {}
37 
38     // Constructs a DisplayList from a SkiaDisplayList
SkiaDisplayListWrapper(std::unique_ptr<skiapipeline::SkiaDisplayList> impl)39     explicit SkiaDisplayListWrapper(std::unique_ptr<skiapipeline::SkiaDisplayList> impl)
40         : mImpl(std::move(impl)) {}
41 
42     // Move support
SkiaDisplayListWrapper(SkiaDisplayListWrapper && other)43     SkiaDisplayListWrapper(SkiaDisplayListWrapper&& other) : mImpl(std::move(other.mImpl)) {}
44     SkiaDisplayListWrapper& operator=(SkiaDisplayListWrapper&& other) {
45         mImpl = std::move(other.mImpl);
46         return *this;
47     }
48 
49     // No copy support
50     SkiaDisplayListWrapper(const SkiaDisplayListWrapper& other) = delete;
51     SkiaDisplayListWrapper& operator=(const SkiaDisplayListWrapper&) = delete;
52 
updateChildren(std::function<void (RenderNode *)> updateFn)53     void updateChildren(std::function<void(RenderNode*)> updateFn) {
54         mImpl->updateChildren(std::move(updateFn));
55     }
56 
57     [[nodiscard]] explicit operator bool() const {
58         return mImpl.get() != nullptr;
59     }
60 
61     // If true this DisplayList contains a backing content, even if that content is empty
62     // If false, there this DisplayList is in an "empty" state
isValid()63     [[nodiscard]] bool isValid() const {
64         return mImpl.get() != nullptr;
65     }
66 
isEmpty()67     [[nodiscard]] bool isEmpty() const {
68         return !hasContent();
69     }
70 
hasContent()71     [[nodiscard]] bool hasContent() const {
72         return mImpl && !(mImpl->isEmpty());
73     }
74 
hasHolePunches()75     [[nodiscard]] bool hasHolePunches() const {
76         return mImpl && mImpl->hasHolePunches();
77     }
78 
containsProjectionReceiver()79     [[nodiscard]] bool containsProjectionReceiver() const {
80         return mImpl && mImpl->containsProjectionReceiver();
81     }
82 
asSkiaDl()83     [[nodiscard]] skiapipeline::SkiaDisplayList* asSkiaDl() {
84         return mImpl.get();
85     }
86 
asSkiaDl()87     [[nodiscard]] const skiapipeline::SkiaDisplayList* asSkiaDl() const {
88         return mImpl.get();
89     }
90 
hasVectorDrawables()91     [[nodiscard]] bool hasVectorDrawables() const {
92         return mImpl && mImpl->hasVectorDrawables();
93     }
94 
95     void clear(RenderNode* owningNode = nullptr) {
96         if (mImpl && owningNode && mImpl->reuseDisplayList(owningNode)) {
97             // TODO: This is a bit sketchy to have a unique_ptr temporarily owned twice
98             // Do something to cleanup reuseDisplayList passing itself to the RenderNode
99             mImpl.release();
100         } else {
101             mImpl = nullptr;
102         }
103     }
104 
getUsedSize()105     [[nodiscard]] size_t getUsedSize() const {
106         return mImpl ? mImpl->getUsedSize() : 0;
107     }
108 
getAllocatedSize()109     [[nodiscard]] size_t getAllocatedSize() const {
110         return mImpl ? mImpl->getAllocatedSize() : 0;
111     }
112 
output(std::ostream & output,uint32_t level)113     void output(std::ostream& output, uint32_t level) const {
114         if (mImpl) {
115             mImpl->output(output, level);
116         }
117     }
118 
hasFunctor()119     [[nodiscard]] bool hasFunctor() const {
120         return mImpl && mImpl->hasFunctor();
121     }
122 
prepareListAndChildren(TreeObserver & observer,TreeInfo & info,bool functorsNeedLayer,std::function<void (RenderNode *,TreeObserver &,TreeInfo &,bool)> childFn)123     bool prepareListAndChildren(
124             TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
125             std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
126         return mImpl && mImpl->prepareListAndChildren(
127                 observer, info, functorsNeedLayer, std::move(childFn));
128     }
129 
syncContents(const WebViewSyncData & data)130     void syncContents(const WebViewSyncData& data) {
131         if (mImpl) {
132             mImpl->syncContents(data);
133         }
134     }
135 
onRemovedFromTree()136     void onRemovedFromTree() {
137         if (mImpl) {
138             mImpl->onRemovedFromTree();
139         }
140     }
141 
hasText()142     [[nodiscard]] bool hasText() const {
143         return mImpl && mImpl->hasText();
144     }
145 
applyColorTransform(ColorTransform transform)146     void applyColorTransform(ColorTransform transform) {
147         if (mImpl) {
148             mImpl->applyColorTransform(transform);
149         }
150     }
151 
152 private:
153     std::unique_ptr<skiapipeline::SkiaDisplayList> mImpl;
154 };
155 
156 
157 /**
158  * Data structure that holds the list of commands used in display list stream
159  */
160 //using DisplayList = skiapipeline::SkiaDisplayList;
161 class MultiDisplayList {
162 private:
163     using SkiaDisplayList = skiapipeline::SkiaDisplayList;
164 
165     struct EmptyList {
hasTextEmptyList166         bool hasText() const { return false; }
updateChildrenEmptyList167         void updateChildren(std::function<void(RenderNode*)> updateFn) {}
isEmptyEmptyList168         bool isEmpty() const { return true; }
containsProjectionReceiverEmptyList169         bool containsProjectionReceiver() const { return false; }
hasVectorDrawablesEmptyList170         bool hasVectorDrawables() const { return false; }
getUsedSizeEmptyList171         size_t getUsedSize() const { return 0; }
getAllocatedSizeEmptyList172         size_t getAllocatedSize() const { return 0; }
outputEmptyList173         void output(std::ostream& output, uint32_t level) const { }
hasFunctorEmptyList174         bool hasFunctor() const { return false; }
prepareListAndChildrenEmptyList175         bool prepareListAndChildren(
176                 TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
177                 std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
178             return false;
179         }
syncContentsEmptyList180         void syncContents(const WebViewSyncData& data) { }
onRemovedFromTreeEmptyList181         void onRemovedFromTree() { }
applyColorTransformEmptyList182         void applyColorTransform(ColorTransform transform) { }
183     };
184 
185     std::variant<EmptyList, std::unique_ptr<SkiaDisplayList>, CanvasOpBuffer> mImpls;
186 
187     template <typename T>
get(T & t)188     static constexpr T& get(T& t) { return t; }
189     template <typename T>
get(const T & t)190     static constexpr const T& get(const T& t) { return t; }
191 
192     template <typename T>
get(std::unique_ptr<T> & t)193     static constexpr T& get(std::unique_ptr<T>& t) { return *t; }
194     template <typename T>
get(const std::unique_ptr<T> & t)195     static constexpr const T& get(const std::unique_ptr<T>& t) { return *t; }
196 
197     template <typename T>
apply(T && t)198     auto apply(T&& t) {
199         return std::visit([&t](auto& it) -> auto {
200             return t(get(it));
201         }, mImpls);
202     }
203 
204     template <typename T>
apply(T && t)205     auto apply(T&& t) const {
206         return std::visit([&t](const auto& it) -> auto {
207             return t(get(it));
208         }, mImpls);
209     }
210 
211 public:
212     // Constructs an empty (invalid) DisplayList
MultiDisplayList()213     explicit MultiDisplayList() {}
214 
215     // Constructs a DisplayList from a SkiaDisplayList
MultiDisplayList(std::unique_ptr<SkiaDisplayList> impl)216     explicit MultiDisplayList(std::unique_ptr<SkiaDisplayList> impl)
217         : mImpls(std::move(impl)) {}
218 
MultiDisplayList(CanvasOpBuffer && opBuffer)219     explicit MultiDisplayList(CanvasOpBuffer&& opBuffer) : mImpls(std::move(opBuffer)) {}
220 
221     // Move support
MultiDisplayList(MultiDisplayList && other)222     MultiDisplayList(MultiDisplayList&& other) : mImpls(std::move(other.mImpls)) {}
223     MultiDisplayList& operator=(MultiDisplayList&& other) {
224         mImpls = std::move(other.mImpls);
225         return *this;
226     }
227 
228     // No copy support
229     MultiDisplayList(const MultiDisplayList& other) = delete;
230     MultiDisplayList& operator=(const MultiDisplayList&) = delete;
231 
updateChildren(std::function<void (RenderNode *)> updateFn)232     void updateChildren(std::function<void(RenderNode*)> updateFn) {
233         apply([&](auto& it) { it.updateChildren(std::move(updateFn)); });
234     }
235 
236     [[nodiscard]] explicit operator bool() const {
237         return isValid();
238     }
239 
240     // If true this DisplayList contains a backing content, even if that content is empty
241     // If false, there this DisplayList is in an "empty" state
isValid()242     [[nodiscard]] bool isValid() const {
243         return mImpls.index() != 0;
244     }
245 
isEmpty()246     [[nodiscard]] bool isEmpty() const {
247         return apply([](const auto& it) -> auto { return it.isEmpty(); });
248     }
249 
hasContent()250     [[nodiscard]] bool hasContent() const {
251         return !isEmpty();
252     }
253 
containsProjectionReceiver()254     [[nodiscard]] bool containsProjectionReceiver() const {
255         return apply([](const auto& it) -> auto { return it.containsProjectionReceiver(); });
256     }
257 
asSkiaDl()258     [[nodiscard]] SkiaDisplayList* asSkiaDl() {
259         return std::get<1>(mImpls).get();
260     }
261 
asSkiaDl()262     [[nodiscard]] const SkiaDisplayList* asSkiaDl() const {
263         return std::get<1>(mImpls).get();
264     }
265 
hasVectorDrawables()266     [[nodiscard]] bool hasVectorDrawables() const {
267         return apply([](const auto& it) -> auto { return it.hasVectorDrawables(); });
268     }
269 
270     void clear(RenderNode* owningNode = nullptr) {
271         if (owningNode && mImpls.index() == 1) {
272             auto& skiaDl = std::get<1>(mImpls);
273             if (skiaDl->reuseDisplayList(owningNode)) {
274                 skiaDl.release();
275             }
276         }
277         mImpls = EmptyList{};
278     }
279 
getUsedSize()280     [[nodiscard]] size_t getUsedSize() const {
281         return apply([](const auto& it) -> auto { return it.getUsedSize(); });
282     }
283 
getAllocatedSize()284     [[nodiscard]] size_t getAllocatedSize() const {
285         return apply([](const auto& it) -> auto { return it.getAllocatedSize(); });
286     }
287 
output(std::ostream & output,uint32_t level)288     void output(std::ostream& output, uint32_t level) const {
289         apply([&](const auto& it) { it.output(output, level); });
290     }
291 
hasFunctor()292     [[nodiscard]] bool hasFunctor() const {
293         return apply([](const auto& it) -> auto { return it.hasFunctor(); });
294     }
295 
prepareListAndChildren(TreeObserver & observer,TreeInfo & info,bool functorsNeedLayer,std::function<void (RenderNode *,TreeObserver &,TreeInfo &,bool)> childFn)296     bool prepareListAndChildren(
297             TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
298             std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
299         return apply([&](auto& it) -> auto {
300             return it.prepareListAndChildren(observer, info, functorsNeedLayer, std::move(childFn));
301         });
302     }
303 
syncContents(const WebViewSyncData & data)304     void syncContents(const WebViewSyncData& data) {
305         apply([&](auto& it) { it.syncContents(data); });
306     }
307 
onRemovedFromTree()308     void onRemovedFromTree() {
309         apply([&](auto& it) { it.onRemovedFromTree(); });
310     }
311 
hasText()312     [[nodiscard]] bool hasText() const {
313         return apply([](const auto& it) -> auto { return it.hasText(); });
314     }
315 
applyColorTransform(ColorTransform transform)316     void applyColorTransform(ColorTransform transform) {
317         apply([=](auto& it) { it.applyColorTransform(transform); });
318     }
319 
asOpBuffer()320     [[nodiscard]] CanvasOpBuffer& asOpBuffer() {
321         return std::get<CanvasOpBuffer>(mImpls);
322     }
323 };
324 
325 // For now stick to the original single-type container to avoid any regressions
326 using DisplayList = SkiaDisplayListWrapper;
327 
328 }  // namespace uirenderer
329 }  // namespace android
330