| Index: src/image/SkImage_Gpu.cpp
 | 
| diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
 | 
| index 67d1b8cd8632498d8c93b6b7a409a9ee4ec73de9..ed9ecffa51c91e1fc61ca147be4c485c465e8d12 100644
 | 
| --- a/src/image/SkImage_Gpu.cpp
 | 
| +++ b/src/image/SkImage_Gpu.cpp
 | 
| @@ -214,33 +214,52 @@ public:
 | 
|          }
 | 
|      }
 | 
|  
 | 
| -    bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
 | 
| -                     SkBitmap*, SkIPoint*) override {
 | 
| -        return false;
 | 
| +    bool filterImage(const SkImageFilter* filter, const SkBitmap& src,
 | 
| +                     const SkImageFilter::Context& ctx, SkBitmap* dst, SkIPoint* offset) override {
 | 
| +        return filter->canFilterImageGPU() &&
 | 
| +               filter->filterImageGPU(this, src, ctx, dst, offset);
 | 
|      }
 | 
|  };
 | 
|  
 | 
| +static SkIRect compute_fast_ibounds(SkImageFilter* filter, const SkIRect& srcBounds) {
 | 
| +    SkRect fastBounds;
 | 
| +    fastBounds.set(srcBounds);
 | 
| +    filter->computeFastBounds(fastBounds, &fastBounds);
 | 
| +    return fastBounds.roundOut();
 | 
| +}
 | 
| +
 | 
|  SkImage* SkImage_Gpu::onApplyFilter(SkImageFilter* filter, SkIPoint* offsetResult,
 | 
|                                      bool forceResultToOriginalSize) const {
 | 
| -    if (!forceResultToOriginalSize || !filter->canFilterImageGPU()) {
 | 
| -        return this->INHERITED::onApplyFilter(filter, offsetResult, forceResultToOriginalSize);
 | 
| -    }
 | 
| +    const SkIRect srcBounds = SkIRect::MakeWH(this->width(), this->height());
 | 
|  
 | 
| -    SkBitmap src;
 | 
| -    GrWrapTextureInBitmap(fTexture, this->width(), this->height(), this->isOpaque(), &src);
 | 
| +    if (forceResultToOriginalSize) {
 | 
| +        SkBitmap src;
 | 
| +        GrWrapTextureInBitmap(fTexture, this->width(), this->height(), this->isOpaque(), &src);
 | 
|  
 | 
| -    GrContext* context = fTexture->getContext();
 | 
| -    SkGpuImageFilterProxy proxy(context);
 | 
| -    SkImageFilter::Context ctx(SkMatrix::I(),
 | 
| -                               SkIRect::MakeWH(this->width(), this->height()),
 | 
| -                               SkImageFilter::Cache::Get());
 | 
| +        const SkIRect clipBounds = srcBounds;
 | 
| +        SkGpuImageFilterProxy proxy(fTexture->getContext());
 | 
| +        SkImageFilter::Context ctx(SkMatrix::I(), clipBounds, SkImageFilter::Cache::Get());
 | 
|  
 | 
| -    SkBitmap dst;
 | 
| -    if (filter->filterImageGPU(&proxy, src, ctx, &dst, offsetResult)) {
 | 
| +        SkBitmap dst;
 | 
| +        if (!filter->filterImage(&proxy, src, ctx, &dst, offsetResult)) {
 | 
| +            return nullptr;
 | 
| +        }
 | 
|          return new SkImage_Gpu(dst.width(), dst.height(), kNeedNewImageUniqueID, dst.alphaType(),
 | 
|                                 dst.getTexture(), SkSurface::kNo_Budgeted);
 | 
|      }
 | 
| -    return nullptr;
 | 
| +
 | 
| +    const SkIRect dstR = compute_fast_ibounds(filter, srcBounds);
 | 
| +
 | 
| +    SkImageInfo info = SkImageInfo::MakeN32Premul(dstR.width(), dstR.height());
 | 
| +    SkAutoTUnref<SkSurface> surface(this->onNewSurface(info));
 | 
| +
 | 
| +    SkPaint paint;
 | 
| +    paint.setImageFilter(filter);
 | 
| +    surface->getCanvas()->drawImage(this, SkIntToScalar(-dstR.x()), SkIntToScalar(-dstR.y()),
 | 
| +                                    &paint);
 | 
| +
 | 
| +    offsetResult->set(dstR.x(), dstR.y());
 | 
| +    return surface->newImageSnapshot();
 | 
|  }
 | 
|  
 | 
|  ///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
| 
 |