Clean up the use of AutoScratchTexture in the gaussian blur and morphology
filters. Instead of passing in AutoScratchTextures for temporaries, we allocate
them inside the function and detach() after rendering. Since the functions now
return a ref()'ed texture, we no longer ref() the result in filter_texture().
Also, the imageblur gm was passing a paint with an image filter both to
saveLayer()/restore(), and to every text draw call. Back when only restore()
was applying filters, this was fine, but since we're now applying filters on all
draw calls, this means we're double-blurring in this GM.
I've reverted the Mac baselines for the imageblur GM to their previous versions;
hopefully this will be correct.
git-svn-id: http://skia.googlecode.com/svn/trunk@4659 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/imageblur.cpp b/gm/imageblur.cpp
index c8dd5d7..f326f45 100644
--- a/gm/imageblur.cpp
+++ b/gm/imageblur.cpp
@@ -32,16 +32,17 @@
SkPaint paint;
paint.setImageFilter(new SkBlurImageFilter(24.0f, 0.0f))->unref();
canvas->saveLayer(NULL, &paint);
- paint.setAntiAlias(true);
const char* str = "The quick brown fox jumped over the lazy dog.";
srand(1234);
+ SkPaint textPaint;
+ textPaint.setAntiAlias(true);
for (int i = 0; i < 25; ++i) {
int x = rand() % WIDTH;
int y = rand() % HEIGHT;
- paint.setColor(rand() % 0x1000000 | 0xFF000000);
- paint.setTextSize(SkIntToScalar(rand() % 300));
+ textPaint.setColor(rand() % 0x1000000 | 0xFF000000);
+ textPaint.setTextSize(SkIntToScalar(rand() % 300));
canvas->drawText(str, strlen(str), SkIntToScalar(x),
- SkIntToScalar(y), paint);
+ SkIntToScalar(y), textPaint);
}
canvas->restore();
}
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index a199beb..f905825 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -591,18 +591,16 @@
/**
* Applies a 2D Gaussian blur to a given texture.
* @param srcTexture The source texture to be blurred.
- * @param temp1 A scratch texture. Must not be NULL.
- * @param temp2 A scratch texture. May be NULL, in which case
- * srcTexture is overwritten with intermediate
- * results.
+ * @param canClobberSrc If true, srcTexture may be overwritten, and
+ * may be returned as the result.
* @param rect The destination rectangle.
* @param sigmaX The blur's standard deviation in X.
* @param sigmaY The blur's standard deviation in Y.
- * @return the blurred texture, which may be temp1, temp2 or srcTexture.
+ * @return the blurred texture, which may be srcTexture ref'ed, or a
+ * new texture. It is the caller's responsibility to unref this texture.
*/
GrTexture* gaussianBlur(GrTexture* srcTexture,
- GrAutoScratchTexture* temp1,
- GrAutoScratchTexture* temp2,
+ bool canClobberSrc,
const SkRect& rect,
float sigmaX, float sigmaY);
@@ -618,18 +616,16 @@
* Applies a 2D morphology to a given texture.
* @param srcTexture The source texture to be blurred.
* @param rect The destination rectangle.
- * @param temp1 A scratch texture. Must not be NULL.
- * @param temp2 A scratch texture. Must not be NULL.
* @param filter The morphology filter. Must be kDilate_Filter or
* kErode_Filter.
* @param radius The morphology radius in X and Y. The filter is
* applied to a fWidth by fHeight rectangle of
* pixels.
- * @return the morphed texture, which may be temp1, temp2 or srcTexture.
+ * @return the morphed texture, which may be srcTexture ref'ed, or a
+ * new texture. It is the caller's responsibility to unref this texture.
*/
GrTexture* applyMorphology(GrTexture* srcTexture,
const GrRect& rect,
- GrTexture* temp1, GrTexture* temp2,
MorphologyType type,
SkISize radius);
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 6e5fb08..67fa5ab 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -1808,13 +1808,11 @@
}
GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
- GrAutoScratchTexture* temp1,
- GrAutoScratchTexture* temp2,
+ bool canClobberSrc,
const SkRect& rect,
float sigmaX, float sigmaY) {
ASSERT_OWNED_RESOURCE(srcTexture);
GrRenderTarget* oldRenderTarget = this->getRenderTarget();
- GrTexture* origTexture = srcTexture;
AutoMatrix avm(this, GrMatrix::I());
SkIRect clearRect;
int scaleFactorX, radiusX;
@@ -1840,12 +1838,10 @@
desc.fHeight = SkScalarFloorToInt(srcRect.height());
desc.fConfig = srcTexture->config();
- temp1->set(this, desc);
- if (temp2) {
- temp2->set(this, desc);
- }
+ GrAutoScratchTexture temp1, temp2;
+ GrTexture* dstTexture = temp1.set(this, desc);
+ GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(this, desc);
- GrTexture* dstTexture = temp1->texture();
GrPaint paint;
paint.reset();
paint.textureSampler(0)->setFilter(GrSamplerState::kBilinear_Filter);
@@ -1860,11 +1856,8 @@
paint.setTexture(0, srcTexture);
this->drawRectToRect(paint, dstRect, srcRect);
srcRect = dstRect;
- SkTSwap(srcTexture, dstTexture);
- // If temp2 is non-NULL, don't render back to origTexture
- if (temp2 && dstTexture == origTexture) {
- dstTexture = temp2->texture();
- }
+ srcTexture = dstTexture;
+ SkTSwap(dstTexture, tempTexture);
}
SkIRect srcIRect;
@@ -1882,10 +1875,8 @@
this->setRenderTarget(dstTexture->asRenderTarget());
convolve_gaussian(fGpu, srcTexture, srcRect, sigmaX, radiusX,
Gr1DKernelEffect::kX_Direction);
- SkTSwap(srcTexture, dstTexture);
- if (temp2 && dstTexture == origTexture) {
- dstTexture = temp2->texture();
- }
+ srcTexture = dstTexture;
+ SkTSwap(dstTexture, tempTexture);
}
if (sigmaY > 0.0f) {
@@ -1900,10 +1891,8 @@
this->setRenderTarget(dstTexture->asRenderTarget());
convolve_gaussian(fGpu, srcTexture, srcRect, sigmaY, radiusY,
Gr1DKernelEffect::kY_Direction);
- SkTSwap(srcTexture, dstTexture);
- if (temp2 && dstTexture == origTexture) {
- dstTexture = temp2->texture();
- }
+ srcTexture = dstTexture;
+ SkTSwap(dstTexture, tempTexture);
}
if (scaleFactorX > 1 || scaleFactorY > 1) {
@@ -1925,27 +1914,40 @@
scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
this->drawRectToRect(paint, dstRect, srcRect);
srcRect = dstRect;
- SkTSwap(srcTexture, dstTexture);
+ srcTexture = dstTexture;
+ SkTSwap(dstTexture, tempTexture);
}
this->setRenderTarget(oldRenderTarget);
- return srcTexture;
+ if (srcTexture == temp1.texture()) {
+ return temp1.detach();
+ } else if (srcTexture == temp2.texture()) {
+ return temp2.detach();
+ } else {
+ srcTexture->ref();
+ return srcTexture;
+ }
}
GrTexture* GrContext::applyMorphology(GrTexture* srcTexture,
const GrRect& rect,
- GrTexture* temp1, GrTexture* temp2,
MorphologyType morphType,
SkISize radius) {
ASSERT_OWNED_RESOURCE(srcTexture);
+ srcTexture->ref();
GrRenderTarget* oldRenderTarget = this->getRenderTarget();
AutoMatrix avm(this, GrMatrix::I());
AutoClip acs(this, GrRect::MakeWH(SkIntToScalar(srcTexture->width()),
SkIntToScalar(srcTexture->height())));
-
+ GrTextureDesc desc;
+ desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
+ desc.fWidth = SkScalarCeilToInt(rect.width());
+ desc.fHeight = SkScalarCeilToInt(rect.height());
+ desc.fConfig = kRGBA_8888_PM_GrPixelConfig;
if (radius.fWidth > 0) {
- this->setRenderTarget(temp1->asRenderTarget());
+ GrAutoScratchTexture ast(this, desc);
+ this->setRenderTarget(ast.texture()->asRenderTarget());
apply_morphology(fGpu, srcTexture, rect, radius.fWidth, morphType,
Gr1DKernelEffect::kX_Direction);
SkIRect clearRect = SkIRect::MakeXYWH(
@@ -1954,13 +1956,16 @@
SkScalarFloorToInt(rect.width()),
radius.fHeight);
this->clear(&clearRect, 0x0);
- srcTexture = temp1;
+ srcTexture->unref();
+ srcTexture = ast.detach();
}
if (radius.fHeight > 0) {
- this->setRenderTarget(temp2->asRenderTarget());
+ GrAutoScratchTexture ast(this, desc);
+ this->setRenderTarget(ast.texture()->asRenderTarget());
apply_morphology(fGpu, srcTexture, rect, radius.fHeight, morphType,
Gr1DKernelEffect::kY_Direction);
- srcTexture = temp2;
+ srcTexture->unref();
+ srcTexture = ast.detach();
}
this->setRenderTarget(oldRenderTarget);
return srcTexture;
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index d0d4604..5e4d8936 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -869,14 +869,11 @@
// Draw hard shadow to pathTexture with path topleft at origin 0,0.
context->drawPath(tempPaint, path, pathFillType, &offset);
- GrAutoScratchTexture temp1, temp2;
// If we're doing a normal blur, we can clobber the pathTexture in the
// gaussianBlur. Otherwise, we need to save it for later compositing.
bool isNormalBlur = blurType == SkMaskFilter::kNormal_BlurType;
- GrTexture* blurTexture = context->gaussianBlur(pathTexture,
- &temp1,
- isNormalBlur ? NULL : &temp2,
- srcRect, sigma, sigma);
+ SkAutoTUnref<GrTexture> blurTexture(context->gaussianBlur(
+ pathTexture, isNormalBlur, srcRect, sigma, sigma));
if (!isNormalBlur) {
GrPaint paint;
@@ -1506,25 +1503,17 @@
texture = dst.detach();
stage->unref();
} else if (filter->asABlur(&blurSize)) {
- GrAutoScratchTexture temp1, temp2;
- texture = context->gaussianBlur(texture, &temp1, &temp2, rect,
+ texture = context->gaussianBlur(texture, false, 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(),
GrContext::kDilate_MorphologyType,
radius);
- texture->ref();
} else if (filter->asAnErode(&radius)) {
- GrAutoScratchTexture temp1(context, desc), temp2(context, desc);
texture = context->applyMorphology(texture, rect,
- temp1.texture(), temp2.texture(),
GrContext::kErode_MorphologyType,
radius);
- texture->ref();
}
return texture;
}