diff --git a/display_list/display_list_vertices.h b/display_list/display_list_vertices.h index 96a06ad43620d..885ef6cfa65e8 100644 --- a/display_list/display_list_vertices.h +++ b/display_list/display_list_vertices.h @@ -108,7 +108,7 @@ class DlVertices { /// /// Vertices are always required. Optional texture coordinates /// and optional colors are reserved depending on the |Flags|. - /// Optional indices will be reserved iff the index_count is + /// Optional indices will be reserved if the index_count is /// positive (>0). /// /// The caller must provide all data that is promised by the diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 366c9ec58cddb..dfa6371392585 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -306,11 +306,12 @@ void Canvas::DrawTextFrame(TextFrame text_frame, Point position, Paint paint) { } void Canvas::DrawVertices(Vertices vertices, - Entity::BlendMode mode, + Entity::BlendMode blend_mode, Paint paint) { std::shared_ptr contents = std::make_shared(std::move(vertices)); contents->SetColor(paint.color); + contents->SetBlendMode(blend_mode); Entity entity; entity.SetTransformation(GetCurrentTransformation()); entity.SetStencilDepth(GetStencilDepth()); diff --git a/impeller/aiks/canvas.h b/impeller/aiks/canvas.h index a58794a9ac6b3..2e7abc61468f3 100644 --- a/impeller/aiks/canvas.h +++ b/impeller/aiks/canvas.h @@ -93,7 +93,9 @@ class Canvas { void DrawTextFrame(TextFrame text_frame, Point position, Paint paint); - void DrawVertices(Vertices vertices, Entity::BlendMode mode, Paint paint); + void DrawVertices(Vertices vertices, + Entity::BlendMode blend_mode, + Paint paint); Picture EndRecordingAsPicture(); diff --git a/impeller/entity/contents/vertices_contents.cc b/impeller/entity/contents/vertices_contents.cc index 2a27b94647d46..ef5bb6d844178 100644 --- a/impeller/entity/contents/vertices_contents.cc +++ b/impeller/entity/contents/vertices_contents.cc @@ -12,6 +12,7 @@ #include "impeller/renderer/formats.h" #include "impeller/renderer/render_pass.h" #include "impeller/renderer/sampler_library.h" +#include "impeller/renderer/vertex_buffer.h" namespace impeller { @@ -28,10 +29,27 @@ void VerticesContents::SetColor(Color color) { color_ = color.Premultiply(); } +void VerticesContents::SetBlendMode(Entity::BlendMode blend_mode) { + blend_mode_ = blend_mode; +} + +static PrimitiveType GetPrimitiveType(const Vertices& vertices) { + switch (vertices.GetMode()) { + case VertexMode::kTriangle: + return PrimitiveType::kTriangle; + case VertexMode::kTriangleStrip: + return PrimitiveType::kTriangleStrip; + } +} + bool VerticesContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - using VS = VerticesVertexShader; + if (!vertices_.IsValid()) { + return true; + } + + using VS = VerticesPipeline::VertexShader; const auto coverage_rect = vertices_.GetBoundingBox(); @@ -43,42 +61,36 @@ bool VerticesContents::Render(const ContentContext& renderer, return true; } - VertexBufferBuilder vertex_builder; - std::vector points = vertices_.GetPoints(); - std::vector indices = vertices_.GetIndices(); - // TODO: colors are currently unused, must be blended with - // paint color based on provided blend mode. - std::vector colors = vertices_.GetColors(); - VertexMode mode = vertices_.GetMode(); - - if (indices.size() == 0) { - for (size_t i = 0; i < points.size(); i += 1) { - VS::PerVertexData data; - data.point = points[i]; - data.vertex_color = color_; - vertex_builder.AppendVertex(data); - } - } else { - for (size_t i = 0; i < indices.size(); i += 1) { - VS::PerVertexData data; - data.point = points[indices[i]]; - data.vertex_color = color_; - vertex_builder.AppendVertex(data); + std::vector vertex_data; + { + const auto& positions = vertices_.GetPositions(); + const auto& colors = vertices_.GetColors(); + for (size_t i = 0; i < positions.size(); i++) { + vertex_data.push_back(VS::PerVertexData{ + .position = positions[i], + // TODO(108047): Blend these colors together when available. Use + // colors[i] as the destination and color_ as the + // source. Always use color_ when vertex colors are not + // supplied. + .color = i < colors.size() ? colors[i] : color_, + }); } } - PrimitiveType primitiveType; - switch (mode) { - case VertexMode::kTriangle: - primitiveType = PrimitiveType::kTriangle; - break; - case VertexMode::kTriangleStrip: - primitiveType = PrimitiveType::kTriangleStrip; - break; - } + size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData); + size_t total_idx_bytes = vertices_.GetIndices().size() * sizeof(uint16_t); - if (!vertex_builder.HasVertices()) { - return true; + auto buffer = renderer.GetContext()->GetTransientsAllocator()->CreateBuffer( + StorageMode::kHostVisible, total_vtx_bytes + total_idx_bytes); + + if (!buffer->CopyHostBuffer(reinterpret_cast(vertex_data.data()), + Range{0, total_vtx_bytes}, 0)) { + return false; + } + if (!buffer->CopyHostBuffer(reinterpret_cast(const_cast( + vertices_.GetIndices().data())), + Range{0, total_idx_bytes}, total_vtx_bytes)) { + return false; } auto& host_buffer = pass.GetTransientsBuffer(); @@ -91,8 +103,14 @@ bool VerticesContents::Render(const ContentContext& renderer, cmd.pipeline = renderer.GetVerticesPipeline(OptionsFromPassAndEntity(pass, entity)); cmd.stencil_reference = entity.GetStencilDepth(); - cmd.primitive_type = primitiveType; - cmd.BindVertices(vertex_builder.CreateVertexBuffer(host_buffer)); + cmd.primitive_type = GetPrimitiveType(vertices_); + cmd.BindVertices({ + .vertex_buffer = {.buffer = buffer, .range = Range{0, total_vtx_bytes}}, + .index_buffer = {.buffer = buffer, + .range = Range{total_vtx_bytes, total_idx_bytes}}, + .index_count = vertices_.GetIndices().size(), + .index_type = IndexType::k16bit, + }); VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); pass.AddCommand(std::move(cmd)); diff --git a/impeller/entity/contents/vertices_contents.h b/impeller/entity/contents/vertices_contents.h index 6529516f8178b..ed7b153a434f1 100644 --- a/impeller/entity/contents/vertices_contents.h +++ b/impeller/entity/contents/vertices_contents.h @@ -10,6 +10,7 @@ #include "flutter/fml/macros.h" #include "impeller/entity/contents/contents.h" +#include "impeller/entity/entity.h" #include "impeller/geometry/color.h" #include "impeller/geometry/path.h" #include "impeller/geometry/point.h" @@ -26,6 +27,8 @@ class VerticesContents final : public Contents { void SetColor(Color color); + void SetBlendMode(Entity::BlendMode blend_mode); + // |Contents| std::optional GetCoverage(const Entity& entity) const override; @@ -37,6 +40,7 @@ class VerticesContents final : public Contents { public: Vertices vertices_; Color color_; + Entity::BlendMode blend_mode_ = Entity::BlendMode::kSource; FML_DISALLOW_COPY_AND_ASSIGN(VerticesContents); }; diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index fe3a442ef44c2..dca12868062f0 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -1055,14 +1055,31 @@ TEST_P(EntityTest, BorderMaskBlurCoverageIsCorrect) { } } -TEST_P(EntityTest, DrawVerticesSolidColorTrianglesWithoutIndex) { - std::vector points = {Point(100, 300), Point(200, 100), - Point(300, 300)}; - std::vector indexes; +TEST_P(EntityTest, DrawVerticesSolidColorTrianglesWithoutIndices) { + std::vector positions = {Point(100, 300), Point(200, 100), + Point(300, 300)}; std::vector colors = {Color::White(), Color::White(), Color::White()}; - Vertices vertices = Vertices(points, indexes, colors, VertexMode::kTriangle, - Rect(100, 100, 300, 300)); + Vertices vertices = Vertices(positions, {} /* indices */, colors, + VertexMode::kTriangle, Rect(100, 100, 300, 300)); + + std::shared_ptr contents = + std::make_shared(vertices); + contents->SetColor(Color::White()); + Entity e; + e.SetTransformation(Matrix::MakeScale(GetContentScale())); + e.SetContents(contents); + + ASSERT_TRUE(OpenPlaygroundHere(e)); +} + +TEST_P(EntityTest, DrawVerticesSolidColorTrianglesWithIndices) { + std::vector positions = {Point(100, 300), Point(200, 100), + Point(300, 300), Point(200, 500)}; + std::vector indices = {0, 1, 2, 0, 2, 3}; + + Vertices vertices = Vertices(positions, indices, {} /* colors */, + VertexMode::kTriangle, Rect(100, 100, 300, 300)); std::shared_ptr contents = std::make_shared(vertices); diff --git a/impeller/entity/shaders/vertices.frag b/impeller/entity/shaders/vertices.frag index 0263c965f294b..ccad5b7d3e141 100644 --- a/impeller/entity/shaders/vertices.frag +++ b/impeller/entity/shaders/vertices.frag @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -in vec4 color; +in vec4 v_color; out vec4 frag_color; void main() { - frag_color = color; + frag_color = v_color; } diff --git a/impeller/entity/shaders/vertices.vert b/impeller/entity/shaders/vertices.vert index 835e01522ebd2..7923be810bdde 100644 --- a/impeller/entity/shaders/vertices.vert +++ b/impeller/entity/shaders/vertices.vert @@ -6,12 +6,12 @@ uniform FrameInfo { mat4 mvp; } frame_info; -in vec2 point; -in vec4 vertex_color; +in vec2 position; +in vec4 color; -out vec4 color; +out vec4 v_color; void main() { - gl_Position = frame_info.mvp * vec4(point, 0.0, 1.0); - color = vertex_color; + gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0); + v_color = color; } diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 847de8c0431cd..276b6751ccb06 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -1233,7 +1233,7 @@ TEST(GeometryTest, VerticesConstructorAndGetters) { Rect(0, 0, 4, 4)); ASSERT_EQ(vertices.GetBoundingBox().value(), Rect(0, 0, 4, 4)); - ASSERT_EQ(vertices.GetPoints(), points); + ASSERT_EQ(vertices.GetPositions(), points); ASSERT_EQ(vertices.GetIndices(), indices); ASSERT_EQ(vertices.GetColors(), colors); ASSERT_EQ(vertices.GetMode(), VertexMode::kTriangle); diff --git a/impeller/geometry/vertices.cc b/impeller/geometry/vertices.cc index 24e46b2a11fad..a93c7c2242cd4 100644 --- a/impeller/geometry/vertices.cc +++ b/impeller/geometry/vertices.cc @@ -11,14 +11,31 @@ Vertices::Vertices(std::vector points, std::vector colors, VertexMode vertex_mode, Rect bounds) - : points_(std::move(points)), + : positions_(std::move(points)), indices_(std::move(indices)), colors_(std::move(colors)), vertex_mode_(vertex_mode), - bounds_(bounds){}; + bounds_(bounds) { + NormalizeIndices(); +} Vertices::~Vertices() = default; +bool Vertices::IsValid() const { + size_t points_size = positions_.size(); + size_t colors_size = colors_.size(); + + if (colors_size > 0 && colors_size != points_size) { + return false; + } + + return true; +} + +std::optional Vertices::GetBoundingBox() const { + return bounds_; +}; + std::optional Vertices::GetTransformedBoundingBox( const Matrix& transform) const { auto bounds = GetBoundingBox(); @@ -28,4 +45,29 @@ std::optional Vertices::GetTransformedBoundingBox( return bounds->TransformBounds(transform); }; +const std::vector& Vertices::GetPositions() const { + return positions_; +} + +const std::vector& Vertices::GetIndices() const { + return indices_; +} + +const std::vector& Vertices::GetColors() const { + return colors_; +} + +VertexMode Vertices::GetMode() const { + return vertex_mode_; +} + +void Vertices::NormalizeIndices() { + if (indices_.size() != 0 || positions_.size() == 0) { + return; + } + for (size_t i = 0; i < positions_.size(); i++) { + indices_.push_back(i); + } +} + } // namespace impeller diff --git a/impeller/geometry/vertices.h b/impeller/geometry/vertices.h index 6fef5828419df..b642a8dc8f625 100644 --- a/impeller/geometry/vertices.h +++ b/impeller/geometry/vertices.h @@ -20,7 +20,7 @@ enum class VertexMode { class Vertices { public: - Vertices(std::vector points, + Vertices(std::vector positions, std::vector indices, std::vector colors, VertexMode vertex_mode, @@ -28,24 +28,28 @@ class Vertices { ~Vertices(); - std::optional GetBoundingBox() const { return bounds_; }; + bool IsValid() const; + + std::optional GetBoundingBox() const; std::optional GetTransformedBoundingBox(const Matrix& transform) const; - const std::vector& GetPoints() const { return points_; } + const std::vector& GetPositions() const; - const std::vector& GetIndices() const { return indices_; } + const std::vector& GetIndices() const; - const std::vector& GetColors() const { return colors_; } + const std::vector& GetColors() const; - VertexMode GetMode() const { return vertex_mode_; } + VertexMode GetMode() const; private: - std::vector points_; + std::vector positions_; std::vector indices_; std::vector colors_; VertexMode vertex_mode_; Rect bounds_; + + void NormalizeIndices(); }; } // namespace impeller