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