Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Unified Diff: src/effects/SkBlurMaskFilter.cpp

Issue 1311583005: Add special case circle blur for Ganesh (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix no-GPU build Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/effects/SkBlurMask.cpp ('k') | src/gpu/GrBlurUtils.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/effects/SkBlurMaskFilter.cpp
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index 2ef86b016291eb0ef721a7471ad40045dc532d05..58242b701715eb472b74cac641eb120e83abd818 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -18,6 +18,7 @@
#include "SkStrokeRec.h"
#if SK_SUPPORT_GPU
+#include "GrCircleBlurFragmentProcessor.h"
#include "GrContext.h"
#include "GrDrawContext.h"
#include "GrTexture.h"
@@ -44,7 +45,7 @@ public:
SkIPoint* margin) const override;
#if SK_SUPPORT_GPU
- bool canFilterMaskGPU(const SkRect& devBounds,
+ bool canFilterMaskGPU(const SkRRect& devRRect,
const SkIRect& clipBounds,
const SkMatrix& ctm,
SkRect* maskRect) const override;
@@ -166,27 +167,25 @@ bool SkBlurMaskFilterImpl::asABlur(BlurRec* rec) const {
bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
const SkMatrix& matrix,
- SkIPoint* margin) const{
+ SkIPoint* margin) const {
SkScalar sigma = this->computeXformedSigma(matrix);
return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, this->getQuality(), margin);
}
bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r,
const SkMatrix& matrix,
- SkIPoint* margin, SkMask::CreateMode createMode) const{
+ SkIPoint* margin, SkMask::CreateMode createMode) const {
SkScalar sigma = computeXformedSigma(matrix);
- return SkBlurMask::BlurRect(sigma, dst, r, fBlurStyle,
- margin, createMode);
+ return SkBlurMask::BlurRect(sigma, dst, r, fBlurStyle, margin, createMode);
}
bool SkBlurMaskFilterImpl::filterRRectMask(SkMask* dst, const SkRRect& r,
const SkMatrix& matrix,
- SkIPoint* margin, SkMask::CreateMode createMode) const{
+ SkIPoint* margin, SkMask::CreateMode createMode) const {
SkScalar sigma = computeXformedSigma(matrix);
- return SkBlurMask::BlurRRect(sigma, dst, r, fBlurStyle,
- margin, createMode);
+ return SkBlurMask::BlurRRect(sigma, dst, r, fBlurStyle, margin, createMode);
}
#include "SkCanvas.h"
@@ -607,51 +606,42 @@ class GrGLRectBlurEffect;
class GrRectBlurEffect : public GrFragmentProcessor {
public:
- virtual ~GrRectBlurEffect();
+ ~GrRectBlurEffect() override { }
const char* name() const override { return "RectBlur"; }
- /**
- * Create a simple filter effect with custom bicubic coefficients.
- */
- static GrFragmentProcessor* Create(GrTextureProvider *textureProvider, const SkRect& rect,
- float sigma) {
- GrTexture *blurProfileTexture = nullptr;
+ static GrFragmentProcessor* Create(GrTextureProvider *textureProvider,
+ const SkRect& rect, float sigma) {
int doubleProfileSize = SkScalarCeilToInt(12*sigma);
if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.height()) {
// if the blur sigma is too large so the gaussian overlaps the whole
// rect in either direction, fall back to CPU path for now.
-
return nullptr;
}
- bool createdBlurProfileTexture = CreateBlurProfileTexture(
- textureProvider, sigma, &blurProfileTexture);
- SkAutoTUnref<GrTexture> hunref(blurProfileTexture);
- if (!createdBlurProfileTexture) {
+ SkAutoTUnref<GrTexture> blurProfile(CreateBlurProfileTexture(textureProvider, sigma));
+ if (!blurProfile) {
return nullptr;
}
- return new GrRectBlurEffect(rect, sigma, blurProfileTexture);
+ return new GrRectBlurEffect(rect, sigma, blurProfile);
}
const SkRect& getRect() const { return fRect; }
float getSigma() const { return fSigma; }
private:
- GrGLFragmentProcessor* onCreateGLInstance() const override;
+ GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile);
- GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blur_profile);
+ GrGLFragmentProcessor* onCreateGLInstance() const override;
- virtual void onGetGLProcessorKey(const GrGLSLCaps& caps,
- GrProcessorKeyBuilder* b) const override;
+ void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
- static bool CreateBlurProfileTexture(GrTextureProvider*, float sigma,
- GrTexture **blurProfileTexture);
+ static GrTexture* CreateBlurProfileTexture(GrTextureProvider*, float sigma);
SkRect fRect;
float fSigma;
@@ -665,7 +655,7 @@ private:
class GrGLRectBlurEffect : public GrGLFragmentProcessor {
public:
GrGLRectBlurEffect(const GrProcessor&) {}
- virtual void emitCode(EmitArgs&) override;
+ void emitCode(EmitArgs&) override;
protected:
void onSetData(const GrGLProgramDataManager&, const GrProcessor&) override;
@@ -738,7 +728,7 @@ void GrGLRectBlurEffect::emitCode(EmitArgs& args) {
}
void GrGLRectBlurEffect::onSetData(const GrGLProgramDataManager& pdman,
- const GrProcessor& proc) {
+ const GrProcessor& proc) {
const GrRectBlurEffect& rbe = proc.cast<GrRectBlurEffect>();
SkRect rect = rbe.getRect();
@@ -746,8 +736,8 @@ void GrGLRectBlurEffect::onSetData(const GrGLProgramDataManager& pdman,
pdman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma()));
}
-bool GrRectBlurEffect::CreateBlurProfileTexture(GrTextureProvider* textureProvider, float sigma,
- GrTexture **blurProfileTexture) {
+GrTexture* GrRectBlurEffect::CreateBlurProfileTexture(GrTextureProvider* textureProvider,
+ float sigma) {
GrSurfaceDesc texDesc;
unsigned int profileSize = SkScalarCeilToInt(6*sigma);
@@ -762,40 +752,29 @@ bool GrRectBlurEffect::CreateBlurProfileTexture(GrTextureProvider* textureProvid
builder[0] = profileSize;
builder.finish();
- uint8_t *profile = nullptr;
- SkAutoTDeleteArray<uint8_t> ada(nullptr);
-
- *blurProfileTexture = textureProvider->findAndRefTextureByUniqueKey(key);
+ GrTexture *blurProfile = textureProvider->findAndRefTextureByUniqueKey(key);
- if (nullptr == *blurProfileTexture) {
+ if (!blurProfile) {
+ SkAutoTDeleteArray<uint8_t> profile(SkBlurMask::ComputeBlurProfile(sigma));
- SkBlurMask::ComputeBlurProfile(sigma, &profile);
- ada.reset(profile);
-
- *blurProfileTexture = textureProvider->createTexture(texDesc, true, profile, 0);
-
- if (nullptr == *blurProfileTexture) {
- return false;
+ blurProfile = textureProvider->createTexture(texDesc, true, profile.get(), 0);
+ if (blurProfile) {
+ textureProvider->assignUniqueKeyToTexture(key, blurProfile);
}
- textureProvider->assignUniqueKeyToTexture(key, *blurProfileTexture);
}
- return true;
+ return blurProfile;
}
-GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma,
- GrTexture *blur_profile)
- : fRect(rect),
- fSigma(sigma),
- fBlurProfileAccess(blur_profile) {
+GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile)
+ : fRect(rect)
+ , fSigma(sigma)
+ , fBlurProfileAccess(blurProfile) {
this->initClassID<GrRectBlurEffect>();
this->addTextureAccess(&fBlurProfileAccess);
this->setWillReadFragmentPosition();
}
-GrRectBlurEffect::~GrRectBlurEffect() {
-}
-
void GrRectBlurEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
GrProcessorKeyBuilder* b) const {
GrGLRectBlurEffect::GenKey(*this, caps, b);
@@ -839,22 +818,31 @@ bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrTextureProvider* texProvider,
return false;
}
- SkRect rect;
- if (!path.isRect(&rect)) {
- return false;
- }
-
+ // TODO: we could handle blurred stroked circles
if (!strokeRec.isFillStyle()) {
return false;
}
SkScalar xformedSigma = this->computeXformedSigma(viewMatrix);
- int pad = SkScalarCeilToInt(6*xformedSigma)/2;
- rect.outset(SkIntToScalar(pad), SkIntToScalar(pad));
+ SkAutoTUnref<const GrFragmentProcessor> fp;
+
+ SkRect rect;
+ if (path.isRect(&rect)) {
+ int pad = SkScalarCeilToInt(6*xformedSigma)/2;
+ rect.outset(SkIntToScalar(pad), SkIntToScalar(pad));
+
+ fp.reset(GrRectBlurEffect::Create(texProvider, rect, xformedSigma));
+ } else if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height())) {
+ fp.reset(GrCircleBlurFragmentProcessor::Create(texProvider, rect, xformedSigma));
+
+ // expand the rect for the coverage geometry
+ int pad = SkScalarCeilToInt(6*xformedSigma)/2;
+ rect.outset(SkIntToScalar(pad), SkIntToScalar(pad));
+ } else {
+ return false;
+ }
- SkAutoTUnref<GrFragmentProcessor> fp(GrRectBlurEffect::Create(
- texProvider, rect, xformedSigma));
if (!fp) {
return false;
}
@@ -870,10 +858,12 @@ bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrTextureProvider* texProvider,
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+
class GrRRectBlurEffect : public GrFragmentProcessor {
public:
- static GrFragmentProcessor* Create(GrTextureProvider*, float sigma, const SkRRect&);
+ static const GrFragmentProcessor* Create(GrTextureProvider*, float sigma, const SkRRect&);
virtual ~GrRRectBlurEffect() {};
const char* name() const override { return "GrRRectBlur"; }
@@ -903,8 +893,12 @@ private:
};
-GrFragmentProcessor* GrRRectBlurEffect::Create(GrTextureProvider* texProvider, float sigma,
- const SkRRect& rrect) {
+const GrFragmentProcessor* GrRRectBlurEffect::Create(GrTextureProvider* texProvider, float sigma,
+ const SkRRect& rrect) {
+ if (rrect.isCircle()) {
+ return GrCircleBlurFragmentProcessor::Create(texProvider, rrect.rect(), sigma);
+ }
+
if (!rrect.isSimpleCircular()) {
return nullptr;
}
@@ -1129,8 +1123,8 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrTextureProvider* texProvid
SkRect proxyRect = rrect.rect();
proxyRect.outset(extra, extra);
- SkAutoTUnref<GrFragmentProcessor> fp(GrRRectBlurEffect::Create(texProvider,
- xformedSigma, rrect));
+ SkAutoTUnref<const GrFragmentProcessor> fp(GrRRectBlurEffect::Create(texProvider,
+ xformedSigma, rrect));
if (!fp) {
return false;
}
@@ -1146,7 +1140,7 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrTextureProvider* texProvid
return true;
}
-bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
+bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect,
const SkIRect& clipBounds,
const SkMatrix& ctm,
SkRect* maskRect) const {
@@ -1155,14 +1149,17 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
return false;
}
- static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64);
- static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32);
+ // We always do circles on the GPU
+ if (!devRRect.isCircle()) {
+ static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64);
+ static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32);
- if (srcBounds.width() <= kMIN_GPU_BLUR_SIZE &&
- srcBounds.height() <= kMIN_GPU_BLUR_SIZE &&
- xformedSigma <= kMIN_GPU_BLUR_SIGMA) {
- // We prefer to blur small rect with small radius via CPU.
- return false;
+ if (devRRect.width() <= kMIN_GPU_BLUR_SIZE &&
+ devRRect.height() <= kMIN_GPU_BLUR_SIZE &&
+ xformedSigma <= kMIN_GPU_BLUR_SIGMA) {
+ // We prefer to blur small rects with small radii on the CPU.
+ return false;
+ }
}
if (nullptr == maskRect) {
@@ -1173,7 +1170,7 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
float sigma3 = 3 * SkScalarToFloat(xformedSigma);
SkRect clipRect = SkRect::Make(clipBounds);
- SkRect srcRect(srcBounds);
+ SkRect srcRect(devRRect.rect());
// Outset srcRect and clipRect by 3 * sigma, to compute affected blur area.
srcRect.outset(sigma3, sigma3);
« no previous file with comments | « src/effects/SkBlurMask.cpp ('k') | src/gpu/GrBlurUtils.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698