From 7cdabedc8b73b70e4aa70c5621a4bdc8e00ede44 Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Fri, 12 Jan 2018 12:06:06 -0500 Subject: Use GrOvalOpFactory ops to draw non-AA rrects, ovals, and arcs. This improves performance. Bug: skia: Change-Id: Ie01170ec084be66ea166b2baffcdb415583aa523 Reviewed-on: https://skia-review.googlesource.com/93321 Commit-Queue: Brian Salomon Reviewed-by: Greg Daniel --- src/gpu/ops/GrOvalOpFactory.cpp | 223 ++++++++++++++++++++++++++-------------- src/gpu/ops/GrOvalOpFactory.h | 40 +++---- 2 files changed, 166 insertions(+), 97 deletions(-) (limited to 'src/gpu/ops') diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp index 9194f673e6..e5f1abf9f2 100644 --- a/src/gpu/ops/GrOvalOpFactory.cpp +++ b/src/gpu/ops/GrOvalOpFactory.cpp @@ -66,10 +66,12 @@ static inline bool circle_stays_circle(const SkMatrix& m) { return m.isSimilarit class CircleGeometryProcessor : public GrGeometryProcessor { public: - CircleGeometryProcessor(bool stroke, bool clipPlane, bool isectPlane, bool unionPlane, + CircleGeometryProcessor(bool stroke, bool clipPlane, bool isectPlane, bool unionPlane, GrAA aa, const SkMatrix& localMatrix) : INHERITED(kCircleGeometryProcessor_ClassID) - , fLocalMatrix(localMatrix) { + , fLocalMatrix(localMatrix) + , fStroke(stroke) + , fAA(aa) { fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); fInCircleEdge = &this->addVertexAttrib("inCircleEdge", kFloat4_GrVertexAttribType); @@ -88,7 +90,6 @@ public: } else { fInUnionPlane = nullptr; } - fStroke = stroke; } ~CircleGeometryProcessor() override {} @@ -174,7 +175,16 @@ private: } fragBuilder->codeAppend("edgeAlpha *= clip;"); } - fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage); + if (GrAA::kYes == cgp.fAA) { + fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage); + } else { + // Using a value less than half is a bit of a hack. If 0.5 is used then filling + // a set of abutting arcs that should create a full circle can leave gaps at pixels + // that neither arc quite owns. Generally speaking, double hitting these pixels + // instead of missing them looks better. + fragBuilder->codeAppendf("%s = edgeAlpha > 0.4999 ? half4(1) : half4(0);", + args.fOutputCoverage); + } } static void GenKey(const GrGeometryProcessor& gp, @@ -187,6 +197,7 @@ private: key |= cgp.fInClipPlane ? 0x04 : 0x0; key |= cgp.fInIsectPlane ? 0x08 : 0x0; key |= cgp.fInUnionPlane ? 0x10 : 0x0; + key |= GrAA::kYes == cgp.fAA ? 0x20 : 0x0; b->add32(key); } @@ -208,6 +219,7 @@ private: const Attribute* fInIsectPlane; const Attribute* fInUnionPlane; bool fStroke; + GrAA fAA; GR_DECLARE_GEOMETRY_PROCESSOR_TEST @@ -218,9 +230,10 @@ GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleGeometryProcessor); #if GR_TEST_UTILS sk_sp CircleGeometryProcessor::TestCreate(GrProcessorTestData* d) { + GrAA aa = d->fRandom->nextBool() ? GrAA::kYes : GrAA::kNo; return sk_sp(new CircleGeometryProcessor( d->fRandom->nextBool(), d->fRandom->nextBool(), d->fRandom->nextBool(), - d->fRandom->nextBool(), GrTest::TestMatrix(d->fRandom))); + d->fRandom->nextBool(), aa, GrTest::TestMatrix(d->fRandom))); } #endif @@ -236,14 +249,15 @@ sk_sp CircleGeometryProcessor::TestCreate(GrProcessorTestDa class EllipseGeometryProcessor : public GrGeometryProcessor { public: - EllipseGeometryProcessor(bool stroke, const SkMatrix& localMatrix) - : INHERITED(kEllipseGeometryProcessor_ClassID) - , fLocalMatrix(localMatrix) { + EllipseGeometryProcessor(bool stroke, GrAA aa, const SkMatrix& localMatrix) + : INHERITED(kEllipseGeometryProcessor_ClassID) + , fLocalMatrix(localMatrix) + , fStroke(stroke) + , fAA(aa) { fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); fInEllipseOffset = &this->addVertexAttrib("inEllipseOffset", kHalf2_GrVertexAttribType); fInEllipseRadii = &this->addVertexAttrib("inEllipseRadii", kHalf4_GrVertexAttribType); - fStroke = stroke; } ~EllipseGeometryProcessor() override {} @@ -318,7 +332,12 @@ private: fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);"); } - fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage); + if (GrAA::kYes == egp.fAA) { + fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage); + } else { + fragBuilder->codeAppendf("%s = edgeAlpha > 0.5 ? half4(1) : half4(0);", + args.fOutputCoverage); + } } static void GenKey(const GrGeometryProcessor& gp, @@ -327,6 +346,7 @@ private: const EllipseGeometryProcessor& egp = gp.cast(); uint16_t key = egp.fStroke ? 0x1 : 0x0; key |= egp.fLocalMatrix.hasPerspective() ? 0x2 : 0x0; + key |= GrAA::kYes == egp.fAA ? 0x4 : 0x0; b->add32(key); } @@ -346,6 +366,7 @@ private: const Attribute* fInEllipseRadii; SkMatrix fLocalMatrix; bool fStroke; + GrAA fAA; GR_DECLARE_GEOMETRY_PROCESSOR_TEST @@ -356,8 +377,9 @@ GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseGeometryProcessor); #if GR_TEST_UTILS sk_sp EllipseGeometryProcessor::TestCreate(GrProcessorTestData* d) { - return sk_sp( - new EllipseGeometryProcessor(d->fRandom->nextBool(), GrTest::TestMatrix(d->fRandom))); + GrAA aa = d->fRandom->nextBool() ? GrAA::kYes : GrAA::kNo; + return sk_sp(new EllipseGeometryProcessor(d->fRandom->nextBool(), aa, + GrTest::TestMatrix(d->fRandom))); } #endif @@ -376,14 +398,15 @@ enum class DIEllipseStyle { kStroke = 0, kHairline, kFill }; class DIEllipseGeometryProcessor : public GrGeometryProcessor { public: - DIEllipseGeometryProcessor(const SkMatrix& viewMatrix, DIEllipseStyle style) + DIEllipseGeometryProcessor(const SkMatrix& viewMatrix, DIEllipseStyle style, GrAA aa) : INHERITED(kDIEllipseGeometryProcessor_ClassID) - , fViewMatrix(viewMatrix) { + , fViewMatrix(viewMatrix) + , fStyle(style) + , fAA(aa) { fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType); fInEllipseOffsets0 = &this->addVertexAttrib("inEllipseOffsets0", kHalf2_GrVertexAttribType); fInEllipseOffsets1 = &this->addVertexAttrib("inEllipseOffsets1", kHalf2_GrVertexAttribType); - fStyle = style; } ~DIEllipseGeometryProcessor() override {} @@ -473,8 +496,12 @@ private: fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"); fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);"); } - - fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage); + if (GrAA::kYes == diegp.fAA) { + fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage); + } else { + fragBuilder->codeAppendf("%s = edgeAlpha > 0.5 ? half4(1) : half4(0);", + args.fOutputCoverage); + } } static void GenKey(const GrGeometryProcessor& gp, @@ -482,6 +509,7 @@ private: GrProcessorKeyBuilder* b) { const DIEllipseGeometryProcessor& diegp = gp.cast(); uint16_t key = static_cast(diegp.fStyle); + key |= GrAA::kYes == diegp.fAA ? 0x80 : 0x0; key |= ComputePosKey(diegp.fViewMatrix) << 10; b->add32(key); } @@ -512,6 +540,7 @@ private: const Attribute* fInEllipseOffsets1; SkMatrix fViewMatrix; DIEllipseStyle fStyle; + GrAA fAA; GR_DECLARE_GEOMETRY_PROCESSOR_TEST @@ -522,8 +551,9 @@ GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseGeometryProcessor); #if GR_TEST_UTILS sk_sp DIEllipseGeometryProcessor::TestCreate(GrProcessorTestData* d) { + GrAA aa = d->fRandom->nextBool() ? GrAA::kYes : GrAA::kNo; return sk_sp(new DIEllipseGeometryProcessor( - GrTest::TestMatrix(d->fRandom), (DIEllipseStyle)(d->fRandom->nextRangeU(0, 2)))); + GrTest::TestMatrix(d->fRandom), (DIEllipseStyle)(d->fRandom->nextRangeU(0, 2)), aa)); } #endif @@ -591,7 +621,7 @@ public: bool fUseCenter; }; - static std::unique_ptr Make(GrPaint&& paint, const SkMatrix& viewMatrix, + static std::unique_ptr Make(GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, SkPoint center, SkScalar radius, const GrStyle& style, const ArcParams* arcParams = nullptr) { SkASSERT(circle_stays_circle(viewMatrix)); @@ -618,13 +648,13 @@ public: break; } } - return Helper::FactoryHelper(std::move(paint), viewMatrix, center, radius, style, - arcParams); + return Helper::FactoryHelper(std::move(paint), aa, viewMatrix, center, radius, + style, arcParams); } - CircleOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix, + CircleOp(const Helper::MakeArgs& helperArgs, GrColor color, GrAA aa, const SkMatrix& viewMatrix, SkPoint center, SkScalar radius, const GrStyle& style, const ArcParams* arcParams) - : GrMeshDrawOp(ClassID()), fHelper(helperArgs, GrAAType::kCoverage) { + : GrMeshDrawOp(ClassID()), fHelper(helperArgs, GrAAType::kCoverage), fAA(aa) { const SkStrokeRec& stroke = style.strokeRec(); SkStrokeRec::Style recStyle = stroke.getStyle(); @@ -816,7 +846,7 @@ private: // Setup geometry processor sk_sp gp(new CircleGeometryProcessor( - !fAllFill, fClipPlane, fClipPlaneIsect, fClipPlaneUnion, localMatrix)); + !fAllFill, fClipPlane, fClipPlaneIsect, fClipPlaneUnion, fAA, localMatrix)); struct CircleVertex { SkPoint fPos; @@ -1105,6 +1135,10 @@ private: return false; } + if (fAA != that->fAA) { + return false; + } + // Because we've set up the ops that don't use the planes with noop values // we can just accumulate used planes by later ops. fClipPlane |= that->fClipPlane; @@ -1139,6 +1173,7 @@ private: bool fClipPlane; bool fClipPlaneIsect; bool fClipPlaneUnion; + GrAA fAA; typedef GrMeshDrawOp INHERITED; }; @@ -1160,7 +1195,7 @@ private: public: DEFINE_OP_CLASS_ID - static std::unique_ptr Make(GrPaint&& paint, const SkMatrix& viewMatrix, + static std::unique_ptr Make(GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, const SkRect& ellipse, const SkStrokeRec& stroke) { DeviceSpaceParams params; // do any matrix crunching before we reset the draw state for device coords @@ -1219,12 +1254,13 @@ public: params.fXRadius += scaledStroke.fX; params.fYRadius += scaledStroke.fY; } - return Helper::FactoryHelper(std::move(paint), viewMatrix, params, stroke); + return Helper::FactoryHelper(std::move(paint), aa, viewMatrix, params, stroke); } - EllipseOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix, - const DeviceSpaceParams& params, const SkStrokeRec& stroke) - : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage) { + EllipseOp(const Helper::MakeArgs& helperArgs, GrColor color, GrAA aa, + const SkMatrix& viewMatrix, const DeviceSpaceParams& params, + const SkStrokeRec& stroke) + : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage), fAA(aa) { SkStrokeRec::Style style = stroke.getStyle(); bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style; @@ -1284,7 +1320,7 @@ private: } // Setup geometry processor - sk_sp gp(new EllipseGeometryProcessor(fStroked, localMatrix)); + sk_sp gp(new EllipseGeometryProcessor(fStroked, fAA, localMatrix)); QuadHelper helper; size_t vertexStride = gp->getVertexStride(); @@ -1356,6 +1392,10 @@ private: return false; } + if (fAA != that->fAA) { + return false; + } + fEllipses.push_back_n(that->fEllipses.count(), that->fEllipses.begin()); this->joinBounds(*that); return true; @@ -1373,6 +1413,7 @@ private: SkMatrix fViewMatrixIfUsingLocalCoords; Helper fHelper; bool fStroked; + GrAA fAA; SkSTArray<1, Ellipse, true> fEllipses; typedef GrMeshDrawOp INHERITED; @@ -1396,7 +1437,7 @@ private: public: DEFINE_OP_CLASS_ID - static std::unique_ptr Make(GrPaint&& paint, const SkMatrix& viewMatrix, + static std::unique_ptr Make(GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, const SkRect& ellipse, const SkStrokeRec& stroke) { DeviceSpaceParams params; params.fCenter = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); @@ -1451,12 +1492,12 @@ public: (params.fInnerXRadius <= 0 || params.fInnerYRadius <= 0)) { params.fStyle = DIEllipseStyle::kFill; } - return Helper::FactoryHelper(std::move(paint), params, viewMatrix); + return Helper::FactoryHelper(std::move(paint), aa, params, viewMatrix); } - DIEllipseOp(Helper::MakeArgs& helperArgs, GrColor color, const DeviceSpaceParams& params, - const SkMatrix& viewMatrix) - : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage) { + DIEllipseOp(Helper::MakeArgs& helperArgs, GrColor color, GrAA aa, + const DeviceSpaceParams& params, const SkMatrix& viewMatrix) + : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage), fAA(aa) { // This expands the outer rect so that after CTM we end up with a half-pixel border SkScalar a = viewMatrix[SkMatrix::kMScaleX]; SkScalar b = viewMatrix[SkMatrix::kMSkewX]; @@ -1511,7 +1552,7 @@ private: void onPrepareDraws(Target* target) override { // Setup geometry processor sk_sp gp( - new DIEllipseGeometryProcessor(this->viewMatrix(), this->style())); + new DIEllipseGeometryProcessor(this->viewMatrix(), this->style(), fAA)); size_t vertexStride = gp->getVertexStride(); SkASSERT(vertexStride == sizeof(DIEllipseVertex)); @@ -1576,6 +1617,10 @@ private: return false; } + if (fAA != that->fAA) { + return false; + } + fEllipses.push_back_n(that->fEllipses.count(), that->fEllipses.begin()); this->joinBounds(*that); return true; @@ -1599,6 +1644,7 @@ private: Helper fHelper; SkSTArray<1, Ellipse, true> fEllipses; + GrAA fAA; typedef GrMeshDrawOp INHERITED; }; @@ -1738,17 +1784,19 @@ public: // A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then strokeOnly indicates // whether the rrect is only stroked or stroked and filled. - static std::unique_ptr Make(GrPaint&& paint, const SkMatrix& viewMatrix, + static std::unique_ptr Make(GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, const SkRect& devRect, float devRadius, float devStrokeWidth, bool strokeOnly) { - return Helper::FactoryHelper(std::move(paint), viewMatrix, devRect, + return Helper::FactoryHelper(std::move(paint), aa, viewMatrix, devRect, devRadius, devStrokeWidth, strokeOnly); } - CircularRRectOp(Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix, - const SkRect& devRect, float devRadius, float devStrokeWidth, bool strokeOnly) + CircularRRectOp(Helper::MakeArgs& helperArgs, GrColor color, GrAA aa, + const SkMatrix& viewMatrix, const SkRect& devRect, float devRadius, + float devStrokeWidth, bool strokeOnly) : INHERITED(ClassID()) , fViewMatrixIfUsingLocalCoords(viewMatrix) - , fHelper(helperArgs, GrAAType::kCoverage) { + , fHelper(helperArgs, GrAAType::kCoverage) + , fAA(aa) { SkRect bounds = devRect; SkASSERT(!(devStrokeWidth <= 0 && strokeOnly)); SkScalar innerRadius = 0.0f; @@ -1910,7 +1958,7 @@ private: // Setup geometry processor sk_sp gp( - new CircleGeometryProcessor(!fAllFill, false, false, false, localMatrix)); + new CircleGeometryProcessor(!fAllFill, false, false, false, fAA, localMatrix)); size_t vertexStride = gp->getVertexStride(); SkASSERT(sizeof(CircleVertex) == vertexStride); @@ -2029,6 +2077,10 @@ private: return false; } + if (fAA != that->fAA) { + return false; + } + fRRects.push_back_n(that->fRRects.count(), that->fRRects.begin()); this->joinBounds(*that); fVertCount += that->fVertCount; @@ -2050,6 +2102,7 @@ private: int fVertCount; int fIndexCount; bool fAllFill; + GrAA fAA; SkSTArray<1, RRect, true> fRRects; typedef GrMeshDrawOp INHERITED; @@ -2087,7 +2140,7 @@ public: // If devStrokeWidths values are <= 0 indicates then fill only. Otherwise, strokeOnly indicates // whether the rrect is only stroked or stroked and filled. - static std::unique_ptr Make(GrPaint&& paint, const SkMatrix& viewMatrix, + static std::unique_ptr Make(GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, const SkRect& devRect, float devXRadius, float devYRadius, SkVector devStrokeWidths, bool strokeOnly) { SkASSERT(devXRadius > 0.5); @@ -2118,15 +2171,15 @@ public: return nullptr; } } - return Helper::FactoryHelper(std::move(paint), viewMatrix, devRect, + return Helper::FactoryHelper(std::move(paint), aa, viewMatrix, devRect, devXRadius, devYRadius, devStrokeWidths, strokeOnly); } - EllipticalRRectOp(Helper::MakeArgs helperArgs, GrColor color, const SkMatrix& viewMatrix, - const SkRect& devRect, float devXRadius, float devYRadius, - SkVector devStrokeHalfWidths, bool strokeOnly) - : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage) { + EllipticalRRectOp(Helper::MakeArgs helperArgs, GrColor color, GrAA aa, + const SkMatrix& viewMatrix, const SkRect& devRect, float devXRadius, + float devYRadius, SkVector devStrokeHalfWidths, bool strokeOnly) + : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage), fAA(aa) { SkScalar innerXRadius = 0.0f; SkScalar innerYRadius = 0.0f; SkRect bounds = devRect; @@ -2192,7 +2245,7 @@ private: } // Setup geometry processor - sk_sp gp(new EllipseGeometryProcessor(fStroked, localMatrix)); + sk_sp gp(new EllipseGeometryProcessor(fStroked, fAA, localMatrix)); size_t vertexStride = gp->getVertexStride(); SkASSERT(vertexStride == sizeof(EllipseVertex)); @@ -2280,7 +2333,9 @@ private: !fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) { return false; } - + if (fAA != that->fAA) { + return false; + } fRRects.push_back_n(that->fRRects.count(), that->fRRects.begin()); this->joinBounds(*that); return true; @@ -2298,12 +2353,14 @@ private: SkMatrix fViewMatrixIfUsingLocalCoords; Helper fHelper; bool fStroked; + GrAA fAA; SkSTArray<1, RRect, true> fRRects; typedef GrMeshDrawOp INHERITED; }; static std::unique_ptr make_rrect_op(GrPaint&& paint, + GrAA aa, const SkMatrix& viewMatrix, const SkRRect& rrect, const SkStrokeRec& stroke) { @@ -2364,55 +2421,58 @@ static std::unique_ptr make_rrect_op(GrPaint&& paint, // if the corners are circles, use the circle renderer if (isCircular) { - return CircularRRectOp::Make(std::move(paint), viewMatrix, bounds, xRadius, scaledStroke.fX, - isStrokeOnly); + return CircularRRectOp::Make(std::move(paint), aa, viewMatrix, bounds, xRadius, + scaledStroke.fX, isStrokeOnly); // otherwise we use the ellipse renderer } else { - return EllipticalRRectOp::Make(std::move(paint), viewMatrix, bounds, xRadius, yRadius, + return EllipticalRRectOp::Make(std::move(paint), aa, viewMatrix, bounds, xRadius, yRadius, scaledStroke, isStrokeOnly); } } -std::unique_ptr GrOvalOpFactory::MakeRRectOp(GrPaint&& paint, - const SkMatrix& viewMatrix, - const SkRRect& rrect, - const SkStrokeRec& stroke, - const GrShaderCaps* shaderCaps) { +std::unique_ptr GrOvalOpFactory::MakeCoverageRRectOp(GrPaint&& paint, + GrAA aa, + const SkMatrix& viewMatrix, + const SkRRect& rrect, + const SkStrokeRec& stroke, + const GrShaderCaps* shaderCaps) { if (rrect.isOval()) { - return MakeOvalOp(std::move(paint), viewMatrix, rrect.getBounds(), stroke, shaderCaps); + return MakeCoverageOvalOp(std::move(paint), aa, viewMatrix, rrect.getBounds(), stroke, + shaderCaps); } if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { return nullptr; } - return make_rrect_op(std::move(paint), viewMatrix, rrect, stroke); + return make_rrect_op(std::move(paint), aa, viewMatrix, rrect, stroke); } /////////////////////////////////////////////////////////////////////////////// -std::unique_ptr GrOvalOpFactory::MakeOvalOp(GrPaint&& paint, - const SkMatrix& viewMatrix, - const SkRect& oval, - const SkStrokeRec& stroke, - const GrShaderCaps* shaderCaps) { +std::unique_ptr GrOvalOpFactory::MakeCoverageOvalOp(GrPaint&& paint, + GrAA aa, + const SkMatrix& viewMatrix, + const SkRect& oval, + const SkStrokeRec& stroke, + const GrShaderCaps* shaderCaps) { // we can draw circles SkScalar width = oval.width(); if (width > SK_ScalarNearlyZero && SkScalarNearlyEqual(width, oval.height()) && circle_stays_circle(viewMatrix)) { SkPoint center = {oval.centerX(), oval.centerY()}; - return CircleOp::Make(std::move(paint), viewMatrix, center, width / 2.f, + return CircleOp::Make(std::move(paint), aa, viewMatrix, center, width / 2.f, GrStyle(stroke, nullptr)); } // prefer the device space ellipse op for batchability if (viewMatrix.rectStaysRect()) { - return EllipseOp::Make(std::move(paint), viewMatrix, oval, stroke); + return EllipseOp::Make(std::move(paint), aa, viewMatrix, oval, stroke); } // Otherwise, if we have shader derivative support, render as device-independent if (shaderCaps->shaderDerivativeSupport()) { - return DIEllipseOp::Make(std::move(paint), viewMatrix, oval, stroke); + return DIEllipseOp::Make(std::move(paint), aa, viewMatrix, oval, stroke); } return nullptr; @@ -2420,11 +2480,10 @@ std::unique_ptr GrOvalOpFactory::MakeOvalOp(GrPaint&& paint, /////////////////////////////////////////////////////////////////////////////// -std::unique_ptr GrOvalOpFactory::MakeArcOp(GrPaint&& paint, const SkMatrix& viewMatrix, - const SkRect& oval, SkScalar startAngle, - SkScalar sweepAngle, bool useCenter, - const GrStyle& style, - const GrShaderCaps* shaderCaps) { +std::unique_ptr GrOvalOpFactory::MakeCoverageArcOp( + GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, const SkRect& oval, + SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const GrStyle& style, + const GrShaderCaps* shaderCaps) { SkASSERT(!oval.isEmpty()); SkASSERT(sweepAngle); SkScalar width = oval.width(); @@ -2437,7 +2496,7 @@ std::unique_ptr GrOvalOpFactory::MakeArcOp(GrPaint&& paint, const SkMa SkPoint center = {oval.centerX(), oval.centerY()}; CircleOp::ArcParams arcParams = {SkDegreesToRadians(startAngle), SkDegreesToRadians(sweepAngle), useCenter}; - return CircleOp::Make(std::move(paint), viewMatrix, center, width / 2.f, style, &arcParams); + return CircleOp::Make(std::move(paint), aa, viewMatrix, center, width / 2.f, style, &arcParams); } /////////////////////////////////////////////////////////////////////////////// @@ -2460,14 +2519,15 @@ GR_DRAW_OP_TEST_DEFINE(CircleOp) { SkStrokeRec stroke = GrTest::TestStrokeRec(random); CircleOp::ArcParams arcParamsTmp; const CircleOp::ArcParams* arcParams = nullptr; + GrAA aa = random->nextBool() ? GrAA::kYes : GrAA::kNo; if (random->nextBool()) { arcParamsTmp.fStartAngleRadians = random->nextSScalar1() * SK_ScalarPI * 2; arcParamsTmp.fSweepAngleRadians = random->nextSScalar1() * SK_ScalarPI * 2 - .01f; arcParamsTmp.fUseCenter = random->nextBool(); arcParams = &arcParamsTmp; } - std::unique_ptr op = CircleOp::Make(std::move(paint), viewMatrix, center, radius, - GrStyle(stroke, nullptr), arcParams); + std::unique_ptr op = CircleOp::Make(std::move(paint), aa, viewMatrix, center, + radius, GrStyle(stroke, nullptr), arcParams); if (op) { return op; } @@ -2477,19 +2537,24 @@ GR_DRAW_OP_TEST_DEFINE(CircleOp) { GR_DRAW_OP_TEST_DEFINE(EllipseOp) { SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); SkRect ellipse = GrTest::TestSquare(random); - return EllipseOp::Make(std::move(paint), viewMatrix, ellipse, GrTest::TestStrokeRec(random)); + GrAA aa = random->nextBool() ? GrAA::kYes : GrAA::kNo; + return EllipseOp::Make(std::move(paint), aa, viewMatrix, ellipse, + GrTest::TestStrokeRec(random)); } GR_DRAW_OP_TEST_DEFINE(DIEllipseOp) { SkMatrix viewMatrix = GrTest::TestMatrix(random); SkRect ellipse = GrTest::TestSquare(random); - return DIEllipseOp::Make(std::move(paint), viewMatrix, ellipse, GrTest::TestStrokeRec(random)); + GrAA aa = random->nextBool() ? GrAA::kYes : GrAA::kNo; + return DIEllipseOp::Make(std::move(paint), aa, viewMatrix, ellipse, + GrTest::TestStrokeRec(random)); } GR_DRAW_OP_TEST_DEFINE(RRectOp) { SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); const SkRRect& rrect = GrTest::TestRRectSimple(random); - return make_rrect_op(std::move(paint), viewMatrix, rrect, GrTest::TestStrokeRec(random)); + GrAA aa = random->nextBool() ? GrAA::kYes : GrAA::kNo; + return make_rrect_op(std::move(paint), aa, viewMatrix, rrect, GrTest::TestStrokeRec(random)); } #endif diff --git a/src/gpu/ops/GrOvalOpFactory.h b/src/gpu/ops/GrOvalOpFactory.h index 1bdf3ee6f6..d31e09ed9c 100644 --- a/src/gpu/ops/GrOvalOpFactory.h +++ b/src/gpu/ops/GrOvalOpFactory.h @@ -22,29 +22,33 @@ class SkStrokeRec; /* * This namespace wraps helper functions that draw ovals, rrects, and arcs (filled & stroked) + * The ops always use coverage even when their non-AA. */ class GrOvalOpFactory { public: - static std::unique_ptr MakeOvalOp(GrPaint&&, - const SkMatrix&, - const SkRect& oval, - const SkStrokeRec&, - const GrShaderCaps*); + static std::unique_ptr MakeCoverageOvalOp(GrPaint&&, + GrAA, + const SkMatrix&, + const SkRect& oval, + const SkStrokeRec&, + const GrShaderCaps*); - static std::unique_ptr MakeRRectOp(GrPaint&&, - const SkMatrix&, - const SkRRect&, - const SkStrokeRec&, - const GrShaderCaps*); + static std::unique_ptr MakeCoverageRRectOp(GrPaint&&, + GrAA, + const SkMatrix&, + const SkRRect&, + const SkStrokeRec&, + const GrShaderCaps*); - static std::unique_ptr MakeArcOp(GrPaint&&, - const SkMatrix&, - const SkRect& oval, - SkScalar startAngle, - SkScalar sweepAngle, - bool useCenter, - const GrStyle&, - const GrShaderCaps*); + static std::unique_ptr MakeCoverageArcOp(GrPaint&&, + GrAA, + const SkMatrix&, + const SkRect& oval, + SkScalar startAngle, + SkScalar sweepAngle, + bool useCenter, + const GrStyle&, + const GrShaderCaps*); }; #endif // GrOvalOpFactory_DEFINED -- cgit v1.2.3