Use GrVertexWriter and support half-float colors in rrect ops
Bug: skia:
Change-Id: Id33ead33cdcd8c4e6b034a33ba0e555a1374b2d4
Reviewed-on: https://skia-review.googlesource.com/c/175426
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index c392364..0c2946c 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -30,14 +30,6 @@
namespace {
-struct EllipseVertex {
- SkPoint fPos;
- GrColor fColor;
- SkPoint fOffset;
- SkPoint fOuterRadii;
- SkPoint fInnerRadii;
-};
-
static inline bool circle_stays_circle(const SkMatrix& m) { return m.isSimilarity(); }
static inline GrPrimitiveProcessor::Attribute color_attribute(bool wideColor) {
@@ -2272,6 +2264,7 @@
fVertCount = rrect_type_to_vert_count(type);
fIndexCount = rrect_type_to_index_count(type);
fAllFill = (kFill_RRectType == type);
+ fWideColor = !SkPMColor4fFitsInBytes(color);
}
const char* name() const override { return "CircularRRectOp"; }
@@ -2307,79 +2300,54 @@
FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
private:
- struct CircleVertex {
- SkPoint fPos;
- GrColor fColor;
- SkPoint fOffset;
- SkScalar fOuterRadius;
- SkScalar fInnerRadius;
- // No half plane, we don't use it here.
- };
-
- static void FillInOverstrokeVerts(CircleVertex** verts, const SkRect& bounds, SkScalar smInset,
+ static void FillInOverstrokeVerts(GrVertexWriter& verts, const SkRect& bounds, SkScalar smInset,
SkScalar bigInset, SkScalar xOffset, SkScalar outerRadius,
- SkScalar innerRadius, GrColor color) {
+ SkScalar innerRadius, const GrVertexColor& color) {
SkASSERT(smInset < bigInset);
// TL
- (*verts)->fPos = SkPoint::Make(bounds.fLeft + smInset, bounds.fTop + smInset);
- (*verts)->fColor = color;
- (*verts)->fOffset = SkPoint::Make(xOffset, 0);
- (*verts)->fOuterRadius = outerRadius;
- (*verts)->fInnerRadius = innerRadius;
- (*verts)++;
+ verts.write(bounds.fLeft + smInset, bounds.fTop + smInset,
+ color,
+ xOffset, 0.0f,
+ outerRadius, innerRadius);
// TR
- (*verts)->fPos = SkPoint::Make(bounds.fRight - smInset, bounds.fTop + smInset);
- (*verts)->fColor = color;
- (*verts)->fOffset = SkPoint::Make(xOffset, 0);
- (*verts)->fOuterRadius = outerRadius;
- (*verts)->fInnerRadius = innerRadius;
- (*verts)++;
+ verts.write(bounds.fRight - smInset, bounds.fTop + smInset,
+ color,
+ xOffset, 0.0f,
+ outerRadius, innerRadius);
- (*verts)->fPos = SkPoint::Make(bounds.fLeft + bigInset, bounds.fTop + bigInset);
- (*verts)->fColor = color;
- (*verts)->fOffset = SkPoint::Make(0, 0);
- (*verts)->fOuterRadius = outerRadius;
- (*verts)->fInnerRadius = innerRadius;
- (*verts)++;
+ verts.write(bounds.fLeft + bigInset, bounds.fTop + bigInset,
+ color,
+ 0.0f, 0.0f,
+ outerRadius, innerRadius);
- (*verts)->fPos = SkPoint::Make(bounds.fRight - bigInset, bounds.fTop + bigInset);
- (*verts)->fColor = color;
- (*verts)->fOffset = SkPoint::Make(0, 0);
- (*verts)->fOuterRadius = outerRadius;
- (*verts)->fInnerRadius = innerRadius;
- (*verts)++;
+ verts.write(bounds.fRight - bigInset, bounds.fTop + bigInset,
+ color,
+ 0.0f, 0.0f,
+ outerRadius, innerRadius);
- (*verts)->fPos = SkPoint::Make(bounds.fLeft + bigInset, bounds.fBottom - bigInset);
- (*verts)->fColor = color;
- (*verts)->fOffset = SkPoint::Make(0, 0);
- (*verts)->fOuterRadius = outerRadius;
- (*verts)->fInnerRadius = innerRadius;
- (*verts)++;
+ verts.write(bounds.fLeft + bigInset, bounds.fBottom - bigInset,
+ color,
+ 0.0f, 0.0f,
+ outerRadius, innerRadius);
- (*verts)->fPos = SkPoint::Make(bounds.fRight - bigInset, bounds.fBottom - bigInset);
- (*verts)->fColor = color;
- (*verts)->fOffset = SkPoint::Make(0, 0);
- (*verts)->fOuterRadius = outerRadius;
- (*verts)->fInnerRadius = innerRadius;
- (*verts)++;
+ verts.write(bounds.fRight - bigInset, bounds.fBottom - bigInset,
+ color,
+ 0.0f, 0.0f,
+ outerRadius, innerRadius);
// BL
- (*verts)->fPos = SkPoint::Make(bounds.fLeft + smInset, bounds.fBottom - smInset);
- (*verts)->fColor = color;
- (*verts)->fOffset = SkPoint::Make(xOffset, 0);
- (*verts)->fOuterRadius = outerRadius;
- (*verts)->fInnerRadius = innerRadius;
- (*verts)++;
+ verts.write(bounds.fLeft + smInset, bounds.fBottom - smInset,
+ color,
+ xOffset, 0.0f,
+ outerRadius, innerRadius);
// BR
- (*verts)->fPos = SkPoint::Make(bounds.fRight - smInset, bounds.fBottom - smInset);
- (*verts)->fColor = color;
- (*verts)->fOffset = SkPoint::Make(xOffset, 0);
- (*verts)->fOuterRadius = outerRadius;
- (*verts)->fInnerRadius = innerRadius;
- (*verts)++;
+ verts.write(bounds.fRight - smInset, bounds.fBottom - smInset,
+ color,
+ xOffset, 0.0f,
+ outerRadius, innerRadius);
}
void onPrepareDraws(Target* target) override {
@@ -2391,17 +2359,15 @@
// Setup geometry processor
sk_sp<GrGeometryProcessor> gp(
- new CircleGeometryProcessor(!fAllFill, false, false, false, false, false,
+ new CircleGeometryProcessor(!fAllFill, false, false, false, false, fWideColor,
localMatrix));
- SkASSERT(sizeof(CircleVertex) == gp->vertexStride());
-
const GrBuffer* vertexBuffer;
int firstVertex;
- CircleVertex* verts = (CircleVertex*)target->makeVertexSpace(
- sizeof(CircleVertex), fVertCount, &vertexBuffer, &firstVertex);
- if (!verts) {
+ GrVertexWriter verts{target->makeVertexSpace(gp->vertexStride(), fVertCount,
+ &vertexBuffer, &firstVertex)};
+ if (!verts.fPtr) {
SkDebugf("Could not allocate vertices\n");
return;
}
@@ -2416,8 +2382,7 @@
int currStartVertex = 0;
for (const auto& rrect : fRRects) {
- // TODO4F: Preserve float colors
- GrColor color = rrect.fColor.toBytes_RGBA();
+ GrVertexColor color(rrect.fColor, fWideColor);
SkScalar outerRadius = rrect.fOuterRadius;
const SkRect& bounds = rrect.fDevBounds;
@@ -2431,33 +2396,25 @@
? rrect.fInnerRadius / rrect.fOuterRadius
: -1.0f / rrect.fOuterRadius;
for (int i = 0; i < 4; ++i) {
- verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]);
- verts->fColor = color;
- verts->fOffset = SkPoint::Make(-1, yOuterRadii[i]);
- verts->fOuterRadius = outerRadius;
- verts->fInnerRadius = innerRadius;
- verts++;
+ verts.write(bounds.fLeft, yCoords[i],
+ color,
+ -1.0f, yOuterRadii[i],
+ outerRadius, innerRadius);
- verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[i]);
- verts->fColor = color;
- verts->fOffset = SkPoint::Make(0, yOuterRadii[i]);
- verts->fOuterRadius = outerRadius;
- verts->fInnerRadius = innerRadius;
- verts++;
+ verts.write(bounds.fLeft + outerRadius, yCoords[i],
+ color,
+ 0.0f, yOuterRadii[i],
+ outerRadius, innerRadius);
- verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords[i]);
- verts->fColor = color;
- verts->fOffset = SkPoint::Make(0, yOuterRadii[i]);
- verts->fOuterRadius = outerRadius;
- verts->fInnerRadius = innerRadius;
- verts++;
+ verts.write(bounds.fRight - outerRadius, yCoords[i],
+ color,
+ 0.0f, yOuterRadii[i],
+ outerRadius, innerRadius);
- verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]);
- verts->fColor = color;
- verts->fOffset = SkPoint::Make(1, yOuterRadii[i]);
- verts->fOuterRadius = outerRadius;
- verts->fInnerRadius = innerRadius;
- verts++;
+ verts.write(bounds.fRight, yCoords[i],
+ color,
+ 1.0f, yOuterRadii[i],
+ outerRadius, innerRadius);
}
// Add the additional vertices for overstroked rrects.
// Effectively this is an additional stroked rrect, with its
@@ -2475,7 +2432,7 @@
// geometry to the outer edge
SkScalar maxOffset = -rrect.fInnerRadius / overstrokeOuterRadius;
- FillInOverstrokeVerts(&verts, bounds, outerRadius, overstrokeOuterRadius, maxOffset,
+ FillInOverstrokeVerts(verts, bounds, outerRadius, overstrokeOuterRadius, maxOffset,
overstrokeOuterRadius, 0.0f, color);
}
@@ -2517,6 +2474,7 @@
fVertCount += that->fVertCount;
fIndexCount += that->fIndexCount;
fAllFill = fAllFill && that->fAllFill;
+ fWideColor = fWideColor || that->fWideColor;
return CombineResult::kMerged;
}
@@ -2533,6 +2491,7 @@
int fVertCount;
int fIndexCount;
bool fAllFill;
+ bool fWideColor;
SkSTArray<1, RRect, true> fRRects;
typedef GrMeshDrawOp INHERITED;
@@ -2638,6 +2597,7 @@
this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo);
// Expand the rect for aa in order to generate the correct vertices.
bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
+ fWideColor = !SkPMColor4fFitsInBytes(color);
fRRects.emplace_back(
RRect{color, devXRadius, devYRadius, innerXRadius, innerYRadius, bounds});
}
@@ -2682,32 +2642,32 @@
}
// Setup geometry processor
- sk_sp<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStroked, false, localMatrix));
-
- SkASSERT(sizeof(EllipseVertex) == gp->vertexStride());
+ sk_sp<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStroked, fWideColor,
+ localMatrix));
// drop out the middle quad if we're stroked
int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPerFillRRect;
sk_sp<const GrBuffer> indexBuffer = get_rrect_index_buffer(
fStroked ? kStroke_RRectType : kFill_RRectType, target->resourceProvider());
- PatternHelper helper(target, GrPrimitiveType::kTriangles, sizeof(EllipseVertex),
+ PatternHelper helper(target, GrPrimitiveType::kTriangles, gp->vertexStride(),
indexBuffer.get(), kVertsPerStandardRRect, indicesPerInstance,
fRRects.count());
- EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(helper.vertices());
- if (!verts || !indexBuffer) {
+ GrVertexWriter verts{helper.vertices()};
+ if (!verts.fPtr || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
for (const auto& rrect : fRRects) {
- // TODO4F: Preserve float colors
- GrColor color = rrect.fColor.toBytes_RGBA();
+ GrVertexColor color(rrect.fColor, fWideColor);
// Compute the reciprocals of the radii here to save time in the shader
- SkScalar xRadRecip = SkScalarInvert(rrect.fXRadius);
- SkScalar yRadRecip = SkScalarInvert(rrect.fYRadius);
- SkScalar xInnerRadRecip = SkScalarInvert(rrect.fInnerXRadius);
- SkScalar yInnerRadRecip = SkScalarInvert(rrect.fInnerYRadius);
+ float reciprocalRadii[4] = {
+ SkScalarInvert(rrect.fXRadius),
+ SkScalarInvert(rrect.fYRadius),
+ SkScalarInvert(rrect.fInnerXRadius),
+ SkScalarInvert(rrect.fInnerYRadius)
+ };
// Extend the radii out half a pixel to antialias.
SkScalar xOuterRadius = rrect.fXRadius + SK_ScalarHalf;
@@ -2732,33 +2692,25 @@
SK_ScalarNearlyZero, yMaxOffset};
for (int i = 0; i < 4; ++i) {
- verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]);
- verts->fColor = color;
- verts->fOffset = SkPoint::Make(xMaxOffset, yOuterOffsets[i]);
- verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
- verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
- verts++;
+ verts.write(bounds.fLeft, yCoords[i],
+ color,
+ xMaxOffset, yOuterOffsets[i],
+ reciprocalRadii);
- verts->fPos = SkPoint::Make(bounds.fLeft + xOuterRadius, yCoords[i]);
- verts->fColor = color;
- verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]);
- verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
- verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
- verts++;
+ verts.write(bounds.fLeft + xOuterRadius, yCoords[i],
+ color,
+ SK_ScalarNearlyZero, yOuterOffsets[i],
+ reciprocalRadii);
- verts->fPos = SkPoint::Make(bounds.fRight - xOuterRadius, yCoords[i]);
- verts->fColor = color;
- verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]);
- verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
- verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
- verts++;
+ verts.write(bounds.fRight - xOuterRadius, yCoords[i],
+ color,
+ SK_ScalarNearlyZero, yOuterOffsets[i],
+ reciprocalRadii);
- verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]);
- verts->fColor = color;
- verts->fOffset = SkPoint::Make(xMaxOffset, yOuterOffsets[i]);
- verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
- verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
- verts++;
+ verts.write(bounds.fRight, yCoords[i],
+ color,
+ xMaxOffset, yOuterOffsets[i],
+ reciprocalRadii);
}
}
auto pipe = fHelper.makePipeline(target);
@@ -2782,6 +2734,7 @@
}
fRRects.push_back_n(that->fRRects.count(), that->fRRects.begin());
+ fWideColor = fWideColor || that->fWideColor;
return CombineResult::kMerged;
}
@@ -2797,6 +2750,7 @@
SkMatrix fViewMatrixIfUsingLocalCoords;
Helper fHelper;
bool fStroked;
+ bool fWideColor;
SkSTArray<1, RRect, true> fRRects;
typedef GrMeshDrawOp INHERITED;