Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
tessellator.h
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#ifndef FLUTTER_IMPELLER_TESSELLATOR_TESSELLATOR_H_
6#define FLUTTER_IMPELLER_TESSELLATOR_TESSELLATOR_H_
7
8#include <functional>
9#include <memory>
10#include <vector>
11
20
21namespace impeller {
22
23/// The size of the point arena buffer stored on the tessellator.
24[[maybe_unused]]
25static constexpr size_t kPointArenaSize = 4096u;
26
27//------------------------------------------------------------------------------
28/// @brief A utility that generates triangles of the specified fill type
29/// given a polyline. This happens on the CPU.
30///
31/// Also contains functionality for optimized generation of circles
32/// and ellipses.
33///
34/// This object is not thread safe, and its methods must not be
35/// called from multiple threads.
36///
38 public:
39 /// Essentially just a vector of Trig objects, but supports storing a
40 /// reference to either a cached vector or a locally generated vector.
41 /// The constructor will fill the vector with quarter circular samples
42 /// for the indicated number of equal divisions if the vector is new.
43 ///
44 /// A given instance of Trigs will always contain at least 2 entries
45 /// which is the minimum number of samples to traverse a quarter circle
46 /// in a single step. The first sample will always be (0, 1) and the last
47 /// sample will always be (1, 0).
48 class Trigs {
49 public:
50 explicit Trigs(Scalar pixel_radius);
51
52 // Utility forwards of the indicated vector methods.
53 size_t inline size() const { return trigs_.size(); }
54 std::vector<Trig>::iterator inline begin() const { return trigs_.begin(); }
55 std::vector<Trig>::iterator inline end() const { return trigs_.end(); }
56 const inline Trig& operator[](size_t index) const { return trigs_[index]; }
57
58 size_t inline GetSteps() const { return trigs_.size() - 1u; }
59
60 private:
61 friend class Tessellator;
62
63 explicit Trigs(std::vector<Trig>& trigs, size_t divisions) : trigs_(trigs) {
64 FML_DCHECK(divisions >= 1);
65 init(divisions);
66 FML_DCHECK(trigs_.size() == divisions + 1);
67 }
68
69 explicit Trigs(size_t divisions)
70 : local_storage_(std::make_unique<std::vector<Trig>>()),
71 trigs_(*local_storage_) {
72 FML_DCHECK(divisions >= 1);
73 init(divisions);
74 FML_DCHECK(trigs_.size() == divisions + 1);
75 }
76
77 // nullptr if a cached vector is used, otherwise the actual storage
78 std::unique_ptr<std::vector<Trig>> local_storage_;
79
80 // Whether or not a cached vector or the local storage is used, this
81 // this reference will always be valid
82 std::vector<Trig>& trigs_;
83
84 // Fill the vector with the indicated number of equal divisions of
85 // trigonometric values if it is empty.
86 void init(size_t divisions);
87 };
88
89 enum class Result {
93 };
94
95 /// @brief A callback function for a |VertexGenerator| to deliver
96 /// the vertices it computes as |Point| objects.
97 using TessellatedVertexProc = std::function<void(const Point& p)>;
98
99 /// @brief An object which produces a list of vertices as |Point|s that
100 /// tessellate a previously provided shape and delivers the vertices
101 /// through a |TessellatedVertexProc| callback.
102 ///
103 /// The object can also provide advance information on how many
104 /// vertices it will generate.
105 ///
106 /// @see |Tessellator::FilledCircle|
107 /// @see |Tessellator::StrokedCircle|
108 /// @see |Tessellator::RoundCapLine|
109 /// @see |Tessellator::FilledEllipse|
111 public:
112 /// @brief Returns the |PrimitiveType| that describes the relationship
113 /// among the list of vertices produced by the |GenerateVertices|
114 /// method.
115 ///
116 /// Most generators will deliver |kTriangleStrip| triangles
117 virtual PrimitiveType GetTriangleType() const = 0;
118
119 /// @brief Returns the number of vertices that the generator plans to
120 /// produce, if known.
121 ///
122 /// This value is advisory only and can be used to reserve space
123 /// where the vertices will be placed, but the count may be an
124 /// estimate.
125 ///
126 /// Implementations are encouraged to avoid overestimating
127 /// the count by too large a number and to provide a best
128 /// guess so as to minimize potential buffer reallocations
129 /// as the vertices are delivered.
130 virtual size_t GetVertexCount() const = 0;
131
132 /// @brief Generate the vertices and deliver them in the necessary
133 /// order (as required by the PrimitiveType) to the given
134 /// callback function.
135 virtual void GenerateVertices(const TessellatedVertexProc& proc) const = 0;
136 };
137
138 /// @brief The |VertexGenerator| implementation common to all shapes
139 /// that are based on a polygonal representation of an ellipse.
141 public:
142 /// |VertexGenerator|
145 }
146
147 /// |VertexGenerator|
148 size_t GetVertexCount() const override {
149 return trigs_.size() * vertices_per_trig_;
150 }
151
152 /// |VertexGenerator|
153 void GenerateVertices(const TessellatedVertexProc& proc) const override {
154 impl_(trigs_, data_, proc);
155 }
156
157 private:
158 friend class Tessellator;
159
160 struct Data {
161 // Circles and Ellipses only use one of these points.
162 // RoundCapLines use both as the endpoints of the unexpanded line.
163 // A round rect can specify its interior rectangle by using the
164 // 2 points as opposing corners.
165 const Point reference_centers[2];
166 // Circular shapes have the same value in radii.width and radii.height
167 const Size radii;
168 // half_width is only used in cases where the generator will be
169 // generating 2 different outlines, such as StrokedCircle
170 const Scalar half_width;
171 };
172
173 typedef void GeneratorProc(const Trigs& trigs,
174 const Data& data,
175 const TessellatedVertexProc& proc);
176
177 GeneratorProc& impl_;
178 const Trigs trigs_;
179 const Data data_;
180 const size_t vertices_per_trig_;
181
182 EllipticalVertexGenerator(GeneratorProc& generator,
183 Trigs&& trigs,
184 PrimitiveType triangle_type,
185 size_t vertices_per_trig,
186 Data&& data);
187 };
188
189 /// @brief The |VertexGenerator| implementation common to all shapes
190 /// that are based on a polygonal representation of an ellipse.
191 class ArcVertexGenerator : public virtual VertexGenerator {
192 public:
193 /// |VertexGenerator|
194 PrimitiveType GetTriangleType() const override;
195
196 /// |VertexGenerator|
197 size_t GetVertexCount() const override;
198
199 /// |VertexGenerator|
200 void GenerateVertices(const TessellatedVertexProc& proc) const override;
201
202 static ArcVertexGenerator MakeFilled(const Arc::Iteration& iteration,
203 Trigs&& trigs,
204 const Rect& oval_bounds,
205 bool use_center,
206 bool supports_triangle_fans);
207
209 const Arc::Iteration& iteration,
210 Trigs&& trigs,
211 const Rect& oval_bounds,
212 Scalar half_width,
213 Cap cap,
214 std::unique_ptr<Trigs> round_cap_trigs);
215
216 private:
217 friend class Tessellator;
218
219 const Arc::Iteration iteration_;
220 const Trigs trigs_;
221 const Rect oval_bounds_;
222
223 // Used only in filled arcs.
224 const bool use_center_;
225 const bool supports_triangle_fans_;
226
227 // Used only in stroked arcs. half_width_ is set to -1.0f for filled arcs.
228 const Scalar half_width_;
229 const Cap cap_;
230 const std::unique_ptr<Trigs> round_cap_trigs_;
231
232 ArcVertexGenerator(const Arc::Iteration& iteration,
233 Trigs&& trigs,
234 const Rect& oval_bounds,
235 bool use_center,
236 bool supports_triangle_fans,
237 Scalar half_width,
238 Cap cap,
239 std::unique_ptr<Trigs> round_cap_trigs);
240 };
241
242 explicit Tessellator(bool supports_32bit_primitive_indices = true);
243
244 virtual ~Tessellator();
245
246 //----------------------------------------------------------------------------
247 /// @brief Given a convex path, create a triangle fan structure.
248 ///
249 /// @param[in] path The path to tessellate.
250 /// @param[in] host_buffer The host buffer for allocation of vertices/index
251 /// data.
252 /// @param[in] tolerance The tolerance value for conversion of the path to
253 /// a polyline. This value is often derived from the
254 /// Matrix::GetMaxBasisLengthXY of the CTM applied to
255 /// the path for rendering.
256 ///
257 /// @return A vertex buffer containing all data from the provided curve.
259 HostBuffer& data_host_buffer,
260 HostBuffer& indexes_host_buffer,
261 Scalar tolerance,
262 bool supports_primitive_restart = false,
263 bool supports_triangle_fan = false);
264
265 /// Visible for testing.
266 ///
267 /// This method only exists for the ease of benchmarking without using the
268 /// real allocator needed by the [host_buffer].
269 static void TessellateConvexInternal(const PathSource& path,
270 std::vector<Point>& point_buffer,
271 std::vector<uint16_t>& index_buffer,
272 Scalar tolerance);
273
274 //----------------------------------------------------------------------------
275 /// @brief The pixel tolerance used by the algorighm to determine how
276 /// many divisions to create for a circle.
277 ///
278 /// No point on the polygon of vertices should deviate from the
279 /// true circle by more than this tolerance.
280 static constexpr Scalar kCircleTolerance = 0.1f;
281
282 /// @brief Create a |VertexGenerator| that can produce vertices for
283 /// a filled circle of the given radius around the given center
284 /// with enough polygon sub-divisions to provide reasonable
285 /// fidelity when viewed under the given view transform.
286 ///
287 /// Note that the view transform is only used to choose the
288 /// number of sample points to use per quarter circle and the
289 /// returned points are not transformed by it, instead they are
290 /// relative to the coordinate space of the center point.
291 EllipticalVertexGenerator FilledCircle(const Matrix& view_transform,
292 const Point& center,
293 Scalar radius);
294
295 /// @brief Create a |VertexGenerator| that can produce vertices for
296 /// a stroked circle of the given radius and half_width around
297 /// the given shared center with enough polygon sub-divisions
298 /// to provide reasonable fidelity when viewed under the given
299 /// view transform. The outer edge of the stroked circle is
300 /// generated at (radius + half_width) and the inner edge is
301 /// generated at (radius - half_width).
302 ///
303 /// Note that the view transform is only used to choose the
304 /// number of sample points to use per quarter circle and the
305 /// returned points are not transformed by it, instead they are
306 /// relative to the coordinate space of the center point.
307 EllipticalVertexGenerator StrokedCircle(const Matrix& view_transform,
308 const Point& center,
309 Scalar radius,
310 Scalar half_width);
311
312 /// @brief Create a |VertexGenerator| that can produce vertices for
313 /// a stroked arc inscribed within the given oval_bounds with
314 /// the given stroke half_width with enough polygon sub-divisions
315 /// to provide reasonable fidelity when viewed under the given
316 /// view transform. The outer edge of the stroked arc is
317 /// generated at (radius + half_width) and the inner edge is
318 /// generated at (radius - half_width).
319 ///
320 /// Note that the view transform is only used to choose the
321 /// number of sample points to use per quarter circle and the
322 /// returned points are not transformed by it, instead they are
323 /// relative to the coordinate space of the oval bounds.
324 ArcVertexGenerator FilledArc(const Matrix& view_transform,
325 const Arc& arc,
326 bool supports_triangle_fans);
327
328 /// @brief Create a |VertexGenerator| that can produce vertices for
329 /// a stroked arc inscribed within the given oval_bounds with
330 /// the given stroke half_width with enough polygon sub-divisions
331 /// to provide reasonable fidelity when viewed under the given
332 /// view transform. The outer edge of the stroked arc is
333 /// generated at (radius + half_width) and the inner edge is
334 /// generated at (radius - half_width).
335 ///
336 /// Note that the arc may not include the center and its bounds
337 /// must be a perfect circle (width == height)
338 ///
339 /// Note that the view transform is only used to choose the
340 /// number of sample points to use per quarter circle and the
341 /// returned points are not transformed by it, instead they are
342 /// relative to the coordinate space of the oval bounds.
343 ArcVertexGenerator StrokedArc(const Matrix& view_transform,
344 const Arc& arc,
345 Cap cap,
346 Scalar half_width);
347
348 /// @brief Create a |VertexGenerator| that can produce vertices for
349 /// a line with round end caps of the given radius with enough
350 /// polygon sub-divisions to provide reasonable fidelity when
351 /// viewed under the given view transform.
352 ///
353 /// Note that the view transform is only used to choose the
354 /// number of sample points to use per quarter circle and the
355 /// returned points are not transformed by it, instead they are
356 /// relative to the coordinate space of the two points.
357 EllipticalVertexGenerator RoundCapLine(const Matrix& view_transform,
358 const Point& p0,
359 const Point& p1,
360 Scalar radius);
361
362 /// @brief Create a |VertexGenerator| that can produce vertices for
363 /// a filled ellipse inscribed within the given bounds with
364 /// enough polygon sub-divisions to provide reasonable
365 /// fidelity when viewed under the given view transform.
366 ///
367 /// Note that the view transform is only used to choose the
368 /// number of sample points to use per quarter circle and the
369 /// returned points are not transformed by it, instead they are
370 /// relative to the coordinate space of the bounds.
371 EllipticalVertexGenerator FilledEllipse(const Matrix& view_transform,
372 const Rect& bounds);
373
374 /// @brief Create a |VertexGenerator| that can produce vertices for
375 /// a filled round rect within the given bounds and corner radii
376 /// with enough polygon sub-divisions to provide reasonable
377 /// fidelity when viewed under the given view transform.
378 ///
379 /// Note that the view transform is only used to choose the
380 /// number of sample points to use per quarter circle and the
381 /// returned points are not transformed by it, instead they are
382 /// relative to the coordinate space of the bounds.
384 const Rect& bounds,
385 const Size& radii);
386
387 /// Retrieve a pre-allocated arena of kPointArenaSize points.
388 std::vector<Point>& GetStrokePointCache();
389
390 /// Return a vector of Trig (cos, sin pairs) structs for a 90 degree
391 /// circle quadrant of the specified pixel radius
393
394 private:
395 class ConvexTessellator {
396 public:
397 virtual ~ConvexTessellator() = default;
398 virtual VertexBuffer TessellateConvex(const PathSource& path,
399 HostBuffer& data_host_buffer,
400 HostBuffer& indexes_host_buffer,
401 Scalar tolerance,
402 bool supports_primitive_restart,
403 bool supports_triangle_fan) = 0;
404 };
405 template <typename IndexT>
407
408 /// Used for polyline generation.
409 std::unique_ptr<ConvexTessellator> convex_tessellator_;
410
411 /// Used for stroke path generation.
412 std::vector<Point> stroke_points_;
413
414 // Data for various Circle/EllipseGenerator classes, cached per
415 // Tessellator instance which is usually the foreground life of an app
416 // if not longer.
417 static constexpr size_t kCachedTrigCount = 300;
418 std::vector<Trig> precomputed_trigs_[kCachedTrigCount];
419
420 Trigs GetTrigsForDivisions(size_t divisions);
421
422 static void GenerateFilledCircle(const Trigs& trigs,
423 const EllipticalVertexGenerator::Data& data,
424 const TessellatedVertexProc& proc);
425
426 static void GenerateStrokedCircle(const Trigs& trigs,
427 const EllipticalVertexGenerator::Data& data,
428 const TessellatedVertexProc& proc);
429
430 static void GenerateFilledArcFan(const Trigs& trigs,
431 const Arc::Iteration& iteration,
432 const Rect& oval_bounds,
433 bool use_center,
434 const TessellatedVertexProc& proc);
435
436 static void GenerateFilledArcStrip(const Trigs& trigs,
437 const Arc::Iteration& iteration,
438 const Rect& oval_bounds,
439 bool use_center,
440 const TessellatedVertexProc& proc);
441
442 static void GenerateStrokedArc(const Trigs& trigs,
443 const Arc::Iteration& iteration,
444 const Rect& oval_bounds,
445 Scalar half_width,
446 Cap cap,
447 const std::unique_ptr<Trigs>& round_cap_trigs,
448 const TessellatedVertexProc& proc);
449
450 static void GenerateRoundCapLine(const Trigs& trigs,
451 const EllipticalVertexGenerator::Data& data,
452 const TessellatedVertexProc& proc);
453
454 static void GenerateFilledEllipse(const Trigs& trigs,
455 const EllipticalVertexGenerator::Data& data,
456 const TessellatedVertexProc& proc);
457
458 static void GenerateFilledRoundRect(
459 const Trigs& trigs,
460 const EllipticalVertexGenerator::Data& data,
461 const TessellatedVertexProc& proc);
462
463 // Generates vertices for the start round cap of a stroke.
464 //
465 // The perpendicular input points 90 degrees clockwise to the direction the
466 // stroke is traveling and is the length of half of the stroke width.
467 //
468 // The start round cap covers a semicircle formed by sweeping the
469 // perpendicular input clockwise 180 degrees about point p. This sweeps a
470 // semicircle with a curve facing away from the stroke's direction of travel.
471 //
472 // The first generated vertex is the midpoint of the semicircle's curve,
473 // directly opposite the semicircle's straight diameter. Vertices progress
474 // in the stroke's direction of travel, ending with two vertices at
475 // (p + perpendicular) and (p - perpendicular) that form the semicircle's
476 // diameter.
477 static void GenerateStartRoundCap(const Point& p,
478 const Vector2& perpendicular,
479 const Trigs& trigs,
480 const TessellatedVertexProc& proc);
481
482 // Generates vertices for the end round cap of a stroke.
483 //
484 // The perpendicular input points 90 degrees clockwise to the direction the
485 // stroke is traveling and is the length of half of the stroke width.
486 //
487 // The end round cap covers a semicircle formed by sweeping the
488 // perpendicular input counterclockwise 180 degrees about point p. This sweeps
489 // a semicircle with a curve facing toward the stroke's direction of travel.
490 //
491 // The generated vertices begin with two vertices at (p + perpendicular) and
492 // (p - perpendicular) which form the semicircle's diameter. Vertices progress
493 // in the stroke's direction of travel, ending with the vertex at the midpoint
494 // of the semicircle's curve.
495 static void GenerateEndRoundCap(const Point& p,
496 const Vector2& perpendicular,
497 const Trigs& trigs,
498 const TessellatedVertexProc& proc);
499
500 Tessellator(const Tessellator&) = delete;
501
502 Tessellator& operator=(const Tessellator&) = delete;
503};
504
505} // namespace impeller
506
507#endif // FLUTTER_IMPELLER_TESSELLATOR_TESSELLATOR_H_
The |VertexGenerator| implementation common to all shapes that are based on a polygonal representatio...
static ArcVertexGenerator MakeStroked(const Arc::Iteration &iteration, Trigs &&trigs, const Rect &oval_bounds, Scalar half_width, Cap cap, std::unique_ptr< Trigs > round_cap_trigs)
size_t GetVertexCount() const override
|VertexGenerator|
PrimitiveType GetTriangleType() const override
|VertexGenerator|
static ArcVertexGenerator MakeFilled(const Arc::Iteration &iteration, Trigs &&trigs, const Rect &oval_bounds, bool use_center, bool supports_triangle_fans)
void GenerateVertices(const TessellatedVertexProc &proc) const override
|VertexGenerator|
The |VertexGenerator| implementation common to all shapes that are based on a polygonal representatio...
PrimitiveType GetTriangleType() const override
|VertexGenerator|
size_t GetVertexCount() const override
|VertexGenerator|
void GenerateVertices(const TessellatedVertexProc &proc) const override
|VertexGenerator|
const Trig & operator[](size_t index) const
Definition tessellator.h:56
std::vector< Trig >::iterator begin() const
Definition tessellator.h:54
std::vector< Trig >::iterator end() const
Definition tessellator.h:55
An object which produces a list of vertices as |Point|s that tessellate a previously provided shape a...
virtual size_t GetVertexCount() const =0
Returns the number of vertices that the generator plans to produce, if known.
virtual PrimitiveType GetTriangleType() const =0
Returns the |PrimitiveType| that describes the relationship among the list of vertices produced by th...
virtual void GenerateVertices(const TessellatedVertexProc &proc) const =0
Generate the vertices and deliver them in the necessary order (as required by the PrimitiveType) to t...
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
Definition tessellator.h:37
Trigs GetTrigsForDeviceRadius(Scalar pixel_radius)
EllipticalVertexGenerator RoundCapLine(const Matrix &view_transform, const Point &p0, const Point &p1, Scalar radius)
Create a |VertexGenerator| that can produce vertices for a line with round end caps of the given radi...
std::vector< Point > & GetStrokePointCache()
Retrieve a pre-allocated arena of kPointArenaSize points.
EllipticalVertexGenerator FilledRoundRect(const Matrix &view_transform, const Rect &bounds, const Size &radii)
Create a |VertexGenerator| that can produce vertices for a filled round rect within the given bounds ...
static constexpr Scalar kCircleTolerance
The pixel tolerance used by the algorighm to determine how many divisions to create for a circle.
VertexBuffer TessellateConvex(const PathSource &path, HostBuffer &data_host_buffer, HostBuffer &indexes_host_buffer, Scalar tolerance, bool supports_primitive_restart=false, bool supports_triangle_fan=false)
Given a convex path, create a triangle fan structure.
EllipticalVertexGenerator FilledCircle(const Matrix &view_transform, const Point &center, Scalar radius)
Create a |VertexGenerator| that can produce vertices for a filled circle of the given radius around t...
ArcVertexGenerator StrokedArc(const Matrix &view_transform, const Arc &arc, Cap cap, Scalar half_width)
Create a |VertexGenerator| that can produce vertices for a stroked arc inscribed within the given ova...
static void TessellateConvexInternal(const PathSource &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
EllipticalVertexGenerator StrokedCircle(const Matrix &view_transform, const Point &center, Scalar radius, Scalar half_width)
Create a |VertexGenerator| that can produce vertices for a stroked circle of the given radius and hal...
friend class ConvexTessellatorImpl
EllipticalVertexGenerator FilledEllipse(const Matrix &view_transform, const Rect &bounds)
Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given ...
std::function< void(const Point &p)> TessellatedVertexProc
A callback function for a |VertexGenerator| to deliver the vertices it computes as |Point| objects.
Definition tessellator.h:97
ArcVertexGenerator FilledArc(const Matrix &view_transform, const Arc &arc, bool supports_triangle_fans)
Create a |VertexGenerator| that can produce vertices for a stroked arc inscribed within the given ova...
#define FML_DCHECK(condition)
Definition logging.h:122
PrimitiveType
Decides how backend draws pixels based on input vertices.
Definition formats.h:355
float Scalar
Definition scalar.h:19
Cap
An enum that describes ways to decorate the end of a path contour.
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
Definition tessellator.h:25
Definition ref_ptr.h:261
Definition data.h:17
A 4x4 matrix using column-major storage.
Definition matrix.h:37
A structure to store the sine and cosine of an angle.
Definition trig.h:16
std::shared_ptr< const fml::Mapping > data