Protect filter_texture() against render target change.
Fix blend filters when input textures are "sloppy" (approx scratch texture match)
Add a new test case to gm/imagefiltersgraph, and reduce its size.

NOTE:  this will require new baselines for the imagefiltersgraph GM.

BUG=950

Review URL: https://codereview.appspot.com/6769043

git-svn-id: http://skia.googlecode.com/svn/trunk@6073 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp
index 816c88e..a85aa6d 100644
--- a/gm/imagefiltersgraph.cpp
+++ b/gm/imagefiltersgraph.cpp
@@ -8,8 +8,10 @@
 #include "gm.h"
 
 #include "SkBitmapSource.h"
+#include "SkBlendImageFilter.h"
 #include "SkBlurImageFilter.h"
 #include "SkColorFilter.h"
+#include "SkColorMatrixFilter.h"
 #include "SkColorFilterImageFilter.h"
 #include "SkMorphologyImageFilter.h"
 
@@ -40,7 +42,7 @@
         canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
     }
 
-    virtual SkISize onISize() { return SkISize::Make(500, 500); }
+    virtual SkISize onISize() { return SkISize::Make(200, 100); }
 
     virtual void onDraw(SkCanvas* canvas) {
         if (!fInitialized) {
@@ -48,19 +50,35 @@
             fInitialized = true;
         }
         canvas->clear(0x00000000);
+        {
+            SkAutoTUnref<SkImageFilter> bitmapSource(new SkBitmapSource(fBitmap));
+            SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED,
+                                                         SkXfermode::kSrcIn_Mode));
+            SkAutoTUnref<SkImageFilter> blur(new SkBlurImageFilter(4.0f, 4.0f, bitmapSource));
+            SkAutoTUnref<SkImageFilter> erode(new SkErodeImageFilter(4, 4, blur));
+            SkAutoTUnref<SkImageFilter> color(new SkColorFilterImageFilter(cf, erode));
+            SkAutoTUnref<SkImageFilter> merge(new SkMergeImageFilter(blur, color));
 
-        SkAutoTUnref<SkImageFilter> bitmapSource(new SkBitmapSource(fBitmap));
+            SkPaint paint;
+            paint.setImageFilter(merge);
+            canvas->drawPaint(paint);
+        }
+        {
+            SkAutoTUnref<SkImageFilter> morph(new SkDilateImageFilter(5, 5));
 
-        SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED,
-                                                     SkXfermode::kSrcIn_Mode));
-        SkAutoTUnref<SkImageFilter> blur(new SkBlurImageFilter(4.0f, 4.0f, bitmapSource));
-        SkAutoTUnref<SkImageFilter> erode(new SkErodeImageFilter(4, 4, blur));
-        SkAutoTUnref<SkImageFilter> color(new SkColorFilterImageFilter(cf, erode));
-        SkAutoTUnref<SkImageFilter> merge(new SkMergeImageFilter(blur, color));
+            SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
+                                    0, SK_Scalar1, 0, 0, 0,
+                                    0, 0, SK_Scalar1, 0, 0,
+                                    0, 0, 0, SkFloatToScalar(0.5f), 0 };
 
-        SkPaint paint;
-        paint.setImageFilter(merge);
-        canvas->drawPaint(paint);
+            SkAutoTUnref<SkColorFilter> matrixFilter(new SkColorMatrixFilter(matrix));
+            SkAutoTUnref<SkImageFilter> colorMorph(new SkColorFilterImageFilter(matrixFilter, morph));
+            SkAutoTUnref<SkImageFilter> blendColor(new SkBlendImageFilter(SkBlendImageFilter::kNormal_Mode, colorMorph));
+
+            SkPaint paint;
+            paint.setImageFilter(blendColor);
+            canvas->drawBitmap(fBitmap, 100, 0, &paint);
+        }
     }
 
 private:
diff --git a/src/effects/SkBlendImageFilter.cpp b/src/effects/SkBlendImageFilter.cpp
index 455ddcb..b93190f 100644
--- a/src/effects/SkBlendImageFilter.cpp
+++ b/src/effects/SkBlendImageFilter.cpp
@@ -203,11 +203,14 @@
     GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
     GrContext::AutoClip ac(context, rect);
 
-    GrMatrix sampleM;
-    sampleM.setIDiv(background->width(), background->height());
+    GrMatrix backgroundTexMatrix, foregroundTexMatrix;
+    backgroundTexMatrix.setIDiv(background->width(), background->height());
+    foregroundTexMatrix.setIDiv(foreground->width(), foreground->height());
     GrPaint paint;
-    paint.colorSampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect, (background.get())), sampleM)->unref();
-    paint.colorSampler(1)->setCustomStage(SkNEW_ARGS(GrBlendEffect, (fMode, foreground.get())), sampleM)->unref();
+    paint.colorSampler(0)->setCustomStage(
+        SkNEW_ARGS(GrSingleTextureEffect, (background.get())), backgroundTexMatrix)->unref();
+    paint.colorSampler(1)->setCustomStage(
+        SkNEW_ARGS(GrBlendEffect, (fMode, foreground.get())), foregroundTexMatrix)->unref();
     context->drawRect(paint, rect);
     return dst;
 }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 52d26bb..fc1f86c 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1478,6 +1478,9 @@
     GrCustomStage* stage;
 
     if (filter->canFilterImageGPU()) {
+        // Save the render target and set it to NULL, so we don't accidentally draw to it in the
+        // filter.  Also set the clip wide open and the matrix to identity.
+        GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
         texture = filter->onFilterImageGPU(&proxy, texture, rect);
     } else if (filter->asNewCustomStage(&stage, texture)) {
         GrAutoScratchTexture dst(context, desc);