Flutter Impeller
impeller::Tessellator Class Reference

A utility that generates triangles of the specified fill type given a polyline. This happens on the CPU. More...

#include <tessellator.h>

Classes

class  EllipticalVertexGenerator
 The |VertexGenerator| implementation common to all shapes that are based on a polygonal representation of an ellipse. More...
 
class  VertexGenerator
 An object which produces a list of vertices as |Point|s that tessellate a previously provided shape and delivers the vertices through a |TessellatedVertexProc| callback. More...
 

Public Types

enum class  Result {
  kSuccess ,
  kInputError ,
  kTessellationError
}
 
using TessellatedVertexProc = std::function< void(const Point &p)>
 A callback function for a |VertexGenerator| to deliver the vertices it computes as |Point| objects. More...
 

Public Member Functions

 Tessellator ()
 
virtual ~Tessellator ()
 
VertexBuffer TessellateConvex (const Path &path, HostBuffer &host_buffer, Scalar tolerance, bool supports_primitive_restart=false, bool supports_triangle_fan=false)
 Given a convex path, create a triangle fan structure. More...
 
VertexBuffer GenerateLineStrip (const Path &path, HostBuffer &host_buffer, Scalar tolerance)
 Given a path, create a line strip primitive structure. More...
 
Path::Polyline CreateTempPolyline (const Path &path, Scalar tolerance)
 Create a temporary polyline. Only one per-process can exist at a time. More...
 
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 the given center with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. More...
 
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 half_width around the given shared center with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. The outer edge of the stroked circle is generated at (radius + half_width) and the inner edge is generated at (radius - half_width). More...
 
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 radius with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. More...
 
EllipticalVertexGenerator FilledEllipse (const Matrix &view_transform, const Rect &bounds)
 Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given bounds with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. More...
 
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 and corner radii with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. More...
 
std::vector< Point > & GetStrokePointCache ()
 Retrieve a pre-allocated arena of kPointArenaSize points. More...
 

Static Public Member Functions

static void TessellateConvexInternal (const Path &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
 

Static Public Attributes

static constexpr Scalar kCircleTolerance = 0.1f
 The pixel tolerance used by the algorighm to determine how many divisions to create for a circle. More...
 

Protected Attributes

std::unique_ptr< std::vector< Point > > point_buffer_
 Used for polyline generation. More...
 
std::unique_ptr< std::vector< uint16_t > > index_buffer_
 
std::vector< Pointstroke_points_
 Used for stroke path generation. More...
 

Detailed Description

A utility that generates triangles of the specified fill type given a polyline. This happens on the CPU.

Also contains functionality for optimized generation of circles and ellipses.

This object is not thread safe, and its methods must not be called from multiple threads.

Definition at line 34 of file tessellator.h.

Member Typedef Documentation

◆ TessellatedVertexProc

using impeller::Tessellator::TessellatedVertexProc = std::function<void(const Point& p)>

A callback function for a |VertexGenerator| to deliver the vertices it computes as |Point| objects.

Definition at line 81 of file tessellator.h.

Member Enumeration Documentation

◆ Result

Enumerator
kSuccess 
kInputError 
kTessellationError 

Definition at line 73 of file tessellator.h.

73  {
74  kSuccess,
75  kInputError,
76  kTessellationError,
77  };

Constructor & Destructor Documentation

◆ Tessellator()

impeller::Tessellator::Tessellator ( )

Definition at line 14 of file tessellator.cc.

15  : point_buffer_(std::make_unique<std::vector<Point>>()),
16  index_buffer_(std::make_unique<std::vector<uint16_t>>()),
18  point_buffer_->reserve(2048);
19  index_buffer_->reserve(2048);
20 }
std::vector< Point > stroke_points_
Used for stroke path generation.
Definition: tessellator.h:317
std::unique_ptr< std::vector< Point > > point_buffer_
Used for polyline generation.
Definition: tessellator.h:314
std::unique_ptr< std::vector< uint16_t > > index_buffer_
Definition: tessellator.h:315
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
Definition: tessellator.h:22

References index_buffer_, and point_buffer_.

