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