From: bsalomon@google.com Date: Wed, 18 Jan 2012 20:34:00 +0000 (+0000) Subject: Pull xfer mode test out of generic draw-as-hairline test. Use coverage rather than... X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~16947 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dd1be60702b3622f49d97651e31d13eaf2175cf8;p=platform%2Fupstream%2FlibSkiaSharp.git Pull xfer mode test out of generic draw-as-hairline test. Use coverage rather than alpha to draw hairlines < 1pix wide in GPU. Review URL: http://codereview.appspot.com/5528112/ git-svn-id: http://skia.googlecode.com/svn/trunk@3070 2bbb7eff-a529-9590-31e7-b0007b416f81 --- diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h index f1d74b2..9f220e0 100644 --- a/include/gpu/GrPaint.h +++ b/include/gpu/GrPaint.h @@ -36,6 +36,7 @@ public: bool fColorMatrixEnabled; GrColor fColor; + uint8_t fCoverage; GrColor fColorFilterColor; SkXfermode::Mode fColorFilterXfermode; @@ -126,6 +127,7 @@ public: fDither = paint.fDither; fColor = paint.fColor; + fCoverage = paint.fCoverage; fColorFilterColor = paint.fColorFilterColor; fColorFilterXfermode = paint.fColorFilterXfermode; @@ -161,6 +163,7 @@ public: this->resetBlend(); this->resetOptions(); this->resetColor(); + this->resetCoverage(); this->resetTextures(); this->resetColorFilter(); this->resetMasks(); @@ -242,6 +245,10 @@ private: fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); } + void resetCoverage() { + fCoverage = 0xff; + } + void resetTextures() { for (int i = 0; i < kMaxTextures; ++i) { this->setTexture(i, NULL); diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index d1b291f..23a6d59 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -860,14 +860,14 @@ static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) { } bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, - SkAlpha* newAlpha) { - SkASSERT(newAlpha); + SkScalar* coverage) { + SkASSERT(coverage); if (SkPaint::kStroke_Style != paint.getStyle()) { return false; } SkScalar strokeWidth = paint.getStrokeWidth(); if (0 == strokeWidth) { - *newAlpha = paint.getAlpha(); + *coverage = SK_Scalar1; return true; } @@ -877,9 +877,6 @@ bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, if (!paint.isAntiAlias()) { return false; } - if (!xfermodeSupportsCoverageAsAlpha(paint.getXfermode())) { - return false; - } if (matrix.hasPerspective()) { return false; } @@ -891,16 +888,7 @@ 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) { - SkScalar modulate = SkScalarAve(len0, len1); -#if 0 - *newAlpha = SkToU8(SkScalarRoundToInt(modulate * paint.getAlpha())); -#else - // this is the old technique, which we preserve for now so we don't - // change previous results (testing) - // the new way seems fine, its just (a tiny bit) different - int scale = (int)SkScalarMul(modulate, 256); - *newAlpha = paint.getAlpha() * scale >> 8; -#endif + *coverage = SkScalarAve(len0, len1); return true; } return false; @@ -947,12 +935,29 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, SkTLazy lazyPaint; { - SkAlpha newAlpha; - if (SkDrawTreatAsHairline(origPaint, *matrix, &newAlpha)) { - lazyPaint.set(origPaint); - lazyPaint.get()->setAlpha(newAlpha); - lazyPaint.get()->setStrokeWidth(0); - paint = lazyPaint.get(); + SkScalar coverage; + if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) { + if (SK_Scalar1 == coverage) { + lazyPaint.set(origPaint); + lazyPaint.get()->setStrokeWidth(0); + paint = lazyPaint.get(); + } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) { + U8CPU newAlpha; +#if 0 + newAlpha = SkToU8(SkScalarRoundToInt(coverage * + origPaint.getAlpha())); +#else + // this is the old technique, which we preserve for now so + // we don't change previous results (testing) + // the new way seems fine, its just (a tiny bit) different + int scale = (int)SkScalarMul(coverage, 256); + newAlpha = origPaint.getAlpha() * scale >> 8; +#endif + lazyPaint.set(origPaint); + lazyPaint.get()->setStrokeWidth(0); + lazyPaint.get()->setAlpha(newAlpha); + paint = lazyPaint.get(); + } } } diff --git a/src/core/SkDrawProcs.h b/src/core/SkDrawProcs.h index 33b870d..2e26ecf 100644 --- a/src/core/SkDrawProcs.h +++ b/src/core/SkDrawProcs.h @@ -35,13 +35,12 @@ struct SkDrawProcs { }; /** - * If the current paint is set to stroke, has a compatible xfermode, and the - * stroke-width when applied to the matrix is <= 1.0, then this returns true, - * and sets newAlpha (simulating a stroke by drawing a hairline + newAlpha). - * If any of these conditions are false, then this returns false and modulate - * is ignored. + * 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&, SkAlpha* newAlpha); +bool SkDrawTreatAsHairline(const SkPaint&, const SkMatrix&, SkScalar* coverage); #endif diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 2137319..754063d 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -2060,6 +2060,7 @@ void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) { drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff); drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode); drawState->setColorMatrix(paint.fColorMatrix); + drawState->setCoverage(paint.fCoverage); if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) { GrPrintf("Partial pixel coverage will be incorrectly blended.\n"); @@ -2254,6 +2255,9 @@ void GrContext::convolve(GrTexture* texture, GrDrawTarget::AutoStateRestore asr(fGpu); GrDrawState* drawState = fGpu->drawState(); + GrRenderTarget* target = drawState->getRenderTarget(); + drawState->reset(); + drawState->setRenderTarget(target); GrMatrix sampleM; sampleM.setIDiv(texture->width(), texture->height()); drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode, @@ -2263,10 +2267,7 @@ void GrContext::convolve(GrTexture* texture, kernel, imageIncrement); - drawState->setViewMatrix(GrMatrix::I()); drawState->setTexture(0, texture); - drawState->setAlpha(0xFF); - drawState->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff); fGpu->drawSimpleRect(rect, NULL, 1 << 0); } diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 96d9fc6..ad15553 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -412,6 +412,7 @@ bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint, grPaint->fDither = skPaint.isDither(); grPaint->fAntiAlias = skPaint.isAntiAlias(); + grPaint->fCoverage = 0xFF; SkXfermode::Coeff sm = SkXfermode::kOne_Coeff; SkXfermode::Coeff dm = SkXfermode::kISA_Coeff; @@ -1061,32 +1062,22 @@ static bool drawWithMaskFilter(GrContext* context, const SkPath& path, } void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, - const SkPaint& origPaint, const SkMatrix* prePathMatrix, + const SkPaint& paint, const SkMatrix* prePathMatrix, bool pathIsMutable) { CHECK_SHOULD_DRAW(draw); bool doFill = true; - SkTLazy lazyPaint; - const SkPaint* paint = &origPaint; - - // can we cheat, and threat a thin stroke as a hairline (w/ modulated alpha) + + SkScalar coverage = SK_Scalar1; + // can we cheat, and threat a thin stroke as a hairline w/ coverage // if we can, we draw lots faster (raster device does this same test) - { - SkAlpha newAlpha; - if (SkDrawTreatAsHairline(*paint, *draw.fMatrix, &newAlpha)) { - lazyPaint.set(*paint); - lazyPaint.get()->setAlpha(newAlpha); - lazyPaint.get()->setStrokeWidth(0); - paint = lazyPaint.get(); - doFill = false; - } + if (SkDrawTreatAsHairline(paint, *draw.fMatrix, &coverage)) { + doFill = false; } - // must reference paint from here down, and not origPaint - // since we may have change the paint (using lazyPaint for storage) GrPaint grPaint; SkAutoCachedTexture act; - if (!this->skPaint2GrPaintShader(*paint, + if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint, @@ -1094,6 +1085,8 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, return; } + grPaint.fCoverage = SkScalarRoundToInt(coverage * grPaint.fCoverage); + // 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). @@ -1115,25 +1108,25 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, // at this point we're done with prePathMatrix SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) - if (doFill && (paint->getPathEffect() || - paint->getStyle() != SkPaint::kFill_Style)) { + if (doFill && (paint.getPathEffect() || + paint.getStyle() != SkPaint::kFill_Style)) { // it is safe to use tmpPath here, even if we already used it for the // prepathmatrix, since getFillPath can take the same object for its // input and output safely. - doFill = paint->getFillPath(*pathPtr, &tmpPath); + doFill = paint.getFillPath(*pathPtr, &tmpPath); pathPtr = &tmpPath; } - if (paint->getMaskFilter()) { + if (paint.getMaskFilter()) { // avoid possibly allocating a new path in transform if we can SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; // transform the path into device space pathPtr->transform(*draw.fMatrix, devPathPtr); - if (!drawWithGPUMaskFilter(fContext, *devPathPtr, paint->getMaskFilter(), + if (!drawWithGPUMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(), *draw.fMatrix, *draw.fClip, draw.fBounder, &grPaint)) { - drawWithMaskFilter(fContext, *devPathPtr, paint->getMaskFilter(), + drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(), *draw.fMatrix, *draw.fClip, draw.fBounder, &grPaint); }