GrDistanceFieldGeoProc.cpp revision 8ed3b9a386374d7996dfbe0c9de13b42f3dd245d
1d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com/*
2d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com * Copyright 2013 Google Inc.
3d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com *
4d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com * Use of this source code is governed by a BSD-style license that can be
5d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com * found in the LICENSE file.
6d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com */
7d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
88ed3b9a386374d7996dfbe0c9de13b42f3dd245djvanverth#include "GrDistanceFieldGeoProc.h"
95a105ff05303ac82a867b8b84a1edd145bd46218jvanverth#include "GrFontAtlasSizes.h"
10605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h"
11eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrTexture.h"
1221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth
13eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "SkDistanceFieldGen.h"
1421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth
15b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h"
16d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLSL.h"
17d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLTexture.h"
18249af15fb82833d2274850c589812b6e69df0033joshualitt#include "gl/GrGLGeometryProcessor.h"
19eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "gl/builders/GrGLProgramBuilder.h"
20d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
2121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth// Assuming a radius of a little less than the diagonal of the fragment
2224ba00825092be0d400074e0121ffc7221950dd9jvanverth#define SK_DistanceFieldAAFactor     "0.65"
232d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
249b98932adaceb7ad0a617ade16616923f6bffe84joshualittstruct DistanceFieldBatchTracker {
259b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrGPInput fInputColorType;
269b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrColor fColor;
27290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    bool fUsesLocalCoords;
289b98932adaceb7ad0a617ade16616923f6bffe84joshualitt};
299b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
30502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldA8TextGeoProc : public GrGLGeometryProcessor {
31d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.compublic:
32502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldA8TextGeoProc(const GrGeometryProcessor&,
3387f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                                   const GrBatchTracker&)
349b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        : fColor(GrColor_ILLEGAL)
359564ce60a657acce89fb956deb8645b324eaad1ejvanverth#ifdef SK_GAMMA_APPLY_TO_A8
3621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        , fDistanceAdjust(-1.0f)
379564ce60a657acce89fb956deb8645b324eaad1ejvanverth#endif
389564ce60a657acce89fb956deb8645b324eaad1ejvanverth        {}
39d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
4036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
41502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldA8TextGeoProc& dfTexEffect =
42502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                args.fGP.cast<GrDistanceFieldA8TextGeoProc>();
439b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldBatchTracker& local = args.fBT.cast<DistanceFieldBatchTracker>();
449b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrGLGPBuilder* pb = args.fPB;
45c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
4630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        SkAssertResult(fsBuilder->enableFeature(
4730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
486c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
492dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
50abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
51abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit attributes
52abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        vsBuilder->emitAttributes(dfTexEffect);
53abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
5421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
5521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        // adjust based on gamma
5621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        const char* distanceAdjustUniName = NULL;
5721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        // width, height, 1/(3*width)
5821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
5921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            kFloat_GrSLType, kDefault_GrSLPrecision,
6021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            "DistanceAdjust", &distanceAdjustUniName);
6121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#endif
62d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
639b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        // Setup pass through color
649b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor,
659b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                    dfTexEffect.inColor(), &fColorUniform);
666c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
67abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // Setup position
68dd2198701b0ec9da61ecf73418cad03642d715e7joshualitt        this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix());
694973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt
70abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit transforms
71bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        const SkMatrix& localMatrix = dfTexEffect.localMatrix();
7246d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName,
73bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                             localMatrix, args.fTransformsIn, args.fTransformsOut);
74abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
75bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // add varyings
76bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag recipScale(kFloat_GrSLType);
77bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag st(kVec2f_GrSLType);
78bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
79bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        const char* viewMatrixName = this->uViewM();
80bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // view matrix name is NULL if identity matrix
81bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        bool useInverseScale = !localMatrix.isIdentity() && viewMatrixName;
82bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        if (isSimilarity && useInverseScale) {
83bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            args.fPB->addVarying("RecipScale", &recipScale, kHigh_GrSLPrecision);
84bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            vsBuilder->codeAppendf("vec2 tx = vec2(%s[0][0], %s[1][0]);",
85bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                                   viewMatrixName, viewMatrixName);
86bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            vsBuilder->codeAppend("float tx2 = dot(tx, tx);");
87bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            vsBuilder->codeAppendf("%s = inversesqrt(tx2);", recipScale.vsOut());
88bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        } else {
89bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
90bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
91bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        }
92bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
93bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag uv(kVec2f_GrSLType);
94bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
95bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // this is only used with text, so our texture bounds always match the glyph atlas
96bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
97bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                               GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
98bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                               dfTexEffect.inTextureCoords()->fName);
99bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
100fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        // Use highp to work around aliasing issues
101fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
102fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
1035a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn());
104fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth
105fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend("\tfloat texColor = ");
106c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0],
107fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                       "uv",
108d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                       kVec2f_GrSLType);
109fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(".r;\n");
11030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat distance = "
111fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                       SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
11221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
11321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        // adjust width based on gamma
11421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
11521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#endif
1166c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
117354eba5cb61801130a84378356434d3cc0a4b71ajvanverth        fsBuilder->codeAppend("float afwidth;");
118bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        if (isSimilarity) {
119354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For uniform scale, we adjust for the effect of the transformation on the distance
120bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            // either by using the inverse scale in the view matrix, or (if there is no view matrix)
121354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // by using the length of the gradient of the texture coordinates. We use st coordinates
122bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            // with the latter to ensure we're mapping 1:1 from texel space to pixel space.
123354eba5cb61801130a84378356434d3cc0a4b71ajvanverth
1244362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
125bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            if (useInverseScale) {
126bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*%s);",
127bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                                       recipScale.fsIn());
128bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            } else {
129bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(%s.x));",
130bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                                       st.fsIn());
131bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            }
1324362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        } else {
133354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For general transforms, to determine the amount of correction we multiply a unit
134354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // vector pointing along the SDF gradient direction by the Jacobian of the st coords
135354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // (which is the inverse transform for this fragment) and take the length of the result.
136354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
137d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // the length of the gradient may be 0, so we need to check for this
138d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // this also compensates for the Adreno, which likes to drop tiles on division by 0
139d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
140d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
141d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
142d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("} else {");
143d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
144d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("}");
145d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth
146bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppendf("vec2 Jdx = dFdx(%s);", st.fsIn());
147bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppendf("vec2 Jdy = dFdy(%s);", st.fsIn());
148354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
149354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
1504362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
1514362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
152354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
1534362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        }
154354eba5cb61801130a84378356434d3cc0a4b71ajvanverth        fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
1554d517fdbb145cb95e5e935470df331e1b6667cfcjvanverth
1562dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
157d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    }
158d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
1597510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager& pdman,
1609b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                         const GrPrimitiveProcessor& proc,
16136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                         const GrBatchTracker& bt) override {
1622d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
163502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>();
16421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        float distanceAdjust = dfTexEffect.getDistanceAdjust();
16521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        if (distanceAdjust != fDistanceAdjust) {
16621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            pdman.set1f(fDistanceAdjustUni, distanceAdjust);
16721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            fDistanceAdjust = distanceAdjust;
1682d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        }
1692d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
1709b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
171ee2af95db72152dfa61c841875df0594ca93437djoshualitt        this->setUniformViewMatrix(pdman, proc.viewMatrix());
172ee2af95db72152dfa61c841875df0594ca93437djoshualitt
1739b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>();
1749b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
1759b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLfloat c[4];
1769b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrColorToRGBAFloat(local.fColor, c);
1779b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            pdman.set4fv(fColorUniform, 1, c);
1789b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            fColor = local.fColor;
1799b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
1806c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org    }
181d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
18246d36f0e7b709a077c647841eee23bd3efdc4117robertphillips    static inline void GenKey(const GrGeometryProcessor& gp,
1839b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                              const GrBatchTracker& bt,
18487f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                              const GrGLCaps&,
185b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                              GrProcessorKeyBuilder* b) {
186502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>();
1879b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>();
1888fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        uint32_t key = dfTexEffect.getFlags();
1898fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        key |= local.fInputColorType << 16;
19046d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0;
19146d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= ComputePosKey(gp.viewMatrix()) << 25;
192bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        key |= (!gp.viewMatrix().isIdentity() && !gp.localMatrix().isIdentity()) ? 0x1 << 27 : 0x0;
1938fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        b->add32(key);
1944362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org    }
1954362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
196d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comprivate:
1979b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrColor       fColor;
1989b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    UniformHandle fColorUniform;
19950282b4390dcddcf3b1d51631c0133045ae1f233mtklein#ifdef SK_GAMMA_APPLY_TO_A8
20021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    float         fDistanceAdjust;
20121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    UniformHandle fDistanceAdjustUni;
20250282b4390dcddcf3b1d51631c0133045ae1f233mtklein#endif
2036c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
204249af15fb82833d2274850c589812b6e69df0033joshualitt    typedef GrGLGeometryProcessor INHERITED;
205d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com};
206d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
207d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com///////////////////////////////////////////////////////////////////////////////
208d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
209502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrColor color,
2108059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                                           const SkMatrix& viewMatrix,
211bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                                                           const SkMatrix& localMatrix,
2122e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt                                                           GrTexture* texture,
2136c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org                                                           const GrTextureParams& params,
2142d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
21521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                                                           float distanceAdjust,
2162d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
21756995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt                                                           uint32_t flags, bool opaqueVertexColors)
218bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth    : INHERITED(color, viewMatrix, localMatrix, opaqueVertexColors)
2192e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    , fTextureAccess(texture, params)
2202d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
22121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    , fDistanceAdjust(distanceAdjust)
2222d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
223249af15fb82833d2274850c589812b6e69df0033joshualitt    , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
2242dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    , fInColor(NULL) {
22578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
226502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    this->initClassID<GrDistanceFieldA8TextGeoProc>();
22771c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
2282dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    if (flags & kColorAttr_DistanceFieldEffectFlag) {
22971c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt        fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
2302dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        this->setHasVertexColor();
2312dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    }
23271c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
2335a105ff05303ac82a867b8b84a1edd145bd46218jvanverth                                                          kVec2s_GrVertexAttribType));
234d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    this->addTextureAccess(&fTextureAccess);
235d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
236d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
237502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldA8TextGeoProc::onIsEqual(const GrGeometryProcessor& other) const {
238502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const GrDistanceFieldA8TextGeoProc& cte = other.cast<GrDistanceFieldA8TextGeoProc>();
239420d7e9a79358908850c74192b4949375563449absalomon    return
24078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth#ifdef SK_GAMMA_APPLY_TO_A8
24121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth           fDistanceAdjust == cte.fDistanceAdjust &&
24278f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth#endif
24378f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth           fFlags == cte.fFlags;
244d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
245d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
246502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldA8TextGeoProc::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
24756995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    out->setUnknownSingleComponent();
248d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
249d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
250502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldA8TextGeoProc::getGLProcessorKey(const GrBatchTracker& bt,
251eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                                     const GrGLCaps& caps,
252eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                                     GrProcessorKeyBuilder* b) const {
253502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldA8TextGeoProc::GenKey(*this, bt, caps, b);
254eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
255eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
256abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualittGrGLPrimitiveProcessor*
257502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldA8TextGeoProc::createGLInstance(const GrBatchTracker& bt,
258abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt                                               const GrGLCaps&) const {
259502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return SkNEW_ARGS(GrGLDistanceFieldA8TextGeoProc, (*this, bt));
260d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
261d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
262502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldA8TextGeoProc::initBatchTracker(GrBatchTracker* bt,
26321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                                                    const GrPipelineInfo& init) const {
2649b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    DistanceFieldBatchTracker* local = bt->cast<DistanceFieldBatchTracker>();
2659b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
2669b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                               SkToBool(fInColor));
267290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    local->fUsesLocalCoords = init.fUsesLocalCoords;
2689b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
2699b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
270502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldA8TextGeoProc::onCanMakeEqual(const GrBatchTracker& m,
271290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                                                  const GrGeometryProcessor& that,
2729b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                                  const GrBatchTracker& t) const {
2739b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    const DistanceFieldBatchTracker& mine = m.cast<DistanceFieldBatchTracker>();
2749b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    const DistanceFieldBatchTracker& theirs = t.cast<DistanceFieldBatchTracker>();
275290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
276290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                                   that, theirs.fUsesLocalCoords) &&
277290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt           CanCombineOutput(mine.fInputColorType, mine.fColor,
2789b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                            theirs.fInputColorType, theirs.fColor);
2799b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
2809b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
281d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com///////////////////////////////////////////////////////////////////////////////
282d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
283502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldA8TextGeoProc);
284d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
285502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrGeometryProcessor* GrDistanceFieldA8TextGeoProc::TestCreate(SkRandom* random,
286b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                              GrContext*,
287b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                              const GrDrawTargetCaps&,
288b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                              GrTexture* textures[]) {
289b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
290b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                      GrProcessorUnitTest::kAlphaTextureIdx;
291d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    static const SkShader::TileMode kTileModes[] = {
292d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kClamp_TileMode,
293d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kRepeat_TileMode,
294d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kMirror_TileMode,
295d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    };
296d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    SkShader::TileMode tileModes[] = {
297d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
298d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
299d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    };
300d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
301d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                                           GrTextureParams::kNone_FilterMode);
302d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
303502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return GrDistanceFieldA8TextGeoProc::Create(GrRandomColor(random),
3048059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                                GrProcessorUnitTest::TestMatrix(random),
305bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                                                GrProcessorUnitTest::TestMatrix(random),
3068059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                                textures[texIdx], params,
3072d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
3082d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                random->nextF(),
3092d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
31078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                random->nextBool() ?
31156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt                                                    kSimilarity_DistanceFieldEffectFlag : 0,
31256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt                                                random->nextBool());
313609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
314609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
315609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
316609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
317502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthstruct DistanceFieldPathBatchTracker {
3189b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrGPInput fInputColorType;
3199b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrColor fColor;
320290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    bool fUsesLocalCoords;
3219b98932adaceb7ad0a617ade16616923f6bffe84joshualitt};
3229b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
323502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldPathGeoProc : public GrGLGeometryProcessor {
324fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthpublic:
325502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldPathGeoProc(const GrGeometryProcessor&,
32687f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                                          const GrBatchTracker&)
327e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        : fColor(GrColor_ILLEGAL), fTextureSize(SkISize::Make(-1, -1)) {}
328fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
32936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
330502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>();
331fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
332502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const DistanceFieldPathBatchTracker& local = args.fBT.cast<DistanceFieldPathBatchTracker>();
3339b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrGLGPBuilder* pb = args.fPB;
334c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
335fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkAssertResult(fsBuilder->enableFeature(
336fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                     GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
337fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
3382dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
339abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
340abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit attributes
341abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        vsBuilder->emitAttributes(dfTexEffect);
342abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
343e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        GrGLVertToFrag v(kVec2f_GrSLType);
3449671ecd44e48e8bbe1361830717b79c9c4dc9d17jvanverth        args.fPB->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
345fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
3469b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        // setup pass through color
3479b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor,
3489b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                    dfTexEffect.inColor(), &fColorUniform);
3492dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
350e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
351e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed
352abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // Setup position
353dd2198701b0ec9da61ecf73418cad03642d715e7joshualitt        this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix());
354abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
355abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit transforms
35646d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName,
357abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt                             dfTexEffect.localMatrix(), args.fTransformsIn, args.fTransformsOut);
3584973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt
359e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        const char* textureSizeUniName = NULL;
360e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
361e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                                              kVec2f_GrSLType, kDefault_GrSLPrecision,
362e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                                              "TextureSize", &textureSizeUniName);
363e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed
364fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        // Use highp to work around aliasing issues
365fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
366fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
367e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn());
368fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth
369fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend("float texColor = ");
370c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0],
371fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                       "uv",
372fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                       kVec2f_GrSLType);
373fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(".r;");
374fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("float distance = "
375fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth            SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
376fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
377fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
378fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
379e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName);
380fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("float afwidth;");
381fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
382354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For uniform scale, we adjust for the effect of the transformation on the distance
383354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // by using the length of the gradient of the texture coordinates. We use st coordinates
384354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // to ensure we're mapping 1:1 from texel space to pixel space.
385354eba5cb61801130a84378356434d3cc0a4b71ajvanverth
386fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            // this gives us a smooth step across approximately one fragment
387fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));");
388fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        } else {
389354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For general transforms, to determine the amount of correction we multiply a unit
390354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // vector pointing along the SDF gradient direction by the Jacobian of the st coords
391354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // (which is the inverse transform for this fragment) and take the length of the result.
392354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
393d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // the length of the gradient may be 0, so we need to check for this
394d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // this also compensates for the Adreno, which likes to drop tiles on division by 0
395d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
396d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
397d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
398d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("} else {");
399d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
400d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("}");
401d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth
402354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
403354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
404354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
405354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
406fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
407fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            // this gives us a smooth step across approximately one fragment
408fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
409fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        }
410fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
411fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
4122dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
413fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
414fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
415fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    virtual void setData(const GrGLProgramDataManager& pdman,
4169b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                         const GrPrimitiveProcessor& proc,
41736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                         const GrBatchTracker& bt) override {
418e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        SkASSERT(fTextureSizeUni.isValid());
419fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
42087f48d997ec29e5eeaa7567355775e93465dd60djoshualitt        GrTexture* texture = proc.texture(0);
421fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        if (texture->width() != fTextureSize.width() ||
422fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            texture->height() != fTextureSize.height()) {
423fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fTextureSize = SkISize::Make(texture->width(), texture->height());
424e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed            pdman.set2f(fTextureSizeUni,
425e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                        SkIntToScalar(fTextureSize.width()),
426e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                        SkIntToScalar(fTextureSize.height()));
427fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        }
4289b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
429ee2af95db72152dfa61c841875df0594ca93437djoshualitt        this->setUniformViewMatrix(pdman, proc.viewMatrix());
430ee2af95db72152dfa61c841875df0594ca93437djoshualitt
431502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const DistanceFieldPathBatchTracker& local = bt.cast<DistanceFieldPathBatchTracker>();
4329b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
4339b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLfloat c[4];
4349b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrColorToRGBAFloat(local.fColor, c);
4359b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            pdman.set4fv(fColorUniform, 1, c);
4369b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            fColor = local.fColor;
4379b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
438fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
439fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
44046d36f0e7b709a077c647841eee23bd3efdc4117robertphillips    static inline void GenKey(const GrGeometryProcessor& gp,
4419b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                              const GrBatchTracker& bt,
44287f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                              const GrGLCaps&,
443fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                              GrProcessorKeyBuilder* b) {
444502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>();
445fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
446502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const DistanceFieldPathBatchTracker& local = bt.cast<DistanceFieldPathBatchTracker>();
4478fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        uint32_t key = dfTexEffect.getFlags();
4488fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        key |= local.fInputColorType << 16;
44946d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0;
45046d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= ComputePosKey(gp.viewMatrix()) << 25;
4518fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        b->add32(key);
452fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
453fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
454fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthprivate:
4559b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    UniformHandle fColorUniform;
456e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed    UniformHandle fTextureSizeUni;
4579b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrColor       fColor;
4589b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    SkISize       fTextureSize;
459fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
460fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    typedef GrGLGeometryProcessor INHERITED;
461fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth};
462fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
463fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth///////////////////////////////////////////////////////////////////////////////
464fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
465502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(
4662e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        GrColor color,
4678059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt        const SkMatrix& viewMatrix,
4682e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        GrTexture* texture,
4692e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        const GrTextureParams& params,
47056995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt        uint32_t flags,
47156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt        bool opaqueVertexColors)
4728059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt    : INHERITED(color, viewMatrix, SkMatrix::I(), opaqueVertexColors)
4732e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    , fTextureAccess(texture, params)
474fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
4752dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    , fInColor(NULL) {
476fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
477502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    this->initClassID<GrDistanceFieldPathGeoProc>();
47871c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
4792dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    if (flags & kColorAttr_DistanceFieldEffectFlag) {
48071c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt        fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
4812dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        this->setHasVertexColor();
4822dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    }
48371c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
484e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                                                          kVec2f_GrVertexAttribType));
485fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    this->addTextureAccess(&fTextureAccess);
486fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
487fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
488502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldPathGeoProc::onIsEqual(const GrGeometryProcessor& other) const {
489502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const GrDistanceFieldPathGeoProc& cte = other.cast<GrDistanceFieldPathGeoProc>();
490420d7e9a79358908850c74192b4949375563449absalomon    return fFlags == cte.fFlags;
491fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
492fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
493502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldPathGeoProc::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
49456995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    out->setUnknownSingleComponent();
495fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
496fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
497502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldPathGeoProc::getGLProcessorKey(const GrBatchTracker& bt,
498502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   const GrGLCaps& caps,
499502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   GrProcessorKeyBuilder* b) const {
500502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldPathGeoProc::GenKey(*this, bt, caps, b);
501eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
502eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
503abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualittGrGLPrimitiveProcessor*
504502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldPathGeoProc::createGLInstance(const GrBatchTracker& bt, const GrGLCaps&) const {
505502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return SkNEW_ARGS(GrGLDistanceFieldPathGeoProc, (*this, bt));
506fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
507fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
508502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldPathGeoProc::initBatchTracker(GrBatchTracker* bt,
509502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                  const GrPipelineInfo& init) const {
510502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    DistanceFieldPathBatchTracker* local = bt->cast<DistanceFieldPathBatchTracker>();
5119b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
5129b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                               SkToBool(fInColor));
513290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    local->fUsesLocalCoords = init.fUsesLocalCoords;
5149b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
5159b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
516502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldPathGeoProc::onCanMakeEqual(const GrBatchTracker& m,
517502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                const GrGeometryProcessor& that,
518502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                const GrBatchTracker& t) const {
519502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const DistanceFieldPathBatchTracker& mine = m.cast<DistanceFieldPathBatchTracker>();
520502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const DistanceFieldPathBatchTracker& theirs = t.cast<DistanceFieldPathBatchTracker>();
521290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
522290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                                   that, theirs.fUsesLocalCoords) &&
523290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt           CanCombineOutput(mine.fInputColorType, mine.fColor,
5249b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                            theirs.fInputColorType, theirs.fColor);
5259b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
5269b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
527fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth///////////////////////////////////////////////////////////////////////////////
528fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
529502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc);
530fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
531502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(SkRandom* random,
532502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                            GrContext*,
533502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                            const GrDrawTargetCaps&,
534502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                            GrTexture* textures[]) {
535fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
536fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                    : GrProcessorUnitTest::kAlphaTextureIdx;
537fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    static const SkShader::TileMode kTileModes[] = {
538fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkShader::kClamp_TileMode,
539fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkShader::kRepeat_TileMode,
540fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkShader::kMirror_TileMode,
541fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    };
542fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    SkShader::TileMode tileModes[] = {
543fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
544fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
545fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    };
546fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode
547fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                                         : GrTextureParams::kNone_FilterMode);
548fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
549502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return GrDistanceFieldPathGeoProc::Create(GrRandomColor(random),
550502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                              GrProcessorUnitTest::TestMatrix(random),
551502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                              textures[texIdx],
552502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                              params,
55356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt        random->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0, random->nextBool());
554fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
555fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
556fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth///////////////////////////////////////////////////////////////////////////////
557fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
5589b98932adaceb7ad0a617ade16616923f6bffe84joshualittstruct DistanceFieldLCDBatchTracker {
5599b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrGPInput fInputColorType;
5609b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrColor fColor;
561290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    bool fUsesLocalCoords;
5629b98932adaceb7ad0a617ade16616923f6bffe84joshualitt};
5639b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
564502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldLCDTextGeoProc : public GrGLGeometryProcessor {
565609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgpublic:
566502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldLCDTextGeoProc(const GrGeometryProcessor&, const GrBatchTracker&)
56721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        : fColor(GrColor_ILLEGAL) {
568502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
56921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    }
570609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
57136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
572502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldLCDTextGeoProc& dfTexEffect =
573502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                args.fGP.cast<GrDistanceFieldLCDTextGeoProc>();
5749b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldLCDBatchTracker& local = args.fBT.cast<DistanceFieldLCDBatchTracker>();
5759b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrGLGPBuilder* pb = args.fPB;
576609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
5772dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
578abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
579abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit attributes
580abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        vsBuilder->emitAttributes(dfTexEffect);
581abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
5829b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        // setup pass through color
5839b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
5849b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                    &fColorUniform);
5859b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
586abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // Setup position
587dd2198701b0ec9da61ecf73418cad03642d715e7joshualitt        this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix());
5884973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt
589abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit transforms
590bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        const SkMatrix& localMatrix = dfTexEffect.localMatrix();
59146d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName,
592bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                             localMatrix, args.fTransformsIn, args.fTransformsOut);
5935b143038cb47763974d2750ed78d436eb6c38beajvanverth
594bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // set up varyings
595bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
596bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag recipScale(kFloat_GrSLType);
597bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag st(kVec2f_GrSLType);
598bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        const char* viewMatrixName = this->uViewM();
599bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // view matrix name is NULL if identity matrix
600bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        bool useInverseScale = !localMatrix.isIdentity() && viewMatrixName;
601bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        if (isUniformScale && useInverseScale) {
602bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            args.fPB->addVarying("RecipScale", &recipScale, kHigh_GrSLPrecision);
603bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            vsBuilder->codeAppendf("vec2 tx = vec2(%s[0][0], %s[1][0]);",
604bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                                   viewMatrixName, viewMatrixName);
605bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            vsBuilder->codeAppend("float tx2 = dot(tx, tx);");
606bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            vsBuilder->codeAppendf("%s = inversesqrt(tx2);", recipScale.vsOut());
607bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        } else {
608bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
609bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
610bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        }
611bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
612bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag uv(kVec2f_GrSLType);
613bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
614bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // this is only used with text, so our texture bounds always match the glyph atlas
615bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
616bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                               GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
617bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                               dfTexEffect.inTextureCoords()->fName);
618bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
619bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // add frag shader code
620c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
62130ba436f04e61d4505fb854d5fc56079636e0788joshualitt
62230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        SkAssertResult(fsBuilder->enableFeature(
62330ba436f04e61d4505fb854d5fc56079636e0788joshualitt                GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
62430ba436f04e61d4505fb854d5fc56079636e0788joshualitt
625609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // create LCD offset adjusted by inverse of transform
626fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        // Use highp to work around aliasing issues
627fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
628fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
6295a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn());
630fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
631fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
6325a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
6335a105ff05303ac82a867b8b84a1edd145bd46218jvanverth            fsBuilder->codeAppend("float delta = -" GR_FONT_ATLAS_LCD_DELTA ";\n");
6345a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        } else {
6355a105ff05303ac82a867b8b84a1edd145bd46218jvanverth            fsBuilder->codeAppend("float delta = " GR_FONT_ATLAS_LCD_DELTA ";\n");
6365a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        }
63778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (isUniformScale) {
638bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            if (useInverseScale) {
639bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                fsBuilder->codeAppendf("float dx = %s;", recipScale.fsIn());
640bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            } else {
641bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                fsBuilder->codeAppendf("float dx = dFdx(%s.x);", st.fsIn());
642bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            }
643bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppend("vec2 offset = vec2(dx*delta, 0.0);");
644609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        } else {
645bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn());
646bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
647bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
648bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
649bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppend("vec2 offset = delta*Jdx;");
650609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
651609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
652609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // green is distance to uv center
65330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 texColor = ");
654c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0], "uv", kVec2f_GrSLType);
65530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
65630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec3 distance;\n");
65730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.y = texColor.r;\n");
658609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // red is distance to left offset
65930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n");
66030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\ttexColor = ");
661c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
66230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
66330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.x = texColor.r;\n");
664609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // blue is distance to right offset
66530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
66630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\ttexColor = ");
667c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
66830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
66930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.z = texColor.r;\n");
6702d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
67130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance = "
672ada68ef2dc986478288a8b8ad867fd3aca431162jvanverth           "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
6732d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
67421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        // adjust width based on gamma
67521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        const char* distanceAdjustUniName = NULL;
67621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
67721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            kVec3f_GrSLType, kDefault_GrSLPrecision,
67821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            "DistanceAdjust", &distanceAdjustUniName);
67921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
68021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth
681609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // To be strictly correct, we should compute the anti-aliasing factor separately
682609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // for each color component. However, this is only important when using perspective
683609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // transformations, and even then using a single factor seems like a reasonable
684609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // trade-off between quality and speed.
685354eba5cb61801130a84378356434d3cc0a4b71ajvanverth        fsBuilder->codeAppend("float afwidth;");
68678f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (isUniformScale) {
687354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For uniform scale, we adjust for the effect of the transformation on the distance
688354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // by using the length of the gradient of the texture coordinates. We use st coordinates
689354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // to ensure we're mapping 1:1 from texel space to pixel space.
690354eba5cb61801130a84378356434d3cc0a4b71ajvanverth
691609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
692354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dx);");
693609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        } else {
694354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For general transforms, to determine the amount of correction we multiply a unit
695354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // vector pointing along the SDF gradient direction by the Jacobian of the st coords
696354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // (which is the inverse transform for this fragment) and take the length of the result.
697354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(distance.r));");
698d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // the length of the gradient may be 0, so we need to check for this
699d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // this also compensates for the Adreno, which likes to drop tiles on division by 0
700d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
701d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
702d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
703d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("} else {");
704d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
705d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("}");
706354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
707354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
708609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
709609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
710354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
711609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
712609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
71321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        fsBuilder->codeAppend(
71421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                      "vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
71530ba436f04e61d4505fb854d5fc56079636e0788joshualitt
7162dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
717609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
718609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
7197510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager& pdman,
7209b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                         const GrPrimitiveProcessor& processor,
72136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                         const GrBatchTracker& bt) override {
72221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        SkASSERT(fDistanceAdjustUni.isValid());
723609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
724502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldLCDTextGeoProc& dfTexEffect =
725502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                processor.cast<GrDistanceFieldLCDTextGeoProc>();
726502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        GrDistanceFieldLCDTextGeoProc::DistanceAdjust wa = dfTexEffect.getDistanceAdjust();
72721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        if (wa != fDistanceAdjust) {
72821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            pdman.set3f(fDistanceAdjustUni,
72921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                        wa.fR,
73021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                        wa.fG,
73121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                        wa.fB);
73221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            fDistanceAdjust = wa;
7332d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        }
7349b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
735ee2af95db72152dfa61c841875df0594ca93437djoshualitt        this->setUniformViewMatrix(pdman, processor.viewMatrix());
736ee2af95db72152dfa61c841875df0594ca93437djoshualitt
7379b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>();
7389b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
7399b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLfloat c[4];
7409b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrColorToRGBAFloat(local.fColor, c);
7419b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            pdman.set4fv(fColorUniform, 1, c);
7429b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            fColor = local.fColor;
7439b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
744609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
745609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
74646d36f0e7b709a077c647841eee23bd3efdc4117robertphillips    static inline void GenKey(const GrGeometryProcessor& gp,
7479b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                              const GrBatchTracker& bt,
74887f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                              const GrGLCaps&,
749b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                              GrProcessorKeyBuilder* b) {
750502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>();
751609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
7529b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>();
7538fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        uint32_t key = dfTexEffect.getFlags();
7548fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        key |= local.fInputColorType << 16;
75546d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0;
75646d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= ComputePosKey(gp.viewMatrix()) << 25;
757bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        key |= (!gp.viewMatrix().isIdentity() && !gp.localMatrix().isIdentity()) ? 0x1 << 27 : 0x0;
7588fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        b->add32(key);
759609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
760609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
761609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgprivate:
76221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    GrColor                                      fColor;
76321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    UniformHandle                                fColorUniform;
764502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust;
76521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    UniformHandle                                fDistanceAdjustUni;
766609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
767249af15fb82833d2274850c589812b6e69df0033joshualitt    typedef GrGLGeometryProcessor INHERITED;
768609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org};
769609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
770609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
771609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
772502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
7738059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                                  GrColor color, const SkMatrix& viewMatrix,
774bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                                                  const SkMatrix& localMatrix,
7752d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                  GrTexture* texture, const GrTextureParams& params,
77621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                                                  DistanceAdjust distanceAdjust,
77778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                  uint32_t flags)
778bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth    : INHERITED(color, viewMatrix, localMatrix)
7792e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    , fTextureAccess(texture, params)
78021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    , fDistanceAdjust(distanceAdjust)
7812dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    , fFlags(flags & kLCD_DistanceFieldEffectMask){
78278f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
783502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    this->initClassID<GrDistanceFieldLCDTextGeoProc>();
78471c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
78571c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
7865a105ff05303ac82a867b8b84a1edd145bd46218jvanverth                                                          kVec2s_GrVertexAttribType));
787609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    this->addTextureAccess(&fTextureAccess);
788609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
789609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
790502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldLCDTextGeoProc::onIsEqual(const GrGeometryProcessor& other) const {
791502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const GrDistanceFieldLCDTextGeoProc& cte = other.cast<GrDistanceFieldLCDTextGeoProc>();
79221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    return (fDistanceAdjust == cte.fDistanceAdjust &&
79378f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth            fFlags == cte.fFlags);
794609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
795609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
796502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldLCDTextGeoProc::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
79756995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    out->setUnknownFourComponents();
79856995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    out->setUsingLCDCoverage();
799609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
800609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
801502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldLCDTextGeoProc::getGLProcessorKey(const GrBatchTracker& bt,
802502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                      const GrGLCaps& caps,
803502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                      GrProcessorKeyBuilder* b) const {
804502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldLCDTextGeoProc::GenKey(*this, bt, caps, b);
805eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
806eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
807abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualittGrGLPrimitiveProcessor*
808502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldLCDTextGeoProc::createGLInstance(const GrBatchTracker& bt,
809502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                const GrGLCaps&) const {
810502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return SkNEW_ARGS(GrGLDistanceFieldLCDTextGeoProc, (*this, bt));
811609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
812609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
813502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldLCDTextGeoProc::initBatchTracker(GrBatchTracker* bt,
814502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                     const GrPipelineInfo& init) const {
8159b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    DistanceFieldLCDBatchTracker* local = bt->cast<DistanceFieldLCDBatchTracker>();
8169b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
817290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    local->fUsesLocalCoords = init.fUsesLocalCoords;
8189b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
8199b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
820502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldLCDTextGeoProc::onCanMakeEqual(const GrBatchTracker& m,
821502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   const GrGeometryProcessor& that,
822502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   const GrBatchTracker& t) const {
8239b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    const DistanceFieldLCDBatchTracker& mine = m.cast<DistanceFieldLCDBatchTracker>();
8249b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    const DistanceFieldLCDBatchTracker& theirs = t.cast<DistanceFieldLCDBatchTracker>();
825290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
826290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                                   that, theirs.fUsesLocalCoords) &&
827290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt           CanCombineOutput(mine.fInputColorType, mine.fColor,
8289b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                            theirs.fInputColorType, theirs.fColor);
8299b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
8309b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
831609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
832609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
833502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc);
834609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
835502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrGeometryProcessor* GrDistanceFieldLCDTextGeoProc::TestCreate(SkRandom* random,
836b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                                 GrContext*,
837b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                                 const GrDrawTargetCaps&,
838b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                                 GrTexture* textures[]) {
839b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
840b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                      GrProcessorUnitTest::kAlphaTextureIdx;
841609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    static const SkShader::TileMode kTileModes[] = {
842609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kClamp_TileMode,
843609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kRepeat_TileMode,
844609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kMirror_TileMode,
845609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    };
846609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    SkShader::TileMode tileModes[] = {
847609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
848609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
849609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    };
850609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
851609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                           GrTextureParams::kNone_FilterMode);
85221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    DistanceAdjust wa = { 0.0f, 0.1f, -0.1f };
85378f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
85478f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
85578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
856502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(random),
857502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                 GrProcessorUnitTest::TestMatrix(random),
858502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                 GrProcessorUnitTest::TestMatrix(random),
859502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                 textures[texIdx], params,
860502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                 wa,
861502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                 flags);
862d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
863