Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 80880ab

Browse files
author
Jonah Williams
authored
[Impeller] delete special handling of RRect. (#41872)
The convex path tessellator is more general purpose than the RRect and shouldn't be any slower. BY removing this class, we make it easier to switch to GPU polyline generation and tessellation for convex shapes.
1 parent 9d1a7b6 commit 80880ab

File tree

5 files changed

+64
-220
lines changed

5 files changed

+64
-220
lines changed

impeller/aiks/canvas.cc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,18 +241,22 @@ void Canvas::DrawRRect(Rect rect, Scalar corner_radius, const Paint& paint) {
241241
if (AttemptDrawBlurredRRect(rect, corner_radius, paint)) {
242242
return;
243243
}
244+
auto path = PathBuilder{}
245+
.SetConvexity(Convexity::kConvex)
246+
.AddRoundedRect(rect, corner_radius)
247+
.TakePath();
244248
if (paint.style == Paint::Style::kFill) {
245249
Entity entity;
246250
entity.SetTransformation(GetCurrentTransformation());
247251
entity.SetStencilDepth(GetStencilDepth());
248252
entity.SetBlendMode(paint.blend_mode);
249-
entity.SetContents(paint.WithFilters(paint.CreateContentsForGeometry(
250-
Geometry::MakeRRect(rect, corner_radius))));
253+
entity.SetContents(paint.WithFilters(
254+
paint.CreateContentsForGeometry(Geometry::MakeFillPath(path))));
251255

252256
GetCurrentPass().AddEntity(entity);
253257
return;
254258
}
255-
DrawPath(PathBuilder{}.AddRoundedRect(rect, corner_radius).TakePath(), paint);
259+
DrawPath(path, paint);
256260
}
257261

258262
void Canvas::DrawCircle(Point center, Scalar radius, const Paint& paint) {
@@ -293,7 +297,11 @@ void Canvas::ClipRect(const Rect& rect, Entity::ClipOperation clip_op) {
293297
void Canvas::ClipRRect(const Rect& rect,
294298
Scalar corner_radius,
295299
Entity::ClipOperation clip_op) {
296-
ClipGeometry(Geometry::MakeRRect(rect, corner_radius), clip_op);
300+
auto path = PathBuilder{}
301+
.SetConvexity(Convexity::kConvex)
302+
.AddRoundedRect(rect, corner_radius)
303+
.TakePath();
304+
ClipGeometry(Geometry::MakeFillPath(path), clip_op);
297305
switch (clip_op) {
298306
case Entity::ClipOperation::kIntersect:
299307
IntersectCulling(rect);

impeller/entity/entity_unittests.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,11 @@ TEST_P(EntityTest, CanDrawRect) {
224224

225225
TEST_P(EntityTest, CanDrawRRect) {
226226
auto contents = std::make_shared<SolidColorContents>();
227-
contents->SetGeometry(Geometry::MakeRRect({100, 100, 100, 100}, 10.0));
227+
auto path = PathBuilder{}
228+
.SetConvexity(Convexity::kConvex)
229+
.AddRoundedRect({100, 100, 100, 100}, 10.0)
230+
.TakePath();
231+
contents->SetGeometry(Geometry::MakeFillPath(path));
228232
contents->SetColor(Color::Red());
229233

230234
Entity entity;

impeller/entity/geometry.cc

Lines changed: 39 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace impeller {
2020
std::pair<std::vector<Point>, std::vector<uint16_t>> TessellateConvex(
2121
Path::Polyline polyline) {
2222
std::vector<Point> output;
23-
std::vector<uint16_t> index;
23+
std::vector<uint16_t> indices;
2424

2525
for (auto j = 0u; j < polyline.contours.size(); j++) {
2626
auto [start, end] = polyline.GetContourPointBounds(j);
@@ -39,12 +39,12 @@ std::pair<std::vector<Point>, std::vector<uint16_t>> TessellateConvex(
3939
const auto& point_b = polyline.points[i];
4040
output.emplace_back(point_b);
4141

42-
index.emplace_back(0);
43-
index.emplace_back(i - 1);
44-
index.emplace_back(i);
42+
indices.emplace_back(0);
43+
indices.emplace_back(i - 1);
44+
indices.emplace_back(i);
4545
}
4646
}
47-
return std::make_pair(output, index);
47+
return std::make_pair(output, indices);
4848
}
4949

5050
Geometry::Geometry() = default;
@@ -64,11 +64,6 @@ std::unique_ptr<Geometry> Geometry::MakeFillPath(const Path& path) {
6464
return std::make_unique<FillPathGeometry>(path);
6565
}
6666

67-
// static
68-
std::unique_ptr<Geometry> Geometry::MakeRRect(Rect rect, Scalar corner_radius) {
69-
return std::make_unique<RRectGeometry>(rect, corner_radius);
70-
}
71-
7267
std::unique_ptr<Geometry> Geometry::MakeStrokePath(const Path& path,
7368
Scalar stroke_width,
7469
Scalar miter_limit,
@@ -139,14 +134,14 @@ GeometryResult FillPathGeometry::GetPositionBuffer(
139134

140135
if (path_.GetFillType() == FillType::kNonZero && //
141136
path_.IsConvex()) {
142-
auto [points, indicies] = TessellateConvex(
137+
auto [points, indices] = TessellateConvex(
143138
path_.CreatePolyline(entity.GetTransformation().GetMaxBasisLength()));
144139

145140
vertex_buffer.vertex_buffer = host_buffer.Emplace(
146141
points.data(), points.size() * sizeof(Point), alignof(Point));
147142
vertex_buffer.index_buffer = host_buffer.Emplace(
148-
indicies.data(), indicies.size() * sizeof(uint16_t), alignof(uint16_t));
149-
vertex_buffer.index_count = indicies.size();
143+
indices.data(), indices.size() * sizeof(uint16_t), alignof(uint16_t));
144+
vertex_buffer.index_count = indices.size();
150145
vertex_buffer.index_type = IndexType::k16bit;
151146

152147
return GeometryResult{
@@ -193,6 +188,37 @@ GeometryResult FillPathGeometry::GetPositionUVBuffer(
193188
RenderPass& pass) {
194189
using VS = TextureFillVertexShader;
195190

191+
if (path_.GetFillType() == FillType::kNonZero && //
192+
path_.IsConvex()) {
193+
auto [points, indices] = TessellateConvex(
194+
path_.CreatePolyline(entity.GetTransformation().GetMaxBasisLength()));
195+
196+
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
197+
vertex_builder.Reserve(points.size());
198+
vertex_builder.ReserveIndices(indices.size());
199+
for (auto i = 0u; i < points.size(); i++) {
200+
VS::PerVertexData data;
201+
data.position = points[i];
202+
auto coverage_coords =
203+
((points[i] - texture_coverage.origin) / texture_coverage.size) /
204+
texture_coverage.size;
205+
data.texture_coords = effect_transform * coverage_coords;
206+
vertex_builder.AppendVertex(data);
207+
}
208+
for (auto i = 0u; i < indices.size(); i++) {
209+
vertex_builder.AppendIndex(indices[i]);
210+
}
211+
212+
return GeometryResult{
213+
.type = PrimitiveType::kTriangle,
214+
.vertex_buffer =
215+
vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer()),
216+
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
217+
entity.GetTransformation(),
218+
.prevent_overdraw = false,
219+
};
220+
}
221+
196222
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
197223
auto tesselation_result = renderer.GetTessellator()->Tessellate(
198224
path_.GetFillType(),
@@ -777,163 +803,4 @@ std::optional<Rect> RectGeometry::GetCoverage(const Matrix& transform) const {
777803
return rect_.TransformBounds(transform);
778804
}
779805

780-
/////// RRect Geometry ///////
781-
782-
RRectGeometry::RRectGeometry(Rect rect, Scalar corner_radius)
783-
: rect_(rect), corner_radius_(corner_radius) {}
784-
785-
RRectGeometry::~RRectGeometry() = default;
786-
787-
static void AppendRRectCorner(Path::Polyline polyline,
788-
Point corner,
789-
VertexBufferBuilder<Point>& vtx_builder) {
790-
for (auto i = 1u; i < polyline.points.size(); i++) {
791-
vtx_builder.AddVertices({
792-
polyline.points[i - 1],
793-
polyline.points[i],
794-
corner,
795-
});
796-
}
797-
}
798-
799-
VertexBufferBuilder<Point> RRectGeometry::CreatePositionBuffer(
800-
const Entity& entity) const {
801-
VertexBufferBuilder<Point> vtx_builder;
802-
803-
// The rounded rectangle is split into parts:
804-
// * four corner sections defined by an arc
805-
// * An interior shape composed of three rectangles.
806-
807-
auto left = rect_.GetLeft();
808-
auto right = rect_.GetRight();
809-
auto bottom = rect_.GetBottom();
810-
auto top = rect_.GetTop();
811-
auto radii = PathBuilder::RoundingRadii(corner_radius_, corner_radius_,
812-
corner_radius_, corner_radius_);
813-
814-
auto topLeft =
815-
PathBuilder{}
816-
.MoveTo({rect_.origin.x, rect_.origin.y + corner_radius_})
817-
.AddRoundedRectTopLeft(rect_, radii)
818-
.TakePath()
819-
.CreatePolyline(entity.GetTransformation().GetMaxBasisLength());
820-
auto topRight =
821-
PathBuilder{}
822-
.MoveTo({right - radii.top_right.x, rect_.origin.y})
823-
.AddRoundedRectTopRight(rect_, radii)
824-
.TakePath()
825-
.CreatePolyline(entity.GetTransformation().GetMaxBasisLength());
826-
auto bottomLeft =
827-
PathBuilder{}
828-
.MoveTo({left + corner_radius_, bottom})
829-
.AddRoundedRectBottomLeft(rect_, radii)
830-
.TakePath()
831-
.CreatePolyline(entity.GetTransformation().GetMaxBasisLength());
832-
auto bottomRight =
833-
PathBuilder{}
834-
.MoveTo({right, bottom - corner_radius_})
835-
.AddRoundedRectBottomRight(rect_, radii)
836-
.TakePath()
837-
.CreatePolyline(entity.GetTransformation().GetMaxBasisLength());
838-
839-
vtx_builder.Reserve(12 * (topLeft.points.size() - 1) + 18);
840-
841-
AppendRRectCorner(topLeft, Point(left + corner_radius_, top + corner_radius_),
842-
vtx_builder);
843-
844-
AppendRRectCorner(topRight,
845-
Point(right - corner_radius_, top + corner_radius_),
846-
vtx_builder);
847-
848-
AppendRRectCorner(bottomLeft,
849-
Point(left + corner_radius_, bottom - corner_radius_),
850-
vtx_builder);
851-
852-
AppendRRectCorner(bottomRight,
853-
Point(right - corner_radius_, bottom - corner_radius_),
854-
vtx_builder);
855-
vtx_builder.AddVertices({
856-
// Top Component.
857-
Point(left + corner_radius_, top + corner_radius_),
858-
Point(left + corner_radius_, top),
859-
Point(right - corner_radius_, top + corner_radius_),
860-
861-
Point(left + corner_radius_, top),
862-
Point(right - corner_radius_, top + corner_radius_),
863-
Point(right - corner_radius_, top),
864-
865-
// Bottom Component.
866-
Point(left + corner_radius_, bottom - corner_radius_),
867-
Point(left + corner_radius_, bottom),
868-
Point(right - corner_radius_, bottom - corner_radius_),
869-
870-
Point(left + corner_radius_, bottom),
871-
Point(right - corner_radius_, bottom - corner_radius_),
872-
Point(right - corner_radius_, bottom),
873-
874-
// // Center Component.
875-
Point(left, top + corner_radius_),
876-
Point(right, top + corner_radius_),
877-
Point(right, bottom - corner_radius_),
878-
879-
Point(left, top + corner_radius_),
880-
Point(left, bottom - corner_radius_),
881-
Point(right, bottom - corner_radius_),
882-
});
883-
884-
return vtx_builder;
885-
}
886-
887-
GeometryResult RRectGeometry::GetPositionBuffer(const ContentContext& renderer,
888-
const Entity& entity,
889-
RenderPass& pass) {
890-
auto vtx_builder = CreatePositionBuffer(entity);
891-
892-
return GeometryResult{
893-
.type = PrimitiveType::kTriangle,
894-
.vertex_buffer =
895-
vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()),
896-
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
897-
entity.GetTransformation(),
898-
.prevent_overdraw = false,
899-
};
900-
}
901-
902-
GeometryResult RRectGeometry::GetPositionUVBuffer(
903-
Rect texture_coverage,
904-
Matrix effect_transform,
905-
const ContentContext& renderer,
906-
const Entity& entity,
907-
RenderPass& pass) {
908-
auto vtx_builder = CreatePositionBuffer(entity);
909-
910-
VertexBufferBuilder<TextureFillVertexShader::PerVertexData> vertex_builder;
911-
vtx_builder.IterateVertices(
912-
[&vertex_builder, &texture_coverage, &effect_transform](Point position) {
913-
TextureFillVertexShader::PerVertexData data;
914-
data.position = position;
915-
auto coverage_coords =
916-
(position - texture_coverage.origin) / texture_coverage.size;
917-
data.texture_coords = effect_transform * coverage_coords;
918-
vertex_builder.AppendVertex(data);
919-
});
920-
921-
return GeometryResult{
922-
.type = PrimitiveType::kTriangle,
923-
.vertex_buffer =
924-
vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer()),
925-
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
926-
entity.GetTransformation(),
927-
.prevent_overdraw = true,
928-
};
929-
}
930-
931-
GeometryVertexType RRectGeometry::GetVertexType() const {
932-
return GeometryVertexType::kPosition;
933-
}
934-
935-
std::optional<Rect> RRectGeometry::GetCoverage(const Matrix& transform) const {
936-
return rect_.TransformBounds(transform);
937-
}
938-
939806
} // namespace impeller

impeller/entity/geometry.h

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ class Geometry {
4646

4747
static std::unique_ptr<Geometry> MakeFillPath(const Path& path);
4848

49-
static std::unique_ptr<Geometry> MakeRRect(Rect rect, Scalar corner_radius);
50-
5149
static std::unique_ptr<Geometry> MakeStrokePath(
5250
const Path& path,
5351
Scalar stroke_width = 0.0,
@@ -262,37 +260,4 @@ class RectGeometry : public Geometry {
262260
FML_DISALLOW_COPY_AND_ASSIGN(RectGeometry);
263261
};
264262

265-
class RRectGeometry : public Geometry {
266-
public:
267-
explicit RRectGeometry(Rect rect, Scalar corner_radius);
268-
269-
~RRectGeometry();
270-
271-
private:
272-
// |Geometry|
273-
GeometryResult GetPositionBuffer(const ContentContext& renderer,
274-
const Entity& entity,
275-
RenderPass& pass) override;
276-
277-
// |Geometry|
278-
GeometryResult GetPositionUVBuffer(Rect texture_coverage,
279-
Matrix effect_transform,
280-
const ContentContext& renderer,
281-
const Entity& entity,
282-
RenderPass& pass) override;
283-
284-
// |Geometry|
285-
GeometryVertexType GetVertexType() const override;
286-
287-
// |Geometry|
288-
std::optional<Rect> GetCoverage(const Matrix& transform) const override;
289-
290-
VertexBufferBuilder<Point> CreatePositionBuffer(const Entity& entity) const;
291-
292-
Rect rect_;
293-
Scalar corner_radius_;
294-
295-
FML_DISALLOW_COPY_AND_ASSIGN(RRectGeometry);
296-
};
297-
298263
} // namespace impeller

impeller/geometry/path_builder.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,6 @@ class PathBuilder {
104104

105105
PathBuilder& AddRoundedRect(Rect rect, Scalar radius);
106106

107-
PathBuilder& AddRoundedRectTopLeft(Rect rect, RoundingRadii radii);
108-
109-
PathBuilder& AddRoundedRectTopRight(Rect rect, RoundingRadii radii);
110-
111-
PathBuilder& AddRoundedRectBottomRight(Rect rect, RoundingRadii radii);
112-
113-
PathBuilder& AddRoundedRectBottomLeft(Rect rect, RoundingRadii radii);
114-
115107
PathBuilder& AddPath(const Path& path);
116108

117109
private:
@@ -120,6 +112,14 @@ class PathBuilder {
120112
Path prototype_;
121113
Convexity convexity_;
122114

115+
PathBuilder& AddRoundedRectTopLeft(Rect rect, RoundingRadii radii);
116+
117+
PathBuilder& AddRoundedRectTopRight(Rect rect, RoundingRadii radii);
118+
119+
PathBuilder& AddRoundedRectBottomRight(Rect rect, RoundingRadii radii);
120+
121+
PathBuilder& AddRoundedRectBottomLeft(Rect rect, RoundingRadii radii);
122+
123123
Point ReflectedQuadraticControlPoint1() const;
124124

125125
Point ReflectedCubicControlPoint1() const;

0 commit comments

Comments
 (0)