| // 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_VERTICES_H_ | |
| #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_VERTICES_H_ | |
| #include "flutter/display_list/display_list_color.h" | |
| #include "flutter/display_list/types.h" | |
| namespace flutter { | |
| //------------------------------------------------------------------------------ | |
| /// @brief Defines the way in which the vertices of a DlVertices object | |
| /// are separated into triangles into which to render. | |
| /// | |
| enum class DlVertexMode { | |
| /// The vertices are taken 3 at a time to form a triangle. | |
| kTriangles, | |
| /// The vertices are taken in overlapping triplets to form triangles, with | |
| /// each triplet sharing 2 of its vertices with the preceding and following | |
| /// triplets. | |
| /// vertices [ABCDE] yield 3 triangles ABC,BCD,CDE | |
| kTriangleStrip, | |
| /// The vertices are taken in overlapping pairs and combined with the first | |
| /// vertex to form triangles that radiate outward from the initial point. | |
| /// vertices [ABCDE] yield 3 triangles ABC,ACD,ADE | |
| kTriangleFan, | |
| }; | |
| inline SkVertices::VertexMode ToSk(DlVertexMode dl_mode) { | |
| return static_cast<SkVertices::VertexMode>(dl_mode); | |
| } | |
| inline DlVertexMode ToDl(SkVertices::VertexMode sk_mode) { | |
| return static_cast<DlVertexMode>(sk_mode); | |
| } | |
| //------------------------------------------------------------------------------ | |
| /// @brief Holds all of the data (both required and optional) for a | |
| /// DisplayList drawVertices call. | |
| /// | |
| /// There are 4 main pices of data: | |
| /// - vertices(): | |
| /// the points on the rendering surface that define the pixels | |
| /// being rendered to in a series of triangles. These points | |
| /// can map to triangles in various ways depending on the | |
| /// supplied |DlVertexMode|. | |
| /// - texture_coordinates(): | |
| /// the points in the DlColorSource to map to the coordinates | |
| /// of the triangles in the vertices(). If missing, the | |
| /// vertex coordinates themselves will be used to map the | |
| /// source colors to the vertices. | |
| /// - colors(): | |
| /// colors to map to each triangle vertex. Note that each | |
| /// vertex is mapped to exactly 1 color even if the DlVertex | |
| /// - indices(): | |
| /// An indirection based on indices into the array of vertices | |
| /// (and by extension, their associated texture_coordinates and | |
| /// colors). Note that the DLVertexMode will still apply to the | |
| /// indices in the same way (and instead of the way) that it | |
| /// would normally be applied to the vertices themselves. The | |
| /// indices are useful, for example, to fill the vertices with | |
| /// a grid of points and then use the indices to define a | |
| /// triangular mesh that covers that grid without having to | |
| /// repeat the vertex (and texture coordinate and color) | |
| /// information for the times when a given grid coordinate | |
| /// gets reused in up to 4 mesh triangles. | |
| /// | |
| /// Note that each vertex is mapped to exactly 1 texture_coordinate and | |
| /// color even if the DlVertexMode or indices specify that it contributes | |
| /// to more than one output triangle. | |
| /// | |
| class DlVertices { | |
| public: | |
| /// @brief A utility class to build up a |DlVertices| object | |
| /// one set of data at a time. | |
| class Builder { | |
| public: | |
| /// @brief flags to indicate/promise which of the optional | |
| /// texture coordinates or colors will be supplied | |
| /// during the build phase. | |
| union Flags { | |
| struct { | |
| unsigned has_texture_coordinates : 1; | |
| unsigned has_colors : 1; | |
| }; | |
| uint32_t mask = 0; | |
| inline Flags operator|(const Flags& rhs) const { | |
| return {.mask = (mask | rhs.mask)}; | |
| } | |
| inline Flags& operator|=(const Flags& rhs) { | |
| mask = mask | rhs.mask; | |
| return *this; | |
| } | |
| }; | |
| static constexpr Flags kNone = {{false, false}}; | |
| static constexpr Flags kHasTextureCoordinates = {{true, false}}; | |
| static constexpr Flags kHasColors = {{false, true}}; | |
| //-------------------------------------------------------------------------- | |
| /// @brief Constructs a Builder and prepares room for the | |
| /// required and optional data. | |
| /// | |
| /// Vertices are always required. Optional texture coordinates | |
| /// and optional colors are reserved depending on the |Flags|. | |
| /// Optional indices will be reserved if the index_count is | |
| /// positive (>0). | |
| /// | |
| /// The caller must provide all data that is promised by the | |
| /// supplied |flags| and |index_count| parameters before | |
| /// calling the |build()| method. | |
| Builder(DlVertexMode mode, int vertex_count, Flags flags, int index_count); | |
| /// Returns true iff the underlying object was successfully allocated. | |
| bool is_valid() { return vertices_ != nullptr; } | |
| /// @brief Copies the indicated list of points as vertices. | |
| /// | |
| /// fails if vertices have already been supplied. | |
| void store_vertices(const SkPoint points[]); | |
| /// @brief Copies the indicated list of float pairs as vertices. | |
| /// | |
| /// fails if vertices have already been supplied. | |
| void store_vertices(const float coordinates[]); | |
| /// @brief Copies the indicated list of points as texture coordinates. | |
| /// | |
| /// fails if texture coordinates have already been supplied or if they | |
| /// were not promised by the flags.has_texture_coordinates. | |
| void store_texture_coordinates(const SkPoint points[]); | |
| /// @brief Copies the indicated list of float pairs as texture coordinates. | |
| /// | |
| /// fails if texture coordinates have already been supplied or if they | |
| /// were not promised by the flags.has_texture_coordinates. | |
| void store_texture_coordinates(const float coordinates[]); | |
| /// @brief Copies the indicated list of colors as vertex colors. | |
| /// | |
| /// fails if colors have already been supplied or if they were not | |
| /// promised by the flags.has_colors. | |
| void store_colors(const DlColor colors[]); | |
| /// @brief Copies the indicated list of unsigned ints as vertex colors | |
| /// in the 32-bit RGBA format. | |
| /// | |
| /// fails if colors have already been supplied or if they were not | |
| /// promised by the flags.has_colors. | |
| void store_colors(const uint32_t colors[]) { | |
| store_colors(reinterpret_cast<const DlColor*>(colors)); | |
| } | |
| /// @brief Copies the indicated list of 16-bit indices as vertex indices. | |
| /// | |
| /// fails if indices have already been supplied or if they were not | |
| /// promised by (index_count > 0). | |
| void store_indices(const uint16_t indices[]); | |
| /// @brief Finalizes and the constructed DlVertices object. | |
| /// | |
| /// fails if any of the optional data promised in the constructor is | |
| /// missing. | |
| std::shared_ptr<DlVertices> build(); | |
| private: | |
| std::shared_ptr<DlVertices> vertices_; | |
| bool needs_vertices_; | |
| bool needs_texture_coords_; | |
| bool needs_colors_; | |
| bool needs_indices_; | |
| }; | |
| //-------------------------------------------------------------------------- | |
| /// @brief Constructs a DlVector with compact inline storage for all | |
| /// of its required and optional lists of data. | |
| /// | |
| /// Vertices are always required. Optional texture coordinates | |
| /// and optional colors are stored if the arguments are non-null. | |
| /// Optional indices will be stored iff the array argument is | |
| /// non-null and the index_count is positive (>0). | |
| static std::shared_ptr<DlVertices> Make(DlVertexMode mode, | |
| int vertex_count, | |
| const SkPoint vertices[], | |
| const SkPoint texture_coordinates[], | |
| const DlColor colors[], | |
| int index_count = 0, | |
| const uint16_t indices[] = nullptr); | |
| /// Returns the size of the object including all of the inlined data. | |
| size_t size() const; | |
| /// Returns the bounds of the vertices. | |
| SkRect bounds() const { return bounds_; } | |
| /// Returns the vertex mode that defines how the vertices (or the indices) | |
| /// are turned into triangles. | |
| DlVertexMode mode() const { return mode_; } | |
| /// Returns the number of vertices, which also applies to the number of | |
| /// texture coordinate and colors if they are provided. | |
| int vertex_count() const { return vertex_count_; } | |
| /// Returns a pointer to the vertex information. Should be non-null. | |
| const SkPoint* vertices() const { | |
| return static_cast<const SkPoint*>(pod(vertices_offset_)); | |
| } | |
| /// Returns a pointer to the vertex texture coordinate | |
| /// or null if none were provided. | |
| const SkPoint* texture_coordinates() const { | |
| return static_cast<const SkPoint*>(pod(texture_coordinates_offset_)); | |
| } | |
| /// Returns a pointer to the vertex colors | |
| /// or null if none were provided. | |
| const DlColor* colors() const { | |
| return static_cast<const DlColor*>(pod(colors_offset_)); | |
| } | |
| /// Returns a pointer to the count of vertex indices | |
| /// or 0 if none were provided. | |
| int index_count() const { return index_count_; } | |
| /// Returns a pointer to the vertex indices | |
| /// or null if none were provided. | |
| const uint16_t* indices() const { | |
| return static_cast<const uint16_t*>(pod(indices_offset_)); | |
| } | |
| // Returns an equivalent sk_sp<SkVertices> analog to this object. | |
| sk_sp<SkVertices> skia_object() const; | |
| bool operator==(DlVertices const& other) const; | |
| bool operator!=(DlVertices const& other) const { return !(*this == other); } | |
| private: | |
| // Constructors are designed to encapsulate arrays sequentially in memory | |
| // which means they can only be called by intantiations that use the | |
| // new (ptr) paradigm which precomputes and preallocates the memory for | |
| // the class body and all of its arrays, such as in Builder. | |
| DlVertices(DlVertexMode mode, | |
| int vertex_count, | |
| const SkPoint vertices[], | |
| const SkPoint texture_coordinates[], | |
| const DlColor colors[], | |
| int index_count, | |
| const uint16_t indices[], | |
| const SkRect* bounds = nullptr); | |
| // This constructor is specifically used by the DlVertices::Builder to | |
| // establish the object before the copying of data is requested. | |
| DlVertices(DlVertexMode mode, | |
| int vertex_count, | |
| Builder::Flags flags, | |
| int index_count); | |
| // The copy constructor has the same memory pre-allocation requirements | |
| // as this other constructors. This particular version is used by the | |
| // DisplaylistBuilder to copy the instance into pre-allocated pod memory | |
| // in the display list buffer. | |
| explicit DlVertices(const DlVertices* other); | |
| DlVertexMode mode_; | |
| int vertex_count_; | |
| size_t vertices_offset_; | |
| size_t texture_coordinates_offset_; | |
| size_t colors_offset_; | |
| int index_count_; | |
| size_t indices_offset_; | |
| SkRect bounds_; | |
| const void* pod(int offset) const { | |
| if (offset <= 0) { | |
| return nullptr; | |
| } | |
| const void* base = static_cast<const void*>(this); | |
| return static_cast<const char*>(base) + offset; | |
| } | |
| friend class DisplayListBuilder; | |
| }; | |
| } // namespace flutter | |
| #endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_VERTICES_H_ |