GrDistanceFieldGeoProc.cpp revision cfc18867d982119d9dc2888bf09f1093012daadd
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);
79221360a514fb4bfff5b461e83262306b2a0f36afjvanverth        args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
80221360a514fb4bfff5b461e83262306b2a0f36afjvanverth        vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
81bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
82bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag uv(kVec2f_GrSLType);
83bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
84bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // this is only used with text, so our texture bounds always match the glyph atlas
85bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
86bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                               GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
87bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                               dfTexEffect.inTextureCoords()->fName);
88bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
89fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        // Use highp to work around aliasing issues
90fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
91fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
925a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn());
93fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth
94fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend("\tfloat texColor = ");
95c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0],
96fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                       "uv",
97d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                       kVec2f_GrSLType);
98fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(".r;\n");
9930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat distance = "
100fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                       SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
10121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
10221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        // adjust width based on gamma
10321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
10421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#endif
1056c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
106354eba5cb61801130a84378356434d3cc0a4b71ajvanverth        fsBuilder->codeAppend("float afwidth;");
107bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        if (isSimilarity) {
108354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For uniform scale, we adjust for the effect of the transformation on the distance
109354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // by using the length of the gradient of the texture coordinates. We use st coordinates
110221360a514fb4bfff5b461e83262306b2a0f36afjvanverth            // to ensure we're mapping 1:1 from texel space to pixel space.
111354eba5cb61801130a84378356434d3cc0a4b71ajvanverth
1124362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
113221360a514fb4bfff5b461e83262306b2a0f36afjvanverth            // we use y to work around a Mali400 bug in the x direction
114221360a514fb4bfff5b461e83262306b2a0f36afjvanverth            fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(%s.y));",
115bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                                       st.fsIn());
1164362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        } else {
117354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For general transforms, to determine the amount of correction we multiply a unit
118354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // vector pointing along the SDF gradient direction by the Jacobian of the st coords
119354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // (which is the inverse transform for this fragment) and take the length of the result.
120354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
121d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // the length of the gradient may be 0, so we need to check for this
122d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // this also compensates for the Adreno, which likes to drop tiles on division by 0
123d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
124d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
125d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
126d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("} else {");
127d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
128d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("}");
129d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth
130bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppendf("vec2 Jdx = dFdx(%s);", st.fsIn());
131bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppendf("vec2 Jdy = dFdy(%s);", st.fsIn());
132354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
133354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
1344362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
1354362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
136354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
1374362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        }
138354eba5cb61801130a84378356434d3cc0a4b71ajvanverth        fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
1394d517fdbb145cb95e5e935470df331e1b6667cfcjvanverth
1402dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
141d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    }
142d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
1437510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager& pdman,
1449b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                         const GrPrimitiveProcessor& proc,
14536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                         const GrBatchTracker& bt) override {
1462d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
147502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>();
14821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        float distanceAdjust = dfTexEffect.getDistanceAdjust();
14921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        if (distanceAdjust != fDistanceAdjust) {
15021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            pdman.set1f(fDistanceAdjustUni, distanceAdjust);
15121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            fDistanceAdjust = distanceAdjust;
1522d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        }
1532d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
1549b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
155ee2af95db72152dfa61c841875df0594ca93437djoshualitt        this->setUniformViewMatrix(pdman, proc.viewMatrix());
156ee2af95db72152dfa61c841875df0594ca93437djoshualitt
1579b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>();
1589b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
1599b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLfloat c[4];
1609b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrColorToRGBAFloat(local.fColor, c);
1619b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            pdman.set4fv(fColorUniform, 1, c);
1629b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            fColor = local.fColor;
1639b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
1646c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org    }
165d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
16646d36f0e7b709a077c647841eee23bd3efdc4117robertphillips    static inline void GenKey(const GrGeometryProcessor& gp,
1679b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                              const GrBatchTracker& bt,
168cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                              const GrGLSLCaps&,
169b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                              GrProcessorKeyBuilder* b) {
170502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>();
1719b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>();
1728fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        uint32_t key = dfTexEffect.getFlags();
1738fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        key |= local.fInputColorType << 16;
17446d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0;
17546d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= ComputePosKey(gp.viewMatrix()) << 25;
1768fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        b->add32(key);
1774362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org    }
1784362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
179d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comprivate:
1809b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrColor       fColor;
1819b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    UniformHandle fColorUniform;
18250282b4390dcddcf3b1d51631c0133045ae1f233mtklein#ifdef SK_GAMMA_APPLY_TO_A8
18321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    float         fDistanceAdjust;
18421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    UniformHandle fDistanceAdjustUni;
18550282b4390dcddcf3b1d51631c0133045ae1f233mtklein#endif
1866c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
187249af15fb82833d2274850c589812b6e69df0033joshualitt    typedef GrGLGeometryProcessor INHERITED;
188d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com};
189d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
190d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com///////////////////////////////////////////////////////////////////////////////
191d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
192502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrColor color,
1938059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                                           const SkMatrix& viewMatrix,
1942e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt                                                           GrTexture* texture,
1956c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org                                                           const GrTextureParams& params,
1962d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
19721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                                                           float distanceAdjust,
1982d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
19956995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt                                                           uint32_t flags, bool opaqueVertexColors)
200221360a514fb4bfff5b461e83262306b2a0f36afjvanverth    : INHERITED(color, viewMatrix, SkMatrix::I(), opaqueVertexColors)
2012e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    , fTextureAccess(texture, params)
2022d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
20321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    , fDistanceAdjust(distanceAdjust)
2042d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
205249af15fb82833d2274850c589812b6e69df0033joshualitt    , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
2062dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    , fInColor(NULL) {
20778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
208502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    this->initClassID<GrDistanceFieldA8TextGeoProc>();
20971c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
2102dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    if (flags & kColorAttr_DistanceFieldEffectFlag) {
21171c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt        fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
2122dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        this->setHasVertexColor();
2132dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    }
21471c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
2155a105ff05303ac82a867b8b84a1edd145bd46218jvanverth                                                          kVec2s_GrVertexAttribType));
216d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    this->addTextureAccess(&fTextureAccess);
217d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
218d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
219502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldA8TextGeoProc::onIsEqual(const GrGeometryProcessor& other) const {
220502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const GrDistanceFieldA8TextGeoProc& cte = other.cast<GrDistanceFieldA8TextGeoProc>();
221420d7e9a79358908850c74192b4949375563449absalomon    return
22278f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth#ifdef SK_GAMMA_APPLY_TO_A8
22321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth           fDistanceAdjust == cte.fDistanceAdjust &&
22478f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth#endif
22578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth           fFlags == cte.fFlags;
226d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
227d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
228502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldA8TextGeoProc::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
22956995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    out->setUnknownSingleComponent();
230d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
231d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
232502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldA8TextGeoProc::getGLProcessorKey(const GrBatchTracker& bt,
233cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                                                     const GrGLSLCaps& caps,
234eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                                     GrProcessorKeyBuilder* b) const {
235502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldA8TextGeoProc::GenKey(*this, bt, caps, b);
236eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
237eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
238abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualittGrGLPrimitiveProcessor*
239502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldA8TextGeoProc::createGLInstance(const GrBatchTracker& bt,
240cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                                               const GrGLSLCaps&) const {
241502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return SkNEW_ARGS(GrGLDistanceFieldA8TextGeoProc, (*this, bt));
242d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
243d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
244502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldA8TextGeoProc::initBatchTracker(GrBatchTracker* bt,
24521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                                                    const GrPipelineInfo& init) const {
2469b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    DistanceFieldBatchTracker* local = bt->cast<DistanceFieldBatchTracker>();
2479b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
2489b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                               SkToBool(fInColor));
249290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    local->fUsesLocalCoords = init.fUsesLocalCoords;
2509b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
2519b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
252502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldA8TextGeoProc::onCanMakeEqual(const GrBatchTracker& m,
253290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                                                  const GrGeometryProcessor& that,
2549b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                                  const GrBatchTracker& t) const {
2559b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    const DistanceFieldBatchTracker& mine = m.cast<DistanceFieldBatchTracker>();
2569b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    const DistanceFieldBatchTracker& theirs = t.cast<DistanceFieldBatchTracker>();
257290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
258290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                                   that, theirs.fUsesLocalCoords) &&
259290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt           CanCombineOutput(mine.fInputColorType, mine.fColor,
2609b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                            theirs.fInputColorType, theirs.fColor);
2619b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
2629b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
263d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com///////////////////////////////////////////////////////////////////////////////
264d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
265502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldA8TextGeoProc);
266d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
267502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrGeometryProcessor* GrDistanceFieldA8TextGeoProc::TestCreate(SkRandom* random,
268b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                              GrContext*,
269b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                              const GrDrawTargetCaps&,
270b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                              GrTexture* textures[]) {
271b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
272b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                      GrProcessorUnitTest::kAlphaTextureIdx;
273d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    static const SkShader::TileMode kTileModes[] = {
274d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kClamp_TileMode,
275d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kRepeat_TileMode,
276d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kMirror_TileMode,
277d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    };
278d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    SkShader::TileMode tileModes[] = {
279d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
280d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
281d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    };
282d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
283d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                                           GrTextureParams::kNone_FilterMode);
284d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
285502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return GrDistanceFieldA8TextGeoProc::Create(GrRandomColor(random),
2868059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                                GrProcessorUnitTest::TestMatrix(random),
2878059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                                textures[texIdx], params,
2882d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
2892d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                random->nextF(),
2902d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
29178f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                random->nextBool() ?
29256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt                                                    kSimilarity_DistanceFieldEffectFlag : 0,
29356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt                                                random->nextBool());
294609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
295609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
296609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
297609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
298502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthstruct DistanceFieldPathBatchTracker {
2999b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrGPInput fInputColorType;
3009b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrColor fColor;
301290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    bool fUsesLocalCoords;
3029b98932adaceb7ad0a617ade16616923f6bffe84joshualitt};
3039b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
304502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldPathGeoProc : public GrGLGeometryProcessor {
305fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthpublic:
306502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldPathGeoProc(const GrGeometryProcessor&,
30787f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                                          const GrBatchTracker&)
308e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        : fColor(GrColor_ILLEGAL), fTextureSize(SkISize::Make(-1, -1)) {}
309fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
31036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
311502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>();
312fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
313502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const DistanceFieldPathBatchTracker& local = args.fBT.cast<DistanceFieldPathBatchTracker>();
3149b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrGLGPBuilder* pb = args.fPB;
315c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
316fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkAssertResult(fsBuilder->enableFeature(
317fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                     GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
318fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
3192dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
320abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
321abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit attributes
322abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        vsBuilder->emitAttributes(dfTexEffect);
323abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
324e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        GrGLVertToFrag v(kVec2f_GrSLType);
3259671ecd44e48e8bbe1361830717b79c9c4dc9d17jvanverth        args.fPB->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
326fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
3279b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        // setup pass through color
3289b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor,
3299b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                    dfTexEffect.inColor(), &fColorUniform);
3302dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
331e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
332e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed
333abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // Setup position
334dd2198701b0ec9da61ecf73418cad03642d715e7joshualitt        this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix());
335abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
336abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit transforms
33746d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName,
338abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt                             dfTexEffect.localMatrix(), args.fTransformsIn, args.fTransformsOut);
3394973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt
340e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        const char* textureSizeUniName = NULL;
341e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
342e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                                              kVec2f_GrSLType, kDefault_GrSLPrecision,
343e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                                              "TextureSize", &textureSizeUniName);
344e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed
345fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        // Use highp to work around aliasing issues
346fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
347fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
348e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn());
349fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth
350fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend("float texColor = ");
351c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0],
352fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                       "uv",
353fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                       kVec2f_GrSLType);
354fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(".r;");
355fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("float distance = "
356fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth            SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
357fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
358fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
359fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
360e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName);
361fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("float afwidth;");
362fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
363354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For uniform scale, we adjust for the effect of the transformation on the distance
364354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // by using the length of the gradient of the texture coordinates. We use st coordinates
365354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // to ensure we're mapping 1:1 from texel space to pixel space.
366354eba5cb61801130a84378356434d3cc0a4b71ajvanverth
367fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            // this gives us a smooth step across approximately one fragment
368bc0273524b039c45dcea2c1ab5ab379c75486c07jvanverth            fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(st.y));");
369fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        } else {
370354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For general transforms, to determine the amount of correction we multiply a unit
371354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // vector pointing along the SDF gradient direction by the Jacobian of the st coords
372354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // (which is the inverse transform for this fragment) and take the length of the result.
373354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
374d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // the length of the gradient may be 0, so we need to check for this
375d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // this also compensates for the Adreno, which likes to drop tiles on division by 0
376d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
377d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
378d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
379d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("} else {");
380d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
381d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("}");
382d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth
383354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
384354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
385354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
386354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
387fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
388fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            // this gives us a smooth step across approximately one fragment
389fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
390fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        }
391fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
392fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
3932dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
394fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
395fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
396fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    virtual void setData(const GrGLProgramDataManager& pdman,
3979b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                         const GrPrimitiveProcessor& proc,
39836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                         const GrBatchTracker& bt) override {
399e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed        SkASSERT(fTextureSizeUni.isValid());
400fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
40187f48d997ec29e5eeaa7567355775e93465dd60djoshualitt        GrTexture* texture = proc.texture(0);
402fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        if (texture->width() != fTextureSize.width() ||
403fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            texture->height() != fTextureSize.height()) {
404fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fTextureSize = SkISize::Make(texture->width(), texture->height());
405e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed            pdman.set2f(fTextureSizeUni,
406e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                        SkIntToScalar(fTextureSize.width()),
407e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                        SkIntToScalar(fTextureSize.height()));
408fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        }
4099b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
410ee2af95db72152dfa61c841875df0594ca93437djoshualitt        this->setUniformViewMatrix(pdman, proc.viewMatrix());
411ee2af95db72152dfa61c841875df0594ca93437djoshualitt
412502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const DistanceFieldPathBatchTracker& local = bt.cast<DistanceFieldPathBatchTracker>();
4139b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
4149b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLfloat c[4];
4159b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrColorToRGBAFloat(local.fColor, c);
4169b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            pdman.set4fv(fColorUniform, 1, c);
4179b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            fColor = local.fColor;
4189b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
419fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
420fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
42146d36f0e7b709a077c647841eee23bd3efdc4117robertphillips    static inline void GenKey(const GrGeometryProcessor& gp,
4229b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                              const GrBatchTracker& bt,
423cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                              const GrGLSLCaps&,
424fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                              GrProcessorKeyBuilder* b) {
425502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>();
426fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
427502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const DistanceFieldPathBatchTracker& local = bt.cast<DistanceFieldPathBatchTracker>();
4288fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        uint32_t key = dfTexEffect.getFlags();
4298fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        key |= local.fInputColorType << 16;
43046d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0;
43146d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= ComputePosKey(gp.viewMatrix()) << 25;
4328fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        b->add32(key);
433fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
434fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
435fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthprivate:
4369b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    UniformHandle fColorUniform;
437e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed    UniformHandle fTextureSizeUni;
4389b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrColor       fColor;
4399b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    SkISize       fTextureSize;
440fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
441fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    typedef GrGLGeometryProcessor INHERITED;
442fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth};
443fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
444fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth///////////////////////////////////////////////////////////////////////////////
445fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
446502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(
4472e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        GrColor color,
4488059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt        const SkMatrix& viewMatrix,
4492e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        GrTexture* texture,
4502e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        const GrTextureParams& params,
45156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt        uint32_t flags,
45256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt        bool opaqueVertexColors)
4538059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt    : INHERITED(color, viewMatrix, SkMatrix::I(), opaqueVertexColors)
4542e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    , fTextureAccess(texture, params)
455fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
4562dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    , fInColor(NULL) {
457fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
458502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    this->initClassID<GrDistanceFieldPathGeoProc>();
45971c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
4602dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    if (flags & kColorAttr_DistanceFieldEffectFlag) {
46171c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt        fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
4622dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        this->setHasVertexColor();
4632dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    }
46471c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
465e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed                                                          kVec2f_GrVertexAttribType));
466fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    this->addTextureAccess(&fTextureAccess);
467fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
468fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
469502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldPathGeoProc::onIsEqual(const GrGeometryProcessor& other) const {
470502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const GrDistanceFieldPathGeoProc& cte = other.cast<GrDistanceFieldPathGeoProc>();
471420d7e9a79358908850c74192b4949375563449absalomon    return fFlags == cte.fFlags;
472fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
473fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
474502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldPathGeoProc::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
47556995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    out->setUnknownSingleComponent();
476fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
477fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
478502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldPathGeoProc::getGLProcessorKey(const GrBatchTracker& bt,
479cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                                                   const GrGLSLCaps& caps,
480502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   GrProcessorKeyBuilder* b) const {
481502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldPathGeoProc::GenKey(*this, bt, caps, b);
482eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
483eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
484abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualittGrGLPrimitiveProcessor*
485cfc18867d982119d9dc2888bf09f1093012daaddjvanverthGrDistanceFieldPathGeoProc::createGLInstance(const GrBatchTracker& bt, const GrGLSLCaps&) const {
486502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return SkNEW_ARGS(GrGLDistanceFieldPathGeoProc, (*this, bt));
487fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
488fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
489502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldPathGeoProc::initBatchTracker(GrBatchTracker* bt,
490502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                  const GrPipelineInfo& init) const {
491502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    DistanceFieldPathBatchTracker* local = bt->cast<DistanceFieldPathBatchTracker>();
4929b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
4939b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                               SkToBool(fInColor));
494290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    local->fUsesLocalCoords = init.fUsesLocalCoords;
4959b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
4969b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
497502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldPathGeoProc::onCanMakeEqual(const GrBatchTracker& m,
498502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                const GrGeometryProcessor& that,
499502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                const GrBatchTracker& t) const {
500502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const DistanceFieldPathBatchTracker& mine = m.cast<DistanceFieldPathBatchTracker>();
501502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const DistanceFieldPathBatchTracker& theirs = t.cast<DistanceFieldPathBatchTracker>();
502290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
503290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                                   that, theirs.fUsesLocalCoords) &&
504290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt           CanCombineOutput(mine.fInputColorType, mine.fColor,
5059b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                            theirs.fInputColorType, theirs.fColor);
5069b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
5079b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
508fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth///////////////////////////////////////////////////////////////////////////////
509fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
510502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc);
511fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
512502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(SkRandom* random,
513502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                            GrContext*,
514502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                            const GrDrawTargetCaps&,
515502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                            GrTexture* textures[]) {
516fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
517fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                    : GrProcessorUnitTest::kAlphaTextureIdx;
518fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    static const SkShader::TileMode kTileModes[] = {
519fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkShader::kClamp_TileMode,
520fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkShader::kRepeat_TileMode,
521fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkShader::kMirror_TileMode,
522fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    };
523fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    SkShader::TileMode tileModes[] = {
524fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
525fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
526fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    };
527fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode
528fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                                         : GrTextureParams::kNone_FilterMode);
529fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
530502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return GrDistanceFieldPathGeoProc::Create(GrRandomColor(random),
531502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                              GrProcessorUnitTest::TestMatrix(random),
532502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                              textures[texIdx],
533502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                              params,
53456995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt        random->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0, random->nextBool());
535fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
536fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
537fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth///////////////////////////////////////////////////////////////////////////////
538fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
5399b98932adaceb7ad0a617ade16616923f6bffe84joshualittstruct DistanceFieldLCDBatchTracker {
5409b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrGPInput fInputColorType;
5419b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    GrColor fColor;
542290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    bool fUsesLocalCoords;
5439b98932adaceb7ad0a617ade16616923f6bffe84joshualitt};
5449b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
545502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldLCDTextGeoProc : public GrGLGeometryProcessor {
546609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgpublic:
547502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldLCDTextGeoProc(const GrGeometryProcessor&, const GrBatchTracker&)
54821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        : fColor(GrColor_ILLEGAL) {
549502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
55021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    }
551609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
55236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
553502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldLCDTextGeoProc& dfTexEffect =
554502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                args.fGP.cast<GrDistanceFieldLCDTextGeoProc>();
5559b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldLCDBatchTracker& local = args.fBT.cast<DistanceFieldLCDBatchTracker>();
5569b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrGLGPBuilder* pb = args.fPB;
557609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
5582dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
559abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
560abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit attributes
561abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        vsBuilder->emitAttributes(dfTexEffect);
562abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
5639b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        // setup pass through color
5649b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
5659b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                    &fColorUniform);
5669b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
567abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // Setup position
568dd2198701b0ec9da61ecf73418cad03642d715e7joshualitt        this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix());
5694973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt
570abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        // emit transforms
571bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        const SkMatrix& localMatrix = dfTexEffect.localMatrix();
57246d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName,
573bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                             localMatrix, args.fTransformsIn, args.fTransformsOut);
5745b143038cb47763974d2750ed78d436eb6c38beajvanverth
575bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // set up varyings
576bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
577bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag recipScale(kFloat_GrSLType);
578bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag st(kVec2f_GrSLType);
579221360a514fb4bfff5b461e83262306b2a0f36afjvanverth        args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
580221360a514fb4bfff5b461e83262306b2a0f36afjvanverth        vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
581bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
582bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        GrGLVertToFrag uv(kVec2f_GrSLType);
583bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
584bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // this is only used with text, so our texture bounds always match the glyph atlas
585bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
586bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                               GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
587bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth                               dfTexEffect.inTextureCoords()->fName);
588bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
589bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth        // add frag shader code
590c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
59130ba436f04e61d4505fb854d5fc56079636e0788joshualitt
59230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        SkAssertResult(fsBuilder->enableFeature(
59330ba436f04e61d4505fb854d5fc56079636e0788joshualitt                GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
59430ba436f04e61d4505fb854d5fc56079636e0788joshualitt
595609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // create LCD offset adjusted by inverse of transform
596fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        // Use highp to work around aliasing issues
597fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
598fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
5995a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn());
600fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth        fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
601fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth                                                             pb->ctxInfo().standard()));
6025a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
6035a105ff05303ac82a867b8b84a1edd145bd46218jvanverth            fsBuilder->codeAppend("float delta = -" GR_FONT_ATLAS_LCD_DELTA ";\n");
6045a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        } else {
6055a105ff05303ac82a867b8b84a1edd145bd46218jvanverth            fsBuilder->codeAppend("float delta = " GR_FONT_ATLAS_LCD_DELTA ";\n");
6065a105ff05303ac82a867b8b84a1edd145bd46218jvanverth        }
60778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (isUniformScale) {
608bc0273524b039c45dcea2c1ab5ab379c75486c07jvanverth            fsBuilder->codeAppendf("float dy = abs(dFdy(%s.y));", st.fsIn());
609221360a514fb4bfff5b461e83262306b2a0f36afjvanverth            fsBuilder->codeAppend("vec2 offset = vec2(dy*delta, 0.0);");
610609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        } else {
611bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn());
612bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth
613bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
614bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
615bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth            fsBuilder->codeAppend("vec2 offset = delta*Jdx;");
616609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
617609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
618609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // green is distance to uv center
61930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 texColor = ");
620c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0], "uv", kVec2f_GrSLType);
62130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
62230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec3 distance;\n");
62330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.y = texColor.r;\n");
624609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // red is distance to left offset
62530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n");
62630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\ttexColor = ");
627c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
62830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
62930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.x = texColor.r;\n");
630609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // blue is distance to right offset
63130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
63230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\ttexColor = ");
633c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
63430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
63530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.z = texColor.r;\n");
6362d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
63730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance = "
638ada68ef2dc986478288a8b8ad867fd3aca431162jvanverth           "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
6392d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
64021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        // adjust width based on gamma
64121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        const char* distanceAdjustUniName = NULL;
64221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
64321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            kVec3f_GrSLType, kDefault_GrSLPrecision,
64421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            "DistanceAdjust", &distanceAdjustUniName);
64521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
64621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth
647609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // To be strictly correct, we should compute the anti-aliasing factor separately
648609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // for each color component. However, this is only important when using perspective
649609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // transformations, and even then using a single factor seems like a reasonable
650609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // trade-off between quality and speed.
651354eba5cb61801130a84378356434d3cc0a4b71ajvanverth        fsBuilder->codeAppend("float afwidth;");
65278f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (isUniformScale) {
653354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For uniform scale, we adjust for the effect of the transformation on the distance
654354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // by using the length of the gradient of the texture coordinates. We use st coordinates
655354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // to ensure we're mapping 1:1 from texel space to pixel space.
656354eba5cb61801130a84378356434d3cc0a4b71ajvanverth
657609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
658bc0273524b039c45dcea2c1ab5ab379c75486c07jvanverth            fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*dy;");
659609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        } else {
660354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // For general transforms, to determine the amount of correction we multiply a unit
661354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // vector pointing along the SDF gradient direction by the Jacobian of the st coords
662354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            // (which is the inverse transform for this fragment) and take the length of the result.
663354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(distance.r));");
664d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // the length of the gradient may be 0, so we need to check for this
665d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            // this also compensates for the Adreno, which likes to drop tiles on division by 0
666d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
667d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
668d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
669d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("} else {");
670d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
671d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth            fsBuilder->codeAppend("}");
672354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
673354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
674609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
675609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
676354eba5cb61801130a84378356434d3cc0a4b71ajvanverth            fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
677609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
678609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
67921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        fsBuilder->codeAppend(
68021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                      "vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
68130ba436f04e61d4505fb854d5fc56079636e0788joshualitt
6822dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
683609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
684609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
6857510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager& pdman,
6869b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                         const GrPrimitiveProcessor& processor,
68736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                         const GrBatchTracker& bt) override {
68821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        SkASSERT(fDistanceAdjustUni.isValid());
689609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
690502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldLCDTextGeoProc& dfTexEffect =
691502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                processor.cast<GrDistanceFieldLCDTextGeoProc>();
692502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        GrDistanceFieldLCDTextGeoProc::DistanceAdjust wa = dfTexEffect.getDistanceAdjust();
69321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth        if (wa != fDistanceAdjust) {
69421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            pdman.set3f(fDistanceAdjustUni,
69521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                        wa.fR,
69621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                        wa.fG,
69721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                        wa.fB);
69821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth            fDistanceAdjust = wa;
6992d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        }
7009b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
701ee2af95db72152dfa61c841875df0594ca93437djoshualitt        this->setUniformViewMatrix(pdman, processor.viewMatrix());
702ee2af95db72152dfa61c841875df0594ca93437djoshualitt
7039b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>();
7049b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
7059b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLfloat c[4];
7069b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrColorToRGBAFloat(local.fColor, c);
7079b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            pdman.set4fv(fColorUniform, 1, c);
7089b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            fColor = local.fColor;
7099b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
710609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
711609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
71246d36f0e7b709a077c647841eee23bd3efdc4117robertphillips    static inline void GenKey(const GrGeometryProcessor& gp,
7139b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                              const GrBatchTracker& bt,
714cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                              const GrGLSLCaps&,
715b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                              GrProcessorKeyBuilder* b) {
716502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth        const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>();
717609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
7189b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>();
7198fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        uint32_t key = dfTexEffect.getFlags();
7208fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        key |= local.fInputColorType << 16;
72146d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0;
72246d36f0e7b709a077c647841eee23bd3efdc4117robertphillips        key |= ComputePosKey(gp.viewMatrix()) << 25;
7238fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt        b->add32(key);
724609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
725609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
726609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgprivate:
72721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    GrColor                                      fColor;
72821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    UniformHandle                                fColorUniform;
729502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust;
73021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    UniformHandle                                fDistanceAdjustUni;
731609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
732249af15fb82833d2274850c589812b6e69df0033joshualitt    typedef GrGLGeometryProcessor INHERITED;
733609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org};
734609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
735609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
736609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
737502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
7388059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                                  GrColor color, const SkMatrix& viewMatrix,
7392d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                  GrTexture* texture, const GrTextureParams& params,
74021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth                                                  DistanceAdjust distanceAdjust,
74178f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                  uint32_t flags)
742221360a514fb4bfff5b461e83262306b2a0f36afjvanverth    : INHERITED(color, viewMatrix, SkMatrix::I())
7432e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    , fTextureAccess(texture, params)
74421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    , fDistanceAdjust(distanceAdjust)
7452dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    , fFlags(flags & kLCD_DistanceFieldEffectMask){
74678f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
747502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    this->initClassID<GrDistanceFieldLCDTextGeoProc>();
74871c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
74971c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
7505a105ff05303ac82a867b8b84a1edd145bd46218jvanverth                                                          kVec2s_GrVertexAttribType));
751609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    this->addTextureAccess(&fTextureAccess);
752609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
753609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
754502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldLCDTextGeoProc::onIsEqual(const GrGeometryProcessor& other) const {
755502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    const GrDistanceFieldLCDTextGeoProc& cte = other.cast<GrDistanceFieldLCDTextGeoProc>();
75621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    return (fDistanceAdjust == cte.fDistanceAdjust &&
75778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth            fFlags == cte.fFlags);
758609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
759609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
760502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldLCDTextGeoProc::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
76156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    out->setUnknownFourComponents();
76256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    out->setUsingLCDCoverage();
763609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
764609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
765502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldLCDTextGeoProc::getGLProcessorKey(const GrBatchTracker& bt,
766cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                                                      const GrGLSLCaps& caps,
767502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                      GrProcessorKeyBuilder* b) const {
768502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    GrGLDistanceFieldLCDTextGeoProc::GenKey(*this, bt, caps, b);
769eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
770eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
771abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualittGrGLPrimitiveProcessor*
772502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldLCDTextGeoProc::createGLInstance(const GrBatchTracker& bt,
773cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                                                const GrGLSLCaps&) const {
774502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return SkNEW_ARGS(GrGLDistanceFieldLCDTextGeoProc, (*this, bt));
775609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
776609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
777502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldLCDTextGeoProc::initBatchTracker(GrBatchTracker* bt,
778502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                     const GrPipelineInfo& init) const {
7799b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    DistanceFieldLCDBatchTracker* local = bt->cast<DistanceFieldLCDBatchTracker>();
7809b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
781290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    local->fUsesLocalCoords = init.fUsesLocalCoords;
7829b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
7839b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
784502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthbool GrDistanceFieldLCDTextGeoProc::onCanMakeEqual(const GrBatchTracker& m,
785502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   const GrGeometryProcessor& that,
786502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   const GrBatchTracker& t) const {
7879b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    const DistanceFieldLCDBatchTracker& mine = m.cast<DistanceFieldLCDBatchTracker>();
7889b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    const DistanceFieldLCDBatchTracker& theirs = t.cast<DistanceFieldLCDBatchTracker>();
789290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
790290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                                   that, theirs.fUsesLocalCoords) &&
791290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt           CanCombineOutput(mine.fInputColorType, mine.fColor,
7929b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                            theirs.fInputColorType, theirs.fColor);
7939b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}
7949b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
795609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
796609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
797502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc);
798609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
799502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrGeometryProcessor* GrDistanceFieldLCDTextGeoProc::TestCreate(SkRandom* random,
800b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                                 GrContext*,
801b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                                 const GrDrawTargetCaps&,
802b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                                 GrTexture* textures[]) {
803b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
804b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                      GrProcessorUnitTest::kAlphaTextureIdx;
805609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    static const SkShader::TileMode kTileModes[] = {
806609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kClamp_TileMode,
807609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kRepeat_TileMode,
808609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kMirror_TileMode,
809609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    };
810609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    SkShader::TileMode tileModes[] = {
811609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
812609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
813609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    };
814609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
815609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                           GrTextureParams::kNone_FilterMode);
81621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth    DistanceAdjust wa = { 0.0f, 0.1f, -0.1f };
81778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
81878f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
81978f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
820502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth    return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(random),
821502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                 GrProcessorUnitTest::TestMatrix(random),
822502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                 textures[texIdx], params,
823502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                 wa,
824502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                 flags);
825d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
826