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

Commit c07f142

Browse files
committed
Add PathCache
1 parent 89e2792 commit c07f142

22 files changed

+746
-259
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,6 +1369,8 @@ ORIGIN: ../../../flutter/impeller/geometry/path.cc + ../../../flutter/LICENSE
13691369
ORIGIN: ../../../flutter/impeller/geometry/path.h + ../../../flutter/LICENSE
13701370
ORIGIN: ../../../flutter/impeller/geometry/path_builder.cc + ../../../flutter/LICENSE
13711371
ORIGIN: ../../../flutter/impeller/geometry/path_builder.h + ../../../flutter/LICENSE
1372+
ORIGIN: ../../../flutter/impeller/geometry/path_cache.cc + ../../../flutter/LICENSE
1373+
ORIGIN: ../../../flutter/impeller/geometry/path_cache.h + ../../../flutter/LICENSE
13721374
ORIGIN: ../../../flutter/impeller/geometry/path_component.cc + ../../../flutter/LICENSE
13731375
ORIGIN: ../../../flutter/impeller/geometry/path_component.h + ../../../flutter/LICENSE
13741376
ORIGIN: ../../../flutter/impeller/geometry/point.cc + ../../../flutter/LICENSE
@@ -4079,6 +4081,8 @@ FILE: ../../../flutter/impeller/geometry/path.cc
40794081
FILE: ../../../flutter/impeller/geometry/path.h
40804082
FILE: ../../../flutter/impeller/geometry/path_builder.cc
40814083
FILE: ../../../flutter/impeller/geometry/path_builder.h
4084+
FILE: ../../../flutter/impeller/geometry/path_cache.cc
4085+
FILE: ../../../flutter/impeller/geometry/path_cache.h
40824086
FILE: ../../../flutter/impeller/geometry/path_component.cc
40834087
FILE: ../../../flutter/impeller/geometry/path_component.h
40844088
FILE: ../../../flutter/impeller/geometry/point.cc

impeller/aiks/aiks_context.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ ContentContext& AiksContext::GetContentContext() const {
3636
return *content_context_;
3737
}
3838

