Pull xfer mode test out of generic draw-as-hairline test. Use coverage rather than...
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 18 Jan 2012 20:34:00 +0000 (20:34 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 18 Jan 2012 20:34:00 +0000 (20:34 +0000)
Review URL: http://codereview.appspot.com/5528112/

git-svn-id: http://skia.googlecode.com/svn/trunk@3070 2bbb7eff-a529-9590-31e7-b0007b416f81

include/gpu/GrPaint.h
src/core/SkDraw.cpp
src/core/SkDrawProcs.h
src/gpu/GrContext.cpp
src/gpu/SkGpuDevice.cpp

index f1d74b2..9f220e0 100644 (file)
@@ -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);
index d1b291f..23a6d59 100644 (file)
@@ -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<SkPaint> 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();
+            }
         }
     }
 
index 33b870d..2e26ecf 100644 (file)
@@ -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
 
index 2137319..754063d 100644 (file)
@@ -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);
 }
 
index 96d9fc6..ad15553 100644 (file)
@@ -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<SkPaint> 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);
         }