// 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,
};

//------------------------------------------------------------------------------
/// @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_));
  }

  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_
