diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 44d93adb4be13..5e4205465850d 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -967,8 +967,7 @@ void DlDispatcher::drawPoints(PointMode mode, // |flutter::DlOpReceiver| void DlDispatcher::drawVertices(const flutter::DlVertices* vertices, flutter::DlBlendMode dl_mode) { - canvas_.DrawVertices(DlVerticesGeometry::MakeVertices(vertices), - ToBlendMode(dl_mode), paint_); + canvas_.DrawVertices(MakeVertices(vertices), ToBlendMode(dl_mode), paint_); } // |flutter::DlOpReceiver| diff --git a/impeller/display_list/dl_vertices_geometry.cc b/impeller/display_list/dl_vertices_geometry.cc index 52c70c7475752..66ad5aac91d15 100644 --- a/impeller/display_list/dl_vertices_geometry.cc +++ b/impeller/display_list/dl_vertices_geometry.cc @@ -4,15 +4,10 @@ #include "impeller/display_list/dl_vertices_geometry.h" -#include "impeller/core/device_buffer.h" -#include "impeller/entity/contents/content_context.h" -#include "impeller/entity/entity.h" -#include "impeller/entity/position_color.vert.h" -#include "impeller/entity/texture_fill.vert.h" -#include "impeller/geometry/matrix.h" -#include "impeller/geometry/path_builder.h" +#include "display_list/dl_vertices.h" +#include "impeller/display_list/skia_conversions.h" +#include "impeller/entity/geometry/vertices_geometry.h" #include "impeller/geometry/point.h" -#include "impeller/renderer/render_pass.h" #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkRect.h" @@ -22,330 +17,48 @@ static Rect ToRect(const SkRect& rect) { return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); } -// Fan mode isn't natively supported. Unroll into triangle mode by -// manipulating the index array. -// -// In Triangle fan, the first vertex is shared across all triangles, and then -// each sliding window of two vertices plus that first vertex defines a -// triangle. -static std::vector fromFanIndices( - const flutter::DlVertices* vertices) { - FML_DCHECK(vertices->vertex_count() >= 3); - FML_DCHECK(vertices->mode() == flutter::DlVertexMode::kTriangleFan); - - std::vector indices; - - // Un-fan index buffer if provided. - if (vertices->index_count() > 0) { - auto* dl_indices = vertices->indices(); - auto center_point = dl_indices[0]; - for (int i = 1; i < vertices->index_count() - 1; i++) { - indices.push_back(center_point); - indices.push_back(dl_indices[i]); - indices.push_back(dl_indices[i + 1]); - } - } else { - // If indices were not provided, create an index buffer that unfans - // triangles instead of re-writing points, colors, et cetera. - for (int i = 1; i < vertices->vertex_count() - 1; i++) { - indices.push_back(0); - indices.push_back(i); - indices.push_back(i + 1); - } - } - return indices; -} - -/////// Vertices Geometry /////// - -// static -std::shared_ptr DlVerticesGeometry::MakeVertices( - const flutter::DlVertices* vertices) { - return std::make_shared(vertices); -} - -DlVerticesGeometry::DlVerticesGeometry(const flutter::DlVertices* vertices) - : vertices_(vertices) { - NormalizeIndices(); -} - -DlVerticesGeometry::~DlVerticesGeometry() = default; - -void DlVerticesGeometry::NormalizeIndices() { - // Convert triangle fan if present. - if (vertices_->mode() == flutter::DlVertexMode::kTriangleFan) { - normalized_indices_ = fromFanIndices(vertices_); - return; - } - - auto index_count = vertices_->index_count(); - auto vertex_count = vertices_->vertex_count(); - if (index_count != 0 || vertex_count == 0) { - return; - } - normalized_indices_.reserve(vertex_count); - for (auto i = 0; i < vertex_count; i++) { - normalized_indices_.push_back(i); - } -} - -static PrimitiveType GetPrimitiveType(const flutter::DlVertices* vertices) { - switch (vertices->mode()) { +static VerticesGeometry::VertexMode ToVertexMode(flutter::DlVertexMode mode) { + switch (mode) { case flutter::DlVertexMode::kTriangles: - return PrimitiveType::kTriangle; + return VerticesGeometry::VertexMode::kTriangles; case flutter::DlVertexMode::kTriangleStrip: - return PrimitiveType::kTriangleStrip; + return VerticesGeometry::VertexMode::kTriangleStrip; case flutter::DlVertexMode::kTriangleFan: - // Unrolled into triangle mode. - return PrimitiveType::kTriangle; - } -} - -std::optional DlVerticesGeometry::GetTextureCoordinateCoverge() const { - if (!HasTextureCoordinates()) { - return std::nullopt; - } - auto vertex_count = vertices_->vertex_count(); - auto* dl_texture_coordinates = vertices_->texture_coordinates(); - if (vertex_count == 0) { - return std::nullopt; - } - - auto left = dl_texture_coordinates[0].x(); - auto top = dl_texture_coordinates[0].y(); - auto right = dl_texture_coordinates[0].x(); - auto bottom = dl_texture_coordinates[0].y(); - - for (auto i = 0; i < vertex_count; i++) { - left = std::min(left, dl_texture_coordinates[i].x()); - top = std::min(top, dl_texture_coordinates[i].y()); - right = std::max(right, dl_texture_coordinates[i].x()); - bottom = std::max(bottom, dl_texture_coordinates[i].y()); - } - return Rect::MakeLTRB(left, top, right, bottom); -} - -bool DlVerticesGeometry::HasVertexColors() const { - return vertices_->colors() != nullptr; -} - -bool DlVerticesGeometry::HasTextureCoordinates() const { - return vertices_->texture_coordinates() != nullptr; -} - -GeometryResult DlVerticesGeometry::GetPositionBuffer( - const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) { - auto index_count = normalized_indices_.size() == 0 - ? vertices_->index_count() - : normalized_indices_.size(); - auto vertex_count = vertices_->vertex_count(); - auto* dl_indices = normalized_indices_.size() == 0 - ? vertices_->indices() - : normalized_indices_.data(); - auto* dl_vertices = vertices_->vertices(); - - size_t total_vtx_bytes = vertex_count * sizeof(float) * 2; - size_t total_idx_bytes = index_count * sizeof(uint16_t); - - DeviceBufferDescriptor buffer_desc; - buffer_desc.size = total_vtx_bytes + total_idx_bytes; - buffer_desc.storage_mode = StorageMode::kHostVisible; - - auto buffer = - renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc); - - if (!buffer->CopyHostBuffer(reinterpret_cast(dl_vertices), - Range{0, total_vtx_bytes}, 0)) { - return {}; - } - if (!buffer->CopyHostBuffer( - reinterpret_cast(const_cast(dl_indices)), - Range{0, total_idx_bytes}, total_vtx_bytes)) { - return {}; - } - - return GeometryResult{ - .type = GetPrimitiveType(vertices_), - .vertex_buffer = - { - .vertex_buffer = {.buffer = buffer, - .range = Range{0, total_vtx_bytes}}, - .index_buffer = {.buffer = buffer, - .range = - Range{total_vtx_bytes, total_idx_bytes}}, - .vertex_count = index_count, - .index_type = IndexType::k16bit, - }, - .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * - entity.GetTransformation(), - .prevent_overdraw = false, + return VerticesGeometry::VertexMode::kTriangleFan; }; } -GeometryResult DlVerticesGeometry::GetPositionColorBuffer( - const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) { - using VS = GeometryColorPipeline::VertexShader; - - auto index_count = normalized_indices_.size() == 0 - ? vertices_->index_count() - : normalized_indices_.size(); - auto vertex_count = vertices_->vertex_count(); - auto* dl_indices = normalized_indices_.size() == 0 - ? vertices_->indices() - : normalized_indices_.data(); - auto* dl_vertices = vertices_->vertices(); - auto* dl_colors = vertices_->colors(); - - std::vector vertex_data(vertex_count); - { - for (auto i = 0; i < vertex_count; i++) { - auto dl_color = dl_colors[i]; - auto color = Color(dl_color.getRedF(), dl_color.getGreenF(), - dl_color.getBlueF(), dl_color.getAlphaF()) - .Premultiply(); - auto sk_point = dl_vertices[i]; - vertex_data[i] = { - .position = Point(sk_point.x(), sk_point.y()), - .color = color, - }; - } +std::shared_ptr MakeVertices( + const flutter::DlVertices* vertices) { + auto bounds = ToRect(vertices->bounds()); + auto mode = ToVertexMode(vertices->mode()); + std::vector positions(vertices->vertex_count()); + for (auto i = 0; i < vertices->vertex_count(); i++) { + positions[i] = skia_conversions::ToPoint(vertices->vertices()[i]); } - size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData); - size_t total_idx_bytes = index_count * sizeof(uint16_t); - - DeviceBufferDescriptor buffer_desc; - buffer_desc.size = total_vtx_bytes + total_idx_bytes; - buffer_desc.storage_mode = StorageMode::kHostVisible; - - auto buffer = - renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc); - - if (!buffer->CopyHostBuffer(reinterpret_cast(vertex_data.data()), - Range{0, total_vtx_bytes}, 0)) { - return {}; + std::vector indices(vertices->index_count()); + for (auto i = 0; i < vertices->index_count(); i++) { + indices[i] = vertices->indices()[i]; } - if (!buffer->CopyHostBuffer( - reinterpret_cast(const_cast(dl_indices)), - Range{0, total_idx_bytes}, total_vtx_bytes)) { - return {}; - } - - return GeometryResult{ - .type = GetPrimitiveType(vertices_), - .vertex_buffer = - { - .vertex_buffer = {.buffer = buffer, - .range = Range{0, total_vtx_bytes}}, - .index_buffer = {.buffer = buffer, - .range = - Range{total_vtx_bytes, total_idx_bytes}}, - .vertex_count = index_count, - .index_type = IndexType::k16bit, - }, - .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * - entity.GetTransformation(), - .prevent_overdraw = false, - }; -} -GeometryResult DlVerticesGeometry::GetPositionUVBuffer( - Rect texture_coverage, - Matrix effect_transform, - const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) { - using VS = TexturePipeline::VertexShader; - - auto index_count = normalized_indices_.size() == 0 - ? vertices_->index_count() - : normalized_indices_.size(); - auto vertex_count = vertices_->vertex_count(); - auto* dl_indices = normalized_indices_.size() == 0 - ? vertices_->indices() - : normalized_indices_.data(); - auto* dl_vertices = vertices_->vertices(); - auto* dl_texture_coordinates = vertices_->texture_coordinates(); - - auto size = texture_coverage.size; - auto origin = texture_coverage.origin; - std::vector vertex_data(vertex_count); - { - for (auto i = 0; i < vertex_count; i++) { - auto sk_point = dl_vertices[i]; - auto texture_coord = dl_texture_coordinates[i]; - auto uv = effect_transform * - Point((texture_coord.x() - origin.x) / size.width, - (texture_coord.y() - origin.y) / size.height); - // From experimentation we need to clamp these values to < 1.0 or else - // there can be flickering. - vertex_data[i] = { - .position = Point(sk_point.x(), sk_point.y()), - .texture_coords = - Point(std::clamp(uv.x, 0.0f, 1.0f - kEhCloseEnough), - std::clamp(uv.y, 0.0f, 1.0f - kEhCloseEnough)), - }; + std::vector colors; + if (vertices->colors()) { + colors.reserve(vertices->vertex_count()); + for (auto i = 0; i < vertices->vertex_count(); i++) { + colors.push_back(skia_conversions::ToColor(vertices->colors()[i])); } } - - size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData); - size_t total_idx_bytes = index_count * sizeof(uint16_t); - - DeviceBufferDescriptor buffer_desc; - buffer_desc.size = total_vtx_bytes + total_idx_bytes; - buffer_desc.storage_mode = StorageMode::kHostVisible; - - auto buffer = - renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc); - - if (!buffer->CopyHostBuffer(reinterpret_cast(vertex_data.data()), - Range{0, total_vtx_bytes}, 0)) { - return {}; - } - if (!buffer->CopyHostBuffer( - reinterpret_cast(const_cast(dl_indices)), - Range{0, total_idx_bytes}, total_vtx_bytes)) { - return {}; - } - - return GeometryResult{ - .type = GetPrimitiveType(vertices_), - .vertex_buffer = - { - .vertex_buffer = {.buffer = buffer, - .range = Range{0, total_vtx_bytes}}, - .index_buffer = {.buffer = buffer, - .range = - Range{total_vtx_bytes, total_idx_bytes}}, - .vertex_count = index_count, - .index_type = IndexType::k16bit, - }, - .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * - entity.GetTransformation(), - .prevent_overdraw = false, - }; -} - -GeometryVertexType DlVerticesGeometry::GetVertexType() const { - auto* dl_colors = vertices_->colors(); - if (dl_colors != nullptr) { - return GeometryVertexType::kColor; - } - auto* dl_texture_coordinates = vertices_->texture_coordinates(); - if (dl_texture_coordinates != nullptr) { - return GeometryVertexType::kUV; + std::vector texture_coordinates; + if (vertices->texture_coordinates()) { + texture_coordinates.reserve(vertices->vertex_count()); + for (auto i = 0; i < vertices->vertex_count(); i++) { + texture_coordinates.push_back( + skia_conversions::ToPoint(vertices->texture_coordinates()[i])); + } } - - return GeometryVertexType::kPosition; -} - -std::optional DlVerticesGeometry::GetCoverage( - const Matrix& transform) const { - return ToRect(vertices_->bounds()).TransformBounds(transform); + return std::make_shared( + positions, indices, texture_coordinates, colors, bounds, mode); } } // namespace impeller diff --git a/impeller/display_list/dl_vertices_geometry.h b/impeller/display_list/dl_vertices_geometry.h index 538b65a6d501b..466ed932a7ce4 100644 --- a/impeller/display_list/dl_vertices_geometry.h +++ b/impeller/display_list/dl_vertices_geometry.h @@ -4,67 +4,13 @@ #pragma once -#include -#include - #include "flutter/display_list/dl_vertices.h" #include "impeller/entity/geometry/vertices_geometry.h" -#include "impeller/geometry/color.h" -#include "impeller/geometry/point.h" -#include "impeller/geometry/rect.h" namespace impeller { -/// @brief A geometry that is created from a vertices object. -class DlVerticesGeometry : public VerticesGeometry { - public: - explicit DlVerticesGeometry(const flutter::DlVertices* vertices); - - ~DlVerticesGeometry(); - - static std::shared_ptr MakeVertices( - const flutter::DlVertices* vertices); - - // |VerticesGeometry| - GeometryResult GetPositionColorBuffer(const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) override; - - // |VerticesGeometry| - GeometryResult GetPositionUVBuffer(Rect texture_coverage, - Matrix effect_transform, - const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) override; - - // |Geometry| - GeometryResult GetPositionBuffer(const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) override; - - // |Geometry| - std::optional GetCoverage(const Matrix& transform) const override; - - // |Geometry| - GeometryVertexType GetVertexType() const override; - - // |VerticesGeometry| - bool HasVertexColors() const override; - - // |VerticesGeometry| - bool HasTextureCoordinates() const override; - - // |VerticesGeometry| - std::optional GetTextureCoordinateCoverge() const override; - - private: - void NormalizeIndices(); - - const flutter::DlVertices* vertices_; - std::vector normalized_indices_; - - FML_DISALLOW_COPY_AND_ASSIGN(DlVerticesGeometry); -}; +std::shared_ptr MakeVertices( + const flutter::DlVertices* vertices); } // namespace impeller diff --git a/impeller/entity/geometry/vertices_geometry.cc b/impeller/entity/geometry/vertices_geometry.cc index 2d27592853513..8c1a0c0d542b2 100644 --- a/impeller/entity/geometry/vertices_geometry.cc +++ b/impeller/entity/geometry/vertices_geometry.cc @@ -4,8 +4,304 @@ #include "impeller/entity/geometry/vertices_geometry.h" +#include + +#include +#include "impeller/core/formats.h" + namespace impeller { +// Fan mode isn't natively supported. Unroll into triangle mode by +// manipulating the index array. // +// In Triangle fan, the first vertex is shared across all triangles, and then +// each sliding window of two vertices plus that first vertex defines a +// triangle. +static std::vector fromFanIndices( + const std::vector& vertices, + const std::vector& indices) { + std::vector unrolled_indices; + + // Un-fan index buffer if provided. + if (indices.size() > 0u) { + if (indices.size() < 3u) { + return {}; + } + + auto center_point = indices[0]; + for (auto i = 1u; i < indices.size() - 1; i++) { + unrolled_indices.push_back(center_point); + unrolled_indices.push_back(indices[i]); + unrolled_indices.push_back(indices[i + 1]); + } + } else { + if (vertices.size() < 3u) { + return {}; + } + + // If indices were not provided, create an index buffer that unfans + // triangles instead of re-writing points, colors, et cetera. + for (auto i = 1u; i < vertices.size() - 1; i++) { + unrolled_indices.push_back(0); + unrolled_indices.push_back(i); + unrolled_indices.push_back(i + 1); + } + } + return unrolled_indices; +} + +/////// Vertices Geometry /////// + +VerticesGeometry::VerticesGeometry(std::vector vertices, + std::vector indices, + std::vector texture_coordinates, + std::vector colors, + Rect bounds, + VertexMode vertex_mode) + : vertices_(std::move(vertices)), + colors_(std::move(colors)), + texture_coordinates_(std::move(texture_coordinates)), + indices_(std::move(indices)), + bounds_(bounds), + vertex_mode_(vertex_mode) { + NormalizeIndices(); +} + +VerticesGeometry::~VerticesGeometry() = default; + +PrimitiveType VerticesGeometry::GetPrimitiveType() const { + switch (vertex_mode_) { + case VerticesGeometry::VertexMode::kTriangleFan: + // Unrolled into triangle mode. + return PrimitiveType::kTriangle; + case VerticesGeometry::VertexMode::kTriangleStrip: + return PrimitiveType::kTriangleStrip; + case VerticesGeometry::VertexMode::kTriangles: + return PrimitiveType::kTriangle; + } +} + +void VerticesGeometry::NormalizeIndices() { + // Convert triangle fan if present. + if (vertex_mode_ == VerticesGeometry::VertexMode::kTriangleFan) { + indices_ = fromFanIndices(vertices_, indices_); + return; + } +} + +bool VerticesGeometry::HasVertexColors() const { + return colors_.size() > 0; +} + +bool VerticesGeometry::HasTextureCoordinates() const { + return texture_coordinates_.size() > 0; +} + +std::optional VerticesGeometry::GetTextureCoordinateCoverge() const { + if (!HasTextureCoordinates()) { + return std::nullopt; + } + auto vertex_count = vertices_.size(); + if (vertex_count == 0) { + return std::nullopt; + } + + return Rect::MakePointBounds(texture_coordinates_.begin(), + texture_coordinates_.end()); +} + +GeometryResult VerticesGeometry::GetPositionBuffer( + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) { + auto index_count = indices_.size(); + auto vertex_count = vertices_.size(); + + size_t total_vtx_bytes = vertex_count * sizeof(float) * 2; + size_t total_idx_bytes = index_count * sizeof(uint16_t); + + DeviceBufferDescriptor buffer_desc; + buffer_desc.size = total_vtx_bytes + total_idx_bytes; + buffer_desc.storage_mode = StorageMode::kHostVisible; + + auto buffer = + renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc); + + if (!buffer->CopyHostBuffer( + reinterpret_cast(vertices_.data()), + Range{0, total_vtx_bytes}, 0)) { + return {}; + } + if (index_count > 0 && + !buffer->CopyHostBuffer( + reinterpret_cast(const_cast(indices_.data())), + Range{0, total_idx_bytes}, total_vtx_bytes)) { + return {}; + } + + return GeometryResult{ + .type = GetPrimitiveType(), + .vertex_buffer = + { + .vertex_buffer = {.buffer = buffer, + .range = Range{0, total_vtx_bytes}}, + .index_buffer = {.buffer = buffer, + .range = + Range{total_vtx_bytes, total_idx_bytes}}, + .vertex_count = index_count > 0 ? index_count : vertex_count, + .index_type = + index_count > 0 ? IndexType::k16bit : IndexType::kNone, + }, + .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + entity.GetTransformation(), + .prevent_overdraw = false, + }; +} + +GeometryResult VerticesGeometry::GetPositionColorBuffer( + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) { + using VS = GeometryColorPipeline::VertexShader; + + auto index_count = indices_.size(); + auto vertex_count = vertices_.size(); + + std::vector vertex_data(vertex_count); + { + for (auto i = 0u; i < vertex_count; i++) { + vertex_data[i] = { + .position = vertices_[i], + .color = colors_[i], + }; + } + } + + size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData); + size_t total_idx_bytes = index_count * sizeof(uint16_t); + + DeviceBufferDescriptor buffer_desc; + buffer_desc.size = total_vtx_bytes + total_idx_bytes; + buffer_desc.storage_mode = StorageMode::kHostVisible; + + auto buffer = + renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc); + + if (!buffer->CopyHostBuffer(reinterpret_cast(vertex_data.data()), + Range{0, total_vtx_bytes}, 0)) { + return {}; + } + if (index_count > 0 && + !buffer->CopyHostBuffer( + reinterpret_cast(const_cast(indices_.data())), + Range{0, total_idx_bytes}, total_vtx_bytes)) { + return {}; + } + + return GeometryResult{ + .type = GetPrimitiveType(), + .vertex_buffer = + { + .vertex_buffer = {.buffer = buffer, + .range = Range{0, total_vtx_bytes}}, + .index_buffer = {.buffer = buffer, + .range = + Range{total_vtx_bytes, total_idx_bytes}}, + .vertex_count = index_count > 0 ? index_count : vertex_count, + .index_type = + index_count > 0 ? IndexType::k16bit : IndexType::kNone, + }, + .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + entity.GetTransformation(), + .prevent_overdraw = false, + }; +} + +GeometryResult VerticesGeometry::GetPositionUVBuffer( + Rect texture_coverage, + Matrix effect_transform, + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) { + using VS = TexturePipeline::VertexShader; + + auto index_count = indices_.size(); + auto vertex_count = vertices_.size(); + auto size = texture_coverage.size; + auto origin = texture_coverage.origin; + std::vector vertex_data(vertex_count); + { + for (auto i = 0u; i < vertex_count; i++) { + auto vertex = vertices_[i]; + auto texture_coord = texture_coordinates_[i]; + auto uv = + effect_transform * Point((texture_coord.x - origin.x) / size.width, + (texture_coord.y - origin.y) / size.height); + // From experimentation we need to clamp these values to < 1.0 or else + // there can be flickering. + vertex_data[i] = { + .position = vertex, + .texture_coords = + Point(std::clamp(uv.x, 0.0f, 1.0f - kEhCloseEnough), + std::clamp(uv.y, 0.0f, 1.0f - kEhCloseEnough)), + }; + } + } + + size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData); + size_t total_idx_bytes = index_count * sizeof(uint16_t); + + DeviceBufferDescriptor buffer_desc; + buffer_desc.size = total_vtx_bytes + total_idx_bytes; + buffer_desc.storage_mode = StorageMode::kHostVisible; + + auto buffer = + renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc); + + if (!buffer->CopyHostBuffer(reinterpret_cast(vertex_data.data()), + Range{0, total_vtx_bytes}, 0)) { + return {}; + } + if (index_count > 0u && + !buffer->CopyHostBuffer( + reinterpret_cast(const_cast(indices_.data())), + Range{0, total_idx_bytes}, total_vtx_bytes)) { + return {}; + } + + return GeometryResult{ + .type = GetPrimitiveType(), + .vertex_buffer = + { + .vertex_buffer = {.buffer = buffer, + .range = Range{0, total_vtx_bytes}}, + .index_buffer = {.buffer = buffer, + .range = + Range{total_vtx_bytes, total_idx_bytes}}, + .vertex_count = index_count > 0 ? index_count : vertex_count, + .index_type = + index_count > 0 ? IndexType::k16bit : IndexType::kNone, + }, + .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + entity.GetTransformation(), + .prevent_overdraw = false, + }; +} + +GeometryVertexType VerticesGeometry::GetVertexType() const { + if (HasVertexColors()) { + return GeometryVertexType::kColor; + } + if (HasTextureCoordinates()) { + return GeometryVertexType::kUV; + } + + return GeometryVertexType::kPosition; +} + +std::optional VerticesGeometry::GetCoverage( + const Matrix& transform) const { + return bounds_.TransformBounds(transform); +} } // namespace impeller diff --git a/impeller/entity/geometry/vertices_geometry.h b/impeller/entity/geometry/vertices_geometry.h index 09a6b377659e5..93ab83679b1e3 100644 --- a/impeller/entity/geometry/vertices_geometry.h +++ b/impeller/entity/geometry/vertices_geometry.h @@ -11,15 +11,61 @@ namespace impeller { /// @brief A geometry that is created from a vertices object. class VerticesGeometry : public Geometry { public: - virtual GeometryResult GetPositionColorBuffer(const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) = 0; + enum class VertexMode { + kTriangles, + kTriangleStrip, + kTriangleFan, + }; - virtual bool HasVertexColors() const = 0; + VerticesGeometry(std::vector vertices, + std::vector indices, + std::vector texture_coordinates, + std::vector colors, + Rect bounds, + VerticesGeometry::VertexMode vertex_mode); - virtual bool HasTextureCoordinates() const = 0; + ~VerticesGeometry(); - virtual std::optional GetTextureCoordinateCoverge() const = 0; + GeometryResult GetPositionColorBuffer(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass); + + // |Geometry| + GeometryResult GetPositionUVBuffer(Rect texture_coverage, + Matrix effect_transform, + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) override; + + // |Geometry| + GeometryResult GetPositionBuffer(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) override; + + // |Geometry| + std::optional GetCoverage(const Matrix& transform) const override; + + // |Geometry| + GeometryVertexType GetVertexType() const override; + + bool HasVertexColors() const; + + bool HasTextureCoordinates() const; + + std::optional GetTextureCoordinateCoverge() const; + + private: + void NormalizeIndices(); + + PrimitiveType GetPrimitiveType() const; + + std::vector vertices_; + std::vector colors_; + std::vector texture_coordinates_; + std::vector indices_; + Rect bounds_; + VerticesGeometry::VertexMode vertex_mode_ = + VerticesGeometry::VertexMode::kTriangles; }; } // namespace impeller