| Index: src/gpu/effects/GrBezierEffect.cpp
|
| diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1603e8488f69fb72fbdc65bd61c16c7535c946b6
|
| --- /dev/null
|
| +++ b/src/gpu/effects/GrBezierEffect.cpp
|
| @@ -0,0 +1,383 @@
|
| +/*
|
| + * 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:
|
| + bool fAntiAlias;
|
| + bool fFill;
|
| +
|
| + typedef GrGLEffect INHERITED;
|
| +};
|
| +
|
| +GrGLConicEffect::GrGLConicEffect(const GrBackendEffectFactory& factory,
|
| + const GrDrawEffect& drawEffect)
|
| + : INHERITED (factory) {
|
| + const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>();
|
| + fAntiAlias = ce.isAntiAliased();
|
| + fFill = ce.isFilled();
|
| +}
|
| +
|
| +void GrGLConicEffect::emitCode(GrGLShaderBuilder* builder,
|
| + const GrDrawEffect& drawEffect,
|
| + EffectKey key,
|
| + const char* outputColor,
|
| + const char* inputColor,
|
| + const TextureSamplerArray& samplers) SK_OVERRIDE {
|
| + const char *vsName, *fsName;
|
| +
|
| + 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 (fAntiAlias) {
|
| + 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 (!fFill) {
|
| + builder->fsCodeAppend("\t\tfunc = abs(func);\n");
|
| + }
|
| + if (fAntiAlias) {
|
| + builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
|
| + }
|
| + if (fFill) {
|
| + if (fAntiAlias) {
|
| + 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 SK_OVERRIDE {
|
| + return GrTBackendEffectFactory<GrConicEffect>::getInstance();
|
| +}
|
| +
|
| +GrConicEffect::GrConicEffect(bool antiAlias, bool fill) : GrEffect() {
|
| + this->addVertexAttrib(kVec4f_GrSLType);
|
| + fAntiAlias = antiAlias;
|
| + fFill= fill;
|
| +}
|
| +
|
| +bool GrConicEffect::onIsEqual(const GrEffect& other) const SK_OVERRIDE {
|
| + const GrConicEffect& ce = CastEffect<GrConicEffect>(other);
|
| + return (ce.fAntiAlias == fAntiAlias && ce.fFill == fFill);
|
| +}
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +
|
| +GR_DEFINE_EFFECT_TEST(GrConicEffect);
|
| +
|
| +GrEffectRef* GrConicEffect::TestCreate(SkMWCRandom* random,
|
| + GrContext*,
|
| + const GrDrawTargetCaps& caps,
|
| + GrTexture*[]) {
|
| + const BezierEffectType effect = static_cast<BezierEffectType>(random->nextULessThan(3));
|
| + return caps.shaderDerivativeSupport() ? GrConicEffect::Create(effect) : NULL;
|
| +}
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +// 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:
|
| + bool fAntiAlias;
|
| + bool fFill;
|
| +
|
| + typedef GrGLEffect INHERITED;
|
| +};
|
| +
|
| +GrGLQuadEffect::GrGLQuadEffect(const GrBackendEffectFactory& factory,
|
| + const GrDrawEffect& drawEffect)
|
| + : INHERITED (factory) {
|
| + const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>();
|
| + fAntiAlias = ce.isAntiAliased();
|
| + fFill = ce.isFilled();
|
| +}
|
| +
|
| +void GrGLQuadEffect::emitCode(GrGLShaderBuilder* builder,
|
| + const GrDrawEffect& drawEffect,
|
| + EffectKey key,
|
| + const char* outputColor,
|
| + const char* inputColor,
|
| + const TextureSamplerArray& samplers) SK_OVERRIDE {
|
| + const char *vsName, *fsName;
|
| + const SkString* attrName =
|
| + builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
|
| + builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
|
| +
|
| + SkAssertResult(builder->enableFeature(
|
| + GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
|
| + builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
|
| +
|
| + if (fAntiAlias) {
|
| + 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 (!fFill) {
|
| + builder->fsCodeAppend("\t\tfunc = abs(func);\n");
|
| + }
|
| + if (fAntiAlias) {
|
| + builder->fsCodeAppend("\t\tedgeAlpha = func / sqrt(dot(gF, gF));\n");
|
| + }
|
| + if (fFill) {
|
| + if (fAntiAlias) {
|
| + 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 SK_OVERRIDE {
|
| + return GrTBackendEffectFactory<GrQuadEffect>::getInstance();
|
| +}
|
| +
|
| +GrQuadEffect::GrQuadEffect(bool antiAlias, bool fill) : GrEffect() {
|
| + this->addVertexAttrib(kVec4f_GrSLType);
|
| + fAntiAlias = antiAlias;
|
| + fFill= fill;
|
| +}
|
| +
|
| +bool GrQuadEffect::onIsEqual(const GrEffect& other) const SK_OVERRIDE {
|
| + const GrQuadEffect& ce = CastEffect<GrQuadEffect>(other);
|
| + return (ce.fAntiAlias == fAntiAlias && ce.fFill == fFill);
|
| +}
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +
|
| +GR_DEFINE_EFFECT_TEST(GrQuadEffect);
|
| +
|
| +GrEffectRef* GrQuadEffect::TestCreate(SkMWCRandom* random,
|
| + GrContext*,
|
| + const GrDrawTargetCaps& caps,
|
| + GrTexture*[]) {
|
| + const BezierEffectType effect = static_cast<BezierEffectType>(random->nextULessThan(3));
|
| + return caps.shaderDerivativeSupport() ? GrQuadEffect::Create(effect) : NULL;
|
| +}
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +// 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:
|
| + bool fAntiAlias;
|
| + bool fFill;
|
| +
|
| + typedef GrGLEffect INHERITED;
|
| +};
|
| +
|
| +GrGLCubicEffect::GrGLCubicEffect(const GrBackendEffectFactory& factory,
|
| + const GrDrawEffect& drawEffect)
|
| + : INHERITED (factory) {
|
| + const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>();
|
| + fAntiAlias = ce.isAntiAliased();
|
| + fFill = ce.isFilled();
|
| +}
|
| +
|
| +void GrGLCubicEffect::emitCode(GrGLShaderBuilder* builder,
|
| + const GrDrawEffect& drawEffect,
|
| + EffectKey key,
|
| + const char* outputColor,
|
| + const char* inputColor,
|
| + const TextureSamplerArray& samplers) SK_OVERRIDE {
|
| + const char *vsName, *fsName;
|
| +
|
| + 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 (fAntiAlias) {
|
| + 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 (!fFill) {
|
| + builder->fsCodeAppend("\t\tfunc = abs(func);\n");
|
| + }
|
| + if (fAntiAlias) {
|
| + builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
|
| + }
|
| + if (fFill) {
|
| + if (fAntiAlias) {
|
| + 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 SK_OVERRIDE {
|
| + return GrTBackendEffectFactory<GrCubicEffect>::getInstance();
|
| +}
|
| +
|
| +GrCubicEffect::GrCubicEffect(bool antiAlias, bool fill) : GrEffect() {
|
| + this->addVertexAttrib(kVec4f_GrSLType);
|
| + fAntiAlias = antiAlias;
|
| + fFill= fill;
|
| +}
|
| +
|
| +bool GrCubicEffect::onIsEqual(const GrEffect& other) const SK_OVERRIDE {
|
| + const GrCubicEffect& ce = CastEffect<GrCubicEffect>(other);
|
| + return (ce.fAntiAlias == fAntiAlias && ce.fFill == fFill);
|
| +}
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +
|
| +GR_DEFINE_EFFECT_TEST(GrCubicEffect);
|
| +
|
| +GrEffectRef* GrCubicEffect::TestCreate(SkMWCRandom* random,
|
| + GrContext*,
|
| + const GrDrawTargetCaps& caps,
|
| + GrTexture*[]) {
|
| + const BezierEffectType effect = static_cast<BezierEffectType>(random->nextULessThan(3));
|
| + return caps.shaderDerivativeSupport() ? GrCubicEffect::Create(effect) : NULL;
|
| +}
|
|
|