diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc index ece7557085fd4..ecc02ab83c0d5 100644 --- a/impeller/entity/contents/texture_contents.cc +++ b/impeller/entity/contents/texture_contents.cc @@ -123,7 +123,7 @@ bool TextureContents::Render(const ContentContext& renderer, VertexBufferBuilder vertex_builder; { const auto tess_result = renderer.GetTessellator()->Tessellate( - path_.GetFillType(), path_.CreatePolyline(), + path_.GetFillType(), path_.CreatePolyline(1.0f), [this, &vertex_builder, &coverage_rect, &texture_size]( const float* vertices, size_t vertices_size, const uint16_t* indices, size_t indices_size) { diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc index fa3f2011d5859..c86eaa68493f7 100644 --- a/impeller/entity/geometry.cc +++ b/impeller/entity/geometry.cc @@ -53,13 +53,11 @@ GeometryResult FillPathGeometry::GetPositionBuffer( const ContentContext& renderer, const Entity& entity, RenderPass& pass) { - auto tolerance = - kDefaultCurveTolerance / entity.GetTransformation().GetMaxBasisLength(); - VertexBuffer vertex_buffer; auto& host_buffer = pass.GetTransientsBuffer(); auto tesselation_result = renderer.GetTessellator()->Tessellate( - path_.GetFillType(), path_.CreatePolyline(tolerance), + path_.GetFillType(), + path_.CreatePolyline(entity.GetTransformation().GetMaxBasisLength()), [&vertex_buffer, &host_buffer]( const float* vertices, size_t vertices_count, const uint16_t* indices, size_t indices_count) { @@ -151,7 +149,7 @@ StrokePathGeometry::JoinProc StrokePathGeometry::GetJoinProc(Join stroke_join) { join_proc = [](VertexBufferBuilder& vtx_builder, const Point& position, const Point& start_offset, const Point& end_offset, Scalar miter_limit, - Scalar tolerance) { + Scalar scale) { CreateBevelAndGetDirection(vtx_builder, position, start_offset, end_offset); }; @@ -160,7 +158,7 @@ StrokePathGeometry::JoinProc StrokePathGeometry::GetJoinProc(Join stroke_join) { join_proc = [](VertexBufferBuilder& vtx_builder, const Point& position, const Point& start_offset, const Point& end_offset, Scalar miter_limit, - Scalar tolerance) { + Scalar scale) { Point start_normal = start_offset.Normalize(); Point end_normal = end_offset.Normalize(); @@ -189,7 +187,7 @@ StrokePathGeometry::JoinProc StrokePathGeometry::GetJoinProc(Join stroke_join) { join_proc = [](VertexBufferBuilder& vtx_builder, const Point& position, const Point& start_offset, const Point& end_offset, Scalar miter_limit, - Scalar tolerance) { + Scalar scale) { Point start_normal = start_offset.Normalize(); Point end_normal = end_offset.Normalize(); @@ -216,7 +214,7 @@ StrokePathGeometry::JoinProc StrokePathGeometry::GetJoinProc(Join stroke_join) { auto arc_points = CubicPathComponent(start_offset, start_handle, middle_handle, middle) - .CreatePolyline(tolerance); + .CreatePolyline(scale); VS::PerVertexData vtx; for (const auto& point : arc_points) { @@ -238,8 +236,7 @@ StrokePathGeometry::CapProc StrokePathGeometry::GetCapProc(Cap stroke_cap) { switch (stroke_cap) { case Cap::kButt: cap_proc = [](VertexBufferBuilder& vtx_builder, - const Point& position, const Point& offset, - Scalar tolerance) { + const Point& position, const Point& offset, Scalar scale) { VS::PerVertexData vtx; vtx.position = position + offset; vtx_builder.AppendVertex(vtx); @@ -249,8 +246,7 @@ StrokePathGeometry::CapProc StrokePathGeometry::GetCapProc(Cap stroke_cap) { break; case Cap::kRound: cap_proc = [](VertexBufferBuilder& vtx_builder, - const Point& position, const Point& offset, - Scalar tolerance) { + const Point& position, const Point& offset, Scalar scale) { VS::PerVertexData vtx; Point forward(offset.y, -offset.x); @@ -260,7 +256,7 @@ StrokePathGeometry::CapProc StrokePathGeometry::GetCapProc(Cap stroke_cap) { CubicPathComponent( offset, offset + forward * PathBuilder::kArcApproximationMagic, forward + offset * PathBuilder::kArcApproximationMagic, forward) - .CreatePolyline(tolerance); + .CreatePolyline(scale); vtx.position = position + offset; vtx_builder.AppendVertex(vtx); @@ -276,8 +272,7 @@ StrokePathGeometry::CapProc StrokePathGeometry::GetCapProc(Cap stroke_cap) { break; case Cap::kSquare: cap_proc = [](VertexBufferBuilder& vtx_builder, - const Point& position, const Point& offset, - Scalar tolerance) { + const Point& position, const Point& offset, Scalar scale) { VS::PerVertexData vtx; Point forward(offset.y, -offset.x); @@ -305,9 +300,9 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices( Cap cap, const StrokePathGeometry::JoinProc& join_proc, const StrokePathGeometry::CapProc& cap_proc, - Scalar tolerance) { + Scalar scale) { VertexBufferBuilder vtx_builder; - auto polyline = path.CreatePolyline(); + auto polyline = path.CreatePolyline(scale); VS::PerVertexData vtx; @@ -333,8 +328,8 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices( switch (contour_end_point_i - contour_start_point_i) { case 1: { Point p = polyline.points[contour_start_point_i]; - cap_proc(vtx_builder, p, {-stroke_width * 0.5f, 0}, tolerance); - cap_proc(vtx_builder, p, {stroke_width * 0.5f, 0}, tolerance); + cap_proc(vtx_builder, p, {-stroke_width * 0.5f, 0}, scale); + cap_proc(vtx_builder, p, {stroke_width * 0.5f, 0}, scale); continue; } case 0: @@ -381,7 +376,7 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices( } auto cap_offset = direction * stroke_width * 0.5; cap_proc(vtx_builder, polyline.points[contour_start_point_i], cap_offset, - tolerance); + scale); } // Generate contour geometry. @@ -402,7 +397,7 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices( // Generate join from the current line to the next line. join_proc(vtx_builder, polyline.points[point_i], previous_offset, - offset, scaled_miter_limit, tolerance); + offset, scaled_miter_limit, scale); } } @@ -412,10 +407,10 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices( Vector2(-contour.end_direction.y, contour.end_direction.x) * stroke_width * 0.5; cap_proc(vtx_builder, polyline.points[contour_end_point_i - 1], - cap_offset, tolerance); + cap_offset, scale); } else { join_proc(vtx_builder, polyline.points[contour_start_point_i], offset, - contour_first_offset, scaled_miter_limit, tolerance); + contour_first_offset, scaled_miter_limit, scale); } } @@ -437,15 +432,11 @@ GeometryResult StrokePathGeometry::GetPositionBuffer( Scalar min_size = 1.0f / sqrt(std::abs(determinant)); Scalar stroke_width = std::max(stroke_width_, min_size); - auto tolerance = - kDefaultCurveTolerance / - (stroke_width_ * entity.GetTransformation().GetMaxBasisLength()); - auto& host_buffer = pass.GetTransientsBuffer(); auto vertex_buffer = CreateSolidStrokeVertices( path_, host_buffer, stroke_width, miter_limit_ * stroke_width_ * 0.5, stroke_cap_, GetJoinProc(stroke_join_), GetCapProc(stroke_cap_), - tolerance); + entity.GetTransformation().GetMaxBasisLength()); return GeometryResult{ .type = PrimitiveType::kTriangleStrip, diff --git a/impeller/entity/geometry.h b/impeller/entity/geometry.h index d5eb6afe49dde..f595eeea775cd 100644 --- a/impeller/entity/geometry.h +++ b/impeller/entity/geometry.h @@ -134,14 +134,14 @@ class StrokePathGeometry : public Geometry { std::function& vtx_builder, const Point& position, const Point& offset, - Scalar tolerance)>; + Scalar scale)>; using JoinProc = std::function& vtx_builder, const Point& position, const Point& start_offset, const Point& end_offset, Scalar miter_limit, - Scalar tolerance)>; + Scalar scale)>; // |Geometry| GeometryResult GetPositionBuffer(const ContentContext& renderer, @@ -167,7 +167,7 @@ class StrokePathGeometry : public Geometry { Cap cap, const JoinProc& join_proc, const CapProc& cap_proc, - Scalar tolerance); + Scalar scale); static StrokePathGeometry::JoinProc GetJoinProc(Join stroke_join); diff --git a/impeller/geometry/geometry_benchmarks.cc b/impeller/geometry/geometry_benchmarks.cc index 06b514b46e61c..d3c1f9ea525c5 100644 --- a/impeller/geometry/geometry_benchmarks.cc +++ b/impeller/geometry/geometry_benchmarks.cc @@ -29,7 +29,7 @@ static void BM_Polyline(benchmark::State& state, Args&&... args) { size_t point_count = 0u; size_t single_point_count = 0u; while (state.KeepRunning()) { - auto polyline = path.CreatePolyline(); + auto polyline = path.CreatePolyline(1.0f); single_point_count = polyline.points.size(); point_count += single_point_count; if (tessellate) { diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 8edada62eaf54..1e3db566866e7 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -17,7 +17,6 @@ #include "impeller/geometry/rect.h" #include "impeller/geometry/scalar.h" #include "impeller/geometry/size.h" -#include "path_component.h" namespace impeller { namespace testing { @@ -577,7 +576,7 @@ TEST(GeometryTest, EmptyPath) { path.GetContourComponentAtIndex(0, c); ASSERT_POINT_NEAR(c.destination, Point()); - Path::Polyline polyline = path.CreatePolyline(); + Path::Polyline polyline = path.CreatePolyline(1.0f); ASSERT_TRUE(polyline.points.empty()); ASSERT_TRUE(polyline.contours.empty()); } @@ -1596,7 +1595,7 @@ TEST(GeometryTest, PathCreatePolyLineDoesNotDuplicatePoints) { path.AddContourComponent({40, 40}); path.AddLinearComponent({40, 40}, {50, 50}); - auto polyline = path.CreatePolyline(); + auto polyline = path.CreatePolyline(1.0f); ASSERT_EQ(polyline.contours.size(), 2u); ASSERT_EQ(polyline.points.size(), 5u); @@ -1682,7 +1681,7 @@ TEST(GeometryTest, PathCreatePolylineGeneratesCorrectContourData) { .LineTo({200, 200}) .Close() .TakePath() - .CreatePolyline(); + .CreatePolyline(1.0f); ASSERT_EQ(polyline.points.size(), 6u); ASSERT_EQ(polyline.contours.size(), 2u); ASSERT_EQ(polyline.contours[0].is_closed, false); @@ -1699,7 +1698,7 @@ TEST(GeometryTest, PolylineGetContourPointBoundsReturnsCorrectRanges) { .LineTo({200, 200}) .Close() .TakePath() - .CreatePolyline(); + .CreatePolyline(1.0f); size_t a1, a2, b1, b2; std::tie(a1, a2) = polyline.GetContourPointBounds(0); std::tie(b1, b2) = polyline.GetContourPointBounds(1); @@ -1713,7 +1712,7 @@ TEST(GeometryTest, PathAddRectPolylineHasCorrectContourData) { Path::Polyline polyline = PathBuilder{} .AddRect(Rect::MakeLTRB(50, 60, 70, 80)) .TakePath() - .CreatePolyline(); + .CreatePolyline(1.0f); ASSERT_EQ(polyline.contours.size(), 1u); ASSERT_TRUE(polyline.contours[0].is_closed); ASSERT_EQ(polyline.contours[0].start_index, 0u); @@ -1738,7 +1737,7 @@ TEST(GeometryTest, PathPolylineDuplicatesAreRemovedForSameContour) { .LineTo({0, 100}) .LineTo({0, 100}) // Insert duplicate at end of contour. .TakePath() - .CreatePolyline(); + .CreatePolyline(1.0f); ASSERT_EQ(polyline.contours.size(), 2u); ASSERT_EQ(polyline.contours[0].start_index, 0u); ASSERT_TRUE(polyline.contours[0].is_closed); diff --git a/impeller/geometry/path.cc b/impeller/geometry/path.cc index cad3774c40863..b5f26937cb325 100644 --- a/impeller/geometry/path.cc +++ b/impeller/geometry/path.cc @@ -7,6 +7,7 @@ #include #include "impeller/geometry/path_component.h" +#include "path_component.h" namespace impeller { @@ -221,8 +222,9 @@ bool Path::UpdateContourComponentAtIndex(size_t index, return true; } -Path::Polyline Path::CreatePolyline(Scalar tolerance) const { +Path::Polyline Path::CreatePolyline(Scalar scale) const { Polyline polyline; + auto tolerance = kDefaultCurveTolerance / scale; std::optional previous_contour_point; auto collect_points = [&polyline, &previous_contour_point]( diff --git a/impeller/geometry/path.h b/impeller/geometry/path.h index 9e348cda2edcc..0c4cf6939950a 100644 --- a/impeller/geometry/path.h +++ b/impeller/geometry/path.h @@ -11,6 +11,7 @@ #include #include "impeller/geometry/path_component.h" +#include "path_component.h" namespace impeller { @@ -122,7 +123,12 @@ class Path { bool UpdateContourComponentAtIndex(size_t index, const ContourComponent& contour); - Polyline CreatePolyline(Scalar tolerance = kDefaultCurveTolerance) const; + /// Callers must provide the scale factor for how this path will be + /// transformed. + /// + /// It is suitable to use the max basis length of the matrix used to transform + /// the path. If the provided scale is 0, curves will revert to lines. + Polyline CreatePolyline(Scalar scale) const; std::optional GetBoundingBox() const; diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc index 79c79cb8e08d7..aec9c770ebca1 100644 --- a/impeller/renderer/renderer_unittests.cc +++ b/impeller/renderer/renderer_unittests.cc @@ -396,7 +396,7 @@ TEST_P(RendererTest, CanRenderInstanced) { PathBuilder{} .AddRect(Rect::MakeXYWH(10, 10, 100, 100)) .TakePath() - .CreatePolyline(), + .CreatePolyline(1.0f), [&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) { diff --git a/impeller/tessellator/tessellator_unittests.cc b/impeller/tessellator/tessellator_unittests.cc index 56c2478540819..0b943d1391254 100644 --- a/impeller/tessellator/tessellator_unittests.cc +++ b/impeller/tessellator/tessellator_unittests.cc @@ -14,7 +14,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { // Zero points. { Tessellator t; - auto polyline = PathBuilder{}.TakePath().CreatePolyline(); + auto polyline = PathBuilder{}.TakePath().CreatePolyline(1.0f); Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices, @@ -27,7 +27,8 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { // One point. { Tessellator t; - auto polyline = PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline(); + auto polyline = + PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline(1.0f); Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices, @@ -40,7 +41,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { { Tessellator t; auto polyline = - PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(); + PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(1.0f); Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices, @@ -58,7 +59,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { auto coord = i * 1.0f; builder.AddLine({coord, coord}, {coord + 1, coord + 1}); } - auto polyline = builder.TakePath().CreatePolyline(); + auto polyline = builder.TakePath().CreatePolyline(1.0f); Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices, @@ -72,7 +73,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { { Tessellator t; auto polyline = - PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(); + PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(1.0f); Tessellator::Result result = t.Tessellate( FillType::kPositive, polyline, [](const float* vertices, size_t vertices_size, const uint16_t* indices,