Implement offset for GPU filter path. Although we can't yet use this in Blink for FEOffset, due to SVG semantics, we can use it to support crop rect (upcoming patch).

This patch adds the parameter to the filterImageGPU() signature, plumbs through the code on the GPU side, and implements support for it in SkXfermodeImageFilter for both raster and GPU.

Of the remaining filters with GPU implementations, Blur, Morphology, Bicubic and Displacement work fine; they're commutative wrt offset and can simply pass it up the chain. Blend is not, but will be removed shortly anyway (has been replaced with SkXfermodeImageFilter in Blink).

R=reed@google.com, bsalomon@google.com

Author: senorblanco@chromium.org

Review URL: https://chromiumcodereview.appspot.com/15995026

git-svn-id: http://skia.googlecode.com/svn/trunk@9977 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 766158f..d9de0ca 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1377,7 +1377,7 @@
 
 static bool filter_texture(SkDevice* device, GrContext* context,
                            GrTexture* texture, SkImageFilter* filter,
-                           int w, int h, SkBitmap* result) {
+                           int w, int h, SkBitmap* result, SkIPoint* offset) {
     GrAssert(filter);
     SkDeviceImageFilterProxy proxy(device);
 
@@ -1385,7 +1385,7 @@
         // 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);
-        return filter->filterImageGPU(&proxy, wrap_texture(texture), result);
+        return filter->filterImageGPU(&proxy, wrap_texture(texture), result, offset);
     } else {
         return false;
     }
@@ -1419,9 +1419,10 @@
         GrSimpleTextureEffect::Create(texture, SkMatrix::I()))->unref();
 
     SkImageFilter* filter = paint.getImageFilter();
+    SkIPoint offset = SkIPoint::Make(0, 0);
     if (NULL != filter) {
         SkBitmap filterBitmap;
-        if (filter_texture(this, fContext, texture, filter, w, h, &filterBitmap)) {
+        if (filter_texture(this, fContext, texture, filter, w, h, &filterBitmap, &offset)) {
             grPaint.colorStage(kBitmapEffectIdx)->setEffect(
                 GrSimpleTextureEffect::Create(filterBitmap.getTexture(), SkMatrix::I()))->unref();
             texture = filterBitmap.getTexture();
@@ -1435,8 +1436,10 @@
                                             SkIntToScalar(top),
                                             SkIntToScalar(w),
                                             SkIntToScalar(h)),
-                            GrRect::MakeWH(SK_Scalar1 * w / texture->width(),
-                                        SK_Scalar1 * h / texture->height()));
+                            GrRect::MakeXYWH(offset.fX,
+                                             offset.fY,
+                                             SK_Scalar1 * w / texture->width(),
+                                             SK_Scalar1 * h / texture->height()));
 }
 
 void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
@@ -1498,12 +1501,15 @@
     SkImageFilter* filter = paint.getImageFilter();
     if (NULL != filter) {
         SkBitmap filterBitmap;
-        if (filter_texture(this, fContext, devTex, filter, w, h, &filterBitmap)) {
+        SkIPoint offset = SkIPoint::Make(0, 0);
+        if (filter_texture(this, fContext, devTex, filter, w, h, &filterBitmap, &offset)) {
             grPaint.colorStage(kBitmapEffectIdx)->setEffect(
                 GrSimpleTextureEffect::Create(filterBitmap.getTexture(), SkMatrix::I()))->unref();
             devTex = filterBitmap.getTexture();
             w = filterBitmap.width();
             h = filterBitmap.height();
+            x += offset.fX;
+            y += offset.fY;
         }
     }
 
@@ -1542,7 +1548,7 @@
     // must be pushed upstack.
     SkAutoCachedTexture act(this, src, NULL, &texture);
 
-    return filter_texture(this, fContext, texture, filter, src.width(), src.height(), result);
+    return filter_texture(this, fContext, texture, filter, src.width(), src.height(), result, offset);
 }
 
 ///////////////////////////////////////////////////////////////////////////////