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:
parent
d7b59c091d
commit
86d4cfdf8e
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()) {
|
||||
|
@ -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&);
|
||||
|
Loading…
Reference in New Issue
Block a user