Revert "Update GrTriangulator to count curves"

This reverts commit 8e2b69440a.

Bug: chromium:1075428
Change-Id: I0be8570193783981a995265d0446db219bc73a87
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/330576
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2020-11-03 13:51:21 -07:00 committed by Skia Commit-Bot
parent d7b59c091d
commit 86d4cfdf8e
5 changed files with 38 additions and 40 deletions

View File

@ -818,12 +818,12 @@ void generate_cubic_points(const SkPoint& p0,
// Stage 1: convert the input path to a set of linear contours (linked list of Vertices).
void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
VertexList* contours, SkArenaAlloc& alloc, Mode mode, int* numCountedCurves) {
VertexList* contours, SkArenaAlloc& alloc, Mode mode, bool *isLinear) {
SkScalar toleranceSqd = tolerance * tolerance;
bool innerPolygons = (Mode::kSimpleInnerPolygons == mode);
SkPoint pts[4];
int localCurveCount = 0;
*isLinear = true;
VertexList* contour = contours;
SkPath::Iter iter(path, false);
if (path.isInverseFillType()) {
@ -839,7 +839,7 @@ void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
switch (verb) {
case SkPath::kConic_Verb: {
++localCurveCount;
*isLinear = false;
if (innerPolygons) {
append_point_to_contour(pts[2], contour, alloc);
break;
@ -863,7 +863,7 @@ void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip
break;
}
case SkPath::kQuad_Verb: {
++localCurveCount;
*isLinear = false;
if (innerPolygons) {
append_point_to_contour(pts[2], contour, alloc);
break;
@ -872,7 +872,7 @@ void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip
break;
}
case SkPath::kCubic_Verb: {
++localCurveCount;
*isLinear = false;
if (innerPolygons) {
append_point_to_contour(pts[3], contour, alloc);
break;
@ -887,7 +887,6 @@ void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip
break;
}
}
*numCountedCurves = localCurveCount;
}
inline bool apply_fill_type(SkPathFillType fillType, int winding) {
@ -2371,7 +2370,7 @@ void* polys_to_triangles(Poly* polys, SkPathFillType fillType, Mode mode, void*
}
Poly* path_to_polys(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
int contourCnt, SkArenaAlloc& alloc, Mode mode, int* numCountedCurves,
int contourCnt, SkArenaAlloc& alloc, Mode mode, bool* isLinear,
VertexList* outerMesh) {
SkPathFillType fillType = path.getFillType();
if (SkPathFillType_IsInverse(fillType)) {
@ -2379,7 +2378,7 @@ Poly* path_to_polys(const SkPath& path, SkScalar tolerance, const SkRect& clipBo
}
std::unique_ptr<VertexList[]> contours(new VertexList[contourCnt]);
path_to_contours(path, tolerance, clipBounds, contours.get(), alloc, mode, numCountedCurves);
path_to_contours(path, tolerance, clipBounds, contours.get(), alloc, mode, isLinear);
return contours_to_polys(contours.get(), contourCnt, path.getFillType(), path.getBounds(),
mode, outerMesh, alloc);
}
@ -2459,16 +2458,16 @@ namespace GrTriangulator {
// Stage 6: Triangulate the monotone polygons into a vertex buffer.
int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
GrEagerVertexAllocator* vertexAllocator, Mode mode, int* numCountedCurves) {
GrEagerVertexAllocator* vertexAllocator, Mode mode, bool* isLinear) {
int contourCnt = get_contour_count(path, tolerance);
if (contourCnt <= 0) {
*numCountedCurves = 0;
*isLinear = true;
return 0;
}
SkArenaAlloc alloc(kArenaChunkSize);
VertexList outerMesh;
Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, mode,
numCountedCurves, &outerMesh);
isLinear, &outerMesh);
SkPathFillType fillType = (Mode::kEdgeAntialias == mode) ?
SkPathFillType::kWinding : path.getFillType();
int64_t count64 = count_points(polys, fillType);
@ -2506,9 +2505,9 @@ int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBou
return 0;
}
SkArenaAlloc alloc(kArenaChunkSize);
int numCountedCurves;
bool isLinear;
Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, Mode::kNormal,
&numCountedCurves, nullptr);
&isLinear, nullptr);
SkPathFillType fillType = path.getFillType();
int64_t count64 = count_points(polys, fillType);
if (0 == count64 || count64 > SK_MaxS32) {

View File

@ -56,7 +56,7 @@ constexpr size_t GetVertexStride(Mode mode) {
}
int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
GrEagerVertexAllocator*, Mode, int* numCountedCurves);
GrEagerVertexAllocator*, Mode, bool *isLinear);
} // namespace GrTriangulator
#endif