39+
PathCache& AiksContext::GetPathCache() {
40+
return path_cache_;
41+
}
42+
3943
bool AiksContext::Render(const Picture& picture, RenderTarget& render_target) {
4044
if (!IsValid()) {
4145
return false;

impeller/aiks/aiks_context.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "flutter/fml/macros.h"
1010
#include "impeller/entity/contents/content_context.h"
11+
#include "impeller/geometry/path_cache.h"
1112
#include "impeller/renderer/context.h"
1213
#include "impeller/renderer/render_target.h"
1314

@@ -30,10 +31,13 @@ class AiksContext {
3031

3132
bool Render(const Picture& picture, RenderTarget& render_target);
3233

34+
PathCache& GetPathCache();
35+
3336
private:
3437
std::shared_ptr<Context> context_;
3538
std::unique_ptr<ContentContext> content_context_;
3639
bool is_valid_ = false;
40+
PathCache path_cache_;
3741

3842
FML_DISALLOW_COPY_AND_ASSIGN(AiksContext);
3943
};

impeller/aiks/canvas.cc

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,15 @@
1919
#include "impeller/entity/contents/vertices_contents.h"
2020
#include "impeller/entity/geometry/geometry.h"
2121
#include "impeller/geometry/path_builder.h"
22+
#include "impeller/geometry/path_cache.h"
2223

2324
namespace impeller {
2425

26+
namespace {
27+
const uint32_t kTagDlRRect = 'dlrr';
28+
const uint32_t kTagDlCircle = 'dlci';
29+
} // namespace
30+
2531
Canvas::Canvas() {
2632
Initialize(std::nullopt);
2733
}
@@ -238,10 +244,18 @@ void Canvas::DrawRRect(Rect rect, Scalar corner_radius, const Paint& paint) {
238244
if (AttemptDrawBlurredRRect(rect, corner_radius, paint)) {
239245
return;
240246
}
241-
auto path = PathBuilder{}
242-
.SetConvexity(Convexity::kConvex)
243-
.AddRoundedRect(rect, corner_radius)
244-
.TakePath();
247+
248+
struct {
249+
Rect rect;
250+
Scalar corner_radius;
251+
} identifier = {.rect = rect, .corner_radius = corner_radius};
252+
auto path = PathCache::GetPath(PathCacheKey(kTagDlRRect, identifier), [&] {
253+
return PathBuilder{}
254+
.SetConvexity(Convexity::kConvex)
255+
.AddRoundedRect(rect, corner_radius)
256+
.TakePath();
257+
});
258+
245259
if (paint.style == Paint::Style::kFill) {
246260
Entity entity;
247261
entity.SetTransformation(GetCurrentTransformation());
@@ -262,10 +276,18 @@ void Canvas::DrawCircle(Point center, Scalar radius, const Paint& paint) {
262276
paint)) {
263277
return;
264278
}
265-
auto circle_path = PathBuilder{}
266-
.AddCircle(center, radius)
267-
.SetConvexity(Convexity::kConvex)
268-
.TakePath();
279+
struct {
280+
Point center;
281+
Scalar radius;
282+
} identifier = {.center = center, .radius = radius};
283+
auto circle_path =
284+
PathCache::GetPath(PathCacheKey(kTagDlCircle, identifier), [&] {
285+
return PathBuilder{}
286+
.AddCircle(center, radius)
287+
.SetConvexity(Convexity::kConvex)
288+
.TakePath();
289+
});
290+
269291
DrawPath(circle_path, paint);
270292
}
271293

impeller/display_list/dl_dispatcher.cc

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -889,10 +889,7 @@ void DlDispatcher::drawRRect(const SkRRect& rrect) {
889889

890890
// |flutter::DlOpReceiver|
891891
void DlDispatcher::drawDRRect(const SkRRect& outer, const SkRRect& inner) {
892-
PathBuilder builder;
893-
builder.AddPath(skia_conversions::ToPath(outer));
894-
builder.AddPath(skia_conversions::ToPath(inner));
895-
canvas_.DrawPath(builder.TakePath(FillType::kOdd), paint_);
892+
canvas_.DrawPath(skia_conversions::ToPath(outer, inner), paint_);
896893
}
897894

898895
// |flutter::DlOpReceiver|

impeller/display_list/skia_conversions.cc

Lines changed: 107 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@
44

55
#include "impeller/display_list/skia_conversions.h"
66
#include "display_list/dl_color.h"
7+
#include "impeller/geometry/path_cache.h"
78
#include "third_party/skia/modules/skparagraph/include/Paragraph.h"
89

910
namespace impeller {
1011
namespace skia_conversions {
1112

13+
namespace {
14+
const uint32_t kTagSkiaPath = 'skpa';
15+
const uint32_t kTagSkiaRRect = 'skrr';
16+
const uint32_t kTagSkiaDRRect = 'skdr';
17+
} // namespace
18+
1219
Rect ToRect(const SkRect& rect) {
1320
return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
1421
}
@@ -47,63 +54,6 @@ PathBuilder::RoundingRadii ToRoundingRadii(const SkRRect& rrect) {
4754
}
4855

4956
Path ToPath(const SkPath& path) {
50-
auto iterator = SkPath::Iter(path, false);
51-
52-
struct PathData {
53-
union {
54-
SkPoint points[4];
55-
};
56-
};
57-
58-
PathBuilder builder;
59-
PathData data;
60-
auto verb = SkPath::Verb::kDone_Verb;
61-
do {
62-
verb = iterator.next(data.points);
63-
switch (verb) {
64-
case SkPath::kMove_Verb:
65-
builder.MoveTo(ToPoint(data.points[0]));
66-
break;
67-
case SkPath::kLine_Verb:
68-
builder.LineTo(ToPoint(data.points[1]));
69-
break;
70-
case SkPath::kQuad_Verb:
71-
builder.QuadraticCurveTo(ToPoint(data.points[1]),
72-
ToPoint(data.points[2]));
73-
break;
74-
case SkPath::kConic_Verb: {
75-
constexpr auto kPow2 = 1; // Only works for sweeps up to 90 degrees.
76-
constexpr auto kQuadCount = 1 + (2 * (1 << kPow2));
77-
SkPoint points[kQuadCount];
78-
const auto curve_count =
79-
SkPath::ConvertConicToQuads(data.points[0], //
80-
data.points[1], //
81-
data.points[2], //
82-
iterator.conicWeight(), //
83-
points, //
84-
kPow2 //
85-
);
86-
87-
for (int curve_index = 0, point_index = 0; //
88-
curve_index < curve_count; //
89-
curve_index++, point_index += 2 //
90-
) {
91-
builder.QuadraticCurveTo(ToPoint(points[point_index + 1]),
92-
ToPoint(points[point_index + 2]));
93-
}
94-
} break;
95-
case SkPath::kCubic_Verb:
96-
builder.CubicCurveTo(ToPoint(data.points[1]), ToPoint(data.points[2]),
97-
ToPoint(data.points[3]));
98-
break;
99-
case SkPath::kClose_Verb:
100-
builder.Close();
101-
break;
102-
case SkPath::kDone_Verb:
103-
break;
104-
}
105-
} while (verb != SkPath::Verb::kDone_Verb);
106-
10757
FillType fill_type;
10858
switch (path.getFillType()) {
10959
case SkPathFillType::kWinding:
@@ -119,16 +69,109 @@ Path ToPath(const SkPath& path) {
11969
fill_type = FillType::kNonZero;
12070
break;
12171
}
122-
builder.SetConvexity(path.isConvex() ? Convexity::kConvex
123-
: Convexity::kUnknown);
124-
return builder.TakePath(fill_type);
72+
auto create_path = [&] {
73+
auto iterator = SkPath::Iter(path, false);
74+
75+
struct PathData {
76+
union {
77+
SkPoint points[4];
78+
};
79+
};
80+
81+
PathBuilder builder;
82+
PathData data;
83+
auto verb = SkPath::Verb::kDone_Verb;
84+
do {
85+
verb = iterator.next(data.points);
86+
switch (verb) {
87+
case SkPath::kMove_Verb:
88+
builder.MoveTo(ToPoint(data.points[0]));
89+
break;
90+
case SkPath::kLine_Verb:
91+
builder.LineTo(ToPoint(data.points[1]));
92+
break;
93+
case SkPath::kQuad_Verb:
94+
builder.QuadraticCurveTo(ToPoint(data.points[1]),
95+
ToPoint(data.points[2]));
96+
break;
97+
case SkPath::kConic_Verb: {
98+
constexpr auto kPow2 = 1; // Only works for sweeps up to 90 degrees.
99+
constexpr auto kQuadCount = 1 + (2 * (1 << kPow2));
100+
SkPoint points[kQuadCount];
101+
const auto curve_count =
102+
SkPath::ConvertConicToQuads(data.points[0], //
103+
data.points[1], //
104+
data.points[2], //
105+
iterator.conicWeight(), //
106+
points, //
107+
kPow2 //
108+
);
109+
110+
for (int curve_index = 0, point_index = 0; //
111+
curve_index < curve_count; //
112+
curve_index++, point_index += 2 //
113+
) {
114+
builder.QuadraticCurveTo(ToPoint(points[point_index + 1]),
115+
ToPoint(points[point_index + 2]));
116+
}
117+
} break;
118+
case SkPath::kCubic_Verb:
119+
builder.CubicCurveTo(ToPoint(data.points[1]), ToPoint(data.points[2]),
120+
ToPoint(data.points[3]));
121+
break;
122+
case SkPath::kClose_Verb:
123+
builder.Close();
124+
break;
125+
case SkPath::kDone_Verb:
126+
break;
127+
}
128+
} while (verb != SkPath::Verb::kDone_Verb);
129+
130+
builder.SetConvexity(path.isConvex() ? Convexity::kConvex
131+
: Convexity::kUnknown);
132+
return builder.TakePath(fill_type);
133+
};
134+
struct {
135+
uint32_t generation_id;
136+
FillType fill_type;
137+
} identifier = {
138+
.generation_id = path.getGenerationID(),
139+
.fill_type = fill_type,
140+
};
141+
return PathCache::GetPath(PathCacheKey(kTagSkiaPath, identifier),
142+
create_path);
125143
}
126144

127145
Path ToPath(const SkRRect& rrect) {
128-
return PathBuilder{}
129-
.AddRoundedRect(ToRect(rrect.getBounds()), ToRoundingRadii(rrect))
130-
.SetConvexity(Convexity::kConvex)
131-
.TakePath();
146+
// SkRRect may have random padding bytes, so first zero initialize the struct
147+
// and then copy the RRect into it.
148+
struct {
149+
SkRRect rrect;
150+
} identifier = {};
151+
identifier.rrect = rrect;
152+
return PathCache::GetPath(PathCacheKey(kTagSkiaRRect, identifier), [&] {
153+
return PathBuilder{}
154+
.AddRoundedRect(ToRect(rrect.getBounds()), ToRoundingRadii(rrect))
155+
.SetConvexity(Convexity::kConvex)
156+
.TakePath();
157+
});
158+
}
159+
160+
Path ToPath(const SkRRect& outer, const SkRRect& inner) {
161+
// SkRRect may have random padding bytes, so first zero initialize the struct
162+
// and then copy the RRect into it.
163+
struct {
164+
SkRRect outer;
165+
SkRRect inner;
166+
} identifier = {};
167+
identifier.outer = outer;
168+
identifier.inner = inner;
169+
return PathCache::GetPath(PathCacheKey(kTagSkiaDRRect, identifier), [&] {
170+
PathBuilder builder;
171+
builder.AddPath(ToPath(outer));
172+
builder.AddPath(ToPath(inner));
173+
return builder.TakePath(FillType::kOdd);
174+
});
132175
}
133176

134177
Point ToPoint(const SkPoint& point) {

impeller/display_list/skia_conversions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ Path ToPath(const SkPath& path);
4242

4343
Path ToPath(const SkRRect& rrect);
4444

45+
Path ToPath(const SkRRect& outer, const SkRRect& inner);
46+
4547
Path PathDataFromTextBlob(const sk_sp<SkTextBlob>& blob);
4648

4749
std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type);

impeller/entity/geometry/geometry.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,27 @@ namespace impeller {
1717

1818
/// Given a convex polyline, create a triangle fan structure.
1919
std::pair<std::vector<Point>, std::vector<uint16_t>> TessellateConvex(
20-
Path::Polyline polyline) {
20+
const Path::Polyline& polyline) {
2121
std::vector<Point> output;
2222
std::vector<uint16_t> indices;
2323

24-
for (auto j = 0u; j < polyline.contours.size(); j++) {
24+
const auto& points = polyline.points();
25+
26+
for (auto j = 0u; j < polyline.contours().size(); j++) {
2527
auto [start, end] = polyline.GetContourPointBounds(j);
26-
auto center = polyline.points[start];
28+
auto center = points[start];
2729

2830
// Some polygons will not self close and an additional triangle
2931
// must be inserted, others will self close and we need to avoid
3032
// inserting an extra triangle.
31-
if (polyline.points[end - 1] == polyline.points[start]) {
33+
if (points[end - 1] == points[start]) {
3234
end--;
3335
}
3436
output.emplace_back(center);
35-
output.emplace_back(polyline.points[start + 1]);
37+
output.emplace_back(points[start + 1]);
3638

3739
for (auto i = start + 2; i < end; i++) {
38-
const auto& point_b = polyline.points[i];
40+
const auto& point_b = points[i];
3941
output.emplace_back(point_b);
4042

4143
indices.emplace_back(0);

impeller/entity/geometry/geometry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ GeometryResult ComputeUVGeometryForRect(Rect source_rect,
4949
/// @brief Given a polyline created from a convex filled path, perform a
5050
/// tessellation.
5151
std::pair<std::vector<Point>, std::vector<uint16_t>> TessellateConvex(
52-
Path::Polyline polyline);
52+
const Path::Polyline& polyline);
5353

5454
class Geometry {
5555
public:

0 commit comments

Comments
 (0)