mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] revert non-zero tessellation optimization. (flutter/engine#48234)
Forgot about the winding order. partially reverts https://github.com/flutter/engine/pull/46282 See https://github.com/flutter/flutter/issues/138598 Reopens https://github.com/flutter/flutter/issues/135458
This commit is contained in:
parent
35434128d8
commit
2753839ce5
@ -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<Point> points;
|
||||
std::vector<float> 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);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// 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 //
|
||||
);
|
||||
}
|
||||
|
||||
::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)
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// 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;
|
||||
}
|
||||
|
||||
if (result != 1) {
|
||||
return Result::kTessellationError;
|
||||
}
|
||||
int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
|
||||
|
||||
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]);
|
||||
}
|
||||
// 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);
|
||||
|
||||
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();
|
||||
// libtess uses an int index internally due to usage of -1 as a sentinel
|
||||
// value.
|
||||
std::vector<uint16_t> indices(element_item_count);
|
||||
for (int i = 0; i < element_item_count; i++) {
|
||||
indices[i] = static_cast<uint16_t>(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);
|
||||
std::vector<Point> points;
|
||||
std::vector<float> data;
|
||||
|
||||
::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);
|
||||
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<uint16_t> indices(element_item_count);
|
||||
for (int i = 0; i < element_item_count; i++) {
|
||||
indices[i] = static_cast<uint16_t>(elements[i]);
|
||||
}
|
||||
if (!callback(vertices, vertex_item_count, indices.data(),
|
||||
element_item_count)) {
|
||||
return Result::kInputError;
|
||||
}
|
||||
} else {
|
||||
std::vector<Point> points;
|
||||
std::vector<float> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user