diff --git a/impeller/tessellator/tessellator.cc b/impeller/tessellator/tessellator.cc index ec6b51974c1ba..292b1f29ecac1 100644 --- a/impeller/tessellator/tessellator.cc +++ b/impeller/tessellator/tessellator.cc @@ -89,142 +89,81 @@ Tessellator::Result Tessellator::Tessellate(const Path& path, constexpr int kVertexSize = 2; constexpr int kPolygonSize = 3; - // If we have a larger polyline and the fill type is non-zero, we can split - // the tessellation up per contour. Since in general the complexity is at - // least nlog(n), this speeds up the processes substantially. - if (polyline.contours.size() > kMultiContourThreshold && - fill_type == FillType::kNonZero) { - std::vector points; - std::vector data; + //---------------------------------------------------------------------------- + /// 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 // + ); + } - //---------------------------------------------------------------------------- - /// Feed contour information to the tessellator. - /// - size_t total = 0u; - 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; - } - - int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize; - auto vertices = tessGetVertices(tessellator); - for (int i = 0; i < vertex_item_count; i += 2) { - points.emplace_back(vertices[i], vertices[i + 1]); - } - - int element_item_count = tessGetElementCount(tessellator) * kPolygonSize; - auto elements = tessGetElements(tessellator); - total += element_item_count; - for (int i = 0; i < element_item_count; i++) { - data.emplace_back(points[elements[i]].x); - data.emplace_back(points[elements[i]].y); - } - points.clear(); + //---------------------------------------------------------------------------- + /// 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; + } + + int element_item_count = tessGetElementCount(tessellator) * kPolygonSize; + + // We default to using a 16bit index buffer, but in cases where we generate + // more tessellated data than this can contain we need to fall back to + // dropping the index buffer entirely. Instead code could instead switch to + // a uint32 index buffer, but this is done for simplicity with the other + // fast path above. + if (element_item_count < USHRT_MAX) { + int vertex_item_count = tessGetVertexCount(tessellator); + auto vertices = tessGetVertices(tessellator); + auto elements = tessGetElements(tessellator); + + // libtess uses an int index internally due to usage of -1 as a sentinel + // value. + std::vector indices(element_item_count); + for (int i = 0; i < element_item_count; i++) { + indices[i] = static_cast(elements[i]); } - if (!callback(data.data(), total, nullptr, 0u)) { + if (!callback(vertices, vertex_item_count, indices.data(), + element_item_count)) { return Result::kInputError; } } else { - //---------------------------------------------------------------------------- - /// 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) - ); + std::vector points; + std::vector data; - if (result != 1) { - return Result::kTessellationError; + int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize; + auto vertices = tessGetVertices(tessellator); + points.reserve(vertex_item_count); + for (int i = 0; i < vertex_item_count; i += 2) { + points.emplace_back(vertices[i], vertices[i + 1]); } int element_item_count = tessGetElementCount(tessellator) * kPolygonSize; - - // We default to using a 16bit index buffer, but in cases where we generate - // more tessellated data than this can contain we need to fall back to - // dropping the index buffer entirely. Instead code could instead switch to - // a uint32 index buffer, but this is done for simplicity with the other - // fast path above. - if (element_item_count < USHRT_MAX) { - int vertex_item_count = tessGetVertexCount(tessellator); - auto vertices = tessGetVertices(tessellator); - auto elements = tessGetElements(tessellator); - - // libtess uses an int index internally due to usage of -1 as a sentinel - // value. - std::vector indices(element_item_count); - for (int i = 0; i < element_item_count; i++) { - indices[i] = static_cast(elements[i]); - } - if (!callback(vertices, vertex_item_count, indices.data(), - element_item_count)) { - return Result::kInputError; - } - } else { - std::vector points; - std::vector data; - - int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize; - auto vertices = tessGetVertices(tessellator); - points.reserve(vertex_item_count); - for (int i = 0; i < vertex_item_count; i += 2) { - points.emplace_back(vertices[i], vertices[i + 1]); - } - - int element_item_count = tessGetElementCount(tessellator) * kPolygonSize; - auto elements = tessGetElements(tessellator); - data.reserve(element_item_count); - for (int i = 0; i < element_item_count; i++) { - data.emplace_back(points[elements[i]].x); - data.emplace_back(points[elements[i]].y); - } - if (!callback(data.data(), element_item_count, nullptr, 0u)) { - return Result::kInputError; - } + auto elements = tessGetElements(tessellator); + data.reserve(element_item_count); + for (int i = 0; i < element_item_count; i++) { + data.emplace_back(points[elements[i]].x); + data.emplace_back(points[elements[i]].y); + } + if (!callback(data.data(), element_item_count, nullptr, 0u)) { + return Result::kInputError; } } diff --git a/impeller/tessellator/tessellator.h b/impeller/tessellator/tessellator.h index 958659a509423..282b47b4829ed 100644 --- a/impeller/tessellator/tessellator.h +++ b/impeller/tessellator/tessellator.h @@ -45,10 +45,6 @@ class Tessellator { ~Tessellator(); - /// @brief An arbitrary value to determine when a multi-contour non-zero fill - /// path should be split into multiple tessellations. - static constexpr size_t kMultiContourThreshold = 30u; - /// @brief A callback that returns the results of the tessellation. /// /// The index buffer may not be populated, in which case [indices] will diff --git a/impeller/tessellator/tessellator_unittests.cc b/impeller/tessellator/tessellator_unittests.cc index 02e848e473cba..b1c807f58f4ab 100644 --- a/impeller/tessellator/tessellator_unittests.cc +++ b/impeller/tessellator/tessellator_unittests.cc @@ -79,27 +79,6 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { ASSERT_EQ(result, Tessellator::Result::kInputError); } - // More than 30 contours, non-zero fill mode. - { - Tessellator t; - PathBuilder builder = {}; - for (auto i = 0u; i < Tessellator::kMultiContourThreshold + 1; i++) { - builder.AddCircle(Point(i, i), 4); - } - auto path = builder.TakePath(FillType::kNonZero); - bool no_indices = false; - Tessellator::Result result = t.Tessellate( - path, 1.0f, - [&no_indices](const float* vertices, size_t vertices_count, - const uint16_t* indices, size_t indices_count) { - no_indices = indices == nullptr; - return true; - }); - - ASSERT_TRUE(no_indices); - ASSERT_EQ(result, Tessellator::Result::kSuccess); - } - // More than uint16 points, odd fill mode. { Tessellator t;