diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc index d57b1e9e67cca..1a361679b3e88 100644 --- a/impeller/entity/contents/texture_contents.cc +++ b/impeller/entity/contents/texture_contents.cc @@ -119,15 +119,24 @@ bool TextureContents::Render(const ContentContext& renderer, { const auto tess_result = renderer.GetTessellator()->Tessellate( path_.GetFillType(), path_.CreatePolyline(), - [this, &vertex_builder, &coverage_rect, &texture_size](Point vtx) { - VS::PerVertexData data; - data.position = vtx; - auto coverage_coords = - (vtx - coverage_rect->origin) / coverage_rect->size; - data.texture_coords = - (source_rect_.origin + source_rect_.size * coverage_coords) / - texture_size; - vertex_builder.AppendVertex(data); + [this, &vertex_builder, &coverage_rect, &texture_size]( + const float* vertices, size_t vertices_size, + const uint16_t* indices, size_t indices_size) { + for (auto i = 0u; i < vertices_size; i++) { + VS::PerVertexData data; + Point vtx = {vertices[i], vertices[i + 1]}; + data.position = vtx; + auto coverage_coords = + (vtx - coverage_rect->origin) / coverage_rect->size; + data.texture_coords = + (source_rect_.origin + source_rect_.size * coverage_coords) / + texture_size; + vertex_builder.AppendVertex(data); + } + for (auto i = 0u; i < indices_size; i++) { + vertex_builder.AppendIndex(indices[i]); + } + return true; }); if (tess_result == Tessellator::Result::kInputError) { diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc index 5cbaf2707e5d1..b24452d8b5173 100644 --- a/impeller/entity/geometry.cc +++ b/impeller/entity/geometry.cc @@ -184,7 +184,7 @@ GeometryResult PathGeometry::GetPositionBuffer( std::shared_ptr tessellator, ISize render_target_size) { VertexBuffer vertex_buffer; - auto tesselation_result = tessellator->TessellateBuilder( + auto tesselation_result = tessellator->Tessellate( path_.GetFillType(), path_.CreatePolyline(), [&vertex_buffer, &host_buffer]( const float* vertices, size_t vertices_count, const uint16_t* indices, diff --git a/impeller/geometry/geometry_benchmarks.cc b/impeller/geometry/geometry_benchmarks.cc index 9b6631871bf45..06b514b46e61c 100644 --- a/impeller/geometry/geometry_benchmarks.cc +++ b/impeller/geometry/geometry_benchmarks.cc @@ -33,7 +33,10 @@ static void BM_Polyline(benchmark::State& state, Args&&... args) { single_point_count = polyline.points.size(); point_count += single_point_count; if (tessellate) { - tess.Tessellate(FillType::kNonZero, polyline, [](Point) {}); + tess.Tessellate( + FillType::kNonZero, polyline, + [](const float* vertices, size_t vertices_size, + const uint16_t* indices, size_t indices_size) { return true; }); } } state.counters["SinglePointCount"] = single_point_count; diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc index c9059780bf4c4..bdb63c62e4602 100644 --- a/impeller/renderer/renderer_unittests.cc +++ b/impeller/renderer/renderer_unittests.cc @@ -397,18 +397,25 @@ TEST_P(RendererTest, CanRenderInstanced) { VertexBufferBuilder builder; - ASSERT_EQ( - Tessellator::Result::kSuccess, - Tessellator{}.Tessellate(FillType::kPositive, - PathBuilder{} - .AddRect(Rect::MakeXYWH(10, 10, 100, 100)) - .TakePath() - .CreatePolyline(), - [&builder](Point vtx) { - VS::PerVertexData data; - data.vtx = vtx; - builder.AppendVertex(data); - })); + ASSERT_EQ(Tessellator::Result::kSuccess, + Tessellator{}.Tessellate( + FillType::kPositive, + PathBuilder{} + .AddRect(Rect::MakeXYWH(10, 10, 100, 100)) + .TakePath() + .CreatePolyline(), + [&builder](const float* vertices, size_t vertices_size, + const uint16_t* indices, size_t indices_size) { + for (auto i = 0u; i < vertices_size; i += 2) { + VS::PerVertexData data; + data.vtx = {vertices[i], vertices[i + 1]}; + builder.AppendVertex(data); + } + for (auto i = 0u; i < indices_size; i++) { + builder.AppendIndex(indices[i]); + } + return true; + })); ASSERT_NE(GetContext(), nullptr); auto pipeline = diff --git a/impeller/tessellator/c/tessellator.cc b/impeller/tessellator/c/tessellator.cc index 7a53d9ceded5d..86a4cdfe85cee 100644 --- a/impeller/tessellator/c/tessellator.cc +++ b/impeller/tessellator/c/tessellator.cc @@ -46,11 +46,22 @@ struct Vertices* Tessellate(PathBuilder* builder, auto smoothing = SmoothingApproximation(scale, angle_tolerance, cusp_limit); auto polyline = path.CreatePolyline(smoothing); std::vector points; - if (Tessellator{}.Tessellate(path.GetFillType(), polyline, - [&points](Point vertex) { - points.push_back(vertex.x); - points.push_back(vertex.y); - }) != Tessellator::Result::kSuccess) { + if (Tessellator{}.Tessellate( + path.GetFillType(), polyline, + [&points](const float* vertices, size_t vertices_size, + const uint16_t* indices, size_t indices_size) { + // Results are expected to be re-duplicated. + std::vector raw_points; + for (auto i = 0u; i < vertices_size; i += 2) { + raw_points.emplace_back(Point{vertices[i], vertices[i + 1]}); + } + for (auto i = 0u; i < indices_size; i++) { + auto point = raw_points[indices[i]]; + points.push_back(point.x); + points.push_back(point.y); + } + return true; + }) != Tessellator::Result::kSuccess) { return nullptr; } diff --git a/impeller/tessellator/tessellator.cc b/impeller/tessellator/tessellator.cc index 72732310d77cd..4e2c3c535f41e 100644 --- a/impeller/tessellator/tessellator.cc +++ b/impeller/tessellator/tessellator.cc @@ -53,82 +53,6 @@ static int ToTessWindingRule(FillType fill_type) { } Tessellator::Result Tessellator::Tessellate( - FillType fill_type, - const Path::Polyline& polyline, - const VertexCallback& callback) const { - if (!callback) { - return Result::kInputError; - } - - if (polyline.points.empty()) { - return Result::kInputError; - } - - auto tessellator = c_tessellator_.get(); - if (!tessellator) { - return Result::kTessellationError; - } - - constexpr int kVertexSize = 2; - constexpr int kPolygonSize = 3; - - //---------------------------------------------------------------------------- - /// Feed contour information to the tessellator. - /// - static_assert(sizeof(Point) == 2 * sizeof(float)); - for (size_t contour_i = 0; contour_i < polyline.contours.size(); - contour_i++) { - size_t start_point_index, end_point_index; - std::tie(start_point_index, end_point_index) = - polyline.GetContourPointBounds(contour_i); - - ::tessAddContour(tessellator, // the C tessellator - kVertexSize, // - polyline.points.data() + start_point_index, // - sizeof(Point), // - end_point_index - start_point_index // - ); - } - - //---------------------------------------------------------------------------- - /// Let's tessellate. - /// - auto result = ::tessTesselate(tessellator, // tessellator - ToTessWindingRule(fill_type), // winding - TESS_POLYGONS, // element type - kPolygonSize, // polygon size - kVertexSize, // vertex size - nullptr // normal (null is automatic) - ); - - if (result != 1) { - return Result::kTessellationError; - } - - // TODO(csg): This copy can be elided entirely for the current use case. - std::vector points; - std::vector indices; - - int vertexItemCount = tessGetVertexCount(tessellator) * kVertexSize; - auto vertices = tessGetVertices(tessellator); - for (int i = 0; i < vertexItemCount; i += 2) { - points.emplace_back(vertices[i], vertices[i + 1]); - } - - int elementItemCount = tessGetElementCount(tessellator) * kPolygonSize; - auto elements = tessGetElements(tessellator); - for (int i = 0; i < elementItemCount; i++) { - indices.emplace_back(elements[i]); - } - - for (auto index : indices) { - auto vtx = points[index]; - callback(vtx); - } - return Result::kSuccess; -} - -Tessellator::Result Tessellator::TessellateBuilder( FillType fill_type, const Path::Polyline& polyline, const BuilderCallback& callback) const { diff --git a/impeller/tessellator/tessellator.h b/impeller/tessellator/tessellator.h index de2b8be168225..3a5ae97bb659b 100644 --- a/impeller/tessellator/tessellator.h +++ b/impeller/tessellator/tessellator.h @@ -43,26 +43,11 @@ class Tessellator { ~Tessellator(); - using VertexCallback = std::function; using BuilderCallback = std::function; - //---------------------------------------------------------------------------- - /// @brief Generates filled triangles from the polyline. A callback is - /// invoked for each vertex of the triangle. - /// - /// @param[in] fill_type The fill rule to use when filling. - /// @param[in] polyline The polyline - /// @param[in] callback The callback - /// - /// @return The result status of the tessellation. - /// - Tessellator::Result Tessellate(FillType fill_type, - const Path::Polyline& polyline, - const VertexCallback& callback) const; - //---------------------------------------------------------------------------- /// @brief Generates filled triangles from the polyline. A callback is /// invoked once for the entire tessellation. @@ -73,9 +58,9 @@ class Tessellator { /// /// @return The result status of the tessellation. /// - Tessellator::Result TessellateBuilder(FillType fill_type, - const Path::Polyline& polyline, - const BuilderCallback& callback) const; + Tessellator::Result Tessellate(FillType fill_type, + const Path::Polyline& polyline, + const BuilderCallback& callback) const; private: CTessellator c_tessellator_; diff --git a/impeller/tessellator/tessellator_unittests.cc b/impeller/tessellator/tessellator_unittests.cc index 24af4306c4fdf..56c2478540819 100644 --- a/impeller/tessellator/tessellator_unittests.cc +++ b/impeller/tessellator/tessellator_unittests.cc @@ -10,64 +10,12 @@ namespace impeller { namespace testing { -TEST(TessellatorTest, TessellatorReturnsCorrectResultStatus) { - // Zero points. - { - Tessellator t; - auto polyline = PathBuilder{}.TakePath().CreatePolyline(); - Tessellator::Result result = - t.Tessellate(FillType::kPositive, polyline, [](Point point) {}); - - ASSERT_EQ(polyline.points.size(), 0u); - ASSERT_EQ(result, Tessellator::Result::kInputError); - } - - // One point. - { - Tessellator t; - auto polyline = PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline(); - Tessellator::Result result = - t.Tessellate(FillType::kPositive, polyline, [](Point point) {}); - - ASSERT_EQ(polyline.points.size(), 1u); - ASSERT_EQ(result, Tessellator::Result::kSuccess); - } - - // Two points. - { - Tessellator t; - auto polyline = - PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(); - Tessellator::Result result = - t.Tessellate(FillType::kPositive, polyline, [](Point point) {}); - - ASSERT_EQ(polyline.points.size(), 2u); - ASSERT_EQ(result, Tessellator::Result::kSuccess); - } - - // Many points. - { - Tessellator t; - PathBuilder builder; - for (int i = 0; i < 1000; i++) { - auto coord = i * 1.0f; - builder.AddLine({coord, coord}, {coord + 1, coord + 1}); - } - auto polyline = builder.TakePath().CreatePolyline(); - Tessellator::Result result = - t.Tessellate(FillType::kPositive, polyline, [](Point point) {}); - - ASSERT_EQ(polyline.points.size(), 2000u); - ASSERT_EQ(result, Tessellator::Result::kSuccess); - } -} - TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { // Zero points. { Tessellator t; auto polyline = PathBuilder{}.TakePath().CreatePolyline(); - Tessellator::Result result = t.TessellateBuilder( + Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices, size_t indices_size) { return true; }); @@ -80,7 +28,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { { Tessellator t; auto polyline = PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline(); - Tessellator::Result result = t.TessellateBuilder( + Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices, size_t indices_size) { return true; }); @@ -93,7 +41,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { Tessellator t; auto polyline = PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(); - Tessellator::Result result = t.TessellateBuilder( + Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices, size_t indices_size) { return true; }); @@ -111,7 +59,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { builder.AddLine({coord, coord}, {coord + 1, coord + 1}); } auto polyline = builder.TakePath().CreatePolyline(); - Tessellator::Result result = t.TessellateBuilder( + Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices, size_t indices_size) { return true; }); @@ -125,7 +73,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { Tessellator t; auto polyline = PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(); - Tessellator::Result result = t.TessellateBuilder( + Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices, size_t indices_size) { return false; });