| // Copyright 2016 The Fuchsia 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 SRC_UI_LIB_ESCHER_SHAPE_MESH_BUILDER_H_ |
| #define SRC_UI_LIB_ESCHER_SHAPE_MESH_BUILDER_H_ |
| |
| #include "src/lib/fxl/memory/ref_counted.h" |
| #include "src/ui/lib/escher/shape/mesh.h" |
| |
| namespace escher { |
| |
| // MeshBuilder is used by Escher clients to generate Meshes. Clients should |
| // obtain one via Escher::NewMeshBuilder(), repeatedly call AddVertex() and |
| // AddIndex() to add data for the Mesh, and then call Build() once all data has |
| // been added. |
| class MeshBuilder : public fxl::RefCountedThreadSafe<MeshBuilder> { |
| public: |
| // Return a mesh constructed from the indices and vertices added by AddIndex() |
| // and AddVertex(), respectively. After this function is called, all the |
| // staging buffers will be cleared so that the builder can be reused. |
| virtual MeshPtr Build() = 0; |
| |
| // Copy the index into the staging buffer, so that it will be uploaded to the |
| // GPU when Build() is called. |
| MeshBuilder& AddIndex(uint32_t index); |
| |
| MeshBuilder& AddTriangle(uint32_t index0, uint32_t index1, uint32_t index2) { |
| AddIndex(index0); |
| AddIndex(index1); |
| return AddIndex(index2); |
| } |
| |
| // Copy |size| bytes of data to the staging buffer; this data represents a |
| // single vertex. |
| MeshBuilder& AddVertexData(const void* ptr, size_t size); |
| |
| // Wrap AddVertexData() to automatically obtain the size from the vertex. |
| template <typename VertexT> |
| MeshBuilder& AddVertex(const VertexT& v); |
| |
| // Return the size of a vertex for the given mesh-spec. |
| size_t vertex_stride() const { return vertex_stride_; } |
| |
| // Return the number of indices that have been added to the builder, so far. |
| size_t index_count() const { return index_count_; } |
| |
| // Return the number of vertices that have been added to the builder, so far. |
| size_t vertex_count() const { return vertex_count_; } |
| |
| // Return pointer to start of data for the vertex at the specified index. |
| uint8_t* GetVertex(size_t index) { |
| FX_DCHECK(index < vertex_count_); |
| return vertex_staging_buffer_.data() + (index * vertex_stride_); |
| } |
| // Return pointer to the i-th index that was added. |
| uint32_t* GetIndex(size_t i) { |
| FX_DCHECK(i < index_count_); |
| return index_staging_buffer_.data() + i; |
| } |
| |
| protected: |
| MeshBuilder(size_t max_vertex_count, size_t max_index_count, size_t vertex_stride); |
| FRIEND_REF_COUNTED_THREAD_SAFE(MeshBuilder); |
| virtual ~MeshBuilder(); |
| |
| const size_t max_vertex_count_; |
| const size_t max_index_count_; |
| const size_t vertex_stride_; |
| std::vector<uint8_t> vertex_staging_buffer_; |
| std::vector<uint32_t> index_staging_buffer_; |
| uint32_t vertex_count_ = 0; |
| uint32_t index_count_ = 0; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(MeshBuilder); |
| }; |
| |
| typedef fxl::RefPtr<MeshBuilder> MeshBuilderPtr; |
| |
| // Inline function definitions. |
| |
| inline MeshBuilder& MeshBuilder::AddIndex(uint32_t index) { |
| FX_DCHECK(index_count_ < max_index_count_); |
| FX_DCHECK(index_count_ < index_staging_buffer_.size()); |
| index_staging_buffer_[index_count_++] = index; |
| return *this; |
| } |
| |
| inline MeshBuilder& MeshBuilder::AddVertexData(const void* ptr, size_t size) { |
| FX_DCHECK(vertex_count_ < max_vertex_count_); |
| FX_DCHECK(size <= vertex_stride_); |
| FX_DCHECK(vertex_count_ * vertex_stride_ < vertex_staging_buffer_.size()); |
| |
| const auto* src_ptr = static_cast<const uint8_t*>(ptr); |
| size_t offset = vertex_stride_ * vertex_count_; |
| ++vertex_count_; |
| std::copy(src_ptr, src_ptr + size, vertex_staging_buffer_.begin() + offset); |
| return *this; |
| } |
| |
| template <typename VertexT> |
| MeshBuilder& MeshBuilder::AddVertex(const VertexT& v) { |
| AddVertexData(&v, sizeof(VertexT)); |
| return *this; |
| } |
| |
| } // namespace escher |
| |
| #endif // SRC_UI_LIB_ESCHER_SHAPE_MESH_BUILDER_H_ |