GPU-based blur cleanup. Clean up some issues raised in code review:
- convolveRect() is too low-level; made it private and exposed convolveInX() and convolveInY() instead - added GrAutoTextureEntry to automatically unlock a texture entry - the clipping and bounder checks were returning false from drawWithGPUMaskFilter(), causing the software blur to kick in; return true instead - the Windows build was giving a spurious warning about reading an uninitialized variable; rearrange the code to fix it Review URL: http://codereview.appspot.com/4710042/ git-svn-id: http://skia.googlecode.com/svn/trunk@1842 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
333d6cb244
commit
aadd9f8b19
@ -491,20 +491,30 @@ public:
|
||||
GrPixelConfig, const void* buffer, size_t stride);
|
||||
|
||||
/**
|
||||
* Performs a 1D convolution over a rectangle of pixels. Set
|
||||
* imageIncrement to (1/w, 0) for a convolution in X, (0, 1/h) for a
|
||||
* convolution in Y, where w, h are the texture dimensions.
|
||||
* @param srcTexture the texture to read from
|
||||
* @param dstRect the destination rectangle
|
||||
* @param imageIncrement the displacement between pixel samples
|
||||
* Applies a 1D convolution kernel in the X direction to a rectangle of
|
||||
* pixels from a given texture.
|
||||
* @param texture the texture to read from
|
||||
* @param rect the destination rectangle
|
||||
* @param kernel the convolution kernel (kernelWidth elements)
|
||||
* @param kernelWidth the width of the convolution kernel
|
||||
*/
|
||||
void convolveRect(GrTexture* srcTexture,
|
||||
const SkRect& dstRect,
|
||||
float imageIncrement[2],
|
||||
const float* kernel,
|
||||
int kernelWidth);
|
||||
void convolveInX(GrTexture* texture,
|
||||
const SkRect& rect,
|
||||
const float* kernel,
|
||||
int kernelWidth);
|
||||
/**
|
||||
* Applies a 1D convolution kernel in the Y direction to a rectangle of
|
||||
* pixels from a given texture.
|
||||
* direction.
|
||||
* @param texture the texture to read from
|
||||
* @param rect the destination rectangle
|
||||
* @param kernel the convolution kernel (kernelWidth elements)
|
||||
* @param kernelWidth the width of the convolution kernel
|
||||
*/
|
||||
void convolveInY(GrTexture* texture,
|
||||
const SkRect& rect,
|
||||
const float* kernel,
|
||||
int kernelWidth);
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
|
||||
@ -630,6 +640,12 @@ private:
|
||||
void cleanupOffscreenAA(GrDrawTarget* target,
|
||||
GrPathRenderer* pr,
|
||||
OffscreenRecord* record);
|
||||
|
||||
void convolve(GrTexture* texture,
|
||||
const SkRect& rect,
|
||||
float imageIncrement[2],
|
||||
const float* kernel,
|
||||
int kernelWidth);
|
||||
|
||||
// computes vertex layout bits based on the paint. If paint expresses
|
||||
// a texture for a stage, the stage coords will be bound to postitions
|
||||
@ -663,6 +679,25 @@ private:
|
||||
GrMatrix fMatrix;
|
||||
};
|
||||
|
||||
/**
|
||||
* Unlocks a texture entry when this goes out of scope. Entry may be NULL.
|
||||
*/
|
||||
class GrAutoUnlockTextureEntry : ::GrNoncopyable {
|
||||
public:
|
||||
GrAutoUnlockTextureEntry(GrContext* context, GrTextureEntry* entry)
|
||||
: fContext(context)
|
||||
, fEntry(entry) {
|
||||
}
|
||||
~GrAutoUnlockTextureEntry() {
|
||||
if (fContext && fEntry) {
|
||||
fContext->unlockTexture(fEntry);
|
||||
}
|
||||
}
|
||||
private:
|
||||
GrContext* fContext;
|
||||
GrTextureEntry* fEntry;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#include "GrContext_impl.h"
|
||||
|
@ -1699,22 +1699,38 @@ GrPathRenderer* GrContext::getPathRenderer(const GrPath& path,
|
||||
}
|
||||
}
|
||||
|
||||
void GrContext::convolveRect(GrTexture* srcTexture,
|
||||
const SkRect& rect,
|
||||
float imageIncrement[2],
|
||||
const float* kernel,
|
||||
int kernelWidth) {
|
||||
void GrContext::convolveInX(GrTexture* texture,
|
||||
const SkRect& rect,
|
||||
const float* kernel,
|
||||
int kernelWidth) {
|
||||
float imageIncrement[2] = {1.0f / texture->width(), 0.0f};
|
||||
convolve(texture, rect, imageIncrement, kernel, kernelWidth);
|
||||
}
|
||||
|
||||
void GrContext::convolveInY(GrTexture* texture,
|
||||
const SkRect& rect,
|
||||
const float* kernel,
|
||||
int kernelWidth) {
|
||||
float imageIncrement[2] = {0.0f, 1.0f / texture->height()};
|
||||
convolve(texture, rect, imageIncrement, kernel, kernelWidth);
|
||||
}
|
||||
|
||||
void GrContext::convolve(GrTexture* texture,
|
||||
const SkRect& rect,
|
||||
float imageIncrement[2],
|
||||
const float* kernel,
|
||||
int kernelWidth) {
|
||||
GrDrawTarget::AutoStateRestore asr(fGpu);
|
||||
GrMatrix sampleM;
|
||||
GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
|
||||
GrSamplerState::kClamp_WrapMode,
|
||||
GrSamplerState::kConvolution_Filter);
|
||||
sampler.setConvolutionParams(kernelWidth, kernel, imageIncrement);
|
||||
sampleM.setScale(GR_Scalar1 / srcTexture->width(),
|
||||
GR_Scalar1 / srcTexture->height());
|
||||
sampleM.setScale(GR_Scalar1 / texture->width(),
|
||||
GR_Scalar1 / texture->height());
|
||||
sampler.setMatrix(sampleM);
|
||||
fGpu->setSamplerState(0, sampler);
|
||||
fGpu->setViewMatrix(GrMatrix::I());
|
||||
fGpu->setTexture(0, srcTexture);
|
||||
fGpu->setTexture(0, texture);
|
||||
fGpu->drawSimpleRect(rect, NULL, 1 << 0);
|
||||
}
|
||||
|
@ -836,12 +836,11 @@ static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
|
||||
SkMaskFilter* filter, const SkMatrix& matrix,
|
||||
const SkRegion& clip, SkBounder* bounder,
|
||||
GrPaint* grp) {
|
||||
SkMaskFilter::BlurInfo info;
|
||||
#if USE_GPU_BLUR
|
||||
SkMaskFilter::BlurType blurType = filter->asABlur(&info);
|
||||
#else
|
||||
SkMaskFilter::BlurType blurType = SkMaskFilter::kNone_BlurType;
|
||||
#if !USE_GPU_BLUR
|
||||
return false;
|
||||
#endif
|
||||
SkMaskFilter::BlurInfo info;
|
||||
SkMaskFilter::BlurType blurType = filter->asABlur(&info);
|
||||
if (SkMaskFilter::kNone_BlurType == blurType) {
|
||||
return false;
|
||||
}
|
||||
@ -871,10 +870,10 @@ static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
|
||||
SkIRect finalIRect;
|
||||
finalRect.roundOut(&finalIRect);
|
||||
if (clip.quickReject(finalIRect)) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (bounder && !bounder->doIRect(finalIRect)) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
GrPoint offset = GrPoint::Make(-srcRect.fLeft, -srcRect.fTop);
|
||||
srcRect.offset(-srcRect.fLeft, -srcRect.fTop);
|
||||
@ -890,6 +889,8 @@ static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
|
||||
|
||||
GrTextureEntry* srcEntry = context->findApproximateKeylessTexture(desc);
|
||||
GrTextureEntry* dstEntry = context->findApproximateKeylessTexture(desc);
|
||||
GrAutoUnlockTextureEntry srcLock(context, srcEntry),
|
||||
dstLock(context, dstEntry);
|
||||
if (NULL == srcEntry || NULL == dstEntry) {
|
||||
return false;
|
||||
}
|
||||
@ -940,6 +941,7 @@ static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
|
||||
paint.setTexture(0, srcTexture);
|
||||
context->drawRect(paint, srcRect);
|
||||
}
|
||||
GrAutoUnlockTextureEntry origLock(context, origEntry);
|
||||
for (int i = 1; i < scaleFactor; i *= 2) {
|
||||
context->setRenderTarget(dstTexture->asRenderTarget());
|
||||
SkRect dstRect(srcRect);
|
||||
@ -957,18 +959,14 @@ static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
|
||||
float* kernel = kernelStorage.get();
|
||||
buildKernel(sigma, kernel, kernelWidth);
|
||||
|
||||
float imageIncrementX[2] = {1.0f / srcTexture->width(), 0.0f};
|
||||
context->setRenderTarget(dstTexture->asRenderTarget());
|
||||
context->clear(NULL, 0);
|
||||
context->convolveRect(srcTexture, srcRect, imageIncrementX, kernel,
|
||||
kernelWidth);
|
||||
context->convolveInX(srcTexture, srcRect, kernel, kernelWidth);
|
||||
SkTSwap(srcTexture, dstTexture);
|
||||
|
||||
float imageIncrementY[2] = {0.0f, 1.0f / srcTexture->height()};
|
||||
context->setRenderTarget(dstTexture->asRenderTarget());
|
||||
context->clear(NULL, 0);
|
||||
context->convolveRect(srcTexture, srcRect, imageIncrementY, kernel,
|
||||
kernelWidth);
|
||||
context->convolveInY(srcTexture, srcRect, kernel, kernelWidth);
|
||||
SkTSwap(srcTexture, dstTexture);
|
||||
|
||||
if (scaleFactor > 1) {
|
||||
@ -1036,13 +1034,6 @@ static bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
|
||||
m.postIDiv(srcTexture->width(), srcTexture->height());
|
||||
grp->getMaskSampler(MASK_IDX)->setMatrix(m);
|
||||
context->drawRect(*grp, finalRect);
|
||||
// FIXME: these unlockTexture() calls could be more safely done with
|
||||
// an RAII guard class.
|
||||
context->unlockTexture(srcEntry);
|
||||
context->unlockTexture(dstEntry);
|
||||
if (origEntry) {
|
||||
context->unlockTexture(origEntry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user