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