| // 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_ |