Add GrPaint stage for xfermodes.
Review URL: https://codereview.chromium.org/12918032

git-svn-id: http://skia.googlecode.com/svn/trunk@8425 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h
index e0a9203..25ec699 100644
--- a/include/gpu/GrPaint.h
+++ b/include/gpu/GrPaint.h
@@ -44,7 +44,7 @@
 class GrPaint {
 public:
     enum {
-        kMaxColorStages     = 2,
+        kMaxColorStages     = 3,
         kMaxCoverageStages  = 1,
     };
 
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 8b7a36e..002c4ed 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -11,6 +11,7 @@
 #include "GrBackendEffectFactory.h"
 #include "GrColor.h"
 #include "GrEffectStage.h"
+#include "GrPaint.h"
 #include "GrRefCnt.h"
 #include "GrRenderTarget.h"
 #include "GrStencil.h"
@@ -22,8 +23,6 @@
 #include "SkMatrix.h"
 #include "SkXfermode.h"
 
-class GrPaint;
-
 /**
  * Type used to describe how attributes bind to program usage
  */
@@ -53,12 +52,13 @@
      * the color / coverage distinction.
      *
      * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
-     * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
-     * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
-     * by GrClipMaskManager.
+     * GrPaint. Stage GrPaint::kTotalStages is earmarked for use by GrTextContext, GrPathRenderer-
+     * derived classes, and the rect/oval helper classes. GrPaint::kTotalStages+1 is earmarked for
+     * clipping by GrClipMaskManager. TODO: replace fixed size array of stages with variable size
+     * arrays of color and coverage stages.
      */
     enum {
-        kNumStages = 5,
+        kNumStages = GrPaint::kTotalStages + 2,
     };
 
     GrDrawState() {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 6f6608a..aca3ba6 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -37,12 +37,13 @@
     #define CHECK_SHOULD_DRAW(draw, forceI) this->prepareDraw(draw, forceI)
 #endif
 
-// we use the same texture slot on GrPaint for bitmaps and shaders
-// (since drawBitmap, drawSprite, and drawDevice ignore skia's shader)
+// we use the same effect slot on GrPaint for bitmaps and shaders (since drawBitmap, drawSprite,
+// and drawDevice ignore SkShader)
 enum {
-    kBitmapTextureIdx = 0,
-    kShaderTextureIdx = 0,
-    kColorFilterTextureIdx = 1
+    kShaderEffectIdx = 0,
+    kBitmapEffectIdx = 0,
+    kColorFilterEffectIdx = 1,
+    kXfermodeEffectIdx = 2,
 };
 
 #define MAX_BLUR_SIGMA 4.0f
@@ -443,7 +444,7 @@
 bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
     GrTexture* texture = fRenderTarget->asTexture();
     if (NULL != texture) {
-        paint->colorStage(kBitmapTextureIdx)->setEffect(
+        paint->colorStage(kBitmapEffectIdx)->setEffect(
             GrSimpleTextureEffect::Create(texture, SkMatrix::I()))->unref();
         return true;
     }
@@ -486,8 +487,7 @@
     SkXfermode* mode = skPaint.getXfermode();
     GrEffectRef* xferEffect = NULL;
     if (SkXfermode::AsNewEffect(mode, dev->context(), &xferEffect, &sm, &dm)) {
-        // We're not ready for xfermode effects yet
-        GrAssert(NULL == xferEffect);
+        SkSafeUnref(grPaint->colorStage(kXfermodeEffectIdx)->setEffect(xferEffect));
     } else {
         //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
 #if 0
@@ -504,7 +504,7 @@
         GrAssert(!constantColor);
     } else {
         grPaint->setColor(SkColor2GrColor(skPaint.getColor()));
-        GrAssert(!grPaint->isColorStageEnabled(kShaderTextureIdx));
+        GrAssert(!grPaint->isColorStageEnabled(kShaderEffectIdx));
     }
 
     SkColorFilter* colorFilter = skPaint.getColorFilter();
@@ -517,7 +517,7 @@
         } else {
             SkAutoTUnref<GrEffectRef> effect(colorFilter->asNewEffect(dev->context()));
             if (NULL != effect.get()) {
-                grPaint->colorStage(kColorFilterTextureIdx)->setEffect(effect);
+                grPaint->colorStage(kColorFilterEffectIdx)->setEffect(effect);
             } else {
                 // TODO: rewrite this using asNewEffect()
                 SkColor color;
@@ -549,7 +549,7 @@
 
     SkAutoTUnref<GrEffectRef> effect(shader->asNewEffect(dev->context(), skPaint));
     if (NULL != effect.get()) {
-        grPaint->colorStage(kShaderTextureIdx)->setEffect(effect);
+        grPaint->colorStage(kShaderEffectIdx)->setEffect(effect);
         return true;
     }
 
@@ -1378,7 +1378,7 @@
     } else {
         effect.reset(GrSimpleTextureEffect::Create(texture, SkMatrix::I(), params));
     }
-    grPaint->colorStage(kBitmapTextureIdx)->setEffect(effect);
+    grPaint->colorStage(kBitmapEffectIdx)->setEffect(effect);
     fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
 }
 
@@ -1460,20 +1460,20 @@
         return;
     }
 
-    GrEffectStage* stage = grPaint.colorStage(kBitmapTextureIdx);
+    GrEffectStage* stage = grPaint.colorStage(kBitmapEffectIdx);
 
     GrTexture* texture;
     stage->reset();
     // draw sprite uses the default texture params
     SkAutoCachedTexture act(this, bitmap, NULL, &texture);
-    grPaint.colorStage(kBitmapTextureIdx)->setEffect(
+    grPaint.colorStage(kBitmapEffectIdx)->setEffect(
         GrSimpleTextureEffect::Create(texture, SkMatrix::I()))->unref();
 
     SkImageFilter* filter = paint.getImageFilter();
     if (NULL != filter) {
         SkBitmap filterBitmap;
         if (filter_texture(this, fContext, texture, filter, w, h, &filterBitmap)) {
-            grPaint.colorStage(kBitmapTextureIdx)->setEffect(
+            grPaint.colorStage(kBitmapEffectIdx)->setEffect(
                 GrSimpleTextureEffect::Create((GrTexture*) filterBitmap.getTexture(), SkMatrix::I()))->unref();
             texture = (GrTexture*) filterBitmap.getTexture();
             w = filterBitmap.width();
@@ -1533,13 +1533,13 @@
     CHECK_SHOULD_DRAW(draw, true);
 
     GrPaint grPaint;
-    grPaint.colorStage(kBitmapTextureIdx)->reset();
+    grPaint.colorStage(kBitmapEffectIdx)->reset();
     if (!dev->bindDeviceAsTexture(&grPaint) ||
         !skPaint2GrPaintNoShader(this, paint, true, false, &grPaint)) {
         return;
     }
 
-    GrTexture* devTex = (*grPaint.getColorStage(kBitmapTextureIdx).getEffect())->texture(0);
+    GrTexture* devTex = (*grPaint.getColorStage(kBitmapEffectIdx).getEffect())->texture(0);
     SkASSERT(NULL != devTex);
 
     const SkBitmap& bm = dev->accessBitmap(false);
@@ -1550,7 +1550,7 @@
     if (NULL != filter) {
         SkBitmap filterBitmap;
         if (filter_texture(this, fContext, devTex, filter, w, h, &filterBitmap)) {
-            grPaint.colorStage(kBitmapTextureIdx)->setEffect(
+            grPaint.colorStage(kBitmapEffectIdx)->setEffect(
                 GrSimpleTextureEffect::Create((GrTexture*) filterBitmap.getTexture(), SkMatrix::I()))->unref();
             devTex = (GrTexture*) filterBitmap.getTexture();
             w = filterBitmap.width();