blob: 8c180da9c84f1d14dc27a3cebcdea1f70a3c94de [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
148 void applyColorTransform(ColorTransform transform) {
149 if (mImpl) {
John Reck064650b2021-01-19 21:29:24 -0500150 mImpl->applyColorTransform(transform);
John Reckbe671952021-01-13 22:39:32 -0500151 }
152 }
153
154private:
155 std::unique_ptr<skiapipeline::SkiaDisplayList> mImpl;
156};
Chris Craik0776a602013-02-14 15:36:01 -0800157
John Reck064650b2021-01-19 21:29:24 -0500158
159/**
160 * Data structure that holds the list of commands used in display list stream
161 */
162//using DisplayList = skiapipeline::SkiaDisplayList;
163class MultiDisplayList {
164private:
165 using SkiaDisplayList = skiapipeline::SkiaDisplayList;
166
167 struct EmptyList {
168 bool hasText() const { return false; }
169 void updateChildren(std::function<void(RenderNode*)> updateFn) {}
170 bool isEmpty() const { return true; }
171 bool containsProjectionReceiver() const { return false; }
172 bool hasVectorDrawables() const { return false; }
173 size_t getUsedSize() const { return 0; }
174 size_t getAllocatedSize() const { return 0; }
175 void output(std::ostream& output, uint32_t level) const { }
176 bool hasFunctor() const { return false; }
177 bool prepareListAndChildren(
178 TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
179 std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
180 return false;
181 }
182 void syncContents(const WebViewSyncData& data) { }
Huihong Luoec68b7c2021-06-25 21:54:16 -0700183 void onRemovedFromTree() { }
John Reck064650b2021-01-19 21:29:24 -0500184 void applyColorTransform(ColorTransform transform) { }
185 };
186
187 std::variant<EmptyList, std::unique_ptr<SkiaDisplayList>, CanvasOpBuffer> mImpls;
188
189 template <typename T>
190 static constexpr T& get(T& t) { return t; }
191 template <typename T>
192 static constexpr const T& get(const T& t) { return t; }
193
194 template <typename T>
195 static constexpr T& get(std::unique_ptr<T>& t) { return *t; }
196 template <typename T>
197 static constexpr const T& get(const std::unique_ptr<T>& t) { return *t; }
198
199 template <typename T>
200 auto apply(T&& t) {
201 return std::visit([&t](auto& it) -> auto {
202 return t(get(it));
203 }, mImpls);
204 }
205
206 template <typename T>
207 auto apply(T&& t) const {
208 return std::visit([&t](const auto& it) -> auto {
209 return t(get(it));
210 }, mImpls);
211 }
212
213public:
214 // Constructs an empty (invalid) DisplayList
215 explicit MultiDisplayList() {}
216
217 // Constructs a DisplayList from a SkiaDisplayList
218 explicit MultiDisplayList(std::unique_ptr<SkiaDisplayList> impl)
219 : mImpls(std::move(impl)) {}
220
221 explicit MultiDisplayList(CanvasOpBuffer&& opBuffer) : mImpls(std::move(opBuffer)) {}
222
223 // Move support
224 MultiDisplayList(MultiDisplayList&& other) : mImpls(std::move(other.mImpls)) {}
225 MultiDisplayList& operator=(MultiDisplayList&& other) {
226 mImpls = std::move(other.mImpls);
227 return *this;
228 }
229
230 // No copy support
231 MultiDisplayList(const MultiDisplayList& other) = delete;
232 MultiDisplayList& operator=(const MultiDisplayList&) = delete;
233
234 void updateChildren(std::function<void(RenderNode*)> updateFn) {
235 apply([&](auto& it) { it.updateChildren(std::move(updateFn)); });
236 }
237
238 [[nodiscard]] explicit operator bool() const {
239 return isValid();
240 }
241
242 // If true this DisplayList contains a backing content, even if that content is empty
243 // If false, there this DisplayList is in an "empty" state
244 [[nodiscard]] bool isValid() const {
245 return mImpls.index() != 0;
246 }
247
248 [[nodiscard]] bool isEmpty() const {
249 return apply([](const auto& it) -> auto { return it.isEmpty(); });
250 }
251
252 [[nodiscard]] bool hasContent() const {
253 return !isEmpty();
254 }
255
256 [[nodiscard]] bool containsProjectionReceiver() const {
257 return apply([](const auto& it) -> auto { return it.containsProjectionReceiver(); });
258 }
259
260 [[nodiscard]] SkiaDisplayList* asSkiaDl() {
261 return std::get<1>(mImpls).get();
262 }
263
264 [[nodiscard]] const SkiaDisplayList* asSkiaDl() const {
265 return std::get<1>(mImpls).get();
266 }
267
268 [[nodiscard]] bool hasVectorDrawables() const {
269 return apply([](const auto& it) -> auto { return it.hasVectorDrawables(); });
270 }
271
272 void clear(RenderNode* owningNode = nullptr) {
273 if (owningNode && mImpls.index() == 1) {
274 auto& skiaDl = std::get<1>(mImpls);
275 if (skiaDl->reuseDisplayList(owningNode)) {
276 skiaDl.release();
277 }
278 }
279 mImpls = EmptyList{};
280 }
281
282 [[nodiscard]] size_t getUsedSize() const {
283 return apply([](const auto& it) -> auto { return it.getUsedSize(); });
284 }
285
286 [[nodiscard]] size_t getAllocatedSize() const {
287 return apply([](const auto& it) -> auto { return it.getAllocatedSize(); });
288 }
289
290 void output(std::ostream& output, uint32_t level) const {
291 apply([&](const auto& it) { it.output(output, level); });
292 }
293
294 [[nodiscard]] bool hasFunctor() const {
295 return apply([](const auto& it) -> auto { return it.hasFunctor(); });
296 }
297
298 bool prepareListAndChildren(
299 TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
300 std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
301 return apply([&](auto& it) -> auto {
302 return it.prepareListAndChildren(observer, info, functorsNeedLayer, std::move(childFn));
303 });
304 }
305
306 void syncContents(const WebViewSyncData& data) {
307 apply([&](auto& it) { it.syncContents(data); });
308 }
309
Huihong Luoec68b7c2021-06-25 21:54:16 -0700310 void onRemovedFromTree() {
311 apply([&](auto& it) { it.onRemovedFromTree(); });
312 }
313
John Reck064650b2021-01-19 21:29:24 -0500314 [[nodiscard]] bool hasText() const {
315 return apply([](const auto& it) -> auto { return it.hasText(); });
316 }
317
318 void applyColorTransform(ColorTransform transform) {
319 apply([=](auto& it) { it.applyColorTransform(transform); });
320 }
321
322 [[nodiscard]] CanvasOpBuffer& asOpBuffer() {
323 return std::get<CanvasOpBuffer>(mImpls);
324 }
325};
326
327// For now stick to the original single-type container to avoid any regressions
328using DisplayList = SkiaDisplayListWrapper;
329
Chris Blume7b8a8082018-11-30 15:51:58 -0800330} // namespace uirenderer
331} // namespace android