aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/effects/GrBezierEffect.cpp
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-22 17:31:06 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-22 17:31:06 +0000
commit89ff637a847b613e04f7ca7ca387203f375115c5 (patch)
tree7d3c0dceb66b26aafcea85d4f3344e3718338437 /src/gpu/effects/GrBezierEffect.cpp
parentcf7be95b19f283e3c5410f977474f433a1e10dad (diff)
Pull out Effect Shaders in GPU Path Renderer
Move the effects in HairLinePathRender (and eventually others into their own class called GrBezierEffects. This will allow for more sharing of code between different path renderers on GPU. BUG= R=bsalomon@google.com, jvanverth@google.com, robertphillips@google.com Author: egdaniel@google.com Review URL: https://chromiumcodereview.appspot.com/23004010 git-svn-id: http://skia.googlecode.com/svn/trunk@10877 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/effects/GrBezierEffect.cpp')
-rw-r--r--src/gpu/effects/GrBezierEffect.cpp390
1 files changed, 390 insertions, 0 deletions
diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp
new file mode 100644
index 0000000000..f4cebd4063
--- /dev/null
+++ b/src/gpu/effects/GrBezierEffect.cpp
@@ -0,0 +1,390 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrBezierEffect.h"
+
+#include "gl/GrGLEffect.h"
+#include "gl/GrGLSL.h"
+#include "GrTBackendEffectFactory.h"
+
+class GrGLConicEffect : public GrGLEffect {
+public:
+ GrGLConicEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
+
+private:
+ GrBezierEdgeType fEdgeType;
+
+ typedef GrGLEffect INHERITED;
+};
+
+GrGLConicEffect::GrGLConicEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>();
+ fEdgeType = ce.getEdgeType();
+}
+
+void GrGLConicEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TextureSamplerArray& samplers) {
+ const char *vsName, *fsName;
+
+ const bool antiAlias = GrBezierEdgeTypeIsAA(fEdgeType);
+ const bool fill = GrBezierEdgeTypeIsFill(fEdgeType);
+
+ if (antiAlias) {
+ SkAssertResult(builder->enableFeature(
+ GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
+ }
+ builder->addVarying(kVec4f_GrSLType, "ConicCoeffs",
+ &vsName, &fsName);
+ const SkString* attr0Name =
+ builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+ builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
+
+ builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
+
+ if (antiAlias) {
+ builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
+ builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
+ builder->fsCodeAppendf("\t\tfloat dfdx =\n"
+ "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
+ fsName, fsName, fsName);
+ builder->fsCodeAppendf("\t\tfloat dfdy =\n"
+ "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
+ fsName, fsName, fsName);
+ builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
+ builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
+ }
+ builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName,
+ fsName, fsName);
+ if (!fill) {
+ builder->fsCodeAppend("\t\tfunc = abs(func);\n");
+ }
+ if (antiAlias) {
+ builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
+ }
+ if (fill) {
+ if (antiAlias) {
+ builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
+ // Add line below for smooth cubic ramp
+ // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+ } else {
+ builder->fsCodeAppend("\t\tedgeAlpha = float(func < 0.0);\n");
+ }
+ } else {
+ builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+ // Add line below for smooth cubic ramp
+ // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+ }
+
+ SkString modulate;
+ GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
+}
+
+GrGLEffect::EffectKey GrGLConicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+ const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>();
+ return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrConicEffect::~GrConicEffect() {}
+
+const GrBackendEffectFactory& GrConicEffect::getFactory() const {
+ return GrTBackendEffectFactory<GrConicEffect>::getInstance();
+}
+
+GrConicEffect::GrConicEffect(GrBezierEdgeType edgeType) : GrEffect() {
+ this->addVertexAttrib(kVec4f_GrSLType);
+ fEdgeType = edgeType;
+}
+
+bool GrConicEffect::onIsEqual(const GrEffect& other) const {
+ const GrConicEffect& ce = CastEffect<GrConicEffect>(other);
+ return (ce.fEdgeType == fEdgeType);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(GrConicEffect);
+
+GrEffectRef* GrConicEffect::TestCreate(SkMWCRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
+ return GrConicEffect::Create(edgeType, caps);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Quad
+//////////////////////////////////////////////////////////////////////////////
+
+class GrGLQuadEffect : public GrGLEffect {
+public:
+ GrGLQuadEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
+
+private:
+ GrBezierEdgeType fEdgeType;
+
+ typedef GrGLEffect INHERITED;
+};
+
+GrGLQuadEffect::GrGLQuadEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>();
+ fEdgeType = ce.getEdgeType();
+}
+
+void GrGLQuadEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TextureSamplerArray& samplers) {
+ const char *vsName, *fsName;
+
+ bool antiAlias = GrBezierEdgeTypeIsAA(fEdgeType);
+ bool fill = GrBezierEdgeTypeIsFill(fEdgeType);
+
+ const SkString* attrName =
+ builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+ builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
+
+ if (antiAlias) {
+ SkAssertResult(builder->enableFeature(
+ GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
+ }
+ builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
+
+ if (antiAlias) {
+ builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
+ builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
+ builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
+ "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n",
+ fsName, fsName);
+ }
+ builder->fsCodeAppendf("\t\tfloat func = (%s.x*%s.x - %s.y);\n", fsName, fsName,
+ fsName);
+ if (!fill) {
+ builder->fsCodeAppend("\t\tfunc = abs(func);\n");
+ }
+ if (antiAlias) {
+ builder->fsCodeAppend("\t\tedgeAlpha = func / sqrt(dot(gF, gF));\n");
+ }
+ if (fill) {
+ if (antiAlias) {
+ builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
+ // Add line below for smooth cubic ramp
+ // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+ } else {
+ builder->fsCodeAppend("\t\tedgeAlpha = float(func < 0.0);\n");
+ }
+ } else {
+ builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+ // Add line below for smooth cubic ramp
+ // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+ }
+
+ SkString modulate;
+ GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
+
+ builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
+}
+
+GrGLEffect::EffectKey GrGLQuadEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+ const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>();
+ return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrQuadEffect::~GrQuadEffect() {}
+
+const GrBackendEffectFactory& GrQuadEffect::getFactory() const {
+ return GrTBackendEffectFactory<GrQuadEffect>::getInstance();
+}
+
+GrQuadEffect::GrQuadEffect(GrBezierEdgeType edgeType) : GrEffect() {
+ this->addVertexAttrib(kVec4f_GrSLType);
+ fEdgeType = edgeType;
+}
+
+bool GrQuadEffect::onIsEqual(const GrEffect& other) const {
+ const GrQuadEffect& ce = CastEffect<GrQuadEffect>(other);
+ return (ce.fEdgeType == fEdgeType);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(GrQuadEffect);
+
+GrEffectRef* GrQuadEffect::TestCreate(SkMWCRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
+ return GrQuadEffect::Create(edgeType, caps);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Cubic
+//////////////////////////////////////////////////////////////////////////////
+
+class GrGLCubicEffect : public GrGLEffect {
+public:
+ GrGLCubicEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
+
+private:
+ GrBezierEdgeType fEdgeType;
+
+ typedef GrGLEffect INHERITED;
+};
+
+GrGLCubicEffect::GrGLCubicEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>();
+ fEdgeType = ce.getEdgeType();
+}
+
+void GrGLCubicEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TextureSamplerArray& samplers) {
+ const char *vsName, *fsName;
+
+ bool antiAlias = GrBezierEdgeTypeIsAA(fEdgeType);
+ bool fill = GrBezierEdgeTypeIsFill(fEdgeType);
+
+ if (antiAlias) {
+ SkAssertResult(builder->enableFeature(
+ GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
+ }
+ builder->addVarying(kVec4f_GrSLType, "CubicCoeffs",
+ &vsName, &fsName);
+ const SkString* attr0Name =
+ builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+ builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
+
+ builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
+
+ if (antiAlias) {
+ builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
+ builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
+ builder->fsCodeAppendf("\t\tfloat dfdx =\n"
+ "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
+ fsName, fsName, fsName, fsName);
+ builder->fsCodeAppendf("\t\tfloat dfdy =\n"
+ "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
+ fsName, fsName, fsName, fsName);
+ builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
+ builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
+ }
+ builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
+ fsName, fsName, fsName, fsName, fsName);
+ if (!fill) {
+ builder->fsCodeAppend("\t\tfunc = abs(func);\n");
+ }
+ if (antiAlias) {
+ builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
+ }
+ if (fill) {
+ if (antiAlias) {
+ builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
+ // Add line below for smooth cubic ramp
+ // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+ } else {
+ builder->fsCodeAppend("\t\tedgeAlpha = float(func < 0.0);\n");
+ }
+ } else {
+ builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+ // Add line below for smooth cubic ramp
+ // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+ }
+
+ SkString modulate;
+ GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
+}
+
+GrGLEffect::EffectKey GrGLCubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+ const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>();
+ return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrCubicEffect::~GrCubicEffect() {}
+
+const GrBackendEffectFactory& GrCubicEffect::getFactory() const {
+ return GrTBackendEffectFactory<GrCubicEffect>::getInstance();
+}
+
+GrCubicEffect::GrCubicEffect(GrBezierEdgeType edgeType) : GrEffect() {
+ this->addVertexAttrib(kVec4f_GrSLType);
+ fEdgeType = edgeType;
+}
+
+bool GrCubicEffect::onIsEqual(const GrEffect& other) const {
+ const GrCubicEffect& ce = CastEffect<GrCubicEffect>(other);
+ return (ce.fEdgeType == fEdgeType);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(GrCubicEffect);
+
+GrEffectRef* GrCubicEffect::TestCreate(SkMWCRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
+ return GrCubicEffect::Create(edgeType, caps);
+}