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

Unified Diff: src/gpu/effects/GrOvalEffect.cpp

Issue 1517573002: Do elliptical clips in normalized space on devices with a "real" mediump (Closed) Base URL: https://skia.googlesource.com/skia.git@circlecorner
Patch Set: fix Created 5 years 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 | src/gpu/effects/GrRRectEffect.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/effects/GrOvalEffect.cpp
diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp
index 4532ddfd3c4f1a1da3213a283f208cd1b3aaa362..c7e685f9022a9077eaf0e8278e7322017b243eaf 100644
--- a/src/gpu/effects/GrOvalEffect.cpp
+++ b/src/gpu/effects/GrOvalEffect.cpp
@@ -133,19 +133,19 @@ void GLCircleEffect::emitCode(EmitArgs& args) {
// mediump. It'd be nice to only to this on mediump devices but we currently don't have the
// caps here.
if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
- fragBuilder->codeAppendf("\t\tfloat d = (length((%s.xy - %s.xy) * %s.w) - 1.0) * %s.z;\n",
+ fragBuilder->codeAppendf("float d = (length((%s.xy - %s.xy) * %s.w) - 1.0) * %s.z;",
circleName, fragmentPos, circleName, circleName);
} else {
- fragBuilder->codeAppendf("\t\tfloat d = (1.0 - length((%s.xy - %s.xy) * %s.w)) * %s.z;\n",
+ fragBuilder->codeAppendf("float d = (1.0 - length((%s.xy - %s.xy) * %s.w)) * %s.z;",
circleName, fragmentPos, circleName, circleName);
}
if (GrProcessorEdgeTypeIsAA(ce.getEdgeType())) {
- fragBuilder->codeAppend("\t\td = clamp(d, 0.0, 1.0);\n");
+ fragBuilder->codeAppend("d = clamp(d, 0.0, 1.0);");
} else {
- fragBuilder->codeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n");
+ fragBuilder->codeAppend("d = d > 0.5 ? 1.0 : 0.0;");
}
- fragBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
+ fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
(GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("d")).c_str());
}
@@ -276,6 +276,7 @@ protected:
private:
GrGLSLProgramDataManager::UniformHandle fEllipseUniform;
+ GrGLSLProgramDataManager::UniformHandle fScaleUniform;
SkPoint fPrevCenter;
SkVector fPrevRadii;
@@ -295,39 +296,55 @@ void GLEllipseEffect::emitCode(EmitArgs& args) {
kVec4f_GrSLType, kHigh_GrSLPrecision,
"ellipse",
&ellipseName);
+ // If we're on a device with a "real" mediump then we'll do the distance computation in a space
+ // that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The
+ // inverse squared radii uniform values are already in this normalized space. The center is
+ // not.
+ const char* scaleName = nullptr;
+ if (args.fGLSLCaps->floatPrecisionVaries()) {
+ fScaleUniform = args.fUniformHandler->addUniform(
+ GrGLSLUniformHandler::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision,
+ "scale", &scaleName);
+ }
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
const char* fragmentPos = fragBuilder->fragmentPosition();
// d is the offset to the ellipse center
- fragBuilder->codeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName);
- fragBuilder->codeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName);
+ fragBuilder->codeAppendf("vec2 d = %s.xy - %s.xy;", fragmentPos, ellipseName);
+ if (scaleName) {
+ fragBuilder->codeAppendf("d *= %s.y;", scaleName);
+ }
+ fragBuilder->codeAppendf("vec2 Z = d * %s.zw;", ellipseName);
// implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
- fragBuilder->codeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n");
+ fragBuilder->codeAppend("float implicit = dot(Z, d) - 1.0;");
// grad_dot is the squared length of the gradient of the implicit.
- fragBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
- // avoid calling inversesqrt on zero.
- fragBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
- fragBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
+ fragBuilder->codeAppendf("float grad_dot = 4.0 * dot(Z, Z);");
+ // Avoid calling inversesqrt on zero.
+ fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
+ fragBuilder->codeAppendf("float approx_dist = implicit * inversesqrt(grad_dot);");
+ if (scaleName) {
+ fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
+ }
switch (ee.getEdgeType()) {
case kFillAA_GrProcessorEdgeType:
- fragBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
+ fragBuilder->codeAppend("float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);");
break;
case kInverseFillAA_GrProcessorEdgeType:
- fragBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
+ fragBuilder->codeAppend("float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
break;
case kFillBW_GrProcessorEdgeType:
- fragBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n");
+ fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 0.0 : 1.0;");
break;
case kInverseFillBW_GrProcessorEdgeType:
- fragBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n");
+ fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 1.0 : 0.0;");
break;
case kHairlineAA_GrProcessorEdgeType:
SkFAIL("Hairline not expected here.");
}
- fragBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
+ fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
(GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
}
@@ -341,8 +358,26 @@ void GLEllipseEffect::onSetData(const GrGLSLProgramDataManager& pdman,
const GrProcessor& effect) {
const EllipseEffect& ee = effect.cast<EllipseEffect>();
if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
- SkScalar invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
- SkScalar invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
+ float invRXSqd;
+ float invRYSqd;
+ // If we're using a scale factor to work around precision issues, choose the larger radius
+ // as the scale factor. The inv radii need to be pre-adjusted by the scale factor.
+ if (fScaleUniform.isValid()) {
+ if (ee.getRadii().fX > ee.getRadii().fY) {
+ invRXSqd = 1.f;
+ invRYSqd = (ee.getRadii().fX * ee.getRadii().fX) /
+ (ee.getRadii().fY * ee.getRadii().fY);
+ pdman.set2f(fScaleUniform, ee.getRadii().fX, 1.f / ee.getRadii().fX);
+ } else {
+ invRXSqd = (ee.getRadii().fY * ee.getRadii().fY) /
+ (ee.getRadii().fX * ee.getRadii().fX);
+ invRYSqd = 1.f;
+ pdman.set2f(fScaleUniform, ee.getRadii().fY, 1.f / ee.getRadii().fY);
+ }
+ } else {
+ invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
+ invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
+ }
pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
fPrevCenter = ee.getCenter();
fPrevRadii = ee.getRadii();
« no previous file with comments | « no previous file | src/gpu/effects/GrRRectEffect.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698