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

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

Issue 1073473005: Rename DistanceFieldTextureEffect.{cpp,h} (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 8 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 | « src/gpu/effects/GrDistanceFieldTextureEffect.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/effects/GrDistanceFieldTextureEffect.cpp
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
deleted file mode 100755
index ad3be5fc045b0be9cd4cc3830d177ff664f781f4..0000000000000000000000000000000000000000
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
+++ /dev/null
@@ -1,862 +0,0 @@
-/*
- * 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 "GrDistanceFieldTextureEffect.h"
-#include "GrFontAtlasSizes.h"
-#include "GrInvariantOutput.h"
-#include "GrTexture.h"
-
-#include "SkDistanceFieldGen.h"
-
-#include "gl/GrGLProcessor.h"
-#include "gl/GrGLSL.h"
-#include "gl/GrGLTexture.h"
-#include "gl/GrGLGeometryProcessor.h"
-#include "gl/builders/GrGLProgramBuilder.h"
-
-// Assuming a radius of a little less than the diagonal of the fragment
-#define SK_DistanceFieldAAFactor "0.65"
-
-struct DistanceFieldBatchTracker {
- GrGPInput fInputColorType;
- GrColor fColor;
- bool fUsesLocalCoords;
-};
-
-class GrGLDistanceFieldA8TextGeoProc : public GrGLGeometryProcessor {
-public:
- GrGLDistanceFieldA8TextGeoProc(const GrGeometryProcessor&,
- const GrBatchTracker&)
- : fColor(GrColor_ILLEGAL)
-#ifdef SK_GAMMA_APPLY_TO_A8
- , fDistanceAdjust(-1.0f)
-#endif
- {}
-
- void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
- const GrDistanceFieldA8TextGeoProc& dfTexEffect =
- args.fGP.cast<GrDistanceFieldA8TextGeoProc>();
- const DistanceFieldBatchTracker& local = args.fBT.cast<DistanceFieldBatchTracker>();
- GrGLGPBuilder* pb = args.fPB;
- GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
- SkAssertResult(fsBuilder->enableFeature(
- GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
-
- GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
-
- // emit attributes
- vsBuilder->emitAttributes(dfTexEffect);
-
-#ifdef SK_GAMMA_APPLY_TO_A8
- // adjust based on gamma
- const char* distanceAdjustUniName = NULL;
- // width, height, 1/(3*width)
- fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kFloat_GrSLType, kDefault_GrSLPrecision,
- "DistanceAdjust", &distanceAdjustUniName);
-#endif
-
- // Setup pass through color
- this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor,
- dfTexEffect.inColor(), &fColorUniform);
-
- // Setup position
- this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix());
-
- // emit transforms
- const SkMatrix& localMatrix = dfTexEffect.localMatrix();
- this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName,
- localMatrix, args.fTransformsIn, args.fTransformsOut);
-
- // add varyings
- GrGLVertToFrag recipScale(kFloat_GrSLType);
- GrGLVertToFrag st(kVec2f_GrSLType);
- bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
- const char* viewMatrixName = this->uViewM();
- // view matrix name is NULL if identity matrix
- bool useInverseScale = !localMatrix.isIdentity() && viewMatrixName;
- if (isSimilarity && useInverseScale) {
- args.fPB->addVarying("RecipScale", &recipScale, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("vec2 tx = vec2(%s[0][0], %s[1][0]);",
- viewMatrixName, viewMatrixName);
- vsBuilder->codeAppend("float tx2 = dot(tx, tx);");
- vsBuilder->codeAppendf("%s = inversesqrt(tx2);", recipScale.vsOut());
- } else {
- args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
- }
-
- GrGLVertToFrag uv(kVec2f_GrSLType);
- args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
- // this is only used with text, so our texture bounds always match the glyph atlas
- vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
- GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
- dfTexEffect.inTextureCoords()->fName);
-
- // Use highp to work around aliasing issues
- fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
- pb->ctxInfo().standard()));
- fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn());
-
- fsBuilder->codeAppend("\tfloat texColor = ");
- fsBuilder->appendTextureLookup(args.fSamplers[0],
- "uv",
- kVec2f_GrSLType);
- fsBuilder->codeAppend(".r;\n");
- fsBuilder->codeAppend("\tfloat distance = "
- SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
-#ifdef SK_GAMMA_APPLY_TO_A8
- // adjust width based on gamma
- fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
-#endif
-
- fsBuilder->codeAppend("float afwidth;");
- if (isSimilarity) {
- // For uniform scale, we adjust for the effect of the transformation on the distance
- // either by using the inverse scale in the view matrix, or (if there is no view matrix)
- // by using the length of the gradient of the texture coordinates. We use st coordinates
- // with the latter to ensure we're mapping 1:1 from texel space to pixel space.
-
- // this gives us a smooth step across approximately one fragment
- if (useInverseScale) {
- fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*%s);",
- recipScale.fsIn());
- } else {
- fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(%s.x));",
- st.fsIn());
- }
- } else {
- // For general transforms, to determine the amount of correction we multiply a unit
- // vector pointing along the SDF gradient direction by the Jacobian of the st coords
- // (which is the inverse transform for this fragment) and take the length of the result.
- fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
- // the length of the gradient may be 0, so we need to check for this
- // this also compensates for the Adreno, which likes to drop tiles on division by 0
- fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
- fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
- fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
- fsBuilder->codeAppend("} else {");
- fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
- fsBuilder->codeAppend("}");
-
- fsBuilder->codeAppendf("vec2 Jdx = dFdx(%s);", st.fsIn());
- fsBuilder->codeAppendf("vec2 Jdy = dFdy(%s);", st.fsIn());
- fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
- fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
-
- // this gives us a smooth step across approximately one fragment
- fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
- }
- fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
-
- fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
- }
-
- virtual void setData(const GrGLProgramDataManager& pdman,
- const GrPrimitiveProcessor& proc,
- const GrBatchTracker& bt) override {
-#ifdef SK_GAMMA_APPLY_TO_A8
- const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>();
- float distanceAdjust = dfTexEffect.getDistanceAdjust();
- if (distanceAdjust != fDistanceAdjust) {
- pdman.set1f(fDistanceAdjustUni, distanceAdjust);
- fDistanceAdjust = distanceAdjust;
- }
-#endif
-
- this->setUniformViewMatrix(pdman, proc.viewMatrix());
-
- const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>();
- if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
- GrGLfloat c[4];
- GrColorToRGBAFloat(local.fColor, c);
- pdman.set4fv(fColorUniform, 1, c);
- fColor = local.fColor;
- }
- }
-
- static inline void GenKey(const GrGeometryProcessor& gp,
- const GrBatchTracker& bt,
- const GrGLCaps&,
- GrProcessorKeyBuilder* b) {
- const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>();
- const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>();
- uint32_t key = dfTexEffect.getFlags();
- key |= local.fInputColorType << 16;
- key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0;
- key |= ComputePosKey(gp.viewMatrix()) << 25;
- key |= (!gp.viewMatrix().isIdentity() && !gp.localMatrix().isIdentity()) ? 0x1 << 27 : 0x0;
- b->add32(key);
- }
-
-private:
- GrColor fColor;
- UniformHandle fColorUniform;
-#ifdef SK_GAMMA_APPLY_TO_A8
- float fDistanceAdjust;
- UniformHandle fDistanceAdjustUni;
-#endif
-
- typedef GrGLGeometryProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrColor color,
- const SkMatrix& viewMatrix,
- const SkMatrix& localMatrix,
- GrTexture* texture,
- const GrTextureParams& params,
-#ifdef SK_GAMMA_APPLY_TO_A8
- float distanceAdjust,
-#endif
- uint32_t flags, bool opaqueVertexColors)
- : INHERITED(color, viewMatrix, localMatrix, opaqueVertexColors)
- , fTextureAccess(texture, params)
-#ifdef SK_GAMMA_APPLY_TO_A8
- , fDistanceAdjust(distanceAdjust)
-#endif
- , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
- , fInColor(NULL) {
- SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
- this->initClassID<GrDistanceFieldA8TextGeoProc>();
- fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
- if (flags & kColorAttr_DistanceFieldEffectFlag) {
- fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
- this->setHasVertexColor();
- }
- fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
- kVec2s_GrVertexAttribType));
- this->addTextureAccess(&fTextureAccess);
-}
-
-bool GrDistanceFieldA8TextGeoProc::onIsEqual(const GrGeometryProcessor& other) const {
- const GrDistanceFieldA8TextGeoProc& cte = other.cast<GrDistanceFieldA8TextGeoProc>();
- return
-#ifdef SK_GAMMA_APPLY_TO_A8
- fDistanceAdjust == cte.fDistanceAdjust &&
-#endif
- fFlags == cte.fFlags;
-}
-
-void GrDistanceFieldA8TextGeoProc::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
- out->setUnknownSingleComponent();
-}
-
-void GrDistanceFieldA8TextGeoProc::getGLProcessorKey(const GrBatchTracker& bt,
- const GrGLCaps& caps,
- GrProcessorKeyBuilder* b) const {
- GrGLDistanceFieldA8TextGeoProc::GenKey(*this, bt, caps, b);
-}
-
-GrGLPrimitiveProcessor*
-GrDistanceFieldA8TextGeoProc::createGLInstance(const GrBatchTracker& bt,
- const GrGLCaps&) const {
- return SkNEW_ARGS(GrGLDistanceFieldA8TextGeoProc, (*this, bt));
-}
-
-void GrDistanceFieldA8TextGeoProc::initBatchTracker(GrBatchTracker* bt,
- const GrPipelineInfo& init) const {
- DistanceFieldBatchTracker* local = bt->cast<DistanceFieldBatchTracker>();
- local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
- SkToBool(fInColor));
- local->fUsesLocalCoords = init.fUsesLocalCoords;
-}
-
-bool GrDistanceFieldA8TextGeoProc::onCanMakeEqual(const GrBatchTracker& m,
- const GrGeometryProcessor& that,
- const GrBatchTracker& t) const {
- const DistanceFieldBatchTracker& mine = m.cast<DistanceFieldBatchTracker>();
- const DistanceFieldBatchTracker& theirs = t.cast<DistanceFieldBatchTracker>();
- return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
- that, theirs.fUsesLocalCoords) &&
- CanCombineOutput(mine.fInputColorType, mine.fColor,
- theirs.fInputColorType, theirs.fColor);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldA8TextGeoProc);
-
-GrGeometryProcessor* GrDistanceFieldA8TextGeoProc::TestCreate(SkRandom* random,
- GrContext*,
- const GrDrawTargetCaps&,
- GrTexture* textures[]) {
- int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
- GrProcessorUnitTest::kAlphaTextureIdx;
- static const SkShader::TileMode kTileModes[] = {
- SkShader::kClamp_TileMode,
- SkShader::kRepeat_TileMode,
- SkShader::kMirror_TileMode,
- };
- SkShader::TileMode tileModes[] = {
- kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
- kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
- };
- GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
- GrTextureParams::kNone_FilterMode);
-
- return GrDistanceFieldA8TextGeoProc::Create(GrRandomColor(random),
- GrProcessorUnitTest::TestMatrix(random),
- GrProcessorUnitTest::TestMatrix(random),
- textures[texIdx], params,
-#ifdef SK_GAMMA_APPLY_TO_A8
- random->nextF(),
-#endif
- random->nextBool() ?
- kSimilarity_DistanceFieldEffectFlag : 0,
- random->nextBool());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-struct DistanceFieldPathBatchTracker {
- GrGPInput fInputColorType;
- GrColor fColor;
- bool fUsesLocalCoords;
-};
-
-class GrGLDistanceFieldPathGeoProc : public GrGLGeometryProcessor {
-public:
- GrGLDistanceFieldPathGeoProc(const GrGeometryProcessor&,
- const GrBatchTracker&)
- : fColor(GrColor_ILLEGAL), fTextureSize(SkISize::Make(-1, -1)) {}
-
- void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
- const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>();
-
- const DistanceFieldPathBatchTracker& local = args.fBT.cast<DistanceFieldPathBatchTracker>();
- GrGLGPBuilder* pb = args.fPB;
- GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
- SkAssertResult(fsBuilder->enableFeature(
- GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
-
- GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
-
- // emit attributes
- vsBuilder->emitAttributes(dfTexEffect);
-
- GrGLVertToFrag v(kVec2f_GrSLType);
- args.fPB->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
-
- // setup pass through color
- this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor,
- dfTexEffect.inColor(), &fColorUniform);
-
- vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
-
- // Setup position
- this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix());
-
- // emit transforms
- this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName,
- dfTexEffect.localMatrix(), args.fTransformsIn, args.fTransformsOut);
-
- const char* textureSizeUniName = NULL;
- fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec2f_GrSLType, kDefault_GrSLPrecision,
- "TextureSize", &textureSizeUniName);
-
- // Use highp to work around aliasing issues
- fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
- pb->ctxInfo().standard()));
- fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn());
-
- fsBuilder->codeAppend("float texColor = ");
- fsBuilder->appendTextureLookup(args.fSamplers[0],
- "uv",
- kVec2f_GrSLType);
- fsBuilder->codeAppend(".r;");
- fsBuilder->codeAppend("float distance = "
- SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
-
- fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
- pb->ctxInfo().standard()));
- fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName);
- fsBuilder->codeAppend("float afwidth;");
- if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
- // For uniform scale, we adjust for the effect of the transformation on the distance
- // by using the length of the gradient of the texture coordinates. We use st coordinates
- // to ensure we're mapping 1:1 from texel space to pixel space.
-
- // this gives us a smooth step across approximately one fragment
- fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));");
- } else {
- // For general transforms, to determine the amount of correction we multiply a unit
- // vector pointing along the SDF gradient direction by the Jacobian of the st coords
- // (which is the inverse transform for this fragment) and take the length of the result.
- fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
- // the length of the gradient may be 0, so we need to check for this
- // this also compensates for the Adreno, which likes to drop tiles on division by 0
- fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
- fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
- fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
- fsBuilder->codeAppend("} else {");
- fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
- fsBuilder->codeAppend("}");
-
- fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
- fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
- fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
- fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
-
- // this gives us a smooth step across approximately one fragment
- fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
- }
- fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
-
- fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
- }
-
- virtual void setData(const GrGLProgramDataManager& pdman,
- const GrPrimitiveProcessor& proc,
- const GrBatchTracker& bt) override {
- SkASSERT(fTextureSizeUni.isValid());
-
- GrTexture* texture = proc.texture(0);
- if (texture->width() != fTextureSize.width() ||
- texture->height() != fTextureSize.height()) {
- fTextureSize = SkISize::Make(texture->width(), texture->height());
- pdman.set2f(fTextureSizeUni,
- SkIntToScalar(fTextureSize.width()),
- SkIntToScalar(fTextureSize.height()));
- }
-
- this->setUniformViewMatrix(pdman, proc.viewMatrix());
-
- const DistanceFieldPathBatchTracker& local = bt.cast<DistanceFieldPathBatchTracker>();
- if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
- GrGLfloat c[4];
- GrColorToRGBAFloat(local.fColor, c);
- pdman.set4fv(fColorUniform, 1, c);
- fColor = local.fColor;
- }
- }
-
- static inline void GenKey(const GrGeometryProcessor& gp,
- const GrBatchTracker& bt,
- const GrGLCaps&,
- GrProcessorKeyBuilder* b) {
- const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>();
-
- const DistanceFieldPathBatchTracker& local = bt.cast<DistanceFieldPathBatchTracker>();
- uint32_t key = dfTexEffect.getFlags();
- key |= local.fInputColorType << 16;
- key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0;
- key |= ComputePosKey(gp.viewMatrix()) << 25;
- b->add32(key);
- }
-
-private:
- UniformHandle fColorUniform;
- UniformHandle fTextureSizeUni;
- GrColor fColor;
- SkISize fTextureSize;
-
- typedef GrGLGeometryProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(
- GrColor color,
- const SkMatrix& viewMatrix,
- GrTexture* texture,
- const GrTextureParams& params,
- uint32_t flags,
- bool opaqueVertexColors)
- : INHERITED(color, viewMatrix, SkMatrix::I(), opaqueVertexColors)
- , fTextureAccess(texture, params)
- , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
- , fInColor(NULL) {
- SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
- this->initClassID<GrDistanceFieldPathGeoProc>();
- fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
- if (flags & kColorAttr_DistanceFieldEffectFlag) {
- fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
- this->setHasVertexColor();
- }
- fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
- kVec2f_GrVertexAttribType));
- this->addTextureAccess(&fTextureAccess);
-}
-
-bool GrDistanceFieldPathGeoProc::onIsEqual(const GrGeometryProcessor& other) const {
- const GrDistanceFieldPathGeoProc& cte = other.cast<GrDistanceFieldPathGeoProc>();
- return fFlags == cte.fFlags;
-}
-
-void GrDistanceFieldPathGeoProc::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
- out->setUnknownSingleComponent();
-}
-
-void GrDistanceFieldPathGeoProc::getGLProcessorKey(const GrBatchTracker& bt,
- const GrGLCaps& caps,
- GrProcessorKeyBuilder* b) const {
- GrGLDistanceFieldPathGeoProc::GenKey(*this, bt, caps, b);
-}
-
-GrGLPrimitiveProcessor*
-GrDistanceFieldPathGeoProc::createGLInstance(const GrBatchTracker& bt, const GrGLCaps&) const {
- return SkNEW_ARGS(GrGLDistanceFieldPathGeoProc, (*this, bt));
-}
-
-void GrDistanceFieldPathGeoProc::initBatchTracker(GrBatchTracker* bt,
- const GrPipelineInfo& init) const {
- DistanceFieldPathBatchTracker* local = bt->cast<DistanceFieldPathBatchTracker>();
- local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
- SkToBool(fInColor));
- local->fUsesLocalCoords = init.fUsesLocalCoords;
-}
-
-bool GrDistanceFieldPathGeoProc::onCanMakeEqual(const GrBatchTracker& m,
- const GrGeometryProcessor& that,
- const GrBatchTracker& t) const {
- const DistanceFieldPathBatchTracker& mine = m.cast<DistanceFieldPathBatchTracker>();
- const DistanceFieldPathBatchTracker& theirs = t.cast<DistanceFieldPathBatchTracker>();
- return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
- that, theirs.fUsesLocalCoords) &&
- CanCombineOutput(mine.fInputColorType, mine.fColor,
- theirs.fInputColorType, theirs.fColor);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc);
-
-GrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(SkRandom* random,
- GrContext*,
- const GrDrawTargetCaps&,
- GrTexture* textures[]) {
- int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
- : GrProcessorUnitTest::kAlphaTextureIdx;
- static const SkShader::TileMode kTileModes[] = {
- SkShader::kClamp_TileMode,
- SkShader::kRepeat_TileMode,
- SkShader::kMirror_TileMode,
- };
- SkShader::TileMode tileModes[] = {
- kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
- kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
- };
- GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode
- : GrTextureParams::kNone_FilterMode);
-
- return GrDistanceFieldPathGeoProc::Create(GrRandomColor(random),
- GrProcessorUnitTest::TestMatrix(random),
- textures[texIdx],
- params,
- random->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0, random->nextBool());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-struct DistanceFieldLCDBatchTracker {
- GrGPInput fInputColorType;
- GrColor fColor;
- bool fUsesLocalCoords;
-};
-
-class GrGLDistanceFieldLCDTextGeoProc : public GrGLGeometryProcessor {
-public:
- GrGLDistanceFieldLCDTextGeoProc(const GrGeometryProcessor&, const GrBatchTracker&)
- : fColor(GrColor_ILLEGAL) {
- fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
- }
-
- void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
- const GrDistanceFieldLCDTextGeoProc& dfTexEffect =
- args.fGP.cast<GrDistanceFieldLCDTextGeoProc>();
- const DistanceFieldLCDBatchTracker& local = args.fBT.cast<DistanceFieldLCDBatchTracker>();
- GrGLGPBuilder* pb = args.fPB;
-
- GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
-
- // emit attributes
- vsBuilder->emitAttributes(dfTexEffect);
-
- // setup pass through color
- this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
- &fColorUniform);
-
- // Setup position
- this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix());
-
- // emit transforms
- const SkMatrix& localMatrix = dfTexEffect.localMatrix();
- this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName,
- localMatrix, args.fTransformsIn, args.fTransformsOut);
-
- // set up varyings
- bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
- GrGLVertToFrag recipScale(kFloat_GrSLType);
- GrGLVertToFrag st(kVec2f_GrSLType);
- const char* viewMatrixName = this->uViewM();
- // view matrix name is NULL if identity matrix
- bool useInverseScale = !localMatrix.isIdentity() && viewMatrixName;
- if (isUniformScale && useInverseScale) {
- args.fPB->addVarying("RecipScale", &recipScale, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("vec2 tx = vec2(%s[0][0], %s[1][0]);",
- viewMatrixName, viewMatrixName);
- vsBuilder->codeAppend("float tx2 = dot(tx, tx);");
- vsBuilder->codeAppendf("%s = inversesqrt(tx2);", recipScale.vsOut());
- } else {
- args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
- }
-
- GrGLVertToFrag uv(kVec2f_GrSLType);
- args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
- // this is only used with text, so our texture bounds always match the glyph atlas
- vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
- GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
- dfTexEffect.inTextureCoords()->fName);
-
- // add frag shader code
- GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
-
- SkAssertResult(fsBuilder->enableFeature(
- GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
-
- // create LCD offset adjusted by inverse of transform
- // Use highp to work around aliasing issues
- fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
- pb->ctxInfo().standard()));
- fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn());
- fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
- pb->ctxInfo().standard()));
- if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
- fsBuilder->codeAppend("float delta = -" GR_FONT_ATLAS_LCD_DELTA ";\n");
- } else {
- fsBuilder->codeAppend("float delta = " GR_FONT_ATLAS_LCD_DELTA ";\n");
- }
- if (isUniformScale) {
- if (useInverseScale) {
- fsBuilder->codeAppendf("float dx = %s;", recipScale.fsIn());
- } else {
- fsBuilder->codeAppendf("float dx = dFdx(%s.x);", st.fsIn());
- }
- fsBuilder->codeAppend("vec2 offset = vec2(dx*delta, 0.0);");
- } else {
- fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn());
-
- fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
- fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
- fsBuilder->codeAppend("vec2 offset = delta*Jdx;");
- }
-
- // green is distance to uv center
- fsBuilder->codeAppend("\tvec4 texColor = ");
- fsBuilder->appendTextureLookup(args.fSamplers[0], "uv", kVec2f_GrSLType);
- fsBuilder->codeAppend(";\n");
- fsBuilder->codeAppend("\tvec3 distance;\n");
- fsBuilder->codeAppend("\tdistance.y = texColor.r;\n");
- // red is distance to left offset
- fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n");
- fsBuilder->codeAppend("\ttexColor = ");
- fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
- fsBuilder->codeAppend(";\n");
- fsBuilder->codeAppend("\tdistance.x = texColor.r;\n");
- // blue is distance to right offset
- fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
- fsBuilder->codeAppend("\ttexColor = ");
- fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
- fsBuilder->codeAppend(";\n");
- fsBuilder->codeAppend("\tdistance.z = texColor.r;\n");
-
- fsBuilder->codeAppend("\tdistance = "
- "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
-
- // adjust width based on gamma
- const char* distanceAdjustUniName = NULL;
- fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec3f_GrSLType, kDefault_GrSLPrecision,
- "DistanceAdjust", &distanceAdjustUniName);
- fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
-
- // To be strictly correct, we should compute the anti-aliasing factor separately
- // for each color component. However, this is only important when using perspective
- // transformations, and even then using a single factor seems like a reasonable
- // trade-off between quality and speed.
- fsBuilder->codeAppend("float afwidth;");
- if (isUniformScale) {
- // For uniform scale, we adjust for the effect of the transformation on the distance
- // by using the length of the gradient of the texture coordinates. We use st coordinates
- // to ensure we're mapping 1:1 from texel space to pixel space.
-
- // this gives us a smooth step across approximately one fragment
- fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dx);");
- } else {
- // For general transforms, to determine the amount of correction we multiply a unit
- // vector pointing along the SDF gradient direction by the Jacobian of the st coords
- // (which is the inverse transform for this fragment) and take the length of the result.
- fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(distance.r));");
- // the length of the gradient may be 0, so we need to check for this
- // this also compensates for the Adreno, which likes to drop tiles on division by 0
- fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
- fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
- fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
- fsBuilder->codeAppend("} else {");
- fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
- fsBuilder->codeAppend("}");
- fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
- fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
-
- // this gives us a smooth step across approximately one fragment
- fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
- }
-
- fsBuilder->codeAppend(
- "vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
-
- fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
- }
-
- virtual void setData(const GrGLProgramDataManager& pdman,
- const GrPrimitiveProcessor& processor,
- const GrBatchTracker& bt) override {
- SkASSERT(fDistanceAdjustUni.isValid());
-
- const GrDistanceFieldLCDTextGeoProc& dfTexEffect =
- processor.cast<GrDistanceFieldLCDTextGeoProc>();
- GrDistanceFieldLCDTextGeoProc::DistanceAdjust wa = dfTexEffect.getDistanceAdjust();
- if (wa != fDistanceAdjust) {
- pdman.set3f(fDistanceAdjustUni,
- wa.fR,
- wa.fG,
- wa.fB);
- fDistanceAdjust = wa;
- }
-
- this->setUniformViewMatrix(pdman, processor.viewMatrix());
-
- const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>();
- if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
- GrGLfloat c[4];
- GrColorToRGBAFloat(local.fColor, c);
- pdman.set4fv(fColorUniform, 1, c);
- fColor = local.fColor;
- }
- }
-
- static inline void GenKey(const GrGeometryProcessor& gp,
- const GrBatchTracker& bt,
- const GrGLCaps&,
- GrProcessorKeyBuilder* b) {
- const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>();
-
- const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>();
- uint32_t key = dfTexEffect.getFlags();
- key |= local.fInputColorType << 16;
- key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0;
- key |= ComputePosKey(gp.viewMatrix()) << 25;
- key |= (!gp.viewMatrix().isIdentity() && !gp.localMatrix().isIdentity()) ? 0x1 << 27 : 0x0;
- b->add32(key);
- }
-
-private:
- GrColor fColor;
- UniformHandle fColorUniform;
- GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust;
- UniformHandle fDistanceAdjustUni;
-
- typedef GrGLGeometryProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
- GrColor color, const SkMatrix& viewMatrix,
- const SkMatrix& localMatrix,
- GrTexture* texture, const GrTextureParams& params,
- DistanceAdjust distanceAdjust,
- uint32_t flags)
- : INHERITED(color, viewMatrix, localMatrix)
- , fTextureAccess(texture, params)
- , fDistanceAdjust(distanceAdjust)
- , fFlags(flags & kLCD_DistanceFieldEffectMask){
- SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
- this->initClassID<GrDistanceFieldLCDTextGeoProc>();
- fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
- fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
- kVec2s_GrVertexAttribType));
- this->addTextureAccess(&fTextureAccess);
-}
-
-bool GrDistanceFieldLCDTextGeoProc::onIsEqual(const GrGeometryProcessor& other) const {
- const GrDistanceFieldLCDTextGeoProc& cte = other.cast<GrDistanceFieldLCDTextGeoProc>();
- return (fDistanceAdjust == cte.fDistanceAdjust &&
- fFlags == cte.fFlags);
-}
-
-void GrDistanceFieldLCDTextGeoProc::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
- out->setUnknownFourComponents();
- out->setUsingLCDCoverage();
-}
-
-void GrDistanceFieldLCDTextGeoProc::getGLProcessorKey(const GrBatchTracker& bt,
- const GrGLCaps& caps,
- GrProcessorKeyBuilder* b) const {
- GrGLDistanceFieldLCDTextGeoProc::GenKey(*this, bt, caps, b);
-}
-
-GrGLPrimitiveProcessor*
-GrDistanceFieldLCDTextGeoProc::createGLInstance(const GrBatchTracker& bt,
- const GrGLCaps&) const {
- return SkNEW_ARGS(GrGLDistanceFieldLCDTextGeoProc, (*this, bt));
-}
-
-void GrDistanceFieldLCDTextGeoProc::initBatchTracker(GrBatchTracker* bt,
- const GrPipelineInfo& init) const {
- DistanceFieldLCDBatchTracker* local = bt->cast<DistanceFieldLCDBatchTracker>();
- local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
- local->fUsesLocalCoords = init.fUsesLocalCoords;
-}
-
-bool GrDistanceFieldLCDTextGeoProc::onCanMakeEqual(const GrBatchTracker& m,
- const GrGeometryProcessor& that,
- const GrBatchTracker& t) const {
- const DistanceFieldLCDBatchTracker& mine = m.cast<DistanceFieldLCDBatchTracker>();
- const DistanceFieldLCDBatchTracker& theirs = t.cast<DistanceFieldLCDBatchTracker>();
- return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
- that, theirs.fUsesLocalCoords) &&
- CanCombineOutput(mine.fInputColorType, mine.fColor,
- theirs.fInputColorType, theirs.fColor);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc);
-
-GrGeometryProcessor* GrDistanceFieldLCDTextGeoProc::TestCreate(SkRandom* random,
- GrContext*,
- const GrDrawTargetCaps&,
- GrTexture* textures[]) {
- int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
- GrProcessorUnitTest::kAlphaTextureIdx;
- static const SkShader::TileMode kTileModes[] = {
- SkShader::kClamp_TileMode,
- SkShader::kRepeat_TileMode,
- SkShader::kMirror_TileMode,
- };
- SkShader::TileMode tileModes[] = {
- kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
- kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
- };
- GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
- GrTextureParams::kNone_FilterMode);
- DistanceAdjust wa = { 0.0f, 0.1f, -0.1f };
- uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
- flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
- flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
- return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(random),
- GrProcessorUnitTest::TestMatrix(random),
- GrProcessorUnitTest::TestMatrix(random),
- textures[texIdx], params,
- wa,
- flags);
-}
« no previous file with comments | « src/gpu/effects/GrDistanceFieldTextureEffect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698