◆ ~Tessellator()

impeller::Tessellator::~Tessellator ( )
virtualdefault

Member Function Documentation

◆ CreateTempPolyline()

Path::Polyline impeller::Tessellator::CreateTempPolyline ( const Path path,
Scalar  tolerance 
)

Create a temporary polyline. Only one per-process can exist at a time.

The tessellator itself is not a thread safe class and should only be used from the raster thread.

Definition at line 28 of file tessellator.cc.

29  {
30  FML_DCHECK(point_buffer_);
31  point_buffer_->clear();
32  auto polyline =
33  path.CreatePolyline(tolerance, std::move(point_buffer_),
34  [this](Path::Polyline::PointBufferPtr point_buffer) {
35  point_buffer_ = std::move(point_buffer);
36  });
37  return polyline;
38 }
const Path::Polyline & polyline
std::unique_ptr< std::vector< Point > > PointBufferPtr
Definition: path.h:149

References impeller::Path::CreatePolyline(), point_buffer_, and polyline.

◆ FilledCircle()

EllipticalVertexGenerator impeller::Tessellator::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 the given center with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform.

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the center point.

Definition at line 339 of file tessellator.cc.

342  {
343  size_t divisions =
344  ComputeQuadrantDivisions(view_transform.GetMaxBasisLengthXY() * radius);
345  return EllipticalVertexGenerator(Tessellator::GenerateFilledCircle,
346  GetTrigsForDivisions(divisions),
348  {
349  .reference_centers = {center, center},
350  .radii = {radius, radius},
351  .half_width = -1.0f,
352  });
353 }
static size_t ComputeQuadrantDivisions(Scalar pixel_radius)
Definition: tessellator.cc:246
Tessellator::EllipticalVertexGenerator EllipticalVertexGenerator
Definition: tessellator.cc:326

References impeller::ComputeQuadrantDivisions(), and impeller::Matrix::GetMaxBasisLengthXY().

◆ FilledEllipse()

EllipticalVertexGenerator impeller::Tessellator::FilledEllipse ( const Matrix view_transform,
const Rect bounds 
)

Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given bounds with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform.

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the bounds.

Definition at line 399 of file tessellator.cc.

401  {
402  if (bounds.IsSquare()) {
403  return FilledCircle(view_transform, bounds.GetCenter(),
404  bounds.GetWidth() * 0.5f);
405  }
406  auto max_radius = bounds.GetSize().MaxDimension();
407  auto divisions = ComputeQuadrantDivisions(
408  view_transform.GetMaxBasisLengthXY() * max_radius);
409  auto center = bounds.GetCenter();
410  return EllipticalVertexGenerator(Tessellator::GenerateFilledEllipse,
411  GetTrigsForDivisions(divisions),
413  {
414  .reference_centers = {center, center},
415  .radii = bounds.GetSize() * 0.5f,
416  .half_width = -1.0f,
417  });
418 }
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...
Definition: tessellator.cc:339

References impeller::ComputeQuadrantDivisions(), impeller::TRect< T >::GetCenter(), impeller::Matrix::GetMaxBasisLengthXY(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), and impeller::TRect< T >::IsSquare().

◆ FilledRoundRect()

EllipticalVertexGenerator impeller::Tessellator::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 and corner radii with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform.

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the bounds.

Definition at line 420 of file tessellator.cc.

423  {
424  if (radii.width * 2 < bounds.GetWidth() ||
425  radii.height * 2 < bounds.GetHeight()) {
426  auto max_radius = radii.MaxDimension();
427  auto divisions = ComputeQuadrantDivisions(
428  view_transform.GetMaxBasisLengthXY() * max_radius);
429  auto upper_left = bounds.GetLeftTop() + radii;
430  auto lower_right = bounds.GetRightBottom() - radii;
431  return EllipticalVertexGenerator(Tessellator::GenerateFilledRoundRect,
432  GetTrigsForDivisions(divisions),
434  {
435  .reference_centers =
436  {
437  upper_left,
438  lower_right,
439  },
440  .radii = radii,
441  .half_width = -1.0f,
442  });
443  } else {
444  return FilledEllipse(view_transform, bounds);
445  }
446 }
EllipticalVertexGenerator FilledEllipse(const Matrix &view_transform, const Rect &bounds)
Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given ...
Definition: tessellator.cc:399

References impeller::ComputeQuadrantDivisions(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeftTop(), impeller::Matrix::GetMaxBasisLengthXY(), impeller::TRect< T >::GetRightBottom(), impeller::TRect< T >::GetWidth(), impeller::TSize< T >::height, impeller::TSize< T >::MaxDimension(), and impeller::TSize< T >::width.

◆ GenerateLineStrip()

VertexBuffer impeller::Tessellator::GenerateLineStrip ( const Path path,
HostBuffer host_buffer,
Scalar  tolerance 
)

Given a path, create a line strip primitive structure.

        A line strip is a series of vertices that draws a line
        rendered at a specified width (in our case, always 1.0
        physical pixel) that is tessellated by the rasterizer. See
        also PrimitiveType::kLineStrip.
Parameters
[in]pathThe path to tessellate.
[in]host_bufferThe host buffer for allocation of vertices/index data.
[in]toleranceThe tolerance value for conversion of the path to a polyline. This value is often derived from the Matrix::GetMaxBasisLengthXY of the CTM applied to the path for rendering.
Returns
A vertex buffer containing all data from the provided curve.

Definition at line 120 of file tessellator.cc.

122  {
123  LineStripVertexWriter writer(stroke_points_);
124  path.WritePolyline(tolerance, writer);
125 
126  const auto [arena_length, oversized_length] = writer.GetVertexCount();
127 
128  if (oversized_length == 0) {
129  return VertexBuffer{
130  .vertex_buffer =
131  host_buffer.Emplace(stroke_points_.data(),
132  arena_length * sizeof(Point), alignof(Point)),
133  .index_buffer = {},
134  .vertex_count = arena_length,
135  .index_type = IndexType::kNone,
136  };
137  }
138  const std::vector<Point>& oversized_data = writer.GetOversizedBuffer();
139  BufferView buffer_view = host_buffer.Emplace(
140  /*buffer=*/nullptr, //
141  (arena_length + oversized_length) * sizeof(Point), //
142  alignof(Point) //
143  );
144  memcpy(buffer_view.GetBuffer()->OnGetContents() +
145  buffer_view.GetRange().offset, //
146  stroke_points_.data(), //
147  arena_length * sizeof(Point) //
148  );
149  memcpy(buffer_view.GetBuffer()->OnGetContents() +
150  buffer_view.GetRange().offset + arena_length * sizeof(Point), //
151  oversized_data.data(), //
152  oversized_data.size() * sizeof(Point) //
153  );
154  buffer_view.GetBuffer()->Flush(buffer_view.GetRange());
155 
156  return VertexBuffer{
157  .vertex_buffer = buffer_view,
158  .index_buffer = {},
159  .vertex_count = arena_length + oversized_length,
160  .index_type = IndexType::kNone,
161  };
162 }
BufferView buffer_view
@ kNone
Does not use the index buffer.
TPoint< Scalar > Point
Definition: point.h:327

References buffer_view, impeller::HostBuffer::Emplace(), impeller::LineStripVertexWriter::GetOversizedBuffer(), impeller::LineStripVertexWriter::GetVertexCount(), impeller::kNone, stroke_points_, impeller::VertexBuffer::vertex_buffer, and impeller::Path::WritePolyline().

◆ GetStrokePointCache()

std::vector< Point > & impeller::Tessellator::GetStrokePointCache ( )

Retrieve a pre-allocated arena of kPointArenaSize points.

Definition at line 24 of file tessellator.cc.

24  {
25  return stroke_points_;
26 }

References stroke_points_.

◆ RoundCapLine()

EllipticalVertexGenerator impeller::Tessellator::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 radius with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform.

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the two points.

Definition at line 376 of file tessellator.cc.

380  {
381  auto along = p1 - p0;
382  auto length = along.GetLength();
383  if (length > kEhCloseEnough) {
384  auto divisions =
385  ComputeQuadrantDivisions(view_transform.GetMaxBasisLengthXY() * radius);
386  return EllipticalVertexGenerator(Tessellator::GenerateRoundCapLine,
387  GetTrigsForDivisions(divisions),
389  {
390  .reference_centers = {p0, p1},
391  .radii = {radius, radius},
392  .half_width = -1.0f,
393  });
394  } else {
395  return FilledCircle(view_transform, p0, radius);
396  }
397 }
constexpr float kEhCloseEnough
Definition: constants.h:57

References impeller::ComputeQuadrantDivisions(), impeller::TPoint< T >::GetLength(), impeller::Matrix::GetMaxBasisLengthXY(), and impeller::kEhCloseEnough.

◆ StrokedCircle()

EllipticalVertexGenerator impeller::Tessellator::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 half_width around the given shared center with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. The outer edge of the stroked circle is generated at (radius + half_width) and the inner edge is generated at (radius - half_width).

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the center point.

Definition at line 355 of file tessellator.cc.

359  {
360  if (half_width > 0) {
361  auto divisions = ComputeQuadrantDivisions(
362  view_transform.GetMaxBasisLengthXY() * radius + half_width);
363  return EllipticalVertexGenerator(Tessellator::GenerateStrokedCircle,
364  GetTrigsForDivisions(divisions),
366  {
367  .reference_centers = {center, center},
368  .radii = {radius, radius},
369  .half_width = half_width,
370  });
371  } else {
372  return FilledCircle(view_transform, center, radius);
373  }
374 }

References impeller::ComputeQuadrantDivisions(), and impeller::Matrix::GetMaxBasisLengthXY().

◆ TessellateConvex()

VertexBuffer impeller::Tessellator::TessellateConvex ( const Path path,
HostBuffer host_buffer,
Scalar  tolerance,
bool  supports_primitive_restart = false,
bool  supports_triangle_fan = false 
)

Given a convex path, create a triangle fan structure.

Parameters
[in]pathThe path to tessellate.
[in]host_bufferThe host buffer for allocation of vertices/index data.
[in]toleranceThe tolerance value for conversion of the path to a polyline. This value is often derived from the Matrix::GetMaxBasisLengthXY of the CTM applied to the path for rendering.
Returns
A vertex buffer containing all data from the provided curve.

Definition at line 40 of file tessellator.cc.

44  {
45  if (supports_primitive_restart) {
46  // Primitive Restart.
47  const auto [point_count, contour_count] = path.CountStorage(tolerance);
48  BufferView point_buffer = host_buffer.Emplace(
49  nullptr, sizeof(Point) * point_count, alignof(Point));
50  BufferView index_buffer = host_buffer.Emplace(
51  nullptr, sizeof(uint16_t) * (point_count + contour_count),
52  alignof(uint16_t));
53 
54  if (supports_triangle_fan) {
55  FanVertexWriter writer(
56  reinterpret_cast<Point*>(point_buffer.GetBuffer()->OnGetContents() +
57  point_buffer.GetRange().offset),
58  reinterpret_cast<uint16_t*>(
59  index_buffer.GetBuffer()->OnGetContents() +
60  index_buffer.GetRange().offset));
61  path.WritePolyline(tolerance, writer);
62  point_buffer.GetBuffer()->Flush(point_buffer.GetRange());
63  index_buffer.GetBuffer()->Flush(index_buffer.GetRange());
64 
65  return VertexBuffer{
66  .vertex_buffer = std::move(point_buffer),
67  .index_buffer = std::move(index_buffer),
68  .vertex_count = writer.GetIndexCount(),
69  .index_type = IndexType::k16bit,
70  };
71  } else {
72  StripVertexWriter writer(
73  reinterpret_cast<Point*>(point_buffer.GetBuffer()->OnGetContents() +
74  point_buffer.GetRange().offset),
75  reinterpret_cast<uint16_t*>(
76  index_buffer.GetBuffer()->OnGetContents() +
77  index_buffer.GetRange().offset));
78  path.WritePolyline(tolerance, writer);
79  point_buffer.GetBuffer()->Flush(point_buffer.GetRange());
80  index_buffer.GetBuffer()->Flush(index_buffer.GetRange());
81 
82  return VertexBuffer{
83  .vertex_buffer = std::move(point_buffer),
84  .index_buffer = std::move(index_buffer),
85  .vertex_count = writer.GetIndexCount(),
86  .index_type = IndexType::k16bit,
87  };
88  }
89  }
90 
91  FML_DCHECK(point_buffer_);
92  FML_DCHECK(index_buffer_);
94 
95  if (point_buffer_->empty()) {
96  return VertexBuffer{
97  .vertex_buffer = {},
98  .index_buffer = {},
99  .vertex_count = 0u,
100  .index_type = IndexType::k16bit,
101  };
102  }
103 
104  BufferView vertex_buffer = host_buffer.Emplace(
105  point_buffer_->data(), sizeof(Point) * point_buffer_->size(),
106  alignof(Point));
107 
108  BufferView index_buffer = host_buffer.Emplace(
109  index_buffer_->data(), sizeof(uint16_t) * index_buffer_->size(),
110  alignof(uint16_t));
111 
112  return VertexBuffer{
113  .vertex_buffer = std::move(vertex_buffer),
114  .index_buffer = std::move(index_buffer),
115  .vertex_count = index_buffer_->size(),
116  .index_type = IndexType::k16bit,
117  };
118 }
static void TessellateConvexInternal(const Path &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
Definition: tessellator.cc:164

References impeller::Path::CountStorage(), impeller::HostBuffer::Emplace(), impeller::DeviceBuffer::Flush(), impeller::BufferView::GetBuffer(), impeller::FanVertexWriter::GetIndexCount(), impeller::StripVertexWriter::GetIndexCount(), impeller::BufferView::GetRange(), index_buffer_, impeller::k16bit, impeller::Range::offset, impeller::DeviceBuffer::OnGetContents(), point_buffer_, TessellateConvexInternal(), impeller::VertexBuffer::vertex_buffer, and impeller::Path::WritePolyline().

◆ TessellateConvexInternal()

void impeller::Tessellator::TessellateConvexInternal ( const Path path,
std::vector< Point > &  point_buffer,
std::vector< uint16_t > &  index_buffer,
Scalar  tolerance 
)
static

Visible for testing.

This method only exists for the ease of benchmarking without using the real allocator needed by the [host_buffer].

Definition at line 164 of file tessellator.cc.

167  {
168  point_buffer.clear();
169  index_buffer.clear();
170 
171  GLESVertexWriter writer(point_buffer, index_buffer);
172 
173  path.WritePolyline(tolerance, writer);
174 }

References impeller::Path::WritePolyline().

Referenced by impeller::BM_Convex(), TessellateConvex(), and impeller::testing::TEST().

Member Data Documentation

◆ index_buffer_

std::unique_ptr<std::vector<uint16_t> > impeller::Tessellator::index_buffer_
protected

Definition at line 315 of file tessellator.h.

Referenced by TessellateConvex(), and Tessellator().

◆ kCircleTolerance

constexpr Scalar impeller::Tessellator::kCircleTolerance = 0.1f
staticconstexpr

The pixel tolerance used by the algorighm to determine how many divisions to create for a circle.

No point on the polygon of vertices should deviate from the true circle by more than this tolerance.

Definition at line 238 of file tessellator.h.

Referenced by impeller::ComputeQuadrantDivisions(), and impeller::testing::TEST().

◆ point_buffer_

std::unique_ptr<std::vector<Point> > impeller::Tessellator::point_buffer_
protected

Used for polyline generation.

Definition at line 314 of file tessellator.h.

Referenced by CreateTempPolyline(), TessellateConvex(), and Tessellator().

◆ stroke_points_

std::vector<Point> impeller::Tessellator::stroke_points_
protected

Used for stroke path generation.

Definition at line 317 of file tessellator.h.

Referenced by GenerateLineStrip(), and GetStrokePointCache().


The documentation for this class was generated from the following files: