diff options
-rw-r--r-- | src/core/SkDraw.cpp | 25 | ||||
-rw-r--r-- | src/core/SkDrawProcs.h | 22 | ||||
-rw-r--r-- | src/gpu/GrAAHairLinePathRenderer.cpp | 22 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 69 | ||||
-rw-r--r-- | src/gpu/GrDefaultPathRenderer.cpp | 28 | ||||
-rw-r--r-- | src/gpu/GrDrawState.cpp | 7 | ||||
-rw-r--r-- | src/gpu/GrDrawState.h | 10 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.h | 9 | ||||
-rw-r--r-- | src/gpu/GrOvalRenderer.cpp | 28 | ||||
-rw-r--r-- | src/gpu/GrOvalRenderer.h | 6 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.h | 15 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 12 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDesc.cpp | 2 |
14 files changed, 148 insertions, 111 deletions
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 0288dee409..52891ea521 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -988,24 +988,11 @@ static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) { } } -bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, - SkScalar* coverage) { - SkASSERT(coverage); - if (SkPaint::kStroke_Style != paint.getStyle()) { - return false; - } - SkScalar strokeWidth = paint.getStrokeWidth(); - if (0 == strokeWidth) { - *coverage = SK_Scalar1; - return true; - } +bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix, + SkScalar* coverage) { + SkASSERT(strokeWidth > 0); + // We need to try to fake a thick-stroke with a modulated hairline. - // if we get here, we need to try to fake a thick-stroke with a modulated - // hairline - - if (!paint.isAntiAlias()) { - return false; - } if (matrix.hasPerspective()) { return false; } @@ -1017,7 +1004,9 @@ bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, SkScalar len0 = fast_len(dst[0]); SkScalar len1 = fast_len(dst[1]); if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) { - *coverage = SkScalarAve(len0, len1); + if (NULL != coverage) { + *coverage = SkScalarAve(len0, len1); + } return true; } return false; diff --git a/src/core/SkDrawProcs.h b/src/core/SkDrawProcs.h index cc2f3ed073..6911e5b017 100644 --- a/src/core/SkDrawProcs.h +++ b/src/core/SkDrawProcs.h @@ -75,12 +75,32 @@ struct SkDrawProcs { #endif }; +bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix&, + SkScalar* coverage); + /** * If the current paint is set to stroke and the stroke-width when applied to * the matrix is <= 1.0, then this returns true, and sets coverage (simulating * a stroke by drawing a hairline with partial coverage). If any of these * conditions are false, then this returns false and coverage is ignored. */ -bool SkDrawTreatAsHairline(const SkPaint&, const SkMatrix&, SkScalar* coverage); +inline bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, + SkScalar* coverage) { + if (SkPaint::kStroke_Style != paint.getStyle()) { + return false; + } + + SkScalar strokeWidth = paint.getStrokeWidth(); + if (0 == strokeWidth) { + *coverage = SK_Scalar1; + return true; + } + + if (!paint.isAntiAlias()) { + return false; + } + + return SkDrawTreatAAStrokeAsHairline(strokeWidth, matrix, coverage); +} #endif diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index 02c44191ad..39563105f8 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -759,7 +759,7 @@ bool GrAAHairLinePathRenderer::createLineGeom(const SkPath& path, } devBounds->set(lines.begin(), lines.count()); for (int i = 0; i < lineCnt; ++i) { - add_line(&lines[2*i], toSrc, drawState->getCoverage(), &verts); + add_line(&lines[2*i], toSrc, drawState->getCoverageColor(), &verts); } // All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the end points. static const SkScalar kSqrtOfOneAndAQuarter = SkFloatToScalar(1.118f); @@ -839,7 +839,13 @@ bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, const SkStrokeRec& stroke, const GrDrawTarget* target, bool antiAlias) const { - if (!stroke.isHairlineStyle() || !antiAlias) { + if (!antiAlias) { + return false; + } + + if (!IsStrokeHairlineOrEquivalent(stroke, + target->getDrawState().getViewMatrix(), + NULL)) { return false; } @@ -888,12 +894,20 @@ bool check_bounds(GrDrawState* drawState, const SkRect& devBounds, void* vertice } bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, - const SkStrokeRec&, + const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) { - GrDrawState* drawState = target->drawState(); + SkScalar hairlineCoverage; + if (IsStrokeHairlineOrEquivalent(stroke, + target->getDrawState().getViewMatrix(), + &hairlineCoverage)) { + uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * + target->getDrawState().getCoverage()); + target->drawState()->setCoverage(newCoverage); + } + SkIRect devClipBounds; target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devClipBounds); diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index b0d34fd039..cab4414ae2 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -43,10 +43,6 @@ SK_CONF_DECLARE(bool, c_Defer, "gpu.deferContext", true, #define BUFFERED_DRAW (c_Defer ? kYes_BufferedDraw : kNo_BufferedDraw) -// When we're using coverage AA but the blend is incompatible (given gpu -// limitations) should we disable AA or draw wrong? -#define DISABLE_COVERAGE_AA_FOR_BLEND 1 - #ifdef SK_DEBUG // change this to a 1 to see notifications when partial coverage fails #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0 @@ -695,14 +691,6 @@ void GrContext::dumpFontCache() const { //////////////////////////////////////////////////////////////////////////////// -namespace { -inline bool disable_coverage_aa_for_blend(GrDrawTarget* target) { - return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage(); -} -} - -//////////////////////////////////////////////////////////////////////////////// - /* create a triangle strip that strokes the specified triangle. There are 8 unique vertices, but we repreat the last 2 to close up. Alternatively we could use an indices array, and then only send 8 verts, but not sure that @@ -746,7 +734,7 @@ static bool apply_aa_to_rect(GrDrawTarget* target, // TODO: remove this ugliness when we drop the fixed-pipe impl *useVertexCoverage = false; if (!target->getDrawState().canTweakAlphaForCoverage()) { - if (disable_coverage_aa_for_blend(target)) { + if (target->shouldDisableCoverageAAForBlend()) { #ifdef SK_DEBUG //GrPrintf("Turning off AA to correctly apply blend.\n"); #endif @@ -1034,14 +1022,10 @@ void GrContext::drawRRect(const GrPaint& paint, AutoCheckFlush acf(this); GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf); - bool useAA = paint.isAntiAlias() && - !target->getDrawState().getRenderTarget()->isMultisampled() && - !disable_coverage_aa_for_blend(target); - - if (!fOvalRenderer->drawSimpleRRect(target, this, useAA, rect, stroke)) { + if (!fOvalRenderer->drawSimpleRRect(target, this, paint.isAntiAlias(), rect, stroke)) { SkPath path; path.addRRect(rect); - this->internalDrawPath(target, useAA, path, stroke); + this->internalDrawPath(target, paint.isAntiAlias(), path, stroke); } } @@ -1058,14 +1042,10 @@ void GrContext::drawOval(const GrPaint& paint, AutoCheckFlush acf(this); GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf); - bool useAA = paint.isAntiAlias() && - !target->getDrawState().getRenderTarget()->isMultisampled() && - !disable_coverage_aa_for_blend(target); - - if (!fOvalRenderer->drawOval(target, this, useAA, oval, stroke)) { + if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, stroke)) { SkPath path; path.addOval(oval); - this->internalDrawPath(target, useAA, path, stroke); + this->internalDrawPath(target, paint.isAntiAlias(), path, stroke); } } @@ -1091,7 +1071,7 @@ static bool is_nested_rects(GrDrawTarget* target, *useVertexCoverage = false; if (!target->getDrawState().canTweakAlphaForCoverage()) { - if (disable_coverage_aa_for_blend(target)) { + if (target->shouldDisableCoverageAAForBlend()) { return false; } else { *useVertexCoverage = true; @@ -1141,15 +1121,17 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok AutoRestoreEffects are; AutoCheckFlush acf(this); GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf); + GrDrawState* drawState = target->drawState(); - bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget()->isMultisampled(); - if (useAA && stroke.getWidth() < 0 && !path.isConvex()) { + bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled(); + + if (useCoverageAA && stroke.getWidth() < 0 && !path.isConvex()) { // Concave AA paths are expensive - try to avoid them for special cases bool useVertexCoverage; SkRect rects[2]; if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) { - SkMatrix origViewMatrix = target->getDrawState().getViewMatrix(); + SkMatrix origViewMatrix = drawState->getViewMatrix(); GrDrawState::AutoViewMatrixRestore avmr; if (!avmr.setIdentity(target->drawState())) { return; @@ -1167,8 +1149,8 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok bool isOval = path.isOval(&ovalRect); if (!isOval || path.isInverseFillType() - || !fOvalRenderer->drawOval(target, this, useAA, ovalRect, stroke)) { - this->internalDrawPath(target, useAA, path, stroke); + || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, stroke)) { + this->internalDrawPath(target, paint.isAntiAlias(), path, stroke); } } @@ -1180,15 +1162,14 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& // the src color (either the input alpha or in the frag shader) to implement // aa. If we have some future driver-mojo path AA that can do the right // thing WRT to the blend then we'll need some query on the PR. - if (disable_coverage_aa_for_blend(target)) { -#ifdef SK_DEBUG - //GrPrintf("Turning off AA to correctly apply blend.\n"); -#endif - useAA = false; - } + bool useCoverageAA = useAA && + !target->getDrawState().getRenderTarget()->isMultisampled() && + !target->shouldDisableCoverageAAForBlend(); + - GrPathRendererChain::DrawType type = useAA ? GrPathRendererChain::kColorAntiAlias_DrawType : - GrPathRendererChain::kColor_DrawType; + GrPathRendererChain::DrawType type = + useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType : + GrPathRendererChain::kColor_DrawType; const SkPath* pathPtr = &path; SkPath tmpPath; @@ -1198,16 +1179,16 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, false, type); if (NULL == pr) { - if (!strokeRec.isHairlineStyle()) { + if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(strokeRec, this->getMatrix(), NULL)) { // It didn't work the 1st time, so try again with the stroked path if (strokeRec.applyToPath(&tmpPath, *pathPtr)) { pathPtr = &tmpPath; strokeRec.setFillStyle(); + if (pathPtr->isEmpty()) { + return; + } } } - if (pathPtr->isEmpty()) { - return; - } // This time, allow SW renderer pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type); @@ -1220,7 +1201,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& return; } - pr->drawPath(*pathPtr, strokeRec, target, useAA); + pr->drawPath(*pathPtr, strokeRec, target, useCoverageAA); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index 85485c86a3..1f20ac2724 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -12,6 +12,7 @@ #include "GrPathUtils.h" #include "SkString.h" #include "SkStrokeRec.h" +#include "SkTLazy.h" #include "SkTrace.h" @@ -325,11 +326,25 @@ FINISHED: } bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, - const SkStrokeRec& stroke, + const SkStrokeRec& origStroke, GrDrawTarget* target, bool stencilOnly) { SkMatrix viewM = target->getDrawState().getViewMatrix(); + SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); + + SkScalar hairlineCoverage; + if (IsStrokeHairlineOrEquivalent(*stroke, target->getDrawState().getViewMatrix(), + &hairlineCoverage)) { + uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * + target->getDrawState().getCoverage()); + target->drawState()->setCoverage(newCoverage); + + if (!stroke->isHairlineStyle()) { + stroke.writable()->setHairlineStyle(); + } + } + SkScalar tol = SK_Scalar1; tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds()); @@ -338,7 +353,7 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, GrPrimitiveType primType; GrDrawTarget::AutoReleaseGeometry arg; if (!this->createGeom(path, - stroke, + *stroke, tol, target, &primType, @@ -361,7 +376,7 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, bool reverse = false; bool lastPassIsBounds; - if (stroke.isHairlineStyle()) { + if (stroke->isHairlineStyle()) { passCount = 1; if (stencilOnly) { passes[0] = &gDirectToStencil; @@ -371,7 +386,7 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, lastPassIsBounds = false; drawFace[0] = GrDrawState::kBoth_DrawFace; } else { - if (single_pass_path(path, stroke)) { + if (single_pass_path(path, *stroke)) { passCount = 1; if (stencilOnly) { passes[0] = &gDirectToStencil; @@ -499,7 +514,10 @@ bool GrDefaultPathRenderer::canDrawPath(const SkPath& path, const GrDrawTarget* target, bool antiAlias) const { // this class can draw any path with any fill but doesn't do any anti-aliasing. - return (stroke.isFillStyle() || stroke.isHairlineStyle()) && !antiAlias; + + return !antiAlias && + (stroke.isFillStyle() || + IsStrokeHairlineOrEquivalent(stroke, target->getDrawState().getViewMatrix(), NULL)); } bool GrDefaultPathRenderer::onDrawPath(const SkPath& path, diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index 1743604a19..1bbcc26325 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -54,7 +54,6 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende this->enableState(GrDrawState::kClip_StateBit); this->setColor(paint.getColor()); - this->setCoverage4(paint.getCoverage()); this->setState(GrDrawState::kDither_StateBit, paint.isDither()); this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias()); @@ -220,7 +219,7 @@ bool GrDrawState::srcAlphaWillBeOne() const { // Check whether coverage is treated as color. If so we run through the coverage computation. if (this->isCoverageDrawing()) { - GrColor coverageColor = this->getCoverage(); + GrColor coverageColor = this->getCoverageColor(); GrColor oldColor = color; color = 0; for (int c = 0; c < 4; ++c) { @@ -312,7 +311,7 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, bool covIsZero = !this->isCoverageDrawing() && !this->hasCoverageVertexAttribute() && - 0 == this->getCoverage(); + 0 == this->getCoverageColor(); // When coeffs are (0,1) there is no reason to draw at all, unless // stenciling is enabled. Having color writes disabled is effectively // (0,1). The same applies when coverage is known to be 0. @@ -327,7 +326,7 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, // check for coverage due to constant coverage, per-vertex coverage, or coverage stage bool hasCoverage = forceCoverage || - 0xffffffff != this->getCoverage() || + 0xffffffff != this->getCoverageColor() || this->hasCoverageVertexAttribute() || fCoverageStages.count() > 0; diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 2e4d7f86c4..3de0b12e85 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -311,15 +311,11 @@ public: fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage); } - /** - * Version of above that specifies 4 channel per-vertex color. The value - * should be premultiplied. - */ - void setCoverage4(GrColor coverage) { - fCommon.fCoverage = coverage; + uint8_t getCoverage() const { + return GrColorUnpackR(fCommon.fCoverage); } - GrColor getCoverage() const { + GrColor getCoverageColor() const { return fCommon.fCoverage; } diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index 266dc0712b..c5058699b5 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -100,6 +100,15 @@ public: */ bool canApplyCoverage() const; + /** When we're using coverage AA but the blend is incompatible (given gpu + * limitations) we should disable AA. */ + bool shouldDisableCoverageAAForBlend() { + // Enable below if we should draw with AA even when it produces + // incorrect blending. + // return false; + return !this->canApplyCoverage(); + } + /** * Given the current draw state and hw support, will HW AA lines be used (if * a line primitive type is drawn)? diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index aeeb85d2e1..8f078dbc45 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -460,7 +460,11 @@ void GrOvalRenderer::reset() { bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bool useAA, const SkRect& oval, const SkStrokeRec& stroke) { - if (!useAA) { + bool useCoverageAA = useAA && + !target->getDrawState().getRenderTarget()->isMultisampled() && + !target->shouldDisableCoverageAAForBlend(); + + if (!useCoverageAA) { return false; } @@ -469,13 +473,13 @@ bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bo // we can draw circles if (SkScalarNearlyEqual(oval.width(), oval.height()) && circle_stays_circle(vm)) { - this->drawCircle(target, useAA, oval, stroke); + this->drawCircle(target, useCoverageAA, oval, stroke); // if we have shader derivative support, render as device-independent } else if (target->caps()->shaderDerivativeSupport()) { - return this->drawDIEllipse(target, useAA, oval, stroke); + return this->drawDIEllipse(target, useCoverageAA, oval, stroke); // otherwise axis-aligned ellipses only } else if (vm.rectStaysRect()) { - return this->drawEllipse(target, useAA, oval, stroke); + return this->drawEllipse(target, useCoverageAA, oval, stroke); } else { return false; } @@ -492,7 +496,7 @@ extern const GrVertexAttrib gCircleVertexAttribs[] = { }; void GrOvalRenderer::drawCircle(GrDrawTarget* target, - bool useAA, + bool useCoverageAA, const SkRect& circle, const SkStrokeRec& stroke) { @@ -597,7 +601,7 @@ extern const GrVertexAttrib gDIEllipseVertexAttribs[] = { }; bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, - bool useAA, + bool useCoverageAA, const SkRect& ellipse, const SkStrokeRec& stroke) { @@ -606,7 +610,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, { // we should have checked for this previously bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect(); - SkASSERT(useAA && isAxisAlignedEllipse); + SkASSERT(useCoverageAA && isAxisAlignedEllipse); } #endif @@ -729,7 +733,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, } bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, - bool useAA, + bool useCoverageAA, const SkRect& ellipse, const SkStrokeRec& stroke) { @@ -882,8 +886,12 @@ GrIndexBuffer* GrOvalRenderer::rRectIndexBuffer(GrGpu* gpu) { bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA, const SkRRect& rrect, const SkStrokeRec& stroke) { + bool useCoverageAA = useAA && + !target->getDrawState().getRenderTarget()->isMultisampled() && + !target->shouldDisableCoverageAAForBlend(); + // only anti-aliased rrects for now - if (!useAA) { + if (!useCoverageAA) { return false; } @@ -891,7 +899,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b #ifdef SK_DEBUG { // we should have checked for this previously - SkASSERT(useAA && vm.rectStaysRect() && rrect.isSimple()); + SkASSERT(useCoverageAA && vm.rectStaysRect() && rrect.isSimple()); } #endif diff --git a/src/gpu/GrOvalRenderer.h b/src/gpu/GrOvalRenderer.h index b58abb7989..9653fccd72 100644 --- a/src/gpu/GrOvalRenderer.h +++ b/src/gpu/GrOvalRenderer.h @@ -37,13 +37,13 @@ public: const SkRRect& rrect, const SkStrokeRec& stroke); private: - bool drawEllipse(GrDrawTarget* target, bool useAA, + bool drawEllipse(GrDrawTarget* target, bool useCoverageAA, const SkRect& ellipse, const SkStrokeRec& stroke); - bool drawDIEllipse(GrDrawTarget* target, bool useAA, + bool drawDIEllipse(GrDrawTarget* target, bool useCoverageAA, const SkRect& ellipse, const SkStrokeRec& stroke); - void drawCircle(GrDrawTarget* target, bool useAA, + void drawCircle(GrDrawTarget* target, bool useCoverageAA, const SkRect& circle, const SkStrokeRec& stroke); diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h index f86eb9fe54..88665c1d42 100644 --- a/src/gpu/GrPathRenderer.h +++ b/src/gpu/GrPathRenderer.h @@ -13,6 +13,7 @@ #include "GrPathRendererChain.h" #include "GrStencil.h" +#include "SkDrawProcs.h" #include "SkStrokeRec.h" #include "SkTArray.h" @@ -137,6 +138,20 @@ public: this->onStencilPath(path, stroke, target); } + // Helper for determining if we can treat a thin stroke as a hairline w/ coverage. + // If we can, we draw lots faster (raster device does this same test). + static bool IsStrokeHairlineOrEquivalent(const SkStrokeRec& stroke, const SkMatrix& matrix, + SkScalar* outCoverage) { + if (stroke.isHairlineStyle()) { + if (NULL != outCoverage) { + *outCoverage = SK_Scalar1; + } + return true; + } + return stroke.getStyle() == SkStrokeRec::kStroke_Style && + SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, outCoverage); + } + protected: /** * Subclass overrides if it has any limitations of stenciling support. diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 063509a5a4..b83baf7fa3 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -846,14 +846,6 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, return; } - // can we cheat, and treat a thin stroke as a hairline w/ coverage - // if we can, we draw lots faster (raster device does this same test) - SkScalar hairlineCoverage; - bool doHairLine = SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage); - if (doHairLine) { - grPaint.setCoverage(SkScalarRoundToInt(hairlineCoverage * grPaint.getCoverage())); - } - // If we have a prematrix, apply it to the path, optimizing for the case // where the original path can in fact be modified in place (even though // its parameter type is const). @@ -883,10 +875,6 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, pathPtr = &effectPath; } - if (!pathEffect && doHairLine) { - stroke.setHairlineStyle(); - } - if (paint.getMaskFilter()) { if (!stroke.isHairlineStyle()) { if (stroke.applyToPath(&tmpPath, *pathPtr)) { diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index accaf884d1..5b030fa36a 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -207,10 +207,10 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts, coverage = 0; } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) { color = 0xffffffff; - coverage = drawState.getCoverage(); + coverage = drawState.getCoverageColor(); } else { color = drawState.getColor(); - coverage = drawState.getCoverage(); + coverage = drawState.getCoverageColor(); } this->setColor(drawState, color, sharedState); diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index e655210a45..381461a03b 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -156,7 +156,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, header->fHasVertexCode = true; } - bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage(); + bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor(); if (skipCoverage) { header->fCoverageInput = kTransBlack_ColorInput; |