From 84a73a609665a170a313a8220544dad657285656 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 May 2023 13:48:46 -0700 Subject: [PATCH] [Impeller] delete special handling of RRect. --- impeller/aiks/canvas.cc | 16 ++- impeller/entity/entity_unittests.cc | 6 +- impeller/entity/geometry.cc | 211 +++++----------------------- impeller/entity/geometry.h | 35 ----- impeller/geometry/path_builder.h | 16 +-- 5 files changed, 64 insertions(+), 220 deletions(-) diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 8ccf32f48067b..8ee384fc5aab6 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -241,18 +241,22 @@ void Canvas::DrawRRect(Rect rect, Scalar corner_radius, const Paint& paint) { if (AttemptDrawBlurredRRect(rect, corner_radius, paint)) { return; } + auto path = PathBuilder{} + .SetConvexity(Convexity::kConvex) + .AddRoundedRect(rect, corner_radius) + .TakePath(); if (paint.style == Paint::Style::kFill) { Entity entity; entity.SetTransformation(GetCurrentTransformation()); entity.SetStencilDepth(GetStencilDepth()); entity.SetBlendMode(paint.blend_mode); - entity.SetContents(paint.WithFilters(paint.CreateContentsForGeometry( - Geometry::MakeRRect(rect, corner_radius)))); + entity.SetContents(paint.WithFilters( + paint.CreateContentsForGeometry(Geometry::MakeFillPath(path)))); GetCurrentPass().AddEntity(entity); return; } - DrawPath(PathBuilder{}.AddRoundedRect(rect, corner_radius).TakePath(), paint); + DrawPath(path, paint); } void Canvas::DrawCircle(Point center, Scalar radius, const Paint& paint) { @@ -293,7 +297,11 @@ void Canvas::ClipRect(const Rect& rect, Entity::ClipOperation clip_op) { void Canvas::ClipRRect(const Rect& rect, Scalar corner_radius, Entity::ClipOperation clip_op) { - ClipGeometry(Geometry::MakeRRect(rect, corner_radius), clip_op); + auto path = PathBuilder{} + .SetConvexity(Convexity::kConvex) + .AddRoundedRect(rect, corner_radius) + .TakePath(); + ClipGeometry(Geometry::MakeFillPath(path), clip_op); switch (clip_op) { case Entity::ClipOperation::kIntersect: IntersectCulling(rect); diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index 1f0376e8461ad..007664bbf3ae1 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -224,7 +224,11 @@ TEST_P(EntityTest, CanDrawRect) { TEST_P(EntityTest, CanDrawRRect) { auto contents = std::make_shared(); - contents->SetGeometry(Geometry::MakeRRect({100, 100, 100, 100}, 10.0)); + auto path = PathBuilder{} + .SetConvexity(Convexity::kConvex) + .AddRoundedRect({100, 100, 100, 100}, 10.0) + .TakePath(); + contents->SetGeometry(Geometry::MakeFillPath(path)); contents->SetColor(Color::Red()); Entity entity; diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc index 8e568c3f2a93b..bfe5227329866 100644 --- a/impeller/entity/geometry.cc +++ b/impeller/entity/geometry.cc @@ -20,7 +20,7 @@ namespace impeller { std::pair, std::vector> TessellateConvex( Path::Polyline polyline) { std::vector output; - std::vector index; + std::vector indices; for (auto j = 0u; j < polyline.contours.size(); j++) { auto [start, end] = polyline.GetContourPointBounds(j); @@ -39,12 +39,12 @@ std::pair, std::vector> TessellateConvex( const auto& point_b = polyline.points[i]; output.emplace_back(point_b); - index.emplace_back(0); - index.emplace_back(i - 1); - index.emplace_back(i); + indices.emplace_back(0); + indices.emplace_back(i - 1); + indices.emplace_back(i); } } - return std::make_pair(output, index); + return std::make_pair(output, indices); } Geometry::Geometry() = default; @@ -64,11 +64,6 @@ std::unique_ptr Geometry::MakeFillPath(const Path& path) { return std::make_unique(path); } -// static -std::unique_ptr Geometry::MakeRRect(Rect rect, Scalar corner_radius) { - return std::make_unique(rect, corner_radius); -} - std::unique_ptr Geometry::MakeStrokePath(const Path& path, Scalar stroke_width, Scalar miter_limit, @@ -139,14 +134,14 @@ GeometryResult FillPathGeometry::GetPositionBuffer( if (path_.GetFillType() == FillType::kNonZero && // path_.IsConvex()) { - auto [points, indicies] = TessellateConvex( + auto [points, indices] = TessellateConvex( path_.CreatePolyline(entity.GetTransformation().GetMaxBasisLength())); vertex_buffer.vertex_buffer = host_buffer.Emplace( points.data(), points.size() * sizeof(Point), alignof(Point)); vertex_buffer.index_buffer = host_buffer.Emplace( - indicies.data(), indicies.size() * sizeof(uint16_t), alignof(uint16_t)); - vertex_buffer.index_count = indicies.size(); + indices.data(), indices.size() * sizeof(uint16_t), alignof(uint16_t)); + vertex_buffer.index_count = indices.size(); vertex_buffer.index_type = IndexType::k16bit; return GeometryResult{ @@ -193,6 +188,37 @@ GeometryResult FillPathGeometry::GetPositionUVBuffer( RenderPass& pass) { using VS = TextureFillVertexShader; + if (path_.GetFillType() == FillType::kNonZero && // + path_.IsConvex()) { + auto [points, indices] = TessellateConvex( + path_.CreatePolyline(entity.GetTransformation().GetMaxBasisLength())); + + VertexBufferBuilder vertex_builder; + vertex_builder.Reserve(points.size()); + vertex_builder.ReserveIndices(indices.size()); + for (auto i = 0u; i < points.size(); i++) { + VS::PerVertexData data; + data.position = points[i]; + auto coverage_coords = + ((points[i] - texture_coverage.origin) / texture_coverage.size) / + texture_coverage.size; + data.texture_coords = effect_transform * coverage_coords; + vertex_builder.AppendVertex(data); + } + for (auto i = 0u; i < indices.size(); i++) { + vertex_builder.AppendIndex(indices[i]); + } + + return GeometryResult{ + .type = PrimitiveType::kTriangle, + .vertex_buffer = + vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer()), + .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + entity.GetTransformation(), + .prevent_overdraw = false, + }; + } + VertexBufferBuilder vertex_builder; auto tesselation_result = renderer.GetTessellator()->Tessellate( path_.GetFillType(), @@ -777,163 +803,4 @@ std::optional RectGeometry::GetCoverage(const Matrix& transform) const { return rect_.TransformBounds(transform); } -/////// RRect Geometry /////// - -RRectGeometry::RRectGeometry(Rect rect, Scalar corner_radius) - : rect_(rect), corner_radius_(corner_radius) {} - -RRectGeometry::~RRectGeometry() = default; - -static void AppendRRectCorner(Path::Polyline polyline, - Point corner, - VertexBufferBuilder& vtx_builder) { - for (auto i = 1u; i < polyline.points.size(); i++) { - vtx_builder.AddVertices({ - polyline.points[i - 1], - polyline.points[i], - corner, - }); - } -} - -VertexBufferBuilder RRectGeometry::CreatePositionBuffer( - const Entity& entity) const { - VertexBufferBuilder vtx_builder; - - // The rounded rectangle is split into parts: - // * four corner sections defined by an arc - // * An interior shape composed of three rectangles. - - auto left = rect_.GetLeft(); - auto right = rect_.GetRight(); - auto bottom = rect_.GetBottom(); - auto top = rect_.GetTop(); - auto radii = PathBuilder::RoundingRadii(corner_radius_, corner_radius_, - corner_radius_, corner_radius_); - - auto topLeft = - PathBuilder{} - .MoveTo({rect_.origin.x, rect_.origin.y + corner_radius_}) - .AddRoundedRectTopLeft(rect_, radii) - .TakePath() - .CreatePolyline(entity.GetTransformation().GetMaxBasisLength()); - auto topRight = - PathBuilder{} - .MoveTo({right - radii.top_right.x, rect_.origin.y}) - .AddRoundedRectTopRight(rect_, radii) - .TakePath() - .CreatePolyline(entity.GetTransformation().GetMaxBasisLength()); - auto bottomLeft = - PathBuilder{} - .MoveTo({left + corner_radius_, bottom}) - .AddRoundedRectBottomLeft(rect_, radii) - .TakePath() - .CreatePolyline(entity.GetTransformation().GetMaxBasisLength()); - auto bottomRight = - PathBuilder{} - .MoveTo({right, bottom - corner_radius_}) - .AddRoundedRectBottomRight(rect_, radii) - .TakePath() - .CreatePolyline(entity.GetTransformation().GetMaxBasisLength()); - - vtx_builder.Reserve(12 * (topLeft.points.size() - 1) + 18); - - AppendRRectCorner(topLeft, Point(left + corner_radius_, top + corner_radius_), - vtx_builder); - - AppendRRectCorner(topRight, - Point(right - corner_radius_, top + corner_radius_), - vtx_builder); - - AppendRRectCorner(bottomLeft, - Point(left + corner_radius_, bottom - corner_radius_), - vtx_builder); - - AppendRRectCorner(bottomRight, - Point(right - corner_radius_, bottom - corner_radius_), - vtx_builder); - vtx_builder.AddVertices({ - // Top Component. - Point(left + corner_radius_, top + corner_radius_), - Point(left + corner_radius_, top), - Point(right - corner_radius_, top + corner_radius_), - - Point(left + corner_radius_, top), - Point(right - corner_radius_, top + corner_radius_), - Point(right - corner_radius_, top), - - // Bottom Component. - Point(left + corner_radius_, bottom - corner_radius_), - Point(left + corner_radius_, bottom), - Point(right - corner_radius_, bottom - corner_radius_), - - Point(left + corner_radius_, bottom), - Point(right - corner_radius_, bottom - corner_radius_), - Point(right - corner_radius_, bottom), - - // // Center Component. - Point(left, top + corner_radius_), - Point(right, top + corner_radius_), - Point(right, bottom - corner_radius_), - - Point(left, top + corner_radius_), - Point(left, bottom - corner_radius_), - Point(right, bottom - corner_radius_), - }); - - return vtx_builder; -} - -GeometryResult RRectGeometry::GetPositionBuffer(const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) { - auto vtx_builder = CreatePositionBuffer(entity); - - return GeometryResult{ - .type = PrimitiveType::kTriangle, - .vertex_buffer = - vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()), - .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * - entity.GetTransformation(), - .prevent_overdraw = false, - }; -} - -GeometryResult RRectGeometry::GetPositionUVBuffer( - Rect texture_coverage, - Matrix effect_transform, - const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) { - auto vtx_builder = CreatePositionBuffer(entity); - - VertexBufferBuilder vertex_builder; - vtx_builder.IterateVertices( - [&vertex_builder, &texture_coverage, &effect_transform](Point position) { - TextureFillVertexShader::PerVertexData data; - data.position = position; - auto coverage_coords = - (position - texture_coverage.origin) / texture_coverage.size; - data.texture_coords = effect_transform * coverage_coords; - vertex_builder.AppendVertex(data); - }); - - return GeometryResult{ - .type = PrimitiveType::kTriangle, - .vertex_buffer = - vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer()), - .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * - entity.GetTransformation(), - .prevent_overdraw = true, - }; -} - -GeometryVertexType RRectGeometry::GetVertexType() const { - return GeometryVertexType::kPosition; -} - -std::optional RRectGeometry::GetCoverage(const Matrix& transform) const { - return rect_.TransformBounds(transform); -} - } // namespace impeller diff --git a/impeller/entity/geometry.h b/impeller/entity/geometry.h index 53fd80ba96954..e3dd56deda339 100644 --- a/impeller/entity/geometry.h +++ b/impeller/entity/geometry.h @@ -46,8 +46,6 @@ class Geometry { static std::unique_ptr MakeFillPath(const Path& path); - static std::unique_ptr MakeRRect(Rect rect, Scalar corner_radius); - static std::unique_ptr MakeStrokePath( const Path& path, Scalar stroke_width = 0.0, @@ -262,37 +260,4 @@ class RectGeometry : public Geometry { FML_DISALLOW_COPY_AND_ASSIGN(RectGeometry); }; -class RRectGeometry : public Geometry { - public: - explicit RRectGeometry(Rect rect, Scalar corner_radius); - - ~RRectGeometry(); - - private: - // |Geometry| - GeometryResult GetPositionBuffer(const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) override; - - // |Geometry| - GeometryResult GetPositionUVBuffer(Rect texture_coverage, - Matrix effect_transform, - const ContentContext& renderer, - const Entity& entity, - RenderPass& pass) override; - - // |Geometry| - GeometryVertexType GetVertexType() const override; - - // |Geometry| - std::optional GetCoverage(const Matrix& transform) const override; - - VertexBufferBuilder CreatePositionBuffer(const Entity& entity) const; - - Rect rect_; - Scalar corner_radius_; - - FML_DISALLOW_COPY_AND_ASSIGN(RRectGeometry); -}; - } // namespace impeller diff --git a/impeller/geometry/path_builder.h b/impeller/geometry/path_builder.h index 56ac9f4dc3f15..52a9139f94f09 100644 --- a/impeller/geometry/path_builder.h +++ b/impeller/geometry/path_builder.h @@ -104,14 +104,6 @@ class PathBuilder { PathBuilder& AddRoundedRect(Rect rect, Scalar radius); - PathBuilder& AddRoundedRectTopLeft(Rect rect, RoundingRadii radii); - - PathBuilder& AddRoundedRectTopRight(Rect rect, RoundingRadii radii); - - PathBuilder& AddRoundedRectBottomRight(Rect rect, RoundingRadii radii); - - PathBuilder& AddRoundedRectBottomLeft(Rect rect, RoundingRadii radii); - PathBuilder& AddPath(const Path& path); private: @@ -120,6 +112,14 @@ class PathBuilder { Path prototype_; Convexity convexity_; + PathBuilder& AddRoundedRectTopLeft(Rect rect, RoundingRadii radii); + + PathBuilder& AddRoundedRectTopRight(Rect rect, RoundingRadii radii); + + PathBuilder& AddRoundedRectBottomRight(Rect rect, RoundingRadii radii); + + PathBuilder& AddRoundedRectBottomLeft(Rect rect, RoundingRadii radii); + Point ReflectedQuadraticControlPoint1() const; Point ReflectedCubicControlPoint1() const;