| // Copyright 2013 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_ | |
| #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_ | |
| #include <memory> | |
| #include <optional> | |
| #include "flutter/display_list/dl_sampling_options.h" | |
| #include "flutter/display_list/geometry/dl_rtree.h" | |
| #include "flutter/fml/logging.h" | |
| // The Flutter DisplayList mechanism encapsulates a persistent sequence of | |
| // rendering operations. | |
| // | |
| // This file contains the definitions for: | |
| // DisplayList: the base class that holds the information about the | |
| // sequence of operations and can dispatch them to a DlOpReceiver | |
| // DlOpReceiver: a pure virtual interface which can be implemented to field | |
| // the requests for purposes such as sending them to an SkCanvas | |
| // or detecting various rendering optimization scenarios | |
| // DisplayListBuilder: a class for constructing a DisplayList from DlCanvas | |
| // method calls and which can act as a DlOpReceiver as well | |
| // | |
| // Other files include various class definitions for dealing with display | |
| // lists, such as: | |
| // skia/dl_sk_*.h: classes to interact between SkCanvas and DisplayList | |
| // (SkCanvas->DisplayList adapter and vice versa) | |
| // | |
| // display_list_utils.h: various utility classes to ease implementing | |
| // a DlOpReceiver, including NOP implementations of | |
| // the attribute, clip, and transform methods, | |
| // classes to track attributes, clips, and transforms | |
| // and a class to compute the bounds of a DisplayList | |
| // Any class implementing DlOpReceiver can inherit from | |
| // these utility classes to simplify its creation | |
| // | |
| // The Flutter DisplayList mechanism is used in a similar manner to the Skia | |
| // SkPicture mechanism. | |
| // | |
| // A DisplayList must be created using a DisplayListBuilder using its stateless | |
| // methods inherited from DlCanvas. | |
| // | |
| // A DisplayList can be read back by implementing the DlOpReceiver virtual | |
| // methods (with help from some of the classes in the utils file) and | |
| // passing an instance to the Dispatch() method, or it can be rendered | |
| // to Skia using a DlSkCanvasDispatcher. | |
| // | |
| // The mechanism is inspired by the SkLiteDL class that is not directly | |
| // supported by Skia, but has been recommended as a basis for custom | |
| // display lists for a number of their customers. | |
| namespace flutter { | |
| #define FOR_EACH_DISPLAY_LIST_OP(V) \ | |
| V(SetAntiAlias) \ | |
| V(SetInvertColors) \ | |
| \ | |
| V(SetStrokeCap) \ | |
| V(SetStrokeJoin) \ | |
| \ | |
| V(SetStyle) \ | |
| V(SetStrokeWidth) \ | |
| V(SetStrokeMiter) \ | |
| \ | |
| V(SetColor) \ | |
| V(SetBlendMode) \ | |
| \ | |
| V(SetPodPathEffect) \ | |
| V(ClearPathEffect) \ | |
| \ | |
| V(ClearColorFilter) \ | |
| V(SetPodColorFilter) \ | |
| \ | |
| V(ClearColorSource) \ | |
| V(SetPodColorSource) \ | |
| V(SetImageColorSource) \ | |
| V(SetRuntimeEffectColorSource) \ | |
| \ | |
| V(ClearImageFilter) \ | |
| V(SetPodImageFilter) \ | |
| V(SetSharedImageFilter) \ | |
| \ | |
| V(ClearMaskFilter) \ | |
| V(SetPodMaskFilter) \ | |
| \ | |
| V(Save) \ | |
| V(SaveLayer) \ | |
| V(SaveLayerBounds) \ | |
| V(SaveLayerBackdrop) \ | |
| V(SaveLayerBackdropBounds) \ | |
| V(Restore) \ | |
| \ | |
| V(Translate) \ | |
| V(Scale) \ | |
| V(Rotate) \ | |
| V(Skew) \ | |
| V(Transform2DAffine) \ | |
| V(TransformFullPerspective) \ | |
| V(TransformReset) \ | |
| \ | |
| V(ClipIntersectRect) \ | |
| V(ClipIntersectRRect) \ | |
| V(ClipIntersectPath) \ | |
| V(ClipDifferenceRect) \ | |
| V(ClipDifferenceRRect) \ | |
| V(ClipDifferencePath) \ | |
| \ | |
| V(DrawPaint) \ | |
| V(DrawColor) \ | |
| \ | |
| V(DrawLine) \ | |
| V(DrawRect) \ | |
| V(DrawOval) \ | |
| V(DrawCircle) \ | |
| V(DrawRRect) \ | |
| V(DrawDRRect) \ | |
| V(DrawArc) \ | |
| V(DrawPath) \ | |
| \ | |
| V(DrawPoints) \ | |
| V(DrawLines) \ | |
| V(DrawPolygon) \ | |
| V(DrawVertices) \ | |
| \ | |
| V(DrawImage) \ | |
| V(DrawImageWithAttr) \ | |
| V(DrawImageRect) \ | |
| V(DrawImageNine) \ | |
| V(DrawImageNineWithAttr) \ | |
| V(DrawAtlas) \ | |
| V(DrawAtlasCulled) \ | |
| \ | |
| V(DrawDisplayList) \ | |
| V(DrawTextBlob) \ | |
| V(DrawTextFrame) \ | |
| \ | |
| V(DrawShadow) \ | |
| V(DrawShadowTransparentOccluder) | |
| #define DL_OP_TO_ENUM_VALUE(name) k##name, | |
| enum class DisplayListOpType { | |
| FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) | |
| #ifdef IMPELLER_ENABLE_3D | |
| DL_OP_TO_ENUM_VALUE(SetSceneColorSource) | |
| #endif // IMPELLER_ENABLE_3D | |
| }; | |
| #undef DL_OP_TO_ENUM_VALUE | |
| class DlOpReceiver; | |
| class DisplayListBuilder; | |
| class SaveLayerOptions { | |
| public: | |
| static const SaveLayerOptions kWithAttributes; | |
| static const SaveLayerOptions kNoAttributes; | |
| SaveLayerOptions() : flags_(0) {} | |
| SaveLayerOptions(const SaveLayerOptions& options) : flags_(options.flags_) {} | |
| explicit SaveLayerOptions(const SaveLayerOptions* options) | |
| : flags_(options->flags_) {} | |
| SaveLayerOptions without_optimizations() const { | |
| SaveLayerOptions options; | |
| options.fRendersWithAttributes = fRendersWithAttributes; | |
| return options; | |
| } | |
| bool renders_with_attributes() const { return fRendersWithAttributes; } | |
| SaveLayerOptions with_renders_with_attributes() const { | |
| SaveLayerOptions options(this); | |
| options.fRendersWithAttributes = true; | |
| return options; | |
| } | |
| bool can_distribute_opacity() const { return fCanDistributeOpacity; } | |
| SaveLayerOptions with_can_distribute_opacity() const { | |
| SaveLayerOptions options(this); | |
| options.fCanDistributeOpacity = true; | |
| return options; | |
| } | |
| SaveLayerOptions& operator=(const SaveLayerOptions& other) { | |
| flags_ = other.flags_; | |
| return *this; | |
| } | |
| bool operator==(const SaveLayerOptions& other) const { | |
| return flags_ == other.flags_; | |
| } | |
| bool operator!=(const SaveLayerOptions& other) const { | |
| return flags_ != other.flags_; | |
| } | |
| private: | |
| union { | |
| struct { | |
| unsigned fRendersWithAttributes : 1; | |
| unsigned fCanDistributeOpacity : 1; | |
| }; | |
| uint32_t flags_; | |
| }; | |
| }; | |
| // Manages a buffer allocated with malloc. | |
| class DisplayListStorage { | |
| public: | |
| DisplayListStorage() = default; | |
| DisplayListStorage(DisplayListStorage&&) = default; | |
| uint8_t* get() const { return ptr_.get(); } | |
| void realloc(size_t count) { | |
| ptr_.reset(static_cast<uint8_t*>(std::realloc(ptr_.release(), count))); | |
| FML_CHECK(ptr_); | |
| } | |
| private: | |
| struct FreeDeleter { | |
| void operator()(uint8_t* p) { std::free(p); } | |
| }; | |
| std::unique_ptr<uint8_t, FreeDeleter> ptr_; | |
| }; | |
| class Culler; | |
| // The base class that contains a sequence of rendering operations | |
| // for dispatch to a DlOpReceiver. These objects must be instantiated | |
| // through an instance of DisplayListBuilder::build(). | |
| class DisplayList : public SkRefCnt { | |
| public: | |
| DisplayList(); | |
| ~DisplayList(); | |
| void Dispatch(DlOpReceiver& ctx) const; | |
| void Dispatch(DlOpReceiver& ctx, const SkRect& cull_rect) const; | |
| void Dispatch(DlOpReceiver& ctx, const SkIRect& cull_rect) const; | |
| // From historical behavior, SkPicture always included nested bytes, | |
| // but nested ops are only included if requested. The defaults used | |
| // here for these accessors follow that pattern. | |
| size_t bytes(bool nested = true) const { | |
| return sizeof(DisplayList) + byte_count_ + | |
| (nested ? nested_byte_count_ : 0); | |
| } | |
| unsigned int op_count(bool nested = false) const { | |
| return op_count_ + (nested ? nested_op_count_ : 0); | |
| } | |
| uint32_t unique_id() const { return unique_id_; } | |
| const SkRect& bounds() const { return bounds_; } | |
| bool has_rtree() const { return rtree_ != nullptr; } | |
| sk_sp<const DlRTree> rtree() const { return rtree_; } | |
| bool Equals(const DisplayList* other) const; | |
| bool Equals(const DisplayList& other) const { return Equals(&other); } | |
| bool Equals(const sk_sp<const DisplayList>& other) const { | |
| return Equals(other.get()); | |
| } | |
| bool can_apply_group_opacity() const { return can_apply_group_opacity_; } | |
| bool isUIThreadSafe() const { return is_ui_thread_safe_; } | |
| /// @brief Indicates if there are any rendering operations in this | |
| /// DisplayList that will modify a surface of transparent black | |
| /// pixels. | |
| /// | |
| /// This condition can be used to determine whether to create a cleared | |
| /// surface, render a DisplayList into it, and then composite the | |
| /// result into a scene. It is not uncommon for code in the engine to | |
| /// come across such degenerate DisplayList objects when slicing up a | |
| /// frame between platform views. | |
| bool modifies_transparent_black() const { | |
| return modifies_transparent_black_; | |
| } | |
| private: | |
| DisplayList(DisplayListStorage&& ptr, | |
| size_t byte_count, | |
| unsigned int op_count, | |
| size_t nested_byte_count, | |
| unsigned int nested_op_count, | |
| const SkRect& bounds, | |
| bool can_apply_group_opacity, | |
| bool is_ui_thread_safe, | |
| bool modifies_transparent_black, | |
| sk_sp<const DlRTree> rtree); | |
| static uint32_t next_unique_id(); | |
| static void DisposeOps(uint8_t* ptr, uint8_t* end); | |
| const DisplayListStorage storage_; | |
| const size_t byte_count_; | |
| const unsigned int op_count_; | |
| const size_t nested_byte_count_; | |
| const unsigned int nested_op_count_; | |
| const uint32_t unique_id_; | |
| const SkRect bounds_; | |
| const bool can_apply_group_opacity_; | |
| const bool is_ui_thread_safe_; | |
| const bool modifies_transparent_black_; | |
| const sk_sp<const DlRTree> rtree_; | |
| void Dispatch(DlOpReceiver& ctx, | |
| uint8_t* ptr, | |
| uint8_t* end, | |
| Culler& culler) const; | |
| friend class DisplayListBuilder; | |
| }; | |
| } // namespace flutter | |
| #endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_ |