GrDistanceFieldGeoProc.cpp revision 2e3b3e369d79e78f7635d4c20e83a47ab571bdf2
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
8d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "GrDistanceFieldTextureEffect.h"
9605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h"
10eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrTexture.h"
11eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "SkDistanceFieldGen.h"
12b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h"
13d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLSL.h"
14d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLTexture.h"
15249af15fb82833d2274850c589812b6e69df0033joshualitt#include "gl/GrGLGeometryProcessor.h"
16eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "gl/builders/GrGLProgramBuilder.h"
17d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
182d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth// Assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2
192d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#define SK_DistanceFieldAAFactor     "0.7071"
202d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
21249af15fb82833d2274850c589812b6e69df0033joshualittclass GrGLDistanceFieldTextureEffect : public GrGLGeometryProcessor {
22d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.compublic:
23eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    GrGLDistanceFieldTextureEffect(const GrGeometryProcessor&,
2487f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                                   const GrBatchTracker&)
25eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        : fTextureSize(SkISize::Make(-1,-1))
269564ce60a657acce89fb956deb8645b324eaad1ejvanverth#ifdef SK_GAMMA_APPLY_TO_A8
279564ce60a657acce89fb956deb8645b324eaad1ejvanverth        , fLuminance(-1.0f)
289564ce60a657acce89fb956deb8645b324eaad1ejvanverth#endif
299564ce60a657acce89fb956deb8645b324eaad1ejvanverth        {}
30d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
31c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt    virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
32249af15fb82833d2274850c589812b6e69df0033joshualitt        const GrDistanceFieldTextureEffect& dfTexEffect =
33c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt                args.fGP.cast<GrDistanceFieldTextureEffect>();
34d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
35c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
3630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        SkAssertResult(fsBuilder->enableFeature(
3730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
386c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
392dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
4074077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt        GrGLVertToFrag v(kVec2f_GrSLType);
4174077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt        args.fPB->addVarying("TextureCoords", &v);
422dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
43d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
442dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        // setup color attribute
452dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        if(dfTexEffect.inColor()) {
462dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt            args.fPB->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
472dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        }
486c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
494973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt        // setup position varying
504973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt        vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(),
512dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                               vsBuilder->uViewM(), dfTexEffect.inPosition()->fName);
522dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
532dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        // setup output coords
542dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(),
552dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                               dfTexEffect.inPosition()->fName);
562dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(),
572dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                               dfTexEffect.inPosition()->fName);
584973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt
596c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        const char* textureSizeUniName = NULL;
60c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
61422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                               kVec2f_GrSLType, kDefault_GrSLPrecision,
62422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                               "TextureSize", &textureSizeUniName);
63d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
6430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 texColor = ");
65c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0],
6674077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                       v.fsIn(),
67d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                       kVec2f_GrSLType);
6830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
6930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat distance = "
70ada68ef2dc986478288a8b8ad867fd3aca431162jvanverth                       SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
716c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
726c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        // we adjust for the effect of the transformation on the distance by using
736c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        // the length of the gradient of the texture coordinates. We use st coordinates
746c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        // to ensure we're mapping 1:1 from texel space to pixel space.
7574077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt        fsBuilder->codeAppendf("\tvec2 uv = %s;\n", v.fsIn());
7630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName);
7730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat afwidth;\n");
7878f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
794362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
80fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));\n");
814362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        } else {
8230ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n");
8330ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n");
844362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
8530ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 uv_grad;\n");
86c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt            if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
874362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org                // this is to compensate for the Adreno, which likes to drop tiles on division by 0
8830ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
8930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
9030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
9130ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t} else {\n");
9230ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
9330ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t}\n");
944362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            } else {
9530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
964362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            }
9730ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
9830ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t                 uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
994362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
1004362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
10130ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
1024362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        }
10330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n");
1044d517fdbb145cb95e5e935470df331e1b6667cfcjvanverth
1052d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1062d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        // adjust based on gamma
1072d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        const char* luminanceUniName = NULL;
1082d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        // width, height, 1/(3*width)
109c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fLuminanceUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
110422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                             kFloat_GrSLType, kDefault_GrSLPrecision,
111422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                             "Luminance", &luminanceUniName);
1122d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
11330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
11430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 gammaColor = ");
115c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
11630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
11730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tval = gammaColor.r;\n");
1182d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
1192d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
1202dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
121d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    }
122d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
1237510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager& pdman,
12487f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                         const GrGeometryProcessor& proc,
12587f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                         const GrBatchTracker&) SK_OVERRIDE {
1266c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        SkASSERT(fTextureSizeUni.isValid());
1274362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
12887f48d997ec29e5eeaa7567355775e93465dd60djoshualitt        GrTexture* texture = proc.texture(0);
1294362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        if (texture->width() != fTextureSize.width() ||
1304362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            texture->height() != fTextureSize.height()) {
1314362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            fTextureSize = SkISize::Make(texture->width(), texture->height());
1327510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen            pdman.set2f(fTextureSizeUni,
1337510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        SkIntToScalar(fTextureSize.width()),
1347510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        SkIntToScalar(fTextureSize.height()));
1356c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        }
1362d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1372d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        const GrDistanceFieldTextureEffect& dfTexEffect =
13887f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                proc.cast<GrDistanceFieldTextureEffect>();
1392d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        float luminance = dfTexEffect.getLuminance();
1402d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        if (luminance != fLuminance) {
1417510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen            pdman.set1f(fLuminanceUni, luminance);
1422d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth            fLuminance = luminance;
1432d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        }
1442d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
1456c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org    }
146d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
14787f48d997ec29e5eeaa7567355775e93465dd60djoshualitt    static inline void GenKey(const GrGeometryProcessor& processor,
14887f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                              const GrBatchTracker&,
14987f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                              const GrGLCaps&,
150b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                              GrProcessorKeyBuilder* b) {
1514362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        const GrDistanceFieldTextureEffect& dfTexEffect =
152b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                processor.cast<GrDistanceFieldTextureEffect>();
1534362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
15478f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        b->add32(dfTexEffect.getFlags());
1554362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org    }
1564362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
157d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comprivate:
1587510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fTextureSizeUni;
1597510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    SkISize                               fTextureSize;
1607510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fLuminanceUni;
1617510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    float                                 fLuminance;
1626c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
163249af15fb82833d2274850c589812b6e69df0033joshualitt    typedef GrGLGeometryProcessor INHERITED;
164d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com};
165d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
166d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com///////////////////////////////////////////////////////////////////////////////
167d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
1682e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualittGrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrColor color,
1692e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt                                                           GrTexture* texture,
1706c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org                                                           const GrTextureParams& params,
1712d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1722d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                           GrTexture* gamma,
1732d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                           const GrTextureParams& gammaParams,
1742d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                           float luminance,
1752d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
17678f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                           uint32_t flags)
1772e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    : INHERITED(color)
1782e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    , fTextureAccess(texture, params)
1792d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1802d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    , fGammaTextureAccess(gamma, gammaParams)
1812d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    , fLuminance(luminance)
1822d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
183249af15fb82833d2274850c589812b6e69df0033joshualitt    , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
1842dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    , fInColor(NULL) {
18578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
186eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    this->initClassID<GrDistanceFieldTextureEffect>();
1872dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType));
1882dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    if (flags & kColorAttr_DistanceFieldEffectFlag) {
1892dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fInColor = &this->addVertexAttrib(GrAttribute("inColor", kVec4ub_GrVertexAttribType));
1902dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        this->setHasVertexColor();
1912dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    }
1922dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords",
1932dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                                                          kVec2f_GrVertexAttribType));
194d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    this->addTextureAccess(&fTextureAccess);
1952d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1962d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    this->addTextureAccess(&fGammaTextureAccess);
1972d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
198d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
199d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
2000e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrDistanceFieldTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
20149586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrDistanceFieldTextureEffect& cte = other.cast<GrDistanceFieldTextureEffect>();
202420d7e9a79358908850c74192b4949375563449absalomon    return
20378f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth#ifdef SK_GAMMA_APPLY_TO_A8
20478f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth           fLuminance == cte.fLuminance &&
20578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth#endif
20678f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth           fFlags == cte.fFlags;
207d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
208d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
209605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielvoid GrDistanceFieldTextureEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
210ccb2e384a036f29d989d3c1468f879324e81a678egdaniel    inout->mulByUnknownAlpha();
211d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
212d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
213eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittvoid GrDistanceFieldTextureEffect::getGLProcessorKey(const GrBatchTracker& bt,
214eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                                     const GrGLCaps& caps,
215eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                                     GrProcessorKeyBuilder* b) const {
216eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    GrGLDistanceFieldTextureEffect::GenKey(*this, bt, caps, b);
217eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
218eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
219eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittGrGLGeometryProcessor*
220eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittGrDistanceFieldTextureEffect::createGLInstance(const GrBatchTracker& bt) const {
221eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    return SkNEW_ARGS(GrGLDistanceFieldTextureEffect, (*this, bt));
222d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
223d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
224d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com///////////////////////////////////////////////////////////////////////////////
225d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
226b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldTextureEffect);
227d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
228b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGeometryProcessor* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
229b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                              GrContext*,
230b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                              const GrDrawTargetCaps&,
231b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                              GrTexture* textures[]) {
232b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
233b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                      GrProcessorUnitTest::kAlphaTextureIdx;
2342d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
235b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    int texIdx2 = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
236b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       GrProcessorUnitTest::kAlphaTextureIdx;
2372d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
238d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    static const SkShader::TileMode kTileModes[] = {
239d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kClamp_TileMode,
240d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kRepeat_TileMode,
241d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kMirror_TileMode,
242d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    };
243d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    SkShader::TileMode tileModes[] = {
244d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
245d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
246d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    };
247d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
248d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                                           GrTextureParams::kNone_FilterMode);
2492d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
2502d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
2512d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                            GrTextureParams::kNone_FilterMode);
2522d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
253d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
2542e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    return GrDistanceFieldTextureEffect::Create(GrRandomColor(random), textures[texIdx], params,
2552d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
2562d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                textures[texIdx2], params2,
2572d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                random->nextF(),
2582d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
25978f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                random->nextBool() ?
26078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                    kSimilarity_DistanceFieldEffectFlag : 0);
261609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
262609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
263609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
264609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
265fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthclass GrGLDistanceFieldNoGammaTextureEffect : public GrGLGeometryProcessor {
266fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthpublic:
267eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    GrGLDistanceFieldNoGammaTextureEffect(const GrGeometryProcessor&,
26887f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                                          const GrBatchTracker&)
269eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        : fTextureSize(SkISize::Make(-1, -1)) {}
270fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
271c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt    virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
272fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        const GrDistanceFieldNoGammaTextureEffect& dfTexEffect =
273c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt                args.fGP.cast<GrDistanceFieldNoGammaTextureEffect>();
274fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
275c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
276fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkAssertResult(fsBuilder->enableFeature(
277fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                     GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
278fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
2792dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
28074077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt        GrGLVertToFrag v(kVec2f_GrSLType);
28174077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt        args.fPB->addVarying("TextureCoords", &v);
282fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
2832dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        // setup color attribute
2842dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        if(dfTexEffect.inColor()) {
2852dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt            args.fPB->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
2862dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        }
2872dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
2882dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
2892dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
2902dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        // setup coord outputs
2912dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(),
2922dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                               dfTexEffect.inPosition()->fName);
2932dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(),
2942dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                               dfTexEffect.inPosition()->fName);
295fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
2964973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt        // setup position varying
2974973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt        vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(),
2982dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                               vsBuilder->uViewM(), dfTexEffect.inPosition()->fName);
2994973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt
300fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        const char* textureSizeUniName = NULL;
301c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
302422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                              kVec2f_GrSLType, kDefault_GrSLPrecision,
303422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                              "TextureSize", &textureSizeUniName);
304fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
305fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("vec4 texColor = ");
306c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0],
30774077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                       v.fsIn(),
308fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                       kVec2f_GrSLType);
309fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend(";");
310fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("float distance = "
311fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
312fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
313fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        // we adjust for the effect of the transformation on the distance by using
314fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        // the length of the gradient of the texture coordinates. We use st coordinates
315fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        // to ensure we're mapping 1:1 from texel space to pixel space.
31674077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt        fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn());
317fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName);
318fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("float afwidth;");
319fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
320fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            // this gives us a smooth step across approximately one fragment
321fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));");
322fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        } else {
323fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
324fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
325fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
326fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("vec2 uv_grad;");
327c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt            if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
328fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                // this is to compensate for the Adreno, which likes to drop tiles on division by 0
329fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                fsBuilder->codeAppend("float uv_len2 = dot(uv, uv);");
330fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                fsBuilder->codeAppend("if (uv_len2 < 0.0001) {");
331fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                fsBuilder->codeAppend("uv_grad = vec2(0.7071, 0.7071);");
332fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                fsBuilder->codeAppend("} else {");
333fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                fsBuilder->codeAppend("uv_grad = uv*inversesqrt(uv_len2);");
334fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                fsBuilder->codeAppend("}");
335fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            } else {
336fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                fsBuilder->codeAppend("uv_grad = normalize(uv);");
337fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            }
338fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("vec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,");
339fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("                 uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);");
340fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
341fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            // this gives us a smooth step across approximately one fragment
342fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
343fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        }
344fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
345fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
3462dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
347fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
348fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
349fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    virtual void setData(const GrGLProgramDataManager& pdman,
35087f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                         const GrGeometryProcessor& proc,
35187f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                         const GrBatchTracker&) SK_OVERRIDE {
352fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkASSERT(fTextureSizeUni.isValid());
353fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
35487f48d997ec29e5eeaa7567355775e93465dd60djoshualitt        GrTexture* texture = proc.texture(0);
355fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        if (texture->width() != fTextureSize.width() ||
356fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            texture->height() != fTextureSize.height()) {
357fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fTextureSize = SkISize::Make(texture->width(), texture->height());
358fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            pdman.set2f(fTextureSizeUni,
359fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                        SkIntToScalar(fTextureSize.width()),
360fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                        SkIntToScalar(fTextureSize.height()));
361fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        }
362fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
363fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
36487f48d997ec29e5eeaa7567355775e93465dd60djoshualitt    static inline void GenKey(const GrGeometryProcessor& proc,
36587f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                              const GrBatchTracker&,
36687f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                              const GrGLCaps&,
367fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                              GrProcessorKeyBuilder* b) {
368fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        const GrDistanceFieldNoGammaTextureEffect& dfTexEffect =
36987f48d997ec29e5eeaa7567355775e93465dd60djoshualitt            proc.cast<GrDistanceFieldNoGammaTextureEffect>();
370fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
371fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        b->add32(dfTexEffect.getFlags());
372fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
373fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
374fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthprivate:
375fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    GrGLProgramDataManager::UniformHandle fTextureSizeUni;
376fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    SkISize                               fTextureSize;
377fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
378fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    typedef GrGLGeometryProcessor INHERITED;
379fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth};
380fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
381fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth///////////////////////////////////////////////////////////////////////////////
382fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
3832e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualittGrDistanceFieldNoGammaTextureEffect::GrDistanceFieldNoGammaTextureEffect(
3842e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        GrColor color,
3852e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        GrTexture* texture,
3862e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        const GrTextureParams& params,
3872e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt        uint32_t flags)
3882e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    : INHERITED(color)
3892e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    , fTextureAccess(texture, params)
390fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
3912dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    , fInColor(NULL) {
392fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
393eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    this->initClassID<GrDistanceFieldNoGammaTextureEffect>();
3942dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType));
3952dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    if (flags & kColorAttr_DistanceFieldEffectFlag) {
3962dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fInColor = &this->addVertexAttrib(GrAttribute("inColor", kVec4ub_GrVertexAttribType));
3972dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        this->setHasVertexColor();
3982dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    }
3992dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords",
4002dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                                                          kVec2f_GrVertexAttribType));
401fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    this->addTextureAccess(&fTextureAccess);
402fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
403fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
4040e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrDistanceFieldNoGammaTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
405fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    const GrDistanceFieldNoGammaTextureEffect& cte =
406fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                                 other.cast<GrDistanceFieldNoGammaTextureEffect>();
407420d7e9a79358908850c74192b4949375563449absalomon    return fFlags == cte.fFlags;
408fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
409fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
410605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielvoid GrDistanceFieldNoGammaTextureEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
411ccb2e384a036f29d989d3c1468f879324e81a678egdaniel    inout->mulByUnknownAlpha();
412fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
413fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
414eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittvoid GrDistanceFieldNoGammaTextureEffect::getGLProcessorKey(const GrBatchTracker& bt,
415eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                                            const GrGLCaps& caps,
416eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                                            GrProcessorKeyBuilder* b) const {
417eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    GrGLDistanceFieldNoGammaTextureEffect::GenKey(*this, bt, caps, b);
418eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
419eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
420eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittGrGLGeometryProcessor*
421eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittGrDistanceFieldNoGammaTextureEffect::createGLInstance(const GrBatchTracker& bt) const {
422eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    return SkNEW_ARGS(GrGLDistanceFieldNoGammaTextureEffect, (*this, bt));
423fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
424fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
425fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth///////////////////////////////////////////////////////////////////////////////
426fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
427fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldNoGammaTextureEffect);
428fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
429fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthGrGeometryProcessor* GrDistanceFieldNoGammaTextureEffect::TestCreate(SkRandom* random,
430fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                                                     GrContext*,
431fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                                                     const GrDrawTargetCaps&,
432fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                                                     GrTexture* textures[]) {
433fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
434fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                    : GrProcessorUnitTest::kAlphaTextureIdx;
435fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    static const SkShader::TileMode kTileModes[] = {
436fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkShader::kClamp_TileMode,
437fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkShader::kRepeat_TileMode,
438fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        SkShader::kMirror_TileMode,
439fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    };
440fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    SkShader::TileMode tileModes[] = {
441fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
442fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
443fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    };
444fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode
445fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth                                                         : GrTextureParams::kNone_FilterMode);
446fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
4472e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    return GrDistanceFieldNoGammaTextureEffect::Create(GrRandomColor(random), textures[texIdx],
4482e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt                                                       params,
449fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        random->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0);
450fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
451fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
452fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth///////////////////////////////////////////////////////////////////////////////
453fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
454249af15fb82833d2274850c589812b6e69df0033joshualittclass GrGLDistanceFieldLCDTextureEffect : public GrGLGeometryProcessor {
455609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgpublic:
456eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    GrGLDistanceFieldLCDTextureEffect(const GrGeometryProcessor&,
45787f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                                      const GrBatchTracker&)
458eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    : fTextureSize(SkISize::Make(-1,-1))
4599564ce60a657acce89fb956deb8645b324eaad1ejvanverth    , fTextColor(GrColor_ILLEGAL) {}
460609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
461c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt    virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
462609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        const GrDistanceFieldLCDTextureEffect& dfTexEffect =
463c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt                args.fGP.cast<GrDistanceFieldLCDTextureEffect>();
464609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
4652dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
46674077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt        GrGLVertToFrag v(kVec2f_GrSLType);
46774077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt        args.fPB->addVarying("TextureCoords", &v);
4682dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
469609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
4702dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        // setup coord outputs
4712dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(),
4722dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                               dfTexEffect.inPosition()->fName);
4732dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(),
4742dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                               dfTexEffect.inPosition()->fName);
475609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
4764973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt        // setup position varying
4774973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt        vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(),
4782dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                               vsBuilder->uViewM(), dfTexEffect.inPosition()->fName);
4794973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt
480609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        const char* textureSizeUniName = NULL;
481609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // width, height, 1/(3*width)
482c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
483422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                              kVec3f_GrSLType, kDefault_GrSLPrecision,
484422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                              "TextureSize", &textureSizeUniName);
485609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
486c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
48730ba436f04e61d4505fb854d5fc56079636e0788joshualitt
48830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        SkAssertResult(fsBuilder->enableFeature(
48930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
49030ba436f04e61d4505fb854d5fc56079636e0788joshualitt
491609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // create LCD offset adjusted by inverse of transform
49274077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt        fsBuilder->codeAppendf("\tvec2 uv = %s;\n", v.fsIn());
49330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName);
49478f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
49578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (isUniformScale) {
49630ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tfloat dx = dFdx(st.x);\n");
49730ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", textureSizeUniName);
498609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        } else {
49930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n");
50030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n");
50130ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUniName);
502609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
503609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
504609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // green is distance to uv center
50530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 texColor = ");
506c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0], "uv", kVec2f_GrSLType);
50730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
50830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec3 distance;\n");
50930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.y = texColor.r;\n");
510609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // red is distance to left offset
51130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n");
51230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\ttexColor = ");
513c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
51430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
51530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.x = texColor.r;\n");
516609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // blue is distance to right offset
51730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
51830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\ttexColor = ");
519c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
52030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
52130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.z = texColor.r;\n");
5222d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
52330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance = "
524ada68ef2dc986478288a8b8ad867fd3aca431162jvanverth           "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
5252d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
526609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // we adjust for the effect of the transformation on the distance by using
527609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // the length of the gradient of the texture coordinates. We use st coordinates
528609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // to ensure we're mapping 1:1 from texel space to pixel space.
529609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
530609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // To be strictly correct, we should compute the anti-aliasing factor separately
531609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // for each color component. However, this is only important when using perspective
532609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // transformations, and even then using a single factor seems like a reasonable
533609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // trade-off between quality and speed.
53430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat afwidth;\n");
53578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (isUniformScale) {
536609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
537fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth            fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*dx);\n");
538609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        } else {
53930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 uv_grad;\n");
540c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt            if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
541609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                // this is to compensate for the Adreno, which likes to drop tiles on division by 0
54230ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
54330ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
54430ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
54530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t} else {\n");
54630ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
54730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t}\n");
548609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            } else {
54930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
550609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            }
55130ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
55230ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t                 uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
553609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
554609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
55530ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
556609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
557609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
55830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n");
559609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
5602d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        // adjust based on gamma
5612d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        const char* textColorUniName = NULL;
5622d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        // width, height, 1/(3*width)
563c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fTextColorUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
564422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                             kVec3f_GrSLType, kDefault_GrSLPrecision,
565422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon                                             "TextColor", &textColorUniName);
5662d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
56730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
56830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 gammaColor = ");
569c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
57030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
57130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tval.x = gammaColor.r;\n");
57230ba436f04e61d4505fb854d5fc56079636e0788joshualitt
57330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName);
57430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tgammaColor = ");
575c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
57630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
57730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tval.y = gammaColor.r;\n");
57830ba436f04e61d4505fb854d5fc56079636e0788joshualitt
57930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName);
58030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tgammaColor = ");
581c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt        fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
58230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
58330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tval.z = gammaColor.r;\n");
58430ba436f04e61d4505fb854d5fc56079636e0788joshualitt
5852dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt        fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
586609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
587609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
5887510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager& pdman,
58987f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                         const GrGeometryProcessor& processor,
59087f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                         const GrBatchTracker&) SK_OVERRIDE {
591609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkASSERT(fTextureSizeUni.isValid());
5922d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        SkASSERT(fTextColorUni.isValid());
593609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
5942d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        const GrDistanceFieldLCDTextureEffect& dfTexEffect =
595b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                processor.cast<GrDistanceFieldLCDTextureEffect>();
596b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        GrTexture* texture = processor.texture(0);
597609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        if (texture->width() != fTextureSize.width() ||
598609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            texture->height() != fTextureSize.height()) {
599609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            fTextureSize = SkISize::Make(texture->width(), texture->height());
600609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            float delta = 1.0f/(3.0f*texture->width());
60178f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth            if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
602609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                delta = -delta;
603609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            }
6047510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen            pdman.set3f(fTextureSizeUni,
6057510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        SkIntToScalar(fTextureSize.width()),
6067510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        SkIntToScalar(fTextureSize.height()),
6077510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        delta);
608609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
6092d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
6102d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        GrColor textColor = dfTexEffect.getTextColor();
6112d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        if (textColor != fTextColor) {
6122d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth            static const float ONE_OVER_255 = 1.f / 255.f;
6137510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen            pdman.set3f(fTextColorUni,
6147510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        GrColorUnpackR(textColor) * ONE_OVER_255,
6157510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        GrColorUnpackG(textColor) * ONE_OVER_255,
6167510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        GrColorUnpackB(textColor) * ONE_OVER_255);
6172d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth            fTextColor = textColor;
6182d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        }
619609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
620609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
62187f48d997ec29e5eeaa7567355775e93465dd60djoshualitt    static inline void GenKey(const GrGeometryProcessor& processor,
62287f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                              const GrBatchTracker&,
62387f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                              const GrGLCaps&,
624b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                              GrProcessorKeyBuilder* b) {
625609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        const GrDistanceFieldLCDTextureEffect& dfTexEffect =
626b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                processor.cast<GrDistanceFieldLCDTextureEffect>();
627609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
62878f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        b->add32(dfTexEffect.getFlags());
629609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
630609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
631609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgprivate:
6327510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fTextureSizeUni;
6337510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    SkISize                               fTextureSize;
6347510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fTextColorUni;
6357510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    SkColor                               fTextColor;
636609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
637249af15fb82833d2274850c589812b6e69df0033joshualitt    typedef GrGLGeometryProcessor INHERITED;
638609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org};
639609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
640609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
641609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
6422d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthGrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
6432e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt                                                  GrColor color,
6442d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                  GrTexture* texture, const GrTextureParams& params,
6452d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                  GrTexture* gamma, const GrTextureParams& gParams,
6462d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                  SkColor textColor,
64778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                  uint32_t flags)
6482e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    : INHERITED(color)
6492e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    , fTextureAccess(texture, params)
6502d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    , fGammaTextureAccess(gamma, gParams)
6512d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    , fTextColor(textColor)
6522dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    , fFlags(flags & kLCD_DistanceFieldEffectMask){
65378f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
654eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    this->initClassID<GrDistanceFieldLCDTextureEffect>();
6552dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType));
6562dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords",
6572dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt                                                          kVec2f_GrVertexAttribType));
658609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    this->addTextureAccess(&fTextureAccess);
6592d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    this->addTextureAccess(&fGammaTextureAccess);
660609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
661609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
6620e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
66349586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrDistanceFieldLCDTextureEffect& cte = other.cast<GrDistanceFieldLCDTextureEffect>();
664420d7e9a79358908850c74192b4949375563449absalomon    return (fTextColor == cte.fTextColor &&
66578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth            fFlags == cte.fFlags);
666609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
667609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
668605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielvoid GrDistanceFieldLCDTextureEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
669ccb2e384a036f29d989d3c1468f879324e81a678egdaniel    inout->mulByUnknownColor();
670309e346744f57fadd66ba3c2f14875c86311682eegdaniel    inout->setUsingLCDCoverage();
671609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
672609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
673eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittvoid GrDistanceFieldLCDTextureEffect::getGLProcessorKey(const GrBatchTracker& bt,
674eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                                        const GrGLCaps& caps,
675eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                                        GrProcessorKeyBuilder* b) const {
676eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    GrGLDistanceFieldLCDTextureEffect::GenKey(*this, bt, caps, b);
677eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
678eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
679eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittGrGLGeometryProcessor*
680eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittGrDistanceFieldLCDTextureEffect::createGLInstance(const GrBatchTracker& bt) const {
681eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    return SkNEW_ARGS(GrGLDistanceFieldLCDTextureEffect, (*this, bt));
682609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
683609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
684609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
685609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
686b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextureEffect);
687609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
688b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGeometryProcessor* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random,
689b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                                 GrContext*,
690b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                                 const GrDrawTargetCaps&,
691b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                                 GrTexture* textures[]) {
692b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
693b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                      GrProcessorUnitTest::kAlphaTextureIdx;
694b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    int texIdx2 = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
695b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       GrProcessorUnitTest::kAlphaTextureIdx;
696609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    static const SkShader::TileMode kTileModes[] = {
697609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kClamp_TileMode,
698609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kRepeat_TileMode,
699609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kMirror_TileMode,
700609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    };
701609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    SkShader::TileMode tileModes[] = {
702609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
703609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
704609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    };
705609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
706609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                           GrTextureParams::kNone_FilterMode);
7072d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
7082d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                           GrTextureParams::kNone_FilterMode);
7092d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    GrColor textColor = GrColorPackRGBA(random->nextULessThan(256),
7102d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                        random->nextULessThan(256),
7112d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                        random->nextULessThan(256),
7122d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                        random->nextULessThan(256));
71378f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
71478f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
71578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
7162e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random), textures[texIdx], params,
7172d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   textures[texIdx2], params2,
7182d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   textColor,
71978f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                   flags);
720d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
721