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

[Impeller] Refactor all tessellation calls to use builder callback, rename. #36706

Merged
merged 4 commits into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions impeller/entity/contents/texture_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,24 @@ bool TextureContents::Render(const ContentContext& renderer,
{
const auto tess_result = renderer.GetTessellator()->Tessellate(
path_.GetFillType(), path_.CreatePolyline(),
[this, &vertex_builder, &coverage_rect, &texture_size](Point vtx) {
VS::PerVertexData data;
data.position = vtx;
auto coverage_coords =
(vtx - coverage_rect->origin) / coverage_rect->size;
data.texture_coords =
(source_rect_.origin + source_rect_.size * coverage_coords) /
texture_size;
vertex_builder.AppendVertex(data);
[this, &vertex_builder, &coverage_rect, &texture_size](
const float* vertices, size_t vertices_size,
const uint16_t* indices, size_t indices_size) {
for (auto i = 0u; i < vertices_size; i++) {
VS::PerVertexData data;
Point vtx = {vertices[i], vertices[i + 1]};
data.position = vtx;
auto coverage_coords =
(vtx - coverage_rect->origin) / coverage_rect->size;
data.texture_coords =
(source_rect_.origin + source_rect_.size * coverage_coords) /
texture_size;
vertex_builder.AppendVertex(data);
}
for (auto i = 0u; i < indices_size; i++) {
vertex_builder.AppendIndex(indices[i]);
}
return true;
});

if (tess_result == Tessellator::Result::kInputError) {
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ GeometryResult PathGeometry::GetPositionBuffer(
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) {
VertexBuffer vertex_buffer;
auto tesselation_result = tessellator->TessellateBuilder(
auto tesselation_result = tessellator->Tessellate(
path_.GetFillType(), path_.CreatePolyline(),
[&vertex_buffer, &host_buffer](
const float* vertices, size_t vertices_count, const uint16_t* indices,
Expand Down
5 changes: 4 additions & 1 deletion impeller/geometry/geometry_benchmarks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ static void BM_Polyline(benchmark::State& state, Args&&... args) {
single_point_count = polyline.points.size();
point_count += single_point_count;
if (tessellate) {
tess.Tessellate(FillType::kNonZero, polyline, [](Point) {});
tess.Tessellate(
FillType::kNonZero, polyline,
[](const float* vertices, size_t vertices_size,
const uint16_t* indices, size_t indices_size) { return true; });
}
}
state.counters["SinglePointCount"] = single_point_count;
Expand Down
31 changes: 19 additions & 12 deletions impeller/renderer/renderer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -397,18 +397,25 @@ TEST_P(RendererTest, CanRenderInstanced) {

VertexBufferBuilder<VS::PerVertexData> builder;

ASSERT_EQ(
Tessellator::Result::kSuccess,
Tessellator{}.Tessellate(FillType::kPositive,
PathBuilder{}
.AddRect(Rect::MakeXYWH(10, 10, 100, 100))
.TakePath()
.CreatePolyline(),
[&builder](Point vtx) {
VS::PerVertexData data;
data.vtx = vtx;
builder.AppendVertex(data);
}));
ASSERT_EQ(Tessellator::Result::kSuccess,
Tessellator{}.Tessellate(
FillType::kPositive,
PathBuilder{}
.AddRect(Rect::MakeXYWH(10, 10, 100, 100))
.TakePath()
.CreatePolyline(),
[&builder](const float* vertices, size_t vertices_size,
const uint16_t* indices, size_t indices_size) {
for (auto i = 0u; i < vertices_size; i += 2) {
VS::PerVertexData data;
data.vtx = {vertices[i], vertices[i + 1]};
builder.AppendVertex(data);
}
for (auto i = 0u; i < indices_size; i++) {
builder.AppendIndex(indices[i]);
}
return true;
}));

ASSERT_NE(GetContext(), nullptr);
auto pipeline =
Expand Down
21 changes: 16 additions & 5 deletions impeller/tessellator/c/tessellator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,22 @@ struct Vertices* Tessellate(PathBuilder* builder,
auto smoothing = SmoothingApproximation(scale, angle_tolerance, cusp_limit);
auto polyline = path.CreatePolyline(smoothing);
std::vector<float> points;
if (Tessellator{}.Tessellate(path.GetFillType(), polyline,
[&points](Point vertex) {
points.push_back(vertex.x);
points.push_back(vertex.y);
}) != Tessellator::Result::kSuccess) {
if (Tessellator{}.Tessellate(
path.GetFillType(), polyline,
[&points](const float* vertices, size_t vertices_size,
const uint16_t* indices, size_t indices_size) {
// Results are expected to be re-duplicated.
std::vector<Point> raw_points;
for (auto i = 0u; i < vertices_size; i += 2) {
raw_points.emplace_back(Point{vertices[i], vertices[i + 1]});
}
for (auto i = 0u; i < indices_size; i++) {
auto point = raw_points[indices[i]];
points.push_back(point.x);
points.push_back(point.y);
}
return true;
}) != Tessellator::Result::kSuccess) {
return nullptr;
}

Expand Down
76 changes: 0 additions & 76 deletions impeller/tessellator/tessellator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,82 +53,6 @@ static int ToTessWindingRule(FillType fill_type) {
}

Tessellator::Result Tessellator::Tessellate(
FillType fill_type,
const Path::Polyline& polyline,
const VertexCallback& callback) const {
if (!callback) {
return Result::kInputError;
}

if (polyline.points.empty()) {
return Result::kInputError;
}

auto tessellator = c_tessellator_.get();
if (!tessellator) {
return Result::kTessellationError;
}

constexpr int kVertexSize = 2;
constexpr int kPolygonSize = 3;

//----------------------------------------------------------------------------
/// Feed contour information to the tessellator.
///
static_assert(sizeof(Point) == 2 * sizeof(float));
for (size_t contour_i = 0; contour_i < polyline.contours.size();
contour_i++) {
size_t start_point_index, end_point_index;
std::tie(start_point_index, end_point_index) =
polyline.GetContourPointBounds(contour_i);

::tessAddContour(tessellator, // the C tessellator
kVertexSize, //
polyline.points.data() + start_point_index, //
sizeof(Point), //
end_point_index - start_point_index //
);
}

//----------------------------------------------------------------------------
/// Let's tessellate.
///
auto result = ::tessTesselate(tessellator, // tessellator
ToTessWindingRule(fill_type), // winding
TESS_POLYGONS, // element type
kPolygonSize, // polygon size
kVertexSize, // vertex size
nullptr // normal (null is automatic)
);

if (result != 1) {
return Result::kTessellationError;
}

// TODO(csg): This copy can be elided entirely for the current use case.
std::vector<Point> points;
std::vector<uint32_t> indices;

int vertexItemCount = tessGetVertexCount(tessellator) * kVertexSize;
auto vertices = tessGetVertices(tessellator);
for (int i = 0; i < vertexItemCount; i += 2) {
points.emplace_back(vertices[i], vertices[i + 1]);
}

int elementItemCount = tessGetElementCount(tessellator) * kPolygonSize;
auto elements = tessGetElements(tessellator);
for (int i = 0; i < elementItemCount; i++) {
indices.emplace_back(elements[i]);
}

for (auto index : indices) {
auto vtx = points[index];
callback(vtx);
}
return Result::kSuccess;
}

Tessellator::Result Tessellator::TessellateBuilder(
FillType fill_type,
const Path::Polyline& polyline,
const BuilderCallback& callback) const {
Expand Down
21 changes: 3 additions & 18 deletions impeller/tessellator/tessellator.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,11 @@ class Tessellator {

~Tessellator();

using VertexCallback = std::function<void(Point)>;
using BuilderCallback = std::function<bool(const float* vertices,
size_t vertices_size,
const uint16_t* indices,
size_t indices_size)>;

//----------------------------------------------------------------------------
/// @brief Generates filled triangles from the polyline. A callback is
/// invoked for each vertex of the triangle.
///
/// @param[in] fill_type The fill rule to use when filling.
/// @param[in] polyline The polyline
/// @param[in] callback The callback
///
/// @return The result status of the tessellation.
///
Tessellator::Result Tessellate(FillType fill_type,
const Path::Polyline& polyline,
const VertexCallback& callback) const;

//----------------------------------------------------------------------------
/// @brief Generates filled triangles from the polyline. A callback is
/// invoked once for the entire tessellation.
Expand All @@ -73,9 +58,9 @@ class Tessellator {
///
/// @return The result status of the tessellation.
///
Tessellator::Result TessellateBuilder(FillType fill_type,
const Path::Polyline& polyline,
const BuilderCallback& callback) const;
Tessellator::Result Tessellate(FillType fill_type,
const Path::Polyline& polyline,
const BuilderCallback& callback) const;

private:
CTessellator c_tessellator_;
Expand Down
62 changes: 5 additions & 57 deletions impeller/tessellator/tessellator_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,64 +10,12 @@
namespace impeller {
namespace testing {

TEST(TessellatorTest, TessellatorReturnsCorrectResultStatus) {
// Zero points.
{
Tessellator t;
auto polyline = PathBuilder{}.TakePath().CreatePolyline();
Tessellator::Result result =
t.Tessellate(FillType::kPositive, polyline, [](Point point) {});

ASSERT_EQ(polyline.points.size(), 0u);
ASSERT_EQ(result, Tessellator::Result::kInputError);
}

// One point.
{
Tessellator t;
auto polyline = PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline();
Tessellator::Result result =
t.Tessellate(FillType::kPositive, polyline, [](Point point) {});

ASSERT_EQ(polyline.points.size(), 1u);
ASSERT_EQ(result, Tessellator::Result::kSuccess);
}

// Two points.
{
Tessellator t;
auto polyline =
PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline();
Tessellator::Result result =
t.Tessellate(FillType::kPositive, polyline, [](Point point) {});

ASSERT_EQ(polyline.points.size(), 2u);
ASSERT_EQ(result, Tessellator::Result::kSuccess);
}

// Many points.
{
Tessellator t;
PathBuilder builder;
for (int i = 0; i < 1000; i++) {
auto coord = i * 1.0f;
builder.AddLine({coord, coord}, {coord + 1, coord + 1});
}
auto polyline = builder.TakePath().CreatePolyline();
Tessellator::Result result =
t.Tessellate(FillType::kPositive, polyline, [](Point point) {});

ASSERT_EQ(polyline.points.size(), 2000u);
ASSERT_EQ(result, Tessellator::Result::kSuccess);
}
}

TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
// Zero points.
{
Tessellator t;
auto polyline = PathBuilder{}.TakePath().CreatePolyline();
Tessellator::Result result = t.TessellateBuilder(
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,
size_t indices_size) { return true; });
Expand All @@ -80,7 +28,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
{
Tessellator t;
auto polyline = PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline();
Tessellator::Result result = t.TessellateBuilder(
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,
size_t indices_size) { return true; });
Expand All @@ -93,7 +41,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
Tessellator t;
auto polyline =
PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline();
Tessellator::Result result = t.TessellateBuilder(
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,
size_t indices_size) { return true; });
Expand All @@ -111,7 +59,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
builder.AddLine({coord, coord}, {coord + 1, coord + 1});
}
auto polyline = builder.TakePath().CreatePolyline();
Tessellator::Result result = t.TessellateBuilder(
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,
size_t indices_size) { return true; });
Expand All @@ -125,7 +73,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
Tessellator t;
auto polyline =
PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline();
Tessellator::Result result = t.TessellateBuilder(
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,
size_t indices_size) { return false; });
Expand Down