blob: b1c5bf49ede5223d638ef7c9ec08719e2d227d5d [file] [log] [blame]
Chris Craik0776a602013-02-14 15:36:01 -08001/*
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
Chris Craik5e00c7c2016-07-06 16:10:09 -070017#pragma once
Chris Craik0776a602013-02-14 15:36:01 -080018
John Reck844516c2021-01-13 10:59:10 -050019#include "pipeline/skia/SkiaDisplayList.h"
John Reck064650b2021-01-19 21:29:24 -050020#include "canvas/CanvasOpBuffer.h"
John Reck844516c2021-01-13 10:59:10 -050021
John Reckbe671952021-01-13 22:39:32 -050022#include <memory>
John Reck064650b2021-01-19 21:29:24 -050023#include <variant>
John Reckbe671952021-01-13 22:39:32 -050024
Chris Craik0776a602013-02-14 15:36:01 -080025namespace android {
26namespace uirenderer {
27
Doris Liu67ce99b2016-05-17 16:50:31 -070028namespace VectorDrawable {
29class Tree;
30};
31typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
32
John Reck064650b2021-01-19 21:29:24 -050033class SkiaDisplayListWrapper {
John Reckbe671952021-01-13 22:39:32 -050034public:
35 // Constructs an empty (invalid) DisplayList
John Reck064650b2021-01-19 21:29:24 -050036 explicit SkiaDisplayListWrapper() {}
John Reckbe671952021-01-13 22:39:32 -050037
38 // Constructs a DisplayList from a SkiaDisplayList
John Reck064650b2021-01-19 21:29:24 -050039 explicit SkiaDisplayListWrapper(std::unique_ptr<skiapipeline::SkiaDisplayList> impl)
John Reckbe671952021-01-13 22:39:32 -050040 : mImpl(std::move(impl)) {}
41
42 // Move support
John Reck064650b2021-01-19 21:29:24 -050043 SkiaDisplayListWrapper(SkiaDisplayListWrapper&& other) : mImpl(std::move(other.mImpl)) {}
44 SkiaDisplayListWrapper& operator=(SkiaDisplayListWrapper&& other) {
John Reckbe671952021-01-13 22:39:32 -050045 mImpl = std::move(other.mImpl);
46 return *this;
47 }
48
49 // No copy support
John Reck064650b2021-01-19 21:29:24 -050050 SkiaDisplayListWrapper(const SkiaDisplayListWrapper& other) = delete;
51 SkiaDisplayListWrapper& operator=(const SkiaDisplayListWrapper&) = delete;
John Reckbe671952021-01-13 22:39:32 -050052
53 void updateChildren(std::function<void(RenderNode*)> updateFn) {
54 mImpl->updateChildren(std::move(updateFn));
55 }
56
John Reck07f3d912023-08-17 12:46:44 -040057 void visit(std::function<void(const RenderNode&)> func) const { mImpl->visit(std::move(func)); }
58
John Reckbe671952021-01-13 22:39:32 -050059 [[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
65 [[nodiscard]] bool isValid() const {
66 return mImpl.get() != nullptr;
67 }
68
69 [[nodiscard]] bool isEmpty() const {
70 return !hasContent();
71 }
72
73 [[nodiscard]] bool hasContent() const {
74 return mImpl && !(mImpl->isEmpty());
75 }
76
Nader Jawad2dc632a2021-03-29 18:51:29 -070077 [[nodiscard]] bool hasHolePunches() const {
78 return mImpl && mImpl->hasHolePunches();
79 }
80
John Reckbe671952021-01-13 22:39:32 -050081 [[nodiscard]] bool containsProjectionReceiver() const {
82 return mImpl && mImpl->containsProjectionReceiver();
83 }
84
85 [[nodiscard]] skiapipeline::SkiaDisplayList* asSkiaDl() {
86 return mImpl.get();
87 }
88
89 [[nodiscard]] const skiapipeline::SkiaDisplayList* asSkiaDl() const {
90 return mImpl.get();
91 }
92
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
107 [[nodiscard]] size_t getUsedSize() const {
108 return mImpl ? mImpl->getUsedSize() : 0;
109 }
110
111 [[nodiscard]] size_t getAllocatedSize() const {
112 return mImpl ? mImpl->getAllocatedSize() : 0;
113 }
114
115 void output(std::ostream& output, uint32_t level) const {
116 if (mImpl) {
117 mImpl->output(output, level);
118 }
119 }
120
121 [[nodiscard]] bool hasFunctor() const {
122 return mImpl && mImpl->hasFunctor();
123 }
124
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
132 void syncContents(const WebViewSyncData& data) {
133 if (mImpl) {
134 mImpl->syncContents(data);
135 }
136 }
137
Huihong Luoec68b7c2021-06-25 21:54:16 -0700138 void onRemovedFromTree() {
139 if (mImpl) {
140 mImpl->onRemovedFromTree();
141 }
142 }
143
John Reckbe671952021-01-13 22:39:32 -0500144 [[nodiscard]] bool hasText() const {
145 return mImpl && mImpl->hasText();
146 }
147
Tyler Freemane0faa692023-11-16 00:48:54 +0000148 [[nodiscard]] bool hasFill() const { return mImpl && mImpl->hasFill(); }
149
John Reckbe671952021-01-13 22:39:32 -0500150 void applyColorTransform(ColorTransform transform) {
151 if (mImpl) {
John Reck064650b2021-01-19 21:29:24 -0500152 mImpl->applyColorTransform(transform);
John Reckbe671952021-01-13 22:39:32 -0500153 }
154 }
155
156private:
157 std::unique_ptr<skiapipeline::SkiaDisplayList> mImpl;
158};
Chris Craik0776a602013-02-14 15:36:01 -0800159
John Reck064650b2021-01-19 21:29:24 -0500160
161/**
162 * Data structure that holds the list of commands used in display list stream
163 */
164//using DisplayList = skiapipeline::SkiaDisplayList;
165class MultiDisplayList {
166private:
167 using SkiaDisplayList = skiapipeline::SkiaDisplayList;
168
169 struct EmptyList {
170 bool hasText() const { return false; }
171 void updateChildren(std::function<void(RenderNode*)> updateFn) {}
172 bool isEmpty() const { return true; }
173 bool containsProjectionReceiver() const { return false; }
174 bool hasVectorDrawables() const { return false; }
175 size_t getUsedSize() const { return 0; }
176 size_t getAllocatedSize() const { return 0; }
177 void output(std::ostream& output, uint32_t level) const { }
178 bool hasFunctor() const { return false; }
179 bool prepareListAndChildren(
180 TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
181 std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
182 return false;
183 }
184 void syncContents(const WebViewSyncData& data) { }
Huihong Luoec68b7c2021-06-25 21:54:16 -0700185 void onRemovedFromTree() { }
John Reck064650b2021-01-19 21:29:24 -0500186 void applyColorTransform(ColorTransform transform) { }
187 };
188
189 std::variant<EmptyList, std::unique_ptr<SkiaDisplayList>, CanvasOpBuffer> mImpls;
190
191 template <typename T>
192 static constexpr T& get(T& t) { return t; }
193 template <typename T>
194 static constexpr const T& get(const T& t) { return t; }
195
196 template <typename T>
197 static constexpr T& get(std::unique_ptr<T>& t) { return *t; }
198 template <typename T>
199 static constexpr const T& get(const std::unique_ptr<T>& t) { return *t; }
200
201 template <typename 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>
209 auto apply(T&& t) const {
210 return std::visit([&t](const auto& it) -> auto {
211 return t(get(it));
212 }, mImpls);
213 }
214
215public:
216 // Constructs an empty (invalid) DisplayList
217 explicit MultiDisplayList() {}
218
219 // Constructs a DisplayList from a SkiaDisplayList
220 explicit MultiDisplayList(std::unique_ptr<SkiaDisplayList> impl)
221 : mImpls(std::move(impl)) {}
222
223 explicit MultiDisplayList(CanvasOpBuffer&& opBuffer) : mImpls(std::move(opBuffer)) {}
224
225 // Move support
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
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
246 [[nodiscard]] bool isValid() const {
247 return mImpls.index() != 0;
248 }
249
250 [[nodiscard]] bool isEmpty() const {
251 return apply([](const auto& it) -> auto { return it.isEmpty(); });
252 }
253
254 [[nodiscard]] bool hasContent() const {
255 return !isEmpty();
256 }
257
258 [[nodiscard]] bool containsProjectionReceiver() const {
259 return apply([](const auto& it) -> auto { return it.containsProjectionReceiver(); });
260 }
261
262 [[nodiscard]] SkiaDisplayList* asSkiaDl() {
263 return std::get<1>(mImpls).get();
264 }
265
266 [[nodiscard]] const SkiaDisplayList* asSkiaDl() const {
267 return std::get<1>(mImpls).get();
268 }
269
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
284 [[nodiscard]] size_t getUsedSize() const {
285 return apply([](const auto& it) -> auto { return it.getUsedSize(); });
286 }
287
288 [[nodiscard]] size_t getAllocatedSize() const {
289 return apply([](const auto& it) -> auto { return it.getAllocatedSize(); });
290 }
291
292 void output(std::ostream& output, uint32_t level) const {
293 apply([&](const auto& it) { it.output(output, level); });
294 }
295
296 [[nodiscard]] bool hasFunctor() const {
297 return apply([](const auto& it) -> auto { return it.hasFunctor(); });
298 }
299
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
308 void syncContents(const WebViewSyncData& data) {
309 apply([&](auto& it) { it.syncContents(data); });
310 }
311
Huihong Luoec68b7c2021-06-25 21:54:16 -0700312 void onRemovedFromTree() {
313 apply([&](auto& it) { it.onRemovedFromTree(); });
314 }
315
John Reck064650b2021-01-19 21:29:24 -0500316 [[nodiscard]] bool hasText() const {
317 return apply([](const auto& it) -> auto { return it.hasText(); });
318 }
319
320 void applyColorTransform(ColorTransform transform) {
321 apply([=](auto& it) { it.applyColorTransform(transform); });
322 }
323
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
330using DisplayList = SkiaDisplayListWrapper;
331
Chris Blume7b8a8082018-11-30 15:51:58 -0800332} // namespace uirenderer
333} // namespace android