Revert "Revert "Support combining per-vertex coverage with color in default GP vertex shader""
This reverts commit ded032c4c989d3ab6fe74db351cdba858aca04ea.
Bug: skia:
Change-Id: I89a0ef492c1930c9ba248fc0a92bc054f2f17205
Reviewed-on: https://skia-review.googlesource.com/c/181840
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp
index 172b6d8..3a81a25 100644
--- a/src/gpu/GrDefaultGeoProcFactory.cpp
+++ b/src/gpu/GrDefaultGeoProcFactory.cpp
@@ -29,7 +29,8 @@
kColorAttributeIsWide_GPFlag = 0x4,
kLocalCoordAttribute_GPFlag = 0x8,
kCoverageAttribute_GPFlag = 0x10,
- kBonesAttribute_GPFlag = 0x20,
+ kCoverageAttributeTweak_GPFlag = 0x20,
+ kBonesAttribute_GPFlag = 0x40,
};
static constexpr int kNumVec2sPerBone = 3; // Our bone matrices are 3x2 matrices passed in as
@@ -83,13 +84,26 @@
// emit attributes
varyingHandler->emitAttributes(gp);
+ bool tweakAlpha = SkToBool(gp.fFlags & kCoverageAttributeTweak_GPFlag);
+ SkASSERT(!tweakAlpha || gp.hasVertexCoverage());
+
// Setup pass through color
- if (gp.hasVertexColor()) {
+ if (gp.hasVertexColor() || tweakAlpha) {
GrGLSLVarying varying(kHalf4_GrSLType);
varyingHandler->addVarying("color", &varying);
- // There are several optional steps to process the color. Start with the attribute:
- vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
+ // There are several optional steps to process the color. Start with the attribute,
+ // or with uniform color (in the case of folding coverage into a uniform color):
+ if (gp.hasVertexColor()) {
+ vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
+ } else {
+ const char* colorUniformName;
+ fColorUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
+ kHalf4_GrSLType,
+ "Color",
+ &colorUniformName);
+ vertBuilder->codeAppendf("half4 color = %s;", colorUniformName);
+ }
// For SkColor, do a red/blue swap, possible color space conversion, and premul
if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) {
@@ -107,6 +121,10 @@
vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
}
+ // Optionally fold coverage into alpha (color).
+ if (tweakAlpha) {
+ vertBuilder->codeAppendf("color = color * %s;", gp.fInCoverage.name());
+ }
vertBuilder->codeAppendf("%s = color;\n", varying.vsOut());
fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
} else {
@@ -192,7 +210,7 @@
}
// Setup coverage as pass through
- if (gp.hasVertexCoverage()) {
+ if (gp.hasVertexCoverage() && !tweakAlpha) {
fragBuilder->codeAppendf("half alpha = 1.0;");
varyingHandler->addPassThroughAttribute(gp.fInCoverage, "alpha");
fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
@@ -213,8 +231,8 @@
GrProcessorKeyBuilder* b) {
const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
uint32_t key = def.fFlags;
- key |= (def.coverage() == 0xff) ? 0x40 : 0;
- key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x80 : 0x0;
+ key |= (def.coverage() == 0xff) ? 0x80 : 0;
+ key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x100 : 0;
key |= ComputePosKey(def.viewMatrix()) << 20;
b->add32(key);
b->add32(GrColorSpaceXform::XformKey(def.fColorSpaceXform.get()));
@@ -396,6 +414,9 @@
}
if (d->fRandom->nextBool()) {
flags |= kCoverageAttribute_GPFlag;
+ if (d->fRandom->nextBool()) {
+ flags |= kCoverageAttributeTweak_GPFlag;
+ }
}
if (d->fRandom->nextBool()) {
flags |= kLocalCoordAttribute_GPFlag;
@@ -430,7 +451,11 @@
} else if (Color::kPremulWideColorAttribute_Type == color.fType) {
flags |= kColorAttribute_GPFlag | kColorAttributeIsWide_GPFlag;
}
- flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverageAttribute_GPFlag : 0;
+ if (Coverage::kAttribute_Type == coverage.fType) {
+ flags |= kCoverageAttribute_GPFlag;
+ } else if (Coverage::kAttributeTweakAlpha_Type == coverage.fType) {
+ flags |= kCoverageAttribute_GPFlag | kCoverageAttributeTweak_GPFlag;
+ }
flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoordAttribute_GPFlag : 0;
uint8_t inCoverage = coverage.fCoverage;
@@ -484,7 +509,11 @@
} else if (Color::kPremulWideColorAttribute_Type == color.fType) {
flags |= kColorAttribute_GPFlag | kColorAttributeIsWide_GPFlag;
}
- flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverageAttribute_GPFlag : 0;
+ if (Coverage::kAttribute_Type == coverage.fType) {
+ flags |= kCoverageAttribute_GPFlag;
+ } else if (Coverage::kAttributeTweakAlpha_Type == coverage.fType) {
+ flags |= kCoverageAttribute_GPFlag | kCoverageAttributeTweak_GPFlag;
+ }
flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoordAttribute_GPFlag : 0;
flags |= kBonesAttribute_GPFlag;
diff --git a/src/gpu/GrDefaultGeoProcFactory.h b/src/gpu/GrDefaultGeoProcFactory.h
index af33668..96363f0 100644
--- a/src/gpu/GrDefaultGeoProcFactory.h
+++ b/src/gpu/GrDefaultGeoProcFactory.h
@@ -50,6 +50,7 @@
kSolid_Type,
kUniform_Type,
kAttribute_Type,
+ kAttributeTweakAlpha_Type,
};
explicit Coverage(uint8_t coverage) : fType(kUniform_Type), fCoverage(coverage) {}
Coverage(Type type) : fType(type), fCoverage(0xff) {
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index 19b859e..b753707 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -175,10 +175,17 @@
/***************************************************************************************/
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
struct AAParams {
bool fTweakAlpha;
GrColor fColor;
};
+#define AA_PARAM const AAParams* aaParams
+#define AA_ARG aaParams
+#else
+#define AA_PARAM bool emitCoverage
+#define AA_ARG emitCoverage
+#endif
typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
@@ -199,10 +206,11 @@
Direction fDirection;
};
-inline void* emit_vertex(Vertex* v, const AAParams* aaParams, void* data) {
+inline void* emit_vertex(Vertex* v, AA_PARAM, void* data) {
GrVertexWriter verts{data};
verts.write(v->fPoint);
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
if (aaParams) {
if (aaParams->fTweakAlpha) {
verts.write(SkAlphaMulQ(aaParams->fColor, SkAlpha255To256(v->fAlpha)));
@@ -210,24 +218,29 @@
verts.write(aaParams->fColor, GrNormalizeByteToFloat(v->fAlpha));
}
}
+#else
+ if (emitCoverage) {
+ verts.write(GrNormalizeByteToFloat(v->fAlpha));
+ }
+#endif
return verts.fPtr;
}
-void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, const AAParams* aaParams, void* data) {
+void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, AA_PARAM, void* data) {
LOG("emit_triangle %g (%g, %g) %d\n", v0->fID, v0->fPoint.fX, v0->fPoint.fY, v0->fAlpha);
LOG(" %g (%g, %g) %d\n", v1->fID, v1->fPoint.fX, v1->fPoint.fY, v1->fAlpha);
LOG(" %g (%g, %g) %d\n", v2->fID, v2->fPoint.fX, v2->fPoint.fY, v2->fAlpha);
#if TESSELLATOR_WIREFRAME
- data = emit_vertex(v0, aaParams, data);
- data = emit_vertex(v1, aaParams, data);
- data = emit_vertex(v1, aaParams, data);
- data = emit_vertex(v2, aaParams, data);
- data = emit_vertex(v2, aaParams, data);
- data = emit_vertex(v0, aaParams, data);
+ data = emit_vertex(v0, AA_ARG, data);
+ data = emit_vertex(v1, AA_ARG, data);
+ data = emit_vertex(v1, AA_ARG, data);
+ data = emit_vertex(v2, AA_ARG, data);
+ data = emit_vertex(v2, AA_ARG, data);
+ data = emit_vertex(v0, AA_ARG, data);
#else
- data = emit_vertex(v0, aaParams, data);
- data = emit_vertex(v1, aaParams, data);
- data = emit_vertex(v2, aaParams, data);
+ data = emit_vertex(v0, AA_ARG, data);
+ data = emit_vertex(v1, AA_ARG, data);
+ data = emit_vertex(v2, AA_ARG, data);
#endif
return data;
}
@@ -553,7 +566,7 @@
}
}
- void* emit(const AAParams* aaParams, void* data) {
+ void* emit(AA_PARAM, void* data) {
Edge* e = fFirstEdge;
VertexList vertices;
vertices.append(e->fTop);
@@ -576,14 +589,14 @@
Vertex* curr = v;
Vertex* next = v->fNext;
if (count == 3) {
- return emit_triangle(prev, curr, next, aaParams, data);
+ return emit_triangle(prev, curr, next, AA_ARG, data);
}
double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.fX;
double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.fY;
double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.fX;
double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.fY;
if (ax * by - ay * bx >= 0.0) {
- data = emit_triangle(prev, curr, next, aaParams, data);
+ data = emit_triangle(prev, curr, next, AA_ARG, data);
v->fPrev->fNext = v->fNext;
v->fNext->fPrev = v->fPrev;
count--;
@@ -640,13 +653,13 @@
}
return poly;
}
- void* emit(const AAParams* aaParams, void *data) {
+ void* emit(AA_PARAM, void *data) {
if (fCount < 3) {
return data;
}
LOG("emit() %d, size %d\n", fID, fCount);
for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) {
- data = m->emit(aaParams, data);
+ data = m->emit(AA_ARG, data);
}
return data;
}
@@ -2166,11 +2179,10 @@
}
// Stage 6: Triangulate the monotone polygons into a vertex buffer.
-void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, const AAParams* aaParams,
- void* data) {
+void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, AA_PARAM, void* data) {
for (Poly* poly = polys; poly; poly = poly->fNext) {
if (apply_fill_type(fillType, poly)) {
- data = poly->emit(aaParams, data);
+ data = poly->emit(AA_ARG, data);
}
}
return data;
@@ -2219,15 +2231,15 @@
return count;
}
-void* outer_mesh_to_triangles(const VertexList& outerMesh, const AAParams* aaParams, void* data) {
+void* outer_mesh_to_triangles(const VertexList& outerMesh, AA_PARAM, void* data) {
for (Vertex* v = outerMesh.fHead; v; v = v->fNext) {
for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
Vertex* v0 = e->fTop;
Vertex* v1 = e->fBottom;
Vertex* v2 = e->fBottom->fPartner;
Vertex* v3 = e->fTop->fPartner;
- data = emit_triangle(v0, v1, v2, aaParams, data);
- data = emit_triangle(v0, v2, v3, aaParams, data);
+ data = emit_triangle(v0, v1, v2, AA_ARG, data);
+ data = emit_triangle(v0, v2, v3, AA_ARG, data);
}
}
return data;
@@ -2240,8 +2252,11 @@
// Stage 6: Triangulate the monotone polygons into a vertex buffer.
int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
- VertexAllocator* vertexAllocator, bool antialias, const GrColor& color,
- bool canTweakAlphaForCoverage, bool* isLinear) {
+ VertexAllocator* vertexAllocator, bool antialias,
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
+ const GrColor& color, bool canTweakAlphaForCoverage,
+#endif
+ bool* isLinear) {
int contourCnt = get_contour_count(path, tolerance);
if (contourCnt <= 0) {
*isLinear = true;
@@ -2268,12 +2283,17 @@
}
LOG("emitting %d verts\n", count);
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
AAParams aaParams;
aaParams.fTweakAlpha = canTweakAlphaForCoverage;
aaParams.fColor = color;
-
void* end = polys_to_triangles(polys, fillType, antialias ? &aaParams : nullptr, verts);
end = outer_mesh_to_triangles(outerMesh, &aaParams, end);
+#else
+ void* end = polys_to_triangles(polys, fillType, antialias, verts);
+ end = outer_mesh_to_triangles(outerMesh, true, end);
+#endif
+
int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast<uint8_t*>(verts))
/ vertexAllocator->stride());
SkASSERT(actualCount <= count);
@@ -2307,7 +2327,11 @@
for (Poly* poly = polys; poly; poly = poly->fNext) {
if (apply_fill_type(fillType, poly)) {
SkPoint* start = pointsEnd;
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
pointsEnd = static_cast<SkPoint*>(poly->emit(nullptr, pointsEnd));
+#else
+ pointsEnd = static_cast<SkPoint*>(poly->emit(false, pointsEnd));
+#endif
while (start != pointsEnd) {
vertsEnd->fPos = *start;
vertsEnd->fWinding = poly->fWinding;
diff --git a/src/gpu/GrTessellator.h b/src/gpu/GrTessellator.h
index 4f82ea8..324a72c 100644
--- a/src/gpu/GrTessellator.h
+++ b/src/gpu/GrTessellator.h
@@ -47,8 +47,11 @@
WindingVertex** verts);
int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
- VertexAllocator*, bool antialias, const GrColor& color,
- bool canTweakAlphaForCoverage, bool *isLinear);
+ VertexAllocator*, bool antialias,
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
+ const GrColor& color, bool canTweakAlphaForCoverage,
+#endif
+ bool *isLinear);
}
#endif
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index 52785eb..1b36698 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -82,13 +82,17 @@
// extract the result vertices and indices from the GrAAConvexTessellator
static void extract_verts(const GrAAConvexTessellator& tess,
void* vertData,
- size_t vertexStride,
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
GrColor color,
+#else
+ const GrVertexColor& color,
+#endif
uint16_t firstIndex,
uint16_t* idxs,
bool tweakAlphaForCoverage) {
GrVertexWriter verts{vertData};
for (int i = 0; i < tess.numPts(); ++i) {
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
verts.write(tess.point(i));
if (tweakAlphaForCoverage) {
SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255);
@@ -98,6 +102,9 @@
} else {
verts.write(color, tess.coverage(i));
}
+#else
+ verts.write(tess.point(i), color, tess.coverage(i));
+#endif
}
for (int i = 0; i < tess.numIndices(); ++i) {
@@ -108,22 +115,23 @@
static sk_sp<GrGeometryProcessor> create_lines_only_gp(const GrShaderCaps* shaderCaps,
bool tweakAlphaForCoverage,
const SkMatrix& viewMatrix,
- bool usesLocalCoords) {
+ bool usesLocalCoords,
+ bool wideColor) {
using namespace GrDefaultGeoProcFactory;
- Coverage::Type coverageType;
- if (tweakAlphaForCoverage) {
- coverageType = Coverage::kSolid_Type;
- } else {
- coverageType = Coverage::kAttribute_Type;
- }
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
+ Coverage::Type coverageType =
+ tweakAlphaForCoverage ? Coverage::kSolid_Type : Coverage::kAttribute_Type;
+#else
+ Coverage::Type coverageType =
+ tweakAlphaForCoverage ? Coverage::kAttributeTweakAlpha_Type : Coverage::kAttribute_Type;
+#endif
LocalCoords::Type localCoordsType =
- usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
- return MakeForDeviceSpace(shaderCaps,
- Color::kPremulGrColorAttribute_Type,
- coverageType,
- localCoordsType,
- viewMatrix);
+ usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
+ Color::Type colorType =
+ wideColor ? Color::kPremulWideColorAttribute_Type : Color::kPremulGrColorAttribute_Type;
+
+ return MakeForDeviceSpace(shaderCaps, colorType, coverageType, localCoordsType, viewMatrix);
}
namespace {
@@ -174,6 +182,11 @@
bounds.outset(w, w);
}
this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo);
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
+ fWideColor = false;
+#else
+ fWideColor = !SkPMColor4fFitsInBytes(color);
+#endif
}
const char* name() const override { return "AAFlatteningConvexPathOp"; }
@@ -243,7 +256,8 @@
sk_sp<GrGeometryProcessor> gp(create_lines_only_gp(target->caps().shaderCaps(),
fHelper.compatibleWithAlphaAsCoverage(),
this->viewMatrix(),
- fHelper.usesLocalCoords()));
+ fHelper.usesLocalCoords(),
+ fWideColor));
if (!gp) {
SkDebugf("Couldn't create a GrGeometryProcessor\n");
return;
@@ -296,9 +310,13 @@
indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t));
}
- // TODO4F: Preserve float colors
- extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride,
- args.fColor.toBytes_RGBA(), vertexCount, indices + indexCount,
+ extract_verts(tess, vertices + vertexStride * vertexCount,
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
+ args.fColor.toBytes_RGBA(),
+#else
+ GrVertexColor(args.fColor, fWideColor),
+#endif
+ vertexCount, indices + indexCount,
fHelper.compatibleWithAlphaAsCoverage());
vertexCount += currentVertices;
indexCount += currentIndices;
@@ -318,6 +336,7 @@
}
fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
+ fWideColor |= that->fWideColor;
return CombineResult::kMerged;
}
@@ -335,6 +354,7 @@
SkSTArray<1, PathData, true> fPaths;
Helper fHelper;
+ bool fWideColor;
typedef GrMeshDrawOp INHERITED;
};
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index a59c161..28ad083 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -277,8 +277,11 @@
bool isLinear;
bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
StaticVertexAllocator allocator(vertexStride, rp, canMapVB);
- int count = GrTessellator::PathToTriangles(getPath(), tol, clipBounds, &allocator,
- false, GrColor(), false, &isLinear);
+ int count = GrTessellator::PathToTriangles(getPath(), tol, clipBounds, &allocator, false,
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
+ GrColor(), false,
+#endif
+ &isLinear);
if (count == 0) {
return;
}
@@ -302,11 +305,12 @@
SkScalar tol = GrPathUtils::kDefaultTolerance;
bool isLinear;
DynamicVertexAllocator allocator(vertexStride, target);
- // TODO4F: Preserve float colors
- int count =
- GrTessellator::PathToTriangles(path, tol, clipBounds, &allocator, true,
- fColor.toBytes_RGBA(),
- fHelper.compatibleWithAlphaAsCoverage(), &isLinear);
+ int count = GrTessellator::PathToTriangles(path, tol, clipBounds, &allocator, true,
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
+ fColor.toBytes_RGBA(),
+ fHelper.compatibleWithAlphaAsCoverage(),
+#endif
+ &isLinear);
if (count == 0) {
return;
}
@@ -325,9 +329,15 @@
: LocalCoords::kUnused_Type;
Coverage::Type coverageType;
if (fAntiAlias) {
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
color = Color(Color::kPremulGrColorAttribute_Type);
+#endif
if (fHelper.compatibleWithAlphaAsCoverage()) {
+#ifdef SK_LEGACY_TESSELLATOR_CPU_COVERAGE
coverageType = Coverage::kSolid_Type;
+#else
+ coverageType = Coverage::kAttributeTweakAlpha_Type;
+#endif
} else {
coverageType = Coverage::kAttribute_Type;
}