Index: src/effects/gradients/SkTwoPointConicalGradient.cpp |
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp |
index 0a5e29b856a3e6c9355cf127c27297fc89e08317..28b9609e9cd7483250cc326b9bf35fabb9b6844f 100644 |
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp |
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp |
@@ -342,6 +342,14 @@ public: |
GrGLConical2Gradient(const GrBackendEffectFactory& factory, const GrDrawEffect&); |
virtual ~GrGLConical2Gradient() { } |
+ virtual void emitCode(GrGLFullShaderBuilder*, |
bsalomon
2013/10/03 14:44:52
Eek.. do we need both virtuals for emitting code o
Chris Dalton
2013/10/03 21:43:22
Done.
|
+ const GrDrawEffect&, |
+ EffectKey, |
+ const char* outputColor, |
+ const char* inputColor, |
+ const TransformedCoordsArray&, |
+ const TextureSamplerArray&) SK_OVERRIDE; |
+ |
virtual void emitCode(GrGLShaderBuilder*, |
const GrDrawEffect&, |
EffectKey, |
@@ -349,6 +357,16 @@ public: |
const char* inputColor, |
const TransformedCoordsArray&, |
const TextureSamplerArray&) SK_OVERRIDE; |
+ |
+ void emitUniforms(GrGLShaderBuilder* builder, EffectKey key); |
+ |
+ void emitFragmentCode(GrGLShaderBuilder*, |
+ EffectKey, |
+ const char* outputColor, |
+ const char* inputColor, |
+ const TransformedCoordsArray&, |
+ const TextureSamplerArray&); |
+ |
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; |
static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps); |
@@ -484,7 +502,7 @@ GrGLConical2Gradient::GrGLConical2Gradient(const GrBackendEffectFactory& factory |
fIsDegenerate = data.isDegenerate(); |
} |
-void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, |
+void GrGLConical2Gradient::emitCode(GrGLFullShaderBuilder* builder, |
const GrDrawEffect&, |
EffectKey key, |
const char* outputColor, |
@@ -492,25 +510,10 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, |
const TransformedCoordsArray& coords, |
const TextureSamplerArray& samplers) { |
this->emitUniforms(builder, key); |
- // 2 copies of uniform array, 1 for each of vertex & fragment shader, |
- // to work around Xoom bug. Doesn't seem to cause performance decrease |
- // in test apps, but need to keep an eye on it. |
- fVSParamUni = builder->addUniformArray(GrGLShaderBuilder::kVertex_Visibility, |
- kFloat_GrSLType, "Conical2VSParams", 6); |
- fFSParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, |
- kFloat_GrSLType, "Conical2FSParams", 6); |
- // For radial gradients without perspective we can pass the linear |
- // part of the quadratic as a varying. |
- GrGLShaderBuilder::VertexBuilder* vertexBuilder = |
- (kVec2f_GrSLType == coords[0].type()) ? builder->getVertexBuilder() : NULL; |
- if (NULL != vertexBuilder) { |
- vertexBuilder->addVarying(kFloat_GrSLType, "Conical2BCoeff", |
- &fVSVaryingName, &fFSVaryingName); |
- } |
- |
- // VS |
- { |
+ if (kVec2f_GrSLType == coords[0].type()) { |
+ // For conical gradients without perspective we can pass the linear |
+ // part of the quadratic as a varying. |
SkString p2; // distance between centers |
SkString p3; // start radius |
SkString p5; // difference in radii (r1 - r0) |
@@ -518,134 +521,160 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, |
builder->getUniformVariable(fVSParamUni).appendArrayAccess(3, &p3); |
builder->getUniformVariable(fVSParamUni).appendArrayAccess(5, &p5); |
- // For radial gradients without perspective we can pass the linear |
- // part of the quadratic as a varying. |
- if (NULL != vertexBuilder) { |
- // r2Var = -2 * (r2Parm[2] * varCoord.x - r2Param[3] * r2Param[5]) |
- vertexBuilder->vsCodeAppendf("\t%s = -2.0 * (%s * %s.x + %s * %s);\n", |
- fVSVaryingName, p2.c_str(), |
- coords[0].getVSName().c_str(), p3.c_str(), p5.c_str()); |
- } |
+ builder->addVarying(kFloat_GrSLType, "Conical2BCoeff", &fVSVaryingName, &fFSVaryingName); |
+ |
+ // r2Var = -2 * (r2Parm[2] * varCoord.x - r2Param[3] * r2Param[5]) |
+ builder->vsCodeAppendf("\t%s = -2.0 * (%s * %s.x + %s * %s);\n", |
+ fVSVaryingName, p2.c_str(), |
+ coords[0].getVSName().c_str(), p3.c_str(), p5.c_str()); |
} |
- // FS |
- { |
- SkString coords2D = builder->ensureFSCoords2D(coords, 0); |
- SkString cName("c"); |
- SkString ac4Name("ac4"); |
- SkString dName("d"); |
- SkString qName("q"); |
- SkString r0Name("r0"); |
- SkString r1Name("r1"); |
- SkString tName("t"); |
- SkString p0; // 4a |
- SkString p1; // 1/a |
- SkString p2; // distance between centers |
- SkString p3; // start radius |
- SkString p4; // start radius squared |
- SkString p5; // difference in radii (r1 - r0) |
+ this->emitFragmentCode(builder, key, outputColor, inputColor, coords, samplers); |
+} |
- builder->getUniformVariable(fFSParamUni).appendArrayAccess(0, &p0); |
- builder->getUniformVariable(fFSParamUni).appendArrayAccess(1, &p1); |
- builder->getUniformVariable(fFSParamUni).appendArrayAccess(2, &p2); |
- builder->getUniformVariable(fFSParamUni).appendArrayAccess(3, &p3); |
- builder->getUniformVariable(fFSParamUni).appendArrayAccess(4, &p4); |
- builder->getUniformVariable(fFSParamUni).appendArrayAccess(5, &p5); |
- |
- // If we we're able to interpolate the linear component, |
- // bVar is the varying; otherwise compute it |
- SkString bVar; |
- if (NULL != vertexBuilder) { |
- bVar = fFSVaryingName; |
- } else { |
- bVar = "b"; |
- builder->fsCodeAppendf("\tfloat %s = -2.0 * (%s * %s.x + %s * %s);\n", |
- bVar.c_str(), p2.c_str(), coords2D.c_str(), |
- p3.c_str(), p5.c_str()); |
- } |
+void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, |
+ const GrDrawEffect&, |
+ EffectKey key, |
+ const char* outputColor, |
+ const char* inputColor, |
+ const TransformedCoordsArray& coords, |
+ const TextureSamplerArray& samplers) { |
+ this->emitUniforms(builder, key); |
+ this->emitFragmentCode(builder, key, outputColor, inputColor, coords, samplers); |
+} |
- // output will default to transparent black (we simply won't write anything |
- // else to it if invalid, instead of discarding or returning prematurely) |
- builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); |
- |
- // c = (x^2)+(y^2) - params[4] |
- builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), |
- coords2D.c_str(), coords2D.c_str(), |
- p4.c_str()); |
- |
- // Non-degenerate case (quadratic) |
- if (!fIsDegenerate) { |
- |
- // ac4 = params[0] * c |
- builder->fsCodeAppendf("\tfloat %s = %s * %s;\n", ac4Name.c_str(), p0.c_str(), |
- cName.c_str()); |
- |
- // d = b^2 - ac4 |
- builder->fsCodeAppendf("\tfloat %s = %s * %s - %s;\n", dName.c_str(), |
- bVar.c_str(), bVar.c_str(), ac4Name.c_str()); |
- |
- // only proceed if discriminant is >= 0 |
- builder->fsCodeAppendf("\tif (%s >= 0.0) {\n", dName.c_str()); |
- |
- // intermediate value we'll use to compute the roots |
- // q = -0.5 * (b +/- sqrt(d)) |
- builder->fsCodeAppendf("\t\tfloat %s = -0.5 * (%s + (%s < 0.0 ? -1.0 : 1.0)" |
- " * sqrt(%s));\n", qName.c_str(), bVar.c_str(), |
- bVar.c_str(), dName.c_str()); |
- |
- // compute both roots |
- // r0 = q * params[1] |
- builder->fsCodeAppendf("\t\tfloat %s = %s * %s;\n", r0Name.c_str(), |
- qName.c_str(), p1.c_str()); |
- // r1 = c / q |
- builder->fsCodeAppendf("\t\tfloat %s = %s / %s;\n", r1Name.c_str(), |
- cName.c_str(), qName.c_str()); |
- |
- // Note: If there are two roots that both generate radius(t) > 0, the |
- // Canvas spec says to choose the larger t. |
- |
- // so we'll look at the larger one first: |
- builder->fsCodeAppendf("\t\tfloat %s = max(%s, %s);\n", tName.c_str(), |
- r0Name.c_str(), r1Name.c_str()); |
- |
- // if r(t) > 0, then we're done; t will be our x coordinate |
- builder->fsCodeAppendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), |
- p5.c_str(), p3.c_str()); |
- |
- builder->fsCodeAppend("\t\t"); |
- this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); |
- |
- // otherwise, if r(t) for the larger root was <= 0, try the other root |
- builder->fsCodeAppend("\t\t} else {\n"); |
- builder->fsCodeAppendf("\t\t\t%s = min(%s, %s);\n", tName.c_str(), |
- r0Name.c_str(), r1Name.c_str()); |
- |
- // if r(t) > 0 for the smaller root, then t will be our x coordinate |
- builder->fsCodeAppendf("\t\t\tif (%s * %s + %s > 0.0) {\n", |
- tName.c_str(), p5.c_str(), p3.c_str()); |
- |
- builder->fsCodeAppend("\t\t\t"); |
- this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); |
- |
- // end if (r(t) > 0) for smaller root |
- builder->fsCodeAppend("\t\t\t}\n"); |
- // end if (r(t) > 0), else, for larger root |
- builder->fsCodeAppend("\t\t}\n"); |
- // end if (discriminant >= 0) |
- builder->fsCodeAppend("\t}\n"); |
- } else { |
+void GrGLConical2Gradient::emitUniforms(GrGLShaderBuilder* builder, EffectKey key) { |
+ this->INHERITED::emitUniforms(builder, key); |
+ // 2 copies of uniform array, 1 for each of vertex & fragment shader, |
+ // to work around Xoom bug. Doesn't seem to cause performance decrease |
+ // in test apps, but need to keep an eye on it. |
+ fVSParamUni = builder->addUniformArray(GrGLShaderBuilder::kVertex_Visibility, |
+ kFloat_GrSLType, "Conical2VSParams", 6); |
+ fFSParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, |
+ kFloat_GrSLType, "Conical2FSParams", 6); |
+} |
- // linear case: t = -c/b |
- builder->fsCodeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(), |
- cName.c_str(), bVar.c_str()); |
+void GrGLConical2Gradient::emitFragmentCode(GrGLShaderBuilder* builder, |
+ EffectKey key, |
+ const char* outputColor, |
+ const char* inputColor, |
+ const TransformedCoordsArray& coords, |
+ const TextureSamplerArray& samplers) { |
+ SkString coords2D = builder->ensureFSCoords2D(coords, 0); |
+ SkString cName("c"); |
+ SkString ac4Name("ac4"); |
+ SkString dName("d"); |
+ SkString qName("q"); |
+ SkString r0Name("r0"); |
+ SkString r1Name("r1"); |
+ SkString tName("t"); |
+ SkString p0; // 4a |
+ SkString p1; // 1/a |
+ SkString p2; // distance between centers |
+ SkString p3; // start radius |
+ SkString p4; // start radius squared |
+ SkString p5; // difference in radii (r1 - r0) |
+ |
+ builder->getUniformVariable(fFSParamUni).appendArrayAccess(0, &p0); |
+ builder->getUniformVariable(fFSParamUni).appendArrayAccess(1, &p1); |
+ builder->getUniformVariable(fFSParamUni).appendArrayAccess(2, &p2); |
+ builder->getUniformVariable(fFSParamUni).appendArrayAccess(3, &p3); |
+ builder->getUniformVariable(fFSParamUni).appendArrayAccess(4, &p4); |
+ builder->getUniformVariable(fFSParamUni).appendArrayAccess(5, &p5); |
+ |
+ // If we we're able to interpolate the linear component, |
+ // bVar is the varying; otherwise compute it |
+ SkString bVar; |
+ if (NULL != fFSVaryingName) { |
+ bVar = fFSVaryingName; |
+ } else { |
+ bVar = "b"; |
+ builder->fsCodeAppendf("\tfloat %s = -2.0 * (%s * %s.x + %s * %s);\n", |
+ bVar.c_str(), p2.c_str(), coords2D.c_str(), |
+ p3.c_str(), p5.c_str()); |
+ } |
- // if r(t) > 0, then t will be the x coordinate |
- builder->fsCodeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), |
- p5.c_str(), p3.c_str()); |
- builder->fsCodeAppend("\t"); |
- this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); |
- builder->fsCodeAppend("\t}\n"); |
- } |
+ // output will default to transparent black (we simply won't write anything |
+ // else to it if invalid, instead of discarding or returning prematurely) |
+ builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); |
+ |
+ // c = (x^2)+(y^2) - params[4] |
+ builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), |
+ coords2D.c_str(), coords2D.c_str(), |
+ p4.c_str()); |
+ |
+ // Non-degenerate case (quadratic) |
+ if (!fIsDegenerate) { |
+ |
+ // ac4 = params[0] * c |
+ builder->fsCodeAppendf("\tfloat %s = %s * %s;\n", ac4Name.c_str(), p0.c_str(), |
+ cName.c_str()); |
+ |
+ // d = b^2 - ac4 |
+ builder->fsCodeAppendf("\tfloat %s = %s * %s - %s;\n", dName.c_str(), |
+ bVar.c_str(), bVar.c_str(), ac4Name.c_str()); |
+ |
+ // only proceed if discriminant is >= 0 |
+ builder->fsCodeAppendf("\tif (%s >= 0.0) {\n", dName.c_str()); |
+ |
+ // intermediate value we'll use to compute the roots |
+ // q = -0.5 * (b +/- sqrt(d)) |
+ builder->fsCodeAppendf("\t\tfloat %s = -0.5 * (%s + (%s < 0.0 ? -1.0 : 1.0)" |
+ " * sqrt(%s));\n", qName.c_str(), bVar.c_str(), |
+ bVar.c_str(), dName.c_str()); |
+ |
+ // compute both roots |
+ // r0 = q * params[1] |
+ builder->fsCodeAppendf("\t\tfloat %s = %s * %s;\n", r0Name.c_str(), |
+ qName.c_str(), p1.c_str()); |
+ // r1 = c / q |
+ builder->fsCodeAppendf("\t\tfloat %s = %s / %s;\n", r1Name.c_str(), |
+ cName.c_str(), qName.c_str()); |
+ |
+ // Note: If there are two roots that both generate radius(t) > 0, the |
+ // Canvas spec says to choose the larger t. |
+ |
+ // so we'll look at the larger one first: |
+ builder->fsCodeAppendf("\t\tfloat %s = max(%s, %s);\n", tName.c_str(), |
+ r0Name.c_str(), r1Name.c_str()); |
+ |
+ // if r(t) > 0, then we're done; t will be our x coordinate |
+ builder->fsCodeAppendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), |
+ p5.c_str(), p3.c_str()); |
+ |
+ builder->fsCodeAppend("\t\t"); |
+ this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); |
+ |
+ // otherwise, if r(t) for the larger root was <= 0, try the other root |
+ builder->fsCodeAppend("\t\t} else {\n"); |
+ builder->fsCodeAppendf("\t\t\t%s = min(%s, %s);\n", tName.c_str(), |
+ r0Name.c_str(), r1Name.c_str()); |
+ |
+ // if r(t) > 0 for the smaller root, then t will be our x coordinate |
+ builder->fsCodeAppendf("\t\t\tif (%s * %s + %s > 0.0) {\n", |
+ tName.c_str(), p5.c_str(), p3.c_str()); |
+ |
+ builder->fsCodeAppend("\t\t\t"); |
+ this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); |
+ |
+ // end if (r(t) > 0) for smaller root |
+ builder->fsCodeAppend("\t\t\t}\n"); |
+ // end if (r(t) > 0), else, for larger root |
+ builder->fsCodeAppend("\t\t}\n"); |
+ // end if (discriminant >= 0) |
+ builder->fsCodeAppend("\t}\n"); |
+ } else { |
+ |
+ // linear case: t = -c/b |
+ builder->fsCodeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(), |
+ cName.c_str(), bVar.c_str()); |
+ |
+ // if r(t) > 0, then t will be the x coordinate |
+ builder->fsCodeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), |
+ p5.c_str(), p3.c_str()); |
+ builder->fsCodeAppend("\t"); |
+ this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); |
+ builder->fsCodeAppend("\t}\n"); |
} |
} |