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