apply imagefilter to all draw calls
Review URL: https://codereview.appspot.com/5856048
git-svn-id: http://skia.googlecode.com/svn/trunk@3476 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 4917dcb..0ac4ed5 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1398,11 +1398,50 @@
fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
}
+static GrTexture* filter_texture(GrContext* context, GrTexture* texture,
+ SkImageFilter* filter, const GrRect& rect) {
+ GrAssert(filter);
+
+ SkSize blurSize;
+ SkISize radius;
+
+ const GrTextureDesc desc = {
+ kRenderTarget_GrTextureFlagBit,
+ rect.width(),
+ rect.height(),
+ kRGBA_8888_PM_GrPixelConfig,
+ {0} // samples
+ };
+
+ if (filter->asABlur(&blurSize)) {
+ GrAutoScratchTexture temp1, temp2;
+ texture = context->gaussianBlur(texture, &temp1, &temp2, rect,
+ blurSize.width(),
+ blurSize.height());
+ texture->ref();
+ } else if (filter->asADilate(&radius)) {
+ GrAutoScratchTexture temp1(context, desc), temp2(context, desc);
+ texture = context->applyMorphology(texture, rect,
+ temp1.texture(), temp2.texture(),
+ GrSamplerState::kDilate_Filter,
+ radius);
+ texture->ref();
+ } else if (filter->asAnErode(&radius)) {
+ GrAutoScratchTexture temp1(context, desc), temp2(context, desc);
+ texture = context->applyMorphology(texture, rect,
+ temp1.texture(), temp2.texture(),
+ GrSamplerState::kErode_Filter,
+ radius);
+ texture->ref();
+ }
+ return texture;
+}
+
void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
int left, int top, const SkPaint& paint) {
CHECK_SHOULD_DRAW(draw);
- SkAutoLockPixels alp(bitmap);
+ SkAutoLockPixels alp(bitmap, !bitmap.getTexture());
if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
return;
}
@@ -1422,50 +1461,19 @@
GrTexture* texture;
sampler->reset();
SkAutoCachedTexture act(this, bitmap, sampler, &texture);
+ grPaint.setTexture(kBitmapTextureIdx, texture);
- SkImageFilter* imageFilter = paint.getImageFilter();
- SkSize blurSize;
- SkISize radius;
- if (NULL != imageFilter && imageFilter->asABlur(&blurSize)) {
- GrAutoScratchTexture temp1, temp2;
- GrTexture* blurTexture = fContext->gaussianBlur(texture, &temp1, &temp2,
- GrRect::MakeWH(w, h),
- blurSize.width(),
- blurSize.height());
- texture = blurTexture;
- grPaint.setTexture(kBitmapTextureIdx, texture);
- } else if (NULL != imageFilter && imageFilter->asADilate(&radius)) {
- const GrTextureDesc desc = {
- kRenderTarget_GrTextureFlagBit,
- w,
- h,
- kRGBA_8888_PM_GrPixelConfig,
- {0} // samples
- };
- GrAutoScratchTexture temp1(fContext, desc), temp2(fContext, desc);
- texture = fContext->applyMorphology(texture, GrRect::MakeWH(w, h),
- temp1.texture(), temp2.texture(),
- GrSamplerState::kDilate_Filter,
- radius);
- grPaint.setTexture(kBitmapTextureIdx, texture);
- } else if (NULL != imageFilter && imageFilter->asAnErode(&radius)) {
- const GrTextureDesc desc = {
- kRenderTarget_GrTextureFlagBit,
- w,
- h,
- kRGBA_8888_PM_GrPixelConfig,
- {0} // samples
- };
- GrAutoScratchTexture temp1(fContext, desc), temp2(fContext, desc);
- texture = fContext->applyMorphology(texture, GrRect::MakeWH(w, h),
- temp1.texture(), temp2.texture(),
- GrSamplerState::kErode_Filter,
- radius);
- grPaint.setTexture(kBitmapTextureIdx, texture);
- } else {
- grPaint.setTexture(kBitmapTextureIdx, texture);
+ SkImageFilter* filter = paint.getImageFilter();
+ if (NULL != filter) {
+ GrTexture* filteredTexture = filter_texture(fContext, texture, filter,
+ GrRect::MakeWH(w, h));
+ if (filteredTexture) {
+ grPaint.setTexture(kBitmapTextureIdx, filteredTexture);
+ texture = filteredTexture;
+ filteredTexture->unref();
+ }
}
-
+
fContext->drawRectToRect(grPaint,
GrRect::MakeXYWH(GrIntToScalar(left),
GrIntToScalar(top),
@@ -1488,6 +1496,18 @@
GrTexture* devTex = grPaint.getTexture(0);
SkASSERT(NULL != devTex);
+ SkImageFilter* filter = paint.getImageFilter();
+ if (NULL != filter) {
+ GrRect rect = GrRect::MakeWH(devTex->width(), devTex->height());
+ GrTexture* filteredTexture = filter_texture(fContext, devTex, filter,
+ rect);
+ if (filteredTexture) {
+ grPaint.setTexture(kBitmapTextureIdx, filteredTexture);
+ devTex = filteredTexture;
+ filteredTexture->unref();
+ }
+ }
+
const SkBitmap& bm = dev->accessBitmap(false);
int w = bm.width();
int h = bm.height();
@@ -1509,27 +1529,43 @@
fContext->drawRectToRect(grPaint, dstRect, srcRect);
}
-bool SkGpuDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
- const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* offset) {
+bool SkGpuDevice::canHandleImageFilter(SkImageFilter* filter) {
SkSize size;
SkISize radius;
if (!filter->asABlur(&size) && !filter->asADilate(&radius) && !filter->asAnErode(&radius)) {
return false;
}
- SkDevice* dev = this->createCompatibleDevice(SkBitmap::kARGB_8888_Config,
- src.width(),
- src.height(),
- false);
- if (NULL == dev) {
+ return true;
+}
+
+bool SkGpuDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) {
+ // want explicitly our impl, so guard against a subclass of us overriding it
+ if (!this->SkGpuDevice::canHandleImageFilter(filter)) {
return false;
}
- SkAutoUnref aur(dev);
- SkCanvas canvas(dev);
- SkPaint paint;
- paint.setImageFilter(filter);
- canvas.drawSprite(src, 0, 0, &paint);
- *result = dev->accessBitmap(false);
+
+ SkAutoLockPixels alp(src, !src.getTexture());
+ if (!src.getTexture() && !src.readyToDraw()) {
+ return false;
+ }
+
+ GrPaint paint;
+ paint.reset();
+
+ GrSamplerState* sampler = paint.textureSampler(kBitmapTextureIdx);
+
+ GrTexture* texture;
+ SkAutoCachedTexture act(this, src, sampler, &texture);
+
+ result->setConfig(src.config(), src.width(), src.height());
+ GrRect rect = GrRect::MakeWH(src.width(), src.height());
+ GrTexture* resultTexture = filter_texture(fContext, texture, filter, rect);
+ if (resultTexture) {
+ result->setPixelRef(new SkGrTexturePixelRef(resultTexture))->unref();
+ resultTexture->unref();
+ }
return true;
}