| Flutter Impeller |

tessellator_libtess.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/tessellator/tessellator_libtess.h"
6
7 #include "impeller/tessellator/path_tessellator.h"
8 #include "third_party/libtess2/Include/tesselator.h"
9
10 namespace impeller {
11
12 static void* HeapAlloc(void* userData, unsigned int size) {
13 return malloc(size);
14 }
15
16 static void* HeapRealloc(void* userData, void* ptr, unsigned int size) {
17 return realloc(ptr, size);
18 }
19
20 static void HeapFree(void* userData, void* ptr) {
21 free(ptr);
22 }
23
24 // Note: these units are "number of entities" for bucket size and not in KB.
25 static const TESSalloc kAlloc = {
26 HeapAlloc, HeapRealloc, HeapFree, 0, /* =userData */
27 16, /* =meshEdgeBucketSize */
28 16, /* =meshVertexBucketSize */
29 16, /* =meshFaceBucketSize */
30 16, /* =dictNodeBucketSize */
31 16, /* =regionBucketSize */
32 0 /* =extraVertices */
33 };
34
35 TessellatorLibtess::TessellatorLibtess()
36 : c_tessellator_(nullptr, &DestroyTessellator) {
37 TESSalloc alloc = kAlloc;
38 {
39 // libTess2 copies the TESSalloc despite the non-const argument.
40 CTessellator tessellator(::tessNewTess(&alloc), &DestroyTessellator);
41 c_tessellator_ = std::move(tessellator);
42 }
43 }
44
45 TessellatorLibtess::~TessellatorLibtess() = default;
46
47 static int ToTessWindingRule(FillType fill_type) {
48 switch (fill_type) {
49 case FillType::kOdd:
50 return TESS_WINDING_ODD;
51 case FillType::kNonZero:
52 return TESS_WINDING_NONZERO;
53 }
54 return TESS_WINDING_ODD;
55 }
56
57 namespace {
58
59 class Polyline : public impeller::PathTessellator::VertexWriter {
60 public:
61 struct Contour {
62 const size_t start;
63 const size_t end;
64
65 size_t size() const { return end - start; }
66 };
67
68 void Write(Point point) override { points.emplace_back(point); }
69
70 void EndContour() override {
71 size_t contour_end = points.size();
72 contours.push_back({contour_start_, contour_end});
73 contour_start_ = contour_end;
74 }
75
76 std::vector<Point> points;
77 std::vector<Contour> contours;
78
79 private:
80 size_t contour_start_ = 0u;
81 };
82
83 } // namespace
84
85 TessellatorLibtess::Result TessellatorLibtess::Tessellate(
86 const PathSource& source,
87 Scalar tolerance,
88 const BuilderCallback& callback) {
89 if (!callback) {
90 return TessellatorLibtess::Result::kInputError;
91 }
92
93 Polyline polyline;
94 PathTessellator::PathToFilledVertices(source, polyline, tolerance);
95
96 auto fill_type = source.GetFillType();
97
98 if (polyline.points.empty()) {
99 return TessellatorLibtess::Result::kInputError;
100 }
101
102 auto tessellator = c_tessellator_.get();
103 if (!tessellator) {
104 return TessellatorLibtess::Result::kTessellationError;
105 }
106
107 constexpr int kVertexSize = 2;
108 constexpr int kPolygonSize = 3;
109
110 //----------------------------------------------------------------------------
111 /// Feed contour information to the tessellator.
112 ///
113 static_assert(sizeof(Point) == 2 * sizeof(float));
114 for (auto contour : polyline.contours) {
115 ::tessAddContour(tessellator, // the C tessellator
116 kVertexSize, //
117 polyline.points.data() + contour.start, //
118 sizeof(Point), //
119 contour.size() //
120 );
121 }
122
123 //----------------------------------------------------------------------------
124 /// Let's tessellate.
125 ///
126 auto result = ::tessTesselate(tessellator, // tessellator
127 ToTessWindingRule(fill_type), // winding
128 TESS_POLYGONS, // element type
129 kPolygonSize, // polygon size
130 kVertexSize, // vertex size
131 nullptr // normal (null is automatic)
132 );
133
134 if (result != 1) {
135 return TessellatorLibtess::Result::kTessellationError;
136 }
137
138 int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
139
140 // We default to using a 16bit index buffer, but in cases where we generate
141 // more tessellated data than this can contain we need to fall back to
142 // dropping the index buffer entirely. Instead code could instead switch to
143 // a uint32 index buffer, but this is done for simplicity with the other
144 // fast path above.
145 if (element_item_count < USHRT_MAX) {
146 int vertex_item_count = tessGetVertexCount(tessellator);
147 auto vertices = tessGetVertices(tessellator);
148 auto elements = tessGetElements(tessellator);
149
150 // libtess uses an int index internally due to usage of -1 as a sentinel
151 // value.
152 std::vector<uint16_t> indices(element_item_count);
153 for (int i = 0; i < element_item_count; i++) {
154 indices[i] = static_cast<uint16_t>(elements[i]);
155 }
156 if (!callback(vertices, vertex_item_count, indices.data(),
157 element_item_count)) {
158 return TessellatorLibtess::Result::kInputError;
159 }
160 } else {
161 std::vector<Point> points;
162 std::vector<float> data;
163
164 int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
165 auto vertices = tessGetVertices(tessellator);
166 points.reserve(vertex_item_count);
167 for (int i = 0; i < vertex_item_count; i += 2) {
168 points.emplace_back(vertices[i], vertices[i + 1]);
169 }
170
171 int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
172 auto elements = tessGetElements(tessellator);
173 data.reserve(element_item_count);
174 for (int i = 0; i < element_item_count; i++) {
175 data.emplace_back(points[elements[i]].x);
176 data.emplace_back(points[elements[i]].y);
177 }
178 if (!callback(data.data(), element_item_count, nullptr, 0u)) {
179 return TessellatorLibtess::Result::kInputError;
180 }
181 }
182
183 return TessellatorLibtess::Result::kSuccess;
184 }
185
186 void DestroyTessellator(TESStesselator* tessellator) {
187 if (tessellator != nullptr) {
188 ::tessDeleteTess(tessellator);
189 }
190 }
191
192 } // namespace impeller
impeller::PathSource
Definition: path_source.h:55
impeller::PathSource::GetFillType
virtual FillType GetFillType() const =0
impeller::PathTessellator::VertexWriter
An interface for generating a multi contour polyline as a triangle strip.
Definition: path_tessellator.h:21
impeller::PathTessellator::PathToFilledVertices
static void PathToFilledVertices(const PathSource &source, VertexWriter &writer, Scalar scale)
Definition: path_tessellator.cc:308
impeller::TessellatorLibtess::BuilderCallback
std::function< bool(const float *vertices, size_t vertices_count, const uint16_t *indices, size_t indices_count)> BuilderCallback
A callback that returns the results of the tessellation.
Definition: tessellator_libtess.h:48
impeller::TessellatorLibtess::Result
Result
Definition: tessellator_libtess.h:35
impeller::TessellatorLibtess::Result::kSuccess
@ kSuccess
impeller::TessellatorLibtess::Result::kInputError
@ kInputError
impeller::TessellatorLibtess::Result::kTessellationError
@ kTessellationError
impeller::TessellatorLibtess::Tessellate
TessellatorLibtess::Result Tessellate(const PathSource &source, Scalar tolerance, const BuilderCallback &callback)
Generates filled triangles from the path. A callback is invoked once for the entire tessellation.
Definition: tessellator_libtess.cc:85
impeller::TessellatorLibtess::TessellatorLibtess
TessellatorLibtess()
Definition: tessellator_libtess.cc:35
impeller::TessellatorLibtess::~TessellatorLibtess
~TessellatorLibtess()
x
int32_t x
Definition: dl_golden_unittests.cc:458
impeller
Definition: allocation.cc:12
impeller::HeapRealloc
static void * HeapRealloc(void *userData, void *ptr, unsigned int size)
Definition: tessellator_libtess.cc:16
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::DestroyTessellator
void DestroyTessellator(TESStesselator *tessellator)
Definition: tessellator_libtess.cc:186
impeller::HeapAlloc
static void * HeapAlloc(void *userData, unsigned int size)
Definition: tessellator_libtess.cc:12
impeller::FillType
FillType
Definition: path_source.h:13
impeller::FillType::kOdd
@ kOdd
impeller::FillType::kNonZero
@ kNonZero
impeller::Point
TPoint< Scalar > Point
Definition: point.h:425
impeller::CTessellator
std::unique_ptr< TESStesselator, decltype(&DestroyTessellator)> CTessellator
Definition: tessellator_libtess.h:20
impeller::ToTessWindingRule
static int ToTessWindingRule(FillType fill_type)
Definition: tessellator_libtess.cc:47
impeller::HeapFree
static void HeapFree(void *userData, void *ptr)
Definition: tessellator_libtess.cc:20
impeller::kAlloc
static const TESSalloc kAlloc
Definition: tessellator_libtess.cc:25
path_tessellator.h
impeller::TPoint< Scalar >
start
const size_t start
Definition: tessellator_libtess.cc:62
end
const size_t end
Definition: tessellator_libtess.cc:63
points
std::vector< Point > points
Definition: tessellator_libtess.cc:76
contours
std::vector< Contour > contours
Definition: tessellator_libtess.cc:77
tessellator_libtess.h
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:69