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

Commit 367f6a2

Browse files
authored
[Impeller] Remove libtess2 from libflutter. (#52357)
- Move libtess-powered functionality into an `impeller::Tessellator` subclass called `impeller::TessellatorLibtess`. - `impeller::Tessellator` now only contains `Tessellator::TessellateConvex` and utilities for fast circles/ellipses. - Use `impeller::TessellatorLibtess` in geometry_benchmarks, renderer_unittests, and the C tessellator API implementation. - Continue using `impeller::Tessellator` in Impeller, but without the libtess2 dependency.
1 parent b5728c2 commit 367f6a2

13 files changed

+288
-212
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40789,6 +40789,8 @@ ORIGIN: ../../../flutter/impeller/tessellator/c/tessellator.h + ../../../flutter
4078940789
ORIGIN: ../../../flutter/impeller/tessellator/dart/lib/tessellator.dart + ../../../flutter/LICENSE
4079040790
ORIGIN: ../../../flutter/impeller/tessellator/tessellator.cc + ../../../flutter/LICENSE
4079140791
ORIGIN: ../../../flutter/impeller/tessellator/tessellator.h + ../../../flutter/LICENSE
40792+
ORIGIN: ../../../flutter/impeller/tessellator/tessellator_libtess.cc + ../../../flutter/LICENSE
40793+
ORIGIN: ../../../flutter/impeller/tessellator/tessellator_libtess.h + ../../../flutter/LICENSE
4079240794
ORIGIN: ../../../flutter/impeller/toolkit/android/choreographer.cc + ../../../flutter/LICENSE
4079340795
ORIGIN: ../../../flutter/impeller/toolkit/android/choreographer.h + ../../../flutter/LICENSE
4079440796
ORIGIN: ../../../flutter/impeller/toolkit/android/hardware_buffer.cc + ../../../flutter/LICENSE
@@ -43666,6 +43668,8 @@ FILE: ../../../flutter/impeller/tessellator/c/tessellator.h
4366643668
FILE: ../../../flutter/impeller/tessellator/dart/lib/tessellator.dart
4366743669
FILE: ../../../flutter/impeller/tessellator/tessellator.cc
4366843670
FILE: ../../../flutter/impeller/tessellator/tessellator.h
43671+
FILE: ../../../flutter/impeller/tessellator/tessellator_libtess.cc
43672+
FILE: ../../../flutter/impeller/tessellator/tessellator_libtess.h
4366943673
FILE: ../../../flutter/impeller/toolkit/android/choreographer.cc
4367043674
FILE: ../../../flutter/impeller/toolkit/android/choreographer.h
4367143675
FILE: ../../../flutter/impeller/toolkit/android/hardware_buffer.cc

impeller/geometry/BUILD.gn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ executable("geometry_benchmarks") {
8787
deps = [
8888
":geometry",
8989
"../entity",
90-
"../tessellator",
90+
"../tessellator:tessellator_libtess",
9191
"//flutter/benchmarking",
9292
]
9393
}

impeller/geometry/geometry_benchmarks.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "impeller/geometry/path.h"
1111
#include "impeller/geometry/path_builder.h"
1212
#include "impeller/tessellator/tessellator.h"
13+
#include "impeller/tessellator/tessellator_libtess.h"
1314

1415
namespace impeller {
1516

@@ -37,7 +38,7 @@ Path CreateQuadratic(bool closed);
3738
Path CreateRRect();
3839
} // namespace
3940

40-
static Tessellator tess;
41+
static TessellatorLibtess tess;
4142

4243
template <class... Args>
4344
static void BM_Polyline(benchmark::State& state, Args&&... args) {

impeller/renderer/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ impeller_component("renderer_unittests") {
135135
":renderer",
136136
"../fixtures",
137137
"../playground:playground_test",
138+
"../tessellator:tessellator_libtess",
138139
"//flutter/testing:testing_lib",
139140
]
140141

impeller/renderer/renderer_unittests.cc

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,18 @@
2424
#include "impeller/fixtures/sepia.frag.h"
2525
#include "impeller/fixtures/sepia.vert.h"
2626
#include "impeller/fixtures/swizzle.frag.h"
27-
#include "impeller/fixtures/test_texture.frag.h"
28-
#include "impeller/fixtures/test_texture.vert.h"
2927
#include "impeller/fixtures/texture.frag.h"
3028
#include "impeller/fixtures/texture.vert.h"
3129
#include "impeller/geometry/path_builder.h"
3230
#include "impeller/playground/playground_test.h"
33-
#include "impeller/renderer/command.h"
3431
#include "impeller/renderer/command_buffer.h"
3532
#include "impeller/renderer/pipeline_builder.h"
3633
#include "impeller/renderer/pipeline_library.h"
3734
#include "impeller/renderer/render_pass.h"
3835
#include "impeller/renderer/render_target.h"
3936
#include "impeller/renderer/renderer.h"
4037
#include "impeller/renderer/vertex_buffer_builder.h"
41-
#include "impeller/tessellator/tessellator.h"
38+
#include "impeller/tessellator/tessellator_libtess.h"
4239
#include "third_party/imgui/imgui.h"
4340

4441
// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
@@ -394,7 +391,7 @@ TEST_P(RendererTest, CanRenderInstanced) {
394391
VertexBufferBuilder<VS::PerVertexData> builder;
395392

396393
ASSERT_EQ(Tessellator::Result::kSuccess,
397-
Tessellator{}.Tessellate(
394+
TessellatorLibtess{}.Tessellate(
398395
PathBuilder{}
399396
.AddRect(Rect::MakeXYWH(10, 10, 100, 100))
400397
.TakePath(FillType::kOdd),

impeller/tessellator/BUILD.gn

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ impeller_component("tessellator") {
1515
deps = [
1616
"../core",
1717
"//flutter/fml",
18+
]
19+
}
20+
21+
impeller_component("tessellator_libtess") {
22+
sources = [
23+
"tessellator_libtess.cc",
24+
"tessellator_libtess.h",
25+
]
26+
27+
public_deps = [ "../geometry" ]
28+
29+
deps = [
30+
":tessellator",
31+
"../core",
32+
"//flutter/fml",
1833
"//third_party/libtess2",
1934
]
2035
}
@@ -30,11 +45,11 @@ impeller_component("tessellator_shared") {
3045
sources = [
3146
"c/tessellator.cc",
3247
"c/tessellator.h",
33-
"tessellator.cc",
34-
"tessellator.h",
3548
]
3649

3750
deps = [
51+
":tessellator",
52+
":tessellator_libtess",
3853
"../core",
3954
"../geometry",
4055
"//flutter/fml",
@@ -50,7 +65,7 @@ impeller_component("tessellator_unittests") {
5065
testonly = true
5166
sources = [ "tessellator_unittests.cc" ]
5267
deps = [
53-
":tessellator",
68+
":tessellator_libtess",
5469
"../geometry:geometry_asserts",
5570
"//flutter/testing",
5671
]

impeller/tessellator/c/tessellator.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#include <vector>
88

9+
#include "impeller/tessellator/tessellator_libtess.h"
10+
911
namespace impeller {
1012
PathBuilder* CreatePathBuilder() {
1113
return new PathBuilder();
@@ -42,7 +44,7 @@ struct Vertices* Tessellate(PathBuilder* builder,
4244
Scalar tolerance) {
4345
auto path = builder->CopyPath(static_cast<FillType>(fill_type));
4446
std::vector<float> points;
45-
if (Tessellator{}.Tessellate(
47+
if (TessellatorLibtess{}.Tessellate(
4648
path, tolerance,
4749
[&points](const float* vertices, size_t vertices_count,
4850
const uint16_t* indices, size_t indices_count) {

impeller/tessellator/c/tessellator.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include <cstdint>
99

1010
#include "impeller/geometry/path_builder.h"
11-
#include "impeller/tessellator/tessellator.h"
1211

1312
#ifdef _WIN32
1413
#define IMPELLER_API __declspec(dllexport)

impeller/tessellator/tessellator.cc

Lines changed: 1 addition & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -4,166 +4,15 @@
44

55
#include "impeller/tessellator/tessellator.h"
66

7-
#include "third_party/libtess2/Include/tesselator.h"
8-
97
namespace impeller {
108

11-
static void* HeapAlloc(void* userData, unsigned int size) {
12-
return malloc(size);
13-
}
14-
15-
static void* HeapRealloc(void* userData, void* ptr, unsigned int size) {
16-
return realloc(ptr, size);
17-
}
18-
19-
static void HeapFree(void* userData, void* ptr) {
20-
free(ptr);
21-
}
22-
23-
// Note: these units are "number of entities" for bucket size and not in KB.
24-
static const TESSalloc kAlloc = {
25-
HeapAlloc, HeapRealloc, HeapFree, 0, /* =userData */
26-
16, /* =meshEdgeBucketSize */
27-
16, /* =meshVertexBucketSize */
28-
16, /* =meshFaceBucketSize */
29-
16, /* =dictNodeBucketSize */
30-
16, /* =regionBucketSize */
31-
0 /* =extraVertices */
32-
};
33-
349
Tessellator::Tessellator()
35-
: point_buffer_(std::make_unique<std::vector<Point>>()),
36-
c_tessellator_(nullptr, &DestroyTessellator) {
10+
: point_buffer_(std::make_unique<std::vector<Point>>()) {
3711
point_buffer_->reserve(2048);
38-
TESSalloc alloc = kAlloc;
39-
{
40-
// libTess2 copies the TESSalloc despite the non-const argument.
41-
CTessellator tessellator(::tessNewTess(&alloc), &DestroyTessellator);
42-
c_tessellator_ = std::move(tessellator);
43-
}
4412
}
4513

4614
Tessellator::~Tessellator() = default;
4715

48-
static int ToTessWindingRule(FillType fill_type) {
49-
switch (fill_type) {
50-
case FillType::kOdd:
51-
return TESS_WINDING_ODD;
52-
case FillType::kNonZero:
53-
return TESS_WINDING_NONZERO;
54-
}
55-
return TESS_WINDING_ODD;
56-
}
57-
58-
Tessellator::Result Tessellator::Tessellate(const Path& path,
59-
Scalar tolerance,
60-
const BuilderCallback& callback) {
61-
if (!callback) {
62-
return Result::kInputError;
63-
}
64-
65-
point_buffer_->clear();
66-
auto polyline =
67-
path.CreatePolyline(tolerance, std::move(point_buffer_),
68-
[this](Path::Polyline::PointBufferPtr point_buffer) {
69-
point_buffer_ = std::move(point_buffer);
70-
});
71-
72-
auto fill_type = path.GetFillType();
73-
74-
if (polyline.points->empty()) {
75-
return Result::kInputError;
76-
}
77-
78-
auto tessellator = c_tessellator_.get();
79-
if (!tessellator) {
80-
return Result::kTessellationError;
81-
}
82-
83-
constexpr int kVertexSize = 2;
84-
constexpr int kPolygonSize = 3;
85-
86-
//----------------------------------------------------------------------------
87-
/// Feed contour information to the tessellator.
88-
///
89-
static_assert(sizeof(Point) == 2 * sizeof(float));
90-
for (size_t contour_i = 0; contour_i < polyline.contours.size();
91-
contour_i++) {
92-
size_t start_point_index, end_point_index;
93-
std::tie(start_point_index, end_point_index) =
94-
polyline.GetContourPointBounds(contour_i);
95-
96-
::tessAddContour(tessellator, // the C tessellator
97-
kVertexSize, //
98-
polyline.points->data() + start_point_index, //
99-
sizeof(Point), //
100-
end_point_index - start_point_index //
101-
);
102-
}
103-
104-
//----------------------------------------------------------------------------
105-
/// Let's tessellate.
106-
///
107-
auto result = ::tessTesselate(tessellator, // tessellator
108-
ToTessWindingRule(fill_type), // winding
109-
TESS_POLYGONS, // element type
110-
kPolygonSize, // polygon size
111-
kVertexSize, // vertex size
112-
nullptr // normal (null is automatic)
113-
);
114-
115-
if (result != 1) {
116-
return Result::kTessellationError;
117-
}
118-
119-
int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
120-
121-
// We default to using a 16bit index buffer, but in cases where we generate
122-
// more tessellated data than this can contain we need to fall back to
123-
// dropping the index buffer entirely. Instead code could instead switch to
124-
// a uint32 index buffer, but this is done for simplicity with the other
125-
// fast path above.
126-
if (element_item_count < USHRT_MAX) {
127-
int vertex_item_count = tessGetVertexCount(tessellator);
128-
auto vertices = tessGetVertices(tessellator);
129-
auto elements = tessGetElements(tessellator);
130-
131-
// libtess uses an int index internally due to usage of -1 as a sentinel
132-
// value.
133-
std::vector<uint16_t> indices(element_item_count);
134-
for (int i = 0; i < element_item_count; i++) {
135-
indices[i] = static_cast<uint16_t>(elements[i]);
136-
}
137-
if (!callback(vertices, vertex_item_count, indices.data(),
138-
element_item_count)) {
139-
return Result::kInputError;
140-
}
141-
} else {
142-
std::vector<Point> points;
143-
std::vector<float> data;
144-
145-
int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
146-
auto vertices = tessGetVertices(tessellator);
147-
points.reserve(vertex_item_count);
148-
for (int i = 0; i < vertex_item_count; i += 2) {
149-
points.emplace_back(vertices[i], vertices[i + 1]);
150-
}
151-
152-
int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
153-
auto elements = tessGetElements(tessellator);
154-
data.reserve(element_item_count);
155-
for (int i = 0; i < element_item_count; i++) {
156-
data.emplace_back(points[elements[i]].x);
157-
data.emplace_back(points[elements[i]].y);
158-
}
159-
if (!callback(data.data(), element_item_count, nullptr, 0u)) {
160-
return Result::kInputError;
161-
}
162-
}
163-
164-
return Result::kSuccess;
165-
}
166-
16716
Path::Polyline Tessellator::CreateTempPolyline(const Path& path,
16817
Scalar tolerance) {
16918
FML_DCHECK(point_buffer_);
@@ -239,12 +88,6 @@ std::vector<Point> Tessellator::TessellateConvex(const Path& path,
23988
return output;
24089
}
24190

242-
void DestroyTessellator(TESStesselator* tessellator) {
243-
if (tessellator != nullptr) {
244-
::tessDeleteTess(tessellator);
245-
}
246-
}
247-
24891
static constexpr int kPrecomputedDivisionCount = 1024;
24992
static int kPrecomputedDivisions[kPrecomputedDivisionCount] = {
25093
// clang-format off

0 commit comments

Comments
 (0)