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(); |
} |
/////////////////////////////////////////////////////////////////////////////////////////////////// |