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 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 isValid()63 [[nodiscard]] bool isValid() const { 64 return mImpl.get() != nullptr; 65 } 66 isEmpty()67 [[nodiscard]] bool isEmpty() const { 68 return !hasContent(); 69 } 70 hasContent()71 [[nodiscard]] bool hasContent() const { 72 return mImpl && !(mImpl->isEmpty()); 73 } 74 hasHolePunches()75 [[nodiscard]] bool hasHolePunches() const { 76 return mImpl && mImpl->hasHolePunches(); 77 } 78 containsProjectionReceiver()79 [[nodiscard]] bool containsProjectionReceiver() const { 80 return mImpl && mImpl->containsProjectionReceiver(); 81 } 82 asSkiaDl()83 [[nodiscard]] skiapipeline::SkiaDisplayList* asSkiaDl() { 84 return mImpl.get(); 85 } 86 asSkiaDl()87 [[nodiscard]] const skiapipeline::SkiaDisplayList* asSkiaDl() const { 88 return mImpl.get(); 89 } 90 hasVectorDrawables()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 getUsedSize()105 [[nodiscard]] size_t getUsedSize() const { 106 return mImpl ? mImpl->getUsedSize() : 0; 107 } 108 getAllocatedSize()109 [[nodiscard]] size_t getAllocatedSize() const { 110 return mImpl ? mImpl->getAllocatedSize() : 0; 111 } 112 output(std::ostream & output,uint32_t level)113 void output(std::ostream& output, uint32_t level) const { 114 if (mImpl) { 115 mImpl->output(output, level); 116 } 117 } 118 hasFunctor()119 [[nodiscard]] bool hasFunctor() const { 120 return mImpl && mImpl->hasFunctor(); 121 } 122 prepareListAndChildren(TreeObserver & observer,TreeInfo & info,bool functorsNeedLayer,std::function<void (RenderNode *,TreeObserver &,TreeInfo &,bool)> childFn)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 syncContents(const WebViewSyncData & data)130 void syncContents(const WebViewSyncData& data) { 131 if (mImpl) { 132 mImpl->syncContents(data); 133 } 134 } 135 onRemovedFromTree()136 void onRemovedFromTree() { 137 if (mImpl) { 138 mImpl->onRemovedFromTree(); 139 } 140 } 141 hasText()142 [[nodiscard]] bool hasText() const { 143 return mImpl && mImpl->hasText(); 144 } 145 applyColorTransform(ColorTransform transform)146 void applyColorTransform(ColorTransform transform) { 147 if (mImpl) { 148 mImpl->applyColorTransform(transform); 149 } 150 } 151 152 private: 153 std::unique_ptr<skiapipeline::SkiaDisplayList> mImpl; 154 }; 155 156 157 /** 158 * Data structure that holds the list of commands used in display list stream 159 */ 160 //using DisplayList = skiapipeline::SkiaDisplayList; 161 class MultiDisplayList { 162 private: 163 using SkiaDisplayList = skiapipeline::SkiaDisplayList; 164 165 struct EmptyList { hasTextEmptyList166 bool hasText() const { return false; } updateChildrenEmptyList167 void updateChildren(std::function<void(RenderNode*)> updateFn) {} isEmptyEmptyList168 bool isEmpty() const { return true; } containsProjectionReceiverEmptyList169 bool containsProjectionReceiver() const { return false; } hasVectorDrawablesEmptyList170 bool hasVectorDrawables() const { return false; } getUsedSizeEmptyList171 size_t getUsedSize() const { return 0; } getAllocatedSizeEmptyList172 size_t getAllocatedSize() const { return 0; } outputEmptyList173 void output(std::ostream& output, uint32_t level) const { } hasFunctorEmptyList174 bool hasFunctor() const { return false; } prepareListAndChildrenEmptyList175 bool prepareListAndChildren( 176 TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer, 177 std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) { 178 return false; 179 } syncContentsEmptyList180 void syncContents(const WebViewSyncData& data) { } onRemovedFromTreeEmptyList181 void onRemovedFromTree() { } applyColorTransformEmptyList182 void applyColorTransform(ColorTransform transform) { } 183 }; 184 185 std::variant<EmptyList, std::unique_ptr<SkiaDisplayList>, CanvasOpBuffer> mImpls; 186 187 template <typename T> get(T & t)188 static constexpr T& get(T& t) { return t; } 189 template <typename T> get(const T & t)190 static constexpr const T& get(const T& t) { return t; } 191 192 template <typename T> get(std::unique_ptr<T> & t)193 static constexpr T& get(std::unique_ptr<T>& t) { return *t; } 194 template <typename T> get(const std::unique_ptr<T> & t)195 static constexpr const T& get(const std::unique_ptr<T>& t) { return *t; } 196 197 template <typename T> apply(T && t)198 auto apply(T&& t) { 199 return std::visit([&t](auto& it) -> auto { 200 return t(get(it)); 201 }, mImpls); 202 } 203 204 template <typename T> apply(T && t)205 auto apply(T&& t) const { 206 return std::visit([&t](const auto& it) -> auto { 207 return t(get(it)); 208 }, mImpls); 209 } 210 211 public: 212 // Constructs an empty (invalid) DisplayList MultiDisplayList()213 explicit MultiDisplayList() {} 214 215 // Constructs a DisplayList from a SkiaDisplayList MultiDisplayList(std::unique_ptr<SkiaDisplayList> impl)216 explicit MultiDisplayList(std::unique_ptr<SkiaDisplayList> impl) 217 : mImpls(std::move(impl)) {} 218 MultiDisplayList(CanvasOpBuffer && opBuffer)219 explicit MultiDisplayList(CanvasOpBuffer&& opBuffer) : mImpls(std::move(opBuffer)) {} 220 221 // Move support MultiDisplayList(MultiDisplayList && other)222 MultiDisplayList(MultiDisplayList&& other) : mImpls(std::move(other.mImpls)) {} 223 MultiDisplayList& operator=(MultiDisplayList&& other) { 224 mImpls = std::move(other.mImpls); 225 return *this; 226 } 227 228 // No copy support 229 MultiDisplayList(const MultiDisplayList& other) = delete; 230 MultiDisplayList& operator=(const MultiDisplayList&) = delete; 231 updateChildren(std::function<void (RenderNode *)> updateFn)232 void updateChildren(std::function<void(RenderNode*)> updateFn) { 233 apply([&](auto& it) { it.updateChildren(std::move(updateFn)); }); 234 } 235 236 [[nodiscard]] explicit operator bool() const { 237 return isValid(); 238 } 239 240 // If true this DisplayList contains a backing content, even if that content is empty 241 // If false, there this DisplayList is in an "empty" state isValid()242 [[nodiscard]] bool isValid() const { 243 return mImpls.index() != 0; 244 } 245 isEmpty()246 [[nodiscard]] bool isEmpty() const { 247 return apply([](const auto& it) -> auto { return it.isEmpty(); }); 248 } 249 hasContent()250 [[nodiscard]] bool hasContent() const { 251 return !isEmpty(); 252 } 253 containsProjectionReceiver()254 [[nodiscard]] bool containsProjectionReceiver() const { 255 return apply([](const auto& it) -> auto { return it.containsProjectionReceiver(); }); 256 } 257 asSkiaDl()258 [[nodiscard]] SkiaDisplayList* asSkiaDl() { 259 return std::get<1>(mImpls).get(); 260 } 261 asSkiaDl()262 [[nodiscard]] const SkiaDisplayList* asSkiaDl() const { 263 return std::get<1>(mImpls).get(); 264 } 265 hasVectorDrawables()266 [[nodiscard]] bool hasVectorDrawables() const { 267 return apply([](const auto& it) -> auto { return it.hasVectorDrawables(); }); 268 } 269 270 void clear(RenderNode* owningNode = nullptr) { 271 if (owningNode && mImpls.index() == 1) { 272 auto& skiaDl = std::get<1>(mImpls); 273 if (skiaDl->reuseDisplayList(owningNode)) { 274 skiaDl.release(); 275 } 276 } 277 mImpls = EmptyList{}; 278 } 279 getUsedSize()280 [[nodiscard]] size_t getUsedSize() const { 281 return apply([](const auto& it) -> auto { return it.getUsedSize(); }); 282 } 283 getAllocatedSize()284 [[nodiscard]] size_t getAllocatedSize() const { 285 return apply([](const auto& it) -> auto { return it.getAllocatedSize(); }); 286 } 287 output(std::ostream & output,uint32_t level)288 void output(std::ostream& output, uint32_t level) const { 289 apply([&](const auto& it) { it.output(output, level); }); 290 } 291 hasFunctor()292 [[nodiscard]] bool hasFunctor() const { 293 return apply([](const auto& it) -> auto { return it.hasFunctor(); }); 294 } 295 prepareListAndChildren(TreeObserver & observer,TreeInfo & info,bool functorsNeedLayer,std::function<void (RenderNode *,TreeObserver &,TreeInfo &,bool)> childFn)296 bool prepareListAndChildren( 297 TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer, 298 std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) { 299 return apply([&](auto& it) -> auto { 300 return it.prepareListAndChildren(observer, info, functorsNeedLayer, std::move(childFn)); 301 }); 302 } 303 syncContents(const WebViewSyncData & data)304 void syncContents(const WebViewSyncData& data) { 305 apply([&](auto& it) { it.syncContents(data); }); 306 } 307 onRemovedFromTree()308 void onRemovedFromTree() { 309 apply([&](auto& it) { it.onRemovedFromTree(); }); 310 } 311 hasText()312 [[nodiscard]] bool hasText() const { 313 return apply([](const auto& it) -> auto { return it.hasText(); }); 314 } 315 applyColorTransform(ColorTransform transform)316 void applyColorTransform(ColorTransform transform) { 317 apply([=](auto& it) { it.applyColorTransform(transform); }); 318 } 319 asOpBuffer()320 [[nodiscard]] CanvasOpBuffer& asOpBuffer() { 321 return std::get<CanvasOpBuffer>(mImpls); 322 } 323 }; 324 325 // For now stick to the original single-type container to avoid any regressions 326 using DisplayList = SkiaDisplayListWrapper; 327 328 } // namespace uirenderer 329 } // namespace android 330