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

Unified Diff: src/effects/SkBlurMaskFilter.cpp

Issue 1395693011: Fix for GM:bigblurs not actually blurring some of the rectangles on Nexus 10. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 2 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 | « no previous file | no next file » | 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 ab631c6bc750b4db5b937b05a02b289e49537b2f..318476608fbfe25d8ad028f9b28428a54523b7f0 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -304,9 +304,9 @@ static SkCachedData* add_cached_rects(SkMask* mask, SkScalar sigma, SkBlurStyle
}
#ifdef SK_IGNORE_FAST_RRECT_BLUR
-SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects" );
+SK_CONF_DECLARE(bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects");
#else
-SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", true, "Use the faster analytic blur approach for ninepatch round rects" );
+SK_CONF_DECLARE(bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", true, "Use the faster analytic blur approach for ninepatch round rects");
#endif
SkMaskFilter::FilterReturn
@@ -444,7 +444,7 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
return kTrue_FilterReturn;
}
-SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects" );
+SK_CONF_DECLARE(bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects");
SkMaskFilter::FilterReturn
SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
@@ -622,14 +622,35 @@ public:
if (!blurProfile) {
return nullptr;
}
- return new GrRectBlurEffect(rect, sigma, blurProfile);
+ // in OpenGL ES, mediump floats have a minimum range of 2^14. If we have coordinates bigger
+ // than that, the shader math will end up with infinities and result in the blur effect not
+ // working correctly. To avoid this, we switch into highp when the coordinates are too big.
+ // As 2^14 is the minimum range but the actual range can be bigger, we might end up
+ // switching to highp sooner than strictly necessary, but most devices that have a bigger
+ // range for mediump also have mediump being exactly the same as highp (e.g. all non-OpenGL
+ // ES devices), and thus incur no additional penalty for the switch.
+ static const SkScalar kMAX_BLUR_COORD = SkIntToScalar(16000);
+ GrSLPrecision precision;
robertphillips 2015/10/19 15:17:54 Is this enough? Don't we also need to check for ne
+ if (rect.top() > kMAX_BLUR_COORD ||
+ rect.left() > kMAX_BLUR_COORD ||
+ rect.bottom() > kMAX_BLUR_COORD ||
+ rect.right() > kMAX_BLUR_COORD ||
+ rect.width() > kMAX_BLUR_COORD ||
+ rect.height() > kMAX_BLUR_COORD) {
+ precision = kHigh_GrSLPrecision;
+ }
+ else {
+ precision = kDefault_GrSLPrecision;
+ }
+ return new GrRectBlurEffect(rect, sigma, blurProfile, precision);
}
const SkRect& getRect() const { return fRect; }
float getSigma() const { return fSigma; }
private:
- GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile);
+ GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile,
+ GrSLPrecision fPrecision);
GrGLFragmentProcessor* onCreateGLInstance() const override;
@@ -644,6 +665,7 @@ private:
SkRect fRect;
float fSigma;
GrTextureAccess fBlurProfileAccess;
+ GrSLPrecision fPrecision;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
@@ -652,9 +674,13 @@ private:
class GrGLRectBlurEffect : public GrGLFragmentProcessor {
public:
- GrGLRectBlurEffect(const GrProcessor&) {}
+ GrGLRectBlurEffect(const GrProcessor&, GrSLPrecision precision)
+ : fPrecision(precision) {
+ }
void emitCode(EmitArgs&) override;
+ static void GenKey(GrSLPrecision precision, GrProcessorKeyBuilder* b);
+
protected:
void onSetData(const GrGLProgramDataManager&, const GrProcessor&) override;
@@ -663,6 +689,7 @@ private:
UniformHandle fProxyRectUniform;
UniformHandle fProfileSizeUniform;
+ GrSLPrecision fPrecision;
typedef GrGLFragmentProcessor INHERITED;
};
@@ -673,24 +700,31 @@ void OutputRectBlurProfileLookup(GrGLFragmentBuilder* fsBuilder,
const char *profileSize, const char *loc,
const char *blurred_width,
const char *sharp_width) {
- fsBuilder->codeAppendf("\tfloat %s;\n", output);
- fsBuilder->codeAppendf("\t\t{\n");
- fsBuilder->codeAppendf("\t\t\tfloat coord = (0.5 * (abs(2.0*%s - %s) - %s))/%s;\n",
+ fsBuilder->codeAppendf("float %s;", output);
+ fsBuilder->codeAppendf("{");
+ fsBuilder->codeAppendf("float coord = ((abs(%s - 0.5 * %s) - 0.5 * %s)) / %s;",
loc, blurred_width, sharp_width, profileSize);
- fsBuilder->codeAppendf("\t\t\t%s = ", output);
+ fsBuilder->codeAppendf("%s = ", output);
fsBuilder->appendTextureLookup(sampler, "vec2(coord,0.5)");
- fsBuilder->codeAppend(".a;\n");
- fsBuilder->codeAppendf("\t\t}\n");
+ fsBuilder->codeAppend(".a;");
+ fsBuilder->codeAppendf("}");
}
+
+void GrGLRectBlurEffect::GenKey(GrSLPrecision precision, GrProcessorKeyBuilder* b) {
+ b->add32(precision);
+}
+
+
void GrGLRectBlurEffect::emitCode(EmitArgs& args) {
const char *rectName;
const char *profileSizeName;
+ const char* precisionString = GrGLShaderVar::PrecisionString(fPrecision, kGLES_GrGLStandard);
fProxyRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType,
- kDefault_GrSLPrecision,
+ fPrecision,
"proxyRect",
&rectName);
fProfileSizeUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
@@ -703,26 +737,29 @@ void GrGLRectBlurEffect::emitCode(EmitArgs& args) {
const char *fragmentPos = fsBuilder->fragmentPosition();
if (args.fInputColor) {
- fsBuilder->codeAppendf("\tvec4 src=%s;\n", args.fInputColor);
+ fsBuilder->codeAppendf("vec4 src=%s;", args.fInputColor);
} else {
- fsBuilder->codeAppendf("\tvec4 src=vec4(1)\n;");
+ fsBuilder->codeAppendf("vec4 src=vec4(1);");
}
- fsBuilder->codeAppendf("\tvec2 translatedPos = %s.xy - %s.xy;\n", fragmentPos, rectName );
- fsBuilder->codeAppendf("\tfloat width = %s.z - %s.x;\n", rectName, rectName);
- fsBuilder->codeAppendf("\tfloat height = %s.w - %s.y;\n", rectName, rectName);
+ fsBuilder->codeAppendf("%s vec2 translatedPos = %s.xy - %s.xy;", precisionString, fragmentPos,
+ rectName);
+ fsBuilder->codeAppendf("%s float width = %s.z - %s.x;", precisionString, rectName, rectName);
+ fsBuilder->codeAppendf("%s float height = %s.w - %s.y;", precisionString, rectName, rectName);
- fsBuilder->codeAppendf("\tvec2 smallDims = vec2(width - %s, height-%s);\n", profileSizeName, profileSizeName);
- fsBuilder->codeAppendf("\tfloat center = 2.0 * floor(%s/2.0 + .25) - 1.0;\n", profileSizeName);
- fsBuilder->codeAppendf("\tvec2 wh = smallDims - vec2(center,center);\n");
+ fsBuilder->codeAppendf("%s vec2 smallDims = vec2(width - %s, height - %s);", precisionString,
+ profileSizeName, profileSizeName);
+ fsBuilder->codeAppendf("%s float center = 2.0 * floor(%s/2.0 + .25) - 1.0;", precisionString,
+ profileSizeName);
+ fsBuilder->codeAppendf("%s vec2 wh = smallDims - vec2(center,center);", precisionString);
OutputRectBlurProfileLookup(fsBuilder, args.fSamplers[0], "horiz_lookup", profileSizeName,
"translatedPos.x", "width", "wh.x");
- OutputRectBlurProfileLookup(fsBuilder, args.fSamplers[0], "vert_lookup", profileSizeName,
+ OutputRectBlurProfileLookup(fsBuilder, args.fSamplers[0], "vert_lookup", profileSizeName,
"translatedPos.y", "height", "wh.y");
- fsBuilder->codeAppendf("\tfloat final = horiz_lookup * vert_lookup;\n");
- fsBuilder->codeAppendf("\t%s = src * final;\n", args.fOutputColor );
+ fsBuilder->codeAppendf("float final = horiz_lookup * vert_lookup;");
+ fsBuilder->codeAppendf("%s = src * final;", args.fOutputColor);
}
void GrGLRectBlurEffect::onSetData(const GrGLProgramDataManager& pdman,
@@ -764,10 +801,12 @@ GrTexture* GrRectBlurEffect::CreateBlurProfileTexture(GrTextureProvider* texture
return blurProfile;
}
-GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile)
+GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile,
+ GrSLPrecision precision)
: fRect(rect)
, fSigma(sigma)
- , fBlurProfileAccess(blurProfile) {
+ , fBlurProfileAccess(blurProfile)
+ , fPrecision(precision) {
this->initClassID<GrRectBlurEffect>();
this->addTextureAccess(&fBlurProfileAccess);
this->setWillReadFragmentPosition();
@@ -775,11 +814,11 @@ GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *b
void GrRectBlurEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
GrProcessorKeyBuilder* b) const {
- GrGLRectBlurEffect::GenKey(*this, caps, b);
+ GrGLRectBlurEffect::GenKey(fPrecision, b);
}
GrGLFragmentProcessor* GrRectBlurEffect::onCreateGLInstance() const {
- return new GrGLRectBlurEffect(*this);
+ return new GrGLRectBlurEffect(*this, fPrecision);
}
bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
@@ -940,14 +979,14 @@ const GrFragmentProcessor* GrRRectBlurEffect::Create(GrTextureProvider* texProvi
smallRRect.setRectXY(smallRect, SkIntToScalar(cornerRadius), SkIntToScalar(cornerRadius));
SkPath path;
- path.addRRect( smallRRect );
+ path.addRRect(smallRRect);
SkDraw::DrawToMask(path, &mask.fBounds, nullptr, nullptr, &mask,
SkMask::kJustRenderImage_CreateMode, SkPaint::kFill_Style);
SkMask blurredMask;
SkBlurMask::BoxBlur(&blurredMask, mask, sigma, kNormal_SkBlurStyle, kHigh_SkBlurQuality,
- nullptr, true );
+ nullptr, true);
unsigned int texSide = smallRectSide + 2*blurRadius;
GrSurfaceDesc texDesc;
@@ -1045,29 +1084,29 @@ void GrGLRRectBlurEffect::emitCode(EmitArgs& args) {
// warp the fragment position to the appropriate part of the 9patch blur texture
- fsBuilder->codeAppendf("\t\tvec2 rectCenter = (%s.xy + %s.zw)/2.0;\n", rectName, rectName);
- fsBuilder->codeAppendf("\t\tvec2 translatedFragPos = %s.xy - %s.xy;\n", fragmentPos, rectName);
- fsBuilder->codeAppendf("\t\tfloat threshold = %s + 2.0*%s;\n", cornerRadiusName, blurRadiusName );
- fsBuilder->codeAppendf("\t\tvec2 middle = %s.zw - %s.xy - 2.0*threshold;\n", rectName, rectName );
+ fsBuilder->codeAppendf("vec2 rectCenter = (%s.xy + %s.zw)/2.0;", rectName, rectName);
+ fsBuilder->codeAppendf("vec2 translatedFragPos = %s.xy - %s.xy;", fragmentPos, rectName);
+ fsBuilder->codeAppendf("float threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName);
+ fsBuilder->codeAppendf("vec2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName);
- fsBuilder->codeAppendf("\t\tif (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {\n" );
- fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.x = threshold;\n");
- fsBuilder->codeAppendf("\t\t} else if (translatedFragPos.x >= (middle.x + threshold)) {\n");
- fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.x -= middle.x - 1.0;\n");
- fsBuilder->codeAppendf("\t\t}\n");
+ fsBuilder->codeAppendf("if (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {");
+ fsBuilder->codeAppendf("translatedFragPos.x = threshold;\n");
+ fsBuilder->codeAppendf("} else if (translatedFragPos.x >= (middle.x + threshold)) {");
+ fsBuilder->codeAppendf("translatedFragPos.x -= middle.x - 1.0;");
+ fsBuilder->codeAppendf("}");
- fsBuilder->codeAppendf("\t\tif (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {\n" );
- fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.y = threshold;\n");
- fsBuilder->codeAppendf("\t\t} else if (translatedFragPos.y >= (middle.y + threshold)) {\n");
- fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.y -= middle.y - 1.0;\n");
- fsBuilder->codeAppendf("\t\t}\n");
+ fsBuilder->codeAppendf("if (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {");
+ fsBuilder->codeAppendf("translatedFragPos.y = threshold;");
+ fsBuilder->codeAppendf("} else if (translatedFragPos.y >= (middle.y + threshold)) {");
+ fsBuilder->codeAppendf("translatedFragPos.y -= middle.y - 1.0;");
+ fsBuilder->codeAppendf("}");
- fsBuilder->codeAppendf("\t\tvec2 proxyDims = vec2(2.0*threshold+1.0);\n");
- fsBuilder->codeAppendf("\t\tvec2 texCoord = translatedFragPos / proxyDims;\n");
+ fsBuilder->codeAppendf("vec2 proxyDims = vec2(2.0*threshold+1.0);");
+ fsBuilder->codeAppendf("vec2 texCoord = translatedFragPos / proxyDims;");
- fsBuilder->codeAppendf("\t%s = ", args.fOutputColor);
+ fsBuilder->codeAppendf("%s = ", args.fOutputColor);
fsBuilder->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers[0], "texCoord");
- fsBuilder->codeAppend(";\n");
+ fsBuilder->codeAppend(";");
}
void GrGLRRectBlurEffect::onSetData(const GrGLProgramDataManager& pdman,
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698