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

Commit cd424ac

Browse files
[CP][Impeller] revert non-zero tessellation optimization. (#48234) (#48459)
Fixes flutter/flutter#138598 Cherry pick request: flutter/flutter#139146
1 parent 7521948 commit cd424ac

File tree

3 files changed

+66
-150
lines changed

3 files changed

+66
-150
lines changed

impeller/tessellator/tessellator.cc

Lines changed: 66 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -78,140 +78,81 @@ Tessellator::Result Tessellator::Tessellate(
7878
constexpr int kVertexSize = 2;
7979
constexpr int kPolygonSize = 3;
8080

81-
// If we have a larger polyline and the fill type is non-zero, we can split
82-
// the tessellation up per contour. Since in general the complexity is at
83-
// least nlog(n), this speeds up the processes substantially.
84-
if (polyline.contours.size() > kMultiContourThreshold &&
85-
fill_type == FillType::kNonZero) {
86-
std::vector<Point> points;
87-
std::vector<float> data;
81+
//----------------------------------------------------------------------------
82+
/// Feed contour information to the tessellator.
83+
///
84+
static_assert(sizeof(Point) == 2 * sizeof(float));
85+
for (size_t contour_i = 0; contour_i < polyline.contours.size();
86+
contour_i++) {
87+
size_t start_point_index, end_point_index;
88+
std::tie(start_point_index, end_point_index) =
89+
polyline.GetContourPointBounds(contour_i);
90+
91+
::tessAddContour(tessellator, // the C tessellator
92+
kVertexSize, //
93+
polyline.points.data() + start_point_index, //
94+
sizeof(Point), //
95+
end_point_index - start_point_index //
96+
);
97+
}
8898

89-
//----------------------------------------------------------------------------
90-
/// Feed contour information to the tessellator.
91-
///
92-
size_t total = 0u;
93-
static_assert(sizeof(Point) == 2 * sizeof(float));
94-
for (size_t contour_i = 0; contour_i < polyline.contours.size();
95-
contour_i++) {
96-
size_t start_point_index, end_point_index;
97-
std::tie(start_point_index, end_point_index) =
98-
polyline.GetContourPointBounds(contour_i);
99-
100-
::tessAddContour(tessellator, // the C tessellator
101-
kVertexSize, //
102-
polyline.points.data() + start_point_index, //
103-
sizeof(Point), //
104-
end_point_index - start_point_index //
105-
);
106-
107-
//----------------------------------------------------------------------------
108-
/// Let's tessellate.
109-
///
110-
auto result = ::tessTesselate(tessellator, // tessellator
111-
ToTessWindingRule(fill_type), // winding
112-
TESS_POLYGONS, // element type
113-
kPolygonSize, // polygon size
114-
kVertexSize, // vertex size
115-
nullptr // normal (null is automatic)
116-
);
117-
118-
if (result != 1) {
119-
return Result::kTessellationError;
120-
}
121-
122-
int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
123-
auto vertices = tessGetVertices(tessellator);
124-
for (int i = 0; i < vertex_item_count; i += 2) {
125-
points.emplace_back(vertices[i], vertices[i + 1]);
126-
}
127-
128-
int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
129-
auto elements = tessGetElements(tessellator);
130-
total += element_item_count;
131-
for (int i = 0; i < element_item_count; i++) {
132-
data.emplace_back(points[elements[i]].x);
133-
data.emplace_back(points[elements[i]].y);
134-
}
135-
points.clear();
99+
//----------------------------------------------------------------------------
100+
/// Let's tessellate.
101+
///
102+
auto result = ::tessTesselate(tessellator, // tessellator
103+
ToTessWindingRule(fill_type), // winding
104+
TESS_POLYGONS, // element type
105+
kPolygonSize, // polygon size
106+
kVertexSize, // vertex size
107+
nullptr // normal (null is automatic)
108+
);
109+
110+
if (result != 1) {
111+
return Result::kTessellationError;
112+
}
113+
114+
int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
115+
116+
// We default to using a 16bit index buffer, but in cases where we generate
117+
// more tessellated data than this can contain we need to fall back to
118+
// dropping the index buffer entirely. Instead code could instead switch to
119+
// a uint32 index buffer, but this is done for simplicity with the other
120+
// fast path above.
121+
if (element_item_count < USHRT_MAX) {
122+
int vertex_item_count = tessGetVertexCount(tessellator);
123+
auto vertices = tessGetVertices(tessellator);
124+
auto elements = tessGetElements(tessellator);
125+
126+
// libtess uses an int index internally due to usage of -1 as a sentinel
127+
// value.
128+
std::vector<uint16_t> indices(element_item_count);
129+
for (int i = 0; i < element_item_count; i++) {
130+
indices[i] = static_cast<uint16_t>(elements[i]);
136131
}
137-
if (!callback(data.data(), total, nullptr, 0u)) {
132+
if (!callback(vertices, vertex_item_count, indices.data(),
133+
element_item_count)) {
138134
return Result::kInputError;
139135
}
140136
} else {
141-
//----------------------------------------------------------------------------
142-
/// Feed contour information to the tessellator.
143-
///
144-
static_assert(sizeof(Point) == 2 * sizeof(float));
145-
for (size_t contour_i = 0; contour_i < polyline.contours.size();
146-
contour_i++) {
147-
size_t start_point_index, end_point_index;
148-
std::tie(start_point_index, end_point_index) =
149-
polyline.GetContourPointBounds(contour_i);
150-
151-
::tessAddContour(tessellator, // the C tessellator
152-
kVertexSize, //
153-
polyline.points.data() + start_point_index, //
154-
sizeof(Point), //
155-
end_point_index - start_point_index //
156-
);
157-
}
158-
159-
//----------------------------------------------------------------------------
160-
/// Let's tessellate.
161-
///
162-
auto result = ::tessTesselate(tessellator, // tessellator
163-
ToTessWindingRule(fill_type), // winding
164-
TESS_POLYGONS, // element type
165-
kPolygonSize, // polygon size
166-
kVertexSize, // vertex size
167-
nullptr // normal (null is automatic)
168-
);
137+
std::vector<Point> points;
138+
std::vector<float> data;
169139

170-
if (result != 1) {
171-
return Result::kTessellationError;
140+
int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
141+
auto vertices = tessGetVertices(tessellator);
142+
points.reserve(vertex_item_count);
143+
for (int i = 0; i < vertex_item_count; i += 2) {
144+
points.emplace_back(vertices[i], vertices[i + 1]);
172145
}
173146

174147
int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
175-
176-
// We default to using a 16bit index buffer, but in cases where we generate
177-
// more tessellated data than this can contain we need to fall back to
178-
// dropping the index buffer entirely. Instead code could instead switch to
179-
// a uint32 index buffer, but this is done for simplicity with the other
180-
// fast path above.
181-
if (element_item_count < USHRT_MAX) {
182-
int vertex_item_count = tessGetVertexCount(tessellator);
183-
auto vertices = tessGetVertices(tessellator);
184-
auto elements = tessGetElements(tessellator);
185-
186-
// libtess uses an int index internally due to usage of -1 as a sentinel
187-
// value.
188-
std::vector<uint16_t> indices(element_item_count);
189-
for (int i = 0; i < element_item_count; i++) {
190-
indices[i] = static_cast<uint16_t>(elements[i]);
191-
}
192-
if (!callback(vertices, vertex_item_count, indices.data(),
193-
element_item_count)) {
194-
return Result::kInputError;
195-
}
196-
} else {
197-
std::vector<Point> points;
198-
std::vector<float> data;
199-
200-
int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
201-
auto vertices = tessGetVertices(tessellator);
202-
for (int i = 0; i < vertex_item_count; i += 2) {
203-
points.emplace_back(vertices[i], vertices[i + 1]);
204-
}
205-
206-
int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
207-
auto elements = tessGetElements(tessellator);
208-
for (int i = 0; i < element_item_count; i++) {
209-
data.emplace_back(points[elements[i]].x);
210-
data.emplace_back(points[elements[i]].y);
211-
}
212-
if (!callback(data.data(), element_item_count, nullptr, 0u)) {
213-
return Result::kInputError;
214-
}
148+
auto elements = tessGetElements(tessellator);
149+
data.reserve(element_item_count);
150+
for (int i = 0; i < element_item_count; i++) {
151+
data.emplace_back(points[elements[i]].x);
152+
data.emplace_back(points[elements[i]].y);
153+
}
154+
if (!callback(data.data(), element_item_count, nullptr, 0u)) {
155+
return Result::kInputError;
215156
}
216157
}
217158

impeller/tessellator/tessellator.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,6 @@ class Tessellator {
4444

4545
~Tessellator();
4646

47-
/// @brief An arbitrary value to determine when a multi-contour non-zero fill
48-
/// path should be split into multiple tessellations.
49-
static constexpr size_t kMultiContourThreshold = 30u;
50-
5147
/// @brief A callback that returns the results of the tessellation.
5248
///
5349
/// The index buffer may not be populated, in which case [indices] will

impeller/tessellator/tessellator_unittests.cc

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,27 +88,6 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
8888
ASSERT_EQ(result, Tessellator::Result::kInputError);
8989
}
9090

91-
// More than 30 contours, non-zero fill mode.
92-
{
93-
Tessellator t;
94-
PathBuilder builder = {};
95-
for (auto i = 0u; i < Tessellator::kMultiContourThreshold + 1; i++) {
96-
builder.AddCircle(Point(i, i), 4);
97-
}
98-
auto polyline = builder.TakePath().CreatePolyline(1.0f);
99-
bool no_indices = false;
100-
Tessellator::Result result = t.Tessellate(
101-
FillType::kNonZero, polyline,
102-
[&no_indices](const float* vertices, size_t vertices_count,
103-
const uint16_t* indices, size_t indices_count) {
104-
no_indices = indices == nullptr;
105-
return true;
106-
});
107-
108-
ASSERT_TRUE(no_indices);
109-
ASSERT_EQ(result, Tessellator::Result::kSuccess);
110-
}
111-
11291
// More than uint16 points, odd fill mode.
11392
{
11493
Tessellator t;

0 commit comments

Comments
 (0)