View File

@ -50,12 +50,12 @@ namespace {
// value.
struct TessInfo {
int fNumVertices;
int fNumCountedCurves;
bool fIsLinear;
SkScalar fTolerance;
};
static sk_sp<SkData> create_data(int numVertices, int numCountedCurves, SkScalar tol) {
TessInfo info { numVertices, numCountedCurves, tol };
static sk_sp<SkData> create_data(int numVertices, bool isLinear, SkScalar tol) {
TessInfo info { numVertices, isLinear, tol };
return SkData::MakeWithCopy(&info, sizeof(info));
}
@ -64,7 +64,7 @@ bool cache_match(const SkData* data, SkScalar tol) {
const TessInfo* info = static_cast<const TessInfo*>(data->data());
return info->fNumCountedCurves == 0 || info->fTolerance < 3.0f * tol;
return info->fIsLinear || info->fTolerance < 3.0f * tol;
}
// Should 'challenger' replace 'incumbent' in the cache if there is a collision?
@ -72,7 +72,7 @@ bool is_newer_better(SkData* incumbent, SkData* challenger) {
const TessInfo* i = static_cast<const TessInfo*>(incumbent->data());
const TessInfo* c = static_cast<const TessInfo*>(challenger->data());
if (i->fNumCountedCurves == 0 || i->fTolerance <= c->fTolerance) {
if (i->fIsLinear || i->fTolerance <= c->fTolerance) {
return false; // prefer the incumbent
}
@ -343,7 +343,7 @@ private:
const GrStyledShape& shape,
const SkIRect& devClipBounds,
SkScalar tol,
int* numCountedCurves) {
bool* isLinear) {
SkRect clipBounds = SkRect::Make(devClipBounds);
SkMatrix vmi;
@ -357,7 +357,7 @@ private:
shape.asPath(&path);
return GrTriangulator::PathToTriangles(path, tol, clipBounds, allocator,
GrTriangulator::Mode::kNormal, numCountedCurves);
GrTriangulator::Mode::kNormal, isLinear);
}
void createNonAAMesh(Target* target) {
@ -400,16 +400,16 @@ private:
bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
StaticVertexAllocator allocator(rp, canMapVB);
int numCountedCurves;
bool isLinear;
int vertexCount = Triangulate(&allocator, fViewMatrix, fShape, fDevClipBounds, tol,
&numCountedCurves);
&isLinear);
if (vertexCount == 0) {
return;
}
fVertexData = allocator.detachVertexData();
key.setCustomData(create_data(vertexCount, numCountedCurves, tol));
key.setCustomData(create_data(vertexCount, isLinear, tol));
auto [tmpV, tmpD] = threadSafeCache->addVertsWithData(key, fVertexData, is_newer_better);
if (tmpV != fVertexData) {
@ -439,11 +439,11 @@ private:
SkScalar tol = GrPathUtils::kDefaultTolerance;
sk_sp<const GrBuffer> vertexBuffer;
int firstVertex;
int numCountedCurves;
bool isLinear;
GrEagerDynamicVertexAllocator allocator(target, &vertexBuffer, &firstVertex);
int vertexCount = GrTriangulator::PathToTriangles(path, tol, clipBounds, &allocator,
GrTriangulator::Mode::kEdgeAntialias,
&numCountedCurves);
&isLinear);
if (vertexCount == 0) {
return;
}
@ -535,16 +535,16 @@ private:
CpuVertexAllocator allocator;
int numCountedCurves;
bool isLinear;
int vertexCount = Triangulate(&allocator, fViewMatrix, fShape, fDevClipBounds, tol,
&numCountedCurves);
&isLinear);
if (vertexCount == 0) {
return;
}
fVertexData = allocator.detachVertexData();
key.setCustomData(create_data(vertexCount, numCountedCurves, tol));
key.setCustomData(create_data(vertexCount, isLinear, tol));
// If some other thread created and cached its own triangulation, the 'is_newer_better'
// predicate will replace the version in the cache if 'fVertexData' is a more accurate

View File

@ -102,11 +102,11 @@ void GrPathTessellateOp::prePreparePrograms(const PrePrepareArgs& args) {
float gpuFragmentWork = bounds.height() * scales[0] * bounds.width() * scales[1];
float cpuTessellationWork = (float)numVerbs * SkNextLog2(numVerbs); // N log N.
if (cpuTessellationWork * 500 + (256 * 256) < gpuFragmentWork) { // Don't try below 256x256.
int numCountedCubics;
bool isLinear;
// This will fail if the inner triangles do not form a simple polygon (e.g., self
// intersection, double winding).
if (this->prePrepareInnerPolygonTriangulation(args, &numCountedCubics)) {
if (numCountedCubics > 0) {
if (this->prePrepareInnerPolygonTriangulation(args, &isLinear)) {
if (!isLinear) {
// Always use indirect draws for cubics instead of tessellation here. Our goal in
// this mode is to maximize GPU performance, and the middle-out topology used by our
// indirect draws is easier on the rasterizer than a tessellated fan. There also
@ -155,7 +155,7 @@ void GrPathTessellateOp::prePreparePrograms(const PrePrepareArgs& args) {
}
bool GrPathTessellateOp::prePrepareInnerPolygonTriangulation(const PrePrepareArgs& args,
int* numCountedCurves) {
bool* isLinear) {
SkASSERT(!fTriangleBuffer);
SkASSERT(fTriangleVertexCount == 0);
SkASSERT(!fStencilTrianglesProgram);
@ -166,7 +166,7 @@ bool GrPathTessellateOp::prePrepareInnerPolygonTriangulation(const PrePrepareArg
fTriangleVertexCount = GrTriangulator::PathToTriangles(fPath, 0, SkRect::MakeEmpty(),
args.fInnerTriangleAllocator,
Mode::kSimpleInnerPolygons,
numCountedCurves);
isLinear);
if (fTriangleVertexCount == 0) {
// Mode::kSimpleInnerPolygons causes PathToTriangles to fail if the inner polygon(s) are not
// simple.
@ -180,7 +180,7 @@ bool GrPathTessellateOp::prePrepareInnerPolygonTriangulation(const PrePrepareArg
// stencilled.
this->prePrepareStencilTrianglesProgram(args);
}
this->prePrepareFillTrianglesProgram(args, *numCountedCurves);
this->prePrepareFillTrianglesProgram(args, *isLinear);
return true;
}
@ -263,8 +263,7 @@ constexpr static GrUserStencilSettings kTestAndResetStencil(
GrUserStencilOp::kKeep,
0xffff>());
void GrPathTessellateOp::prePrepareFillTrianglesProgram(const PrePrepareArgs& args,
int numCountedCurves) {
void GrPathTessellateOp::prePrepareFillTrianglesProgram(const PrePrepareArgs& args, bool isLinear) {
SkASSERT(!fFillTrianglesProgram);
if (fOpFlags & OpFlags::kStencilOnly) {
@ -302,7 +301,7 @@ void GrPathTessellateOp::prePrepareFillTrianglesProgram(const PrePrepareArgs& ar
if (fStencilTrianglesProgram) {
// The path was already stencilled. Here we just need to do a cover pass.
stencil = &kTestAndResetStencil;
} else if (numCountedCurves == 0) {
} else if (isLinear) {
// There are no stencilled curves. We can ignore stencil and fill the path directly.
stencil = &GrUserStencilSettings::kUnused;
} else if (SkPathFillType::kWinding == fPath.getFillType()) {

View File

@ -75,13 +75,13 @@ private:
// Returns false if the inner triangles do not form a simple polygon (e.g., self intersection,
// double winding). Non-simple polygons would need to split edges in order to avoid overlap,
// and this is not an option as it would introduce T-junctions with the outer cubics.
bool prePrepareInnerPolygonTriangulation(const PrePrepareArgs&, int* numCountedCurves);
bool prePrepareInnerPolygonTriangulation(const PrePrepareArgs&, bool* isLinear);
void prePrepareStencilTrianglesProgram(const PrePrepareArgs&);
template<typename ShaderType> void prePrepareStencilCubicsProgram(const PrePrepareArgs&);
void prePreparePipelineForStencils(const PrePrepareArgs&);
void prePrepareFillTrianglesProgram(const PrePrepareArgs&, int numCountedCurves);
void prePrepareFillTrianglesProgram(const PrePrepareArgs&, bool isLinear);
void prePrepareFillCubicHullsProgram(const PrePrepareArgs&);
void prePrepareFillBoundingBoxProgram(const PrePrepareArgs&);
void prePreparePipelineForFills(const PrePrepareArgs&);