GrDistanceFieldGeoProc.cpp revision 30ba436f04e61d4505fb854d5fc56079636e0788
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
830ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h"
9d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "GrDistanceFieldTextureEffect.h"
10d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLEffect.h"
11d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLSL.h"
12d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLTexture.h"
13d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLVertexEffect.h"
14d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "GrTBackendEffectFactory.h"
15d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "GrTexture.h"
16d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
17762cd804375ff8478427dba4fe29379562b8fb60commit-bot@chromium.org#include "SkDistanceFieldGen.h"
18d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
192d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth// To get optical sizes people don't complain about when we blit correctly,
202d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth// we need to slightly bold each glyph. On the Mac, we need a larger bold value.
212d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#if defined(SK_BUILD_FOR_MAC)
222d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#define SK_DistanceFieldLCDFactor    "0.33"
232d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#define SK_DistanceFieldNonLCDFactor "0.25"
242d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#else
252d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#define SK_DistanceFieldLCDFactor    "0.05"
262d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#define SK_DistanceFieldNonLCDFactor "0.05"
272d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
282d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
292d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth// Assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2
302d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#define SK_DistanceFieldAAFactor     "0.7071"
312d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
32d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comclass GrGLDistanceFieldTextureEffect : public GrGLVertexEffect {
33d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.compublic:
34a3b532743dbb1d54a4c17a2574083ef93c949d50skia.committer@gmail.com    GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory,
356c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org                                   const GrDrawEffect& drawEffect)
366c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        : INHERITED (factory)
374362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        , fTextureSize(SkISize::Make(-1,-1)) {}
38d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
3930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitCode(GrGLFullProgramBuilder* builder,
40d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                          const GrDrawEffect& drawEffect,
4163e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon                          const GrEffectKey& key,
42d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                          const char* outputColor,
43d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                          const char* inputColor,
44d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                          const TransformedCoordsArray&,
45d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                          const TextureSamplerArray& samplers) SK_OVERRIDE {
46d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldTextureEffect>().numVertexAttribs());
47d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
4830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
4930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        SkAssertResult(fsBuilder->enableFeature(
5030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
514362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        const GrDistanceFieldTextureEffect& dfTexEffect =
524362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org                                              drawEffect.castEffect<GrDistanceFieldTextureEffect>();
536c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
54d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkString fsCoordName;
556c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        const char* vsCoordName;
566c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        const char* fsCoordNamePtr;
576c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
586c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        fsCoordName = fsCoordNamePtr;
59d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
6030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
6130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        const SkString* attr0Name =
6230ba436f04e61d4505fb854d5fc56079636e0788joshualitt            vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
6330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
646c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
656c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        const char* textureSizeUniName = NULL;
6630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fTextureSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
676c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org                                              kVec2f_GrSLType, "TextureSize",
686c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org                                              &textureSizeUniName);
69d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
7030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 texColor = ");
7130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->appendTextureLookup(samplers[0],
72d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                       fsCoordName.c_str(),
73d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                       kVec2f_GrSLType);
7430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
7530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat distance = "
762d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                          SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ")"
772d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                          "+ " SK_DistanceFieldNonLCDFactor ";\n");
786c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
796c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        // we adjust for the effect of the transformation on the distance by using
806c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        // the length of the gradient of the texture coordinates. We use st coordinates
816c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        // to ensure we're mapping 1:1 from texel space to pixel space.
8230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
8330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName);
8430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat afwidth;\n");
8578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
864362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
8730ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx(st.x);\n");
884362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        } else {
8930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n");
9030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n");
914362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
9230ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 uv_grad;\n");
934362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
944362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org                // this is to compensate for the Adreno, which likes to drop tiles on division by 0
9530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
9630ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
9730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
9830ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t} else {\n");
9930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
10030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t}\n");
1014362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            } else {
10230ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
1034362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            }
10430ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
10530ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t                 uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
1064362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
1074362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
10830ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
1094362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        }
11030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n");
1114d517fdbb145cb95e5e935470df331e1b6667cfcjvanverth
1122d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1132d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        // adjust based on gamma
1142d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        const char* luminanceUniName = NULL;
1152d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        // width, height, 1/(3*width)
11630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fLuminanceUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1172d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                            kFloat_GrSLType, "Luminance",
1182d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                            &luminanceUniName);
1192d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
12030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
12130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 gammaColor = ");
12230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
12330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
12430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tval = gammaColor.r;\n");
1252d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
1262d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
12730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
128d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                   (GrGLSLExpr4(inputColor) * GrGLSLExpr1("val")).c_str());
129d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    }
130d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
1317510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager& pdman,
1326c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org                         const GrDrawEffect& drawEffect) SK_OVERRIDE {
1336c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        SkASSERT(fTextureSizeUni.isValid());
1344362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
135f99f884cd82528684779e40413f1ceaf277dad2dbsalomon        GrTexture* texture = drawEffect.effect()->texture(0);
1364362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        if (texture->width() != fTextureSize.width() ||
1374362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            texture->height() != fTextureSize.height()) {
1384362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org            fTextureSize = SkISize::Make(texture->width(), texture->height());
1397510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen            pdman.set2f(fTextureSizeUni,
1407510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        SkIntToScalar(fTextureSize.width()),
1417510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        SkIntToScalar(fTextureSize.height()));
1426c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org        }
1432d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1442d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        const GrDistanceFieldTextureEffect& dfTexEffect =
1452d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                              drawEffect.castEffect<GrDistanceFieldTextureEffect>();
1462d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        float luminance = dfTexEffect.getLuminance();
1472d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        if (luminance != fLuminance) {
1487510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen            pdman.set1f(fLuminanceUni, luminance);
1492d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth            fLuminance = luminance;
1502d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        }
1512d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
1526c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org    }
153d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
15463e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon    static inline void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&,
15563e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon                              GrEffectKeyBuilder* b) {
1564362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        const GrDistanceFieldTextureEffect& dfTexEffect =
1574362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org                                              drawEffect.castEffect<GrDistanceFieldTextureEffect>();
1584362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
15978f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        b->add32(dfTexEffect.getFlags());
1604362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org    }
1614362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org
162d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comprivate:
1637510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fTextureSizeUni;
1647510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    SkISize                               fTextureSize;
1657510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fLuminanceUni;
1667510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    float                                 fLuminance;
1676c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org
168d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    typedef GrGLVertexEffect INHERITED;
169d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com};
170d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
171d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com///////////////////////////////////////////////////////////////////////////////
172d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
173d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comGrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture,
1746c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org                                                           const GrTextureParams& params,
1752d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1762d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                           GrTexture* gamma,
1772d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                           const GrTextureParams& gammaParams,
1782d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                           float luminance,
1792d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
18078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                           uint32_t flags)
1816c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org    : fTextureAccess(texture, params)
1822d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1832d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    , fGammaTextureAccess(gamma, gammaParams)
1842d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    , fLuminance(luminance)
1852d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
18678f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    , fFlags(flags & kNonLCD_DistanceFieldEffectMask) {
18778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
188d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    this->addTextureAccess(&fTextureAccess);
1892d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
1902d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    this->addTextureAccess(&fGammaTextureAccess);
1912d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
192d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    this->addVertexAttrib(kVec2f_GrSLType);
193d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
194d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
195d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.combool GrDistanceFieldTextureEffect::onIsEqual(const GrEffect& other) const {
196d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    const GrDistanceFieldTextureEffect& cte = CastEffect<GrDistanceFieldTextureEffect>(other);
19778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    return fTextureAccess == cte.fTextureAccess &&
19878f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth#ifdef SK_GAMMA_APPLY_TO_A8
19978f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth           fGammaTextureAccess == cte.fGammaTextureAccess &&
20078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth           fLuminance == cte.fLuminance &&
20178f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth#endif
20278f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth           fFlags == cte.fFlags;
203d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
204d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
205d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comvoid GrDistanceFieldTextureEffect::getConstantColorComponents(GrColor* color,
206d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                                             uint32_t* validFlags) const {
207d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    if ((*validFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(*color) &&
208d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        GrPixelConfigIsOpaque(this->texture(0)->config())) {
209d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        *validFlags = kA_GrColorComponentFlag;
210d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    } else {
211d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        *validFlags = 0;
212d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    }
213d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
214d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
215d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comconst GrBackendEffectFactory& GrDistanceFieldTextureEffect::getFactory() const {
216d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    return GrTBackendEffectFactory<GrDistanceFieldTextureEffect>::getInstance();
217d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
218d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
219d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com///////////////////////////////////////////////////////////////////////////////
220d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
221d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comGR_DEFINE_EFFECT_TEST(GrDistanceFieldTextureEffect);
222d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
22383d081ae1d731b5039e99823620f5e287542ee39bsalomonGrEffect* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
22483d081ae1d731b5039e99823620f5e287542ee39bsalomon                                                   GrContext*,
22583d081ae1d731b5039e99823620f5e287542ee39bsalomon                                                   const GrDrawTargetCaps&,
22683d081ae1d731b5039e99823620f5e287542ee39bsalomon                                                   GrTexture* textures[]) {
227d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
228d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                      GrEffectUnitTest::kAlphaTextureIdx;
2292d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
2302d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    int texIdx2 = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
2312d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                       GrEffectUnitTest::kAlphaTextureIdx;
2322d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
233d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    static const SkShader::TileMode kTileModes[] = {
234d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kClamp_TileMode,
235d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kRepeat_TileMode,
236d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkShader::kMirror_TileMode,
237d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    };
238d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    SkShader::TileMode tileModes[] = {
239d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
240d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
241d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    };
242d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
243d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                                           GrTextureParams::kNone_FilterMode);
2442d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
2452d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
2462d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                            GrTextureParams::kNone_FilterMode);
2472d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
248d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
249609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    return GrDistanceFieldTextureEffect::Create(textures[texIdx], params,
2502d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8
2512d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                textures[texIdx2], params2,
2522d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                random->nextF(),
2532d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif
25478f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                random->nextBool() ?
25578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                    kSimilarity_DistanceFieldEffectFlag : 0);
256609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
257609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
258609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
259609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
260609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgclass GrGLDistanceFieldLCDTextureEffect : public GrGLVertexEffect {
261609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgpublic:
262609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    GrGLDistanceFieldLCDTextureEffect(const GrBackendEffectFactory& factory,
263609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                                      const GrDrawEffect& drawEffect)
264609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    : INHERITED (factory)
265609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    , fTextureSize(SkISize::Make(-1,-1)) {}
266609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
26730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitCode(GrGLFullProgramBuilder* builder,
268609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                          const GrDrawEffect& drawEffect,
26963e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon                          const GrEffectKey& key,
270609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                          const char* outputColor,
271609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                          const char* inputColor,
272609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                          const TransformedCoordsArray&,
273609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                          const TextureSamplerArray& samplers) SK_OVERRIDE {
274609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>().numVertexAttribs());
275609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
276609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        const GrDistanceFieldLCDTextureEffect& dfTexEffect =
277609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                                           drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>();
278609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
279609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkString fsCoordName;
280609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        const char* vsCoordName;
281609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        const char* fsCoordNamePtr;
282609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
283609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        fsCoordName = fsCoordNamePtr;
284609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
28530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
28630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        const SkString* attr0Name =
28730ba436f04e61d4505fb854d5fc56079636e0788joshualitt            vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
28830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
289609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
290609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        const char* textureSizeUniName = NULL;
291609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // width, height, 1/(3*width)
29230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fTextureSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
293609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                                              kVec3f_GrSLType, "TextureSize",
294609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                                              &textureSizeUniName);
295609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
29630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
29730ba436f04e61d4505fb854d5fc56079636e0788joshualitt
29830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        SkAssertResult(fsBuilder->enableFeature(
29930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
30030ba436f04e61d4505fb854d5fc56079636e0788joshualitt
301609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // create LCD offset adjusted by inverse of transform
30230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
30330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName);
30478f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
30578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (isUniformScale) {
30630ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tfloat dx = dFdx(st.x);\n");
30730ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", textureSizeUniName);
308609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        } else {
30930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n");
31030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n");
31130ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUniName);
312609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
313609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
314609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // green is distance to uv center
31530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 texColor = ");
31630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->appendTextureLookup(samplers[0], "uv", kVec2f_GrSLType);
31730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
31830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec3 distance;\n");
31930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.y = texColor.r;\n");
320609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // red is distance to left offset
32130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n");
32230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\ttexColor = ");
32330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->appendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
32430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
32530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.x = texColor.r;\n");
326609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // blue is distance to right offset
32730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
32830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\ttexColor = ");
32930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->appendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
33030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
33130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance.z = texColor.r;\n");
3322d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
33330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tdistance = "
3342d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth            "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"))"
3352d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth            "+ vec3(" SK_DistanceFieldLCDFactor ");\n");
3362d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
337609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // we adjust for the effect of the transformation on the distance by using
338609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // the length of the gradient of the texture coordinates. We use st coordinates
339609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // to ensure we're mapping 1:1 from texel space to pixel space.
340609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
341609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // To be strictly correct, we should compute the anti-aliasing factor separately
342609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // for each color component. However, this is only important when using perspective
343609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // transformations, and even then using a single factor seems like a reasonable
344609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        // trade-off between quality and speed.
34530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tfloat afwidth;\n");
34678f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        if (isUniformScale) {
347609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
34830ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\n");
349609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        } else {
35030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 uv_grad;\n");
351609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
352609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                // this is to compensate for the Adreno, which likes to drop tiles on division by 0
35330ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
35430ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
35530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
35630ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t} else {\n");
35730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
35830ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t}\n");
359609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            } else {
36030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
361609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            }
36230ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
36330ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t                 uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
364609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
365609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            // this gives us a smooth step across approximately one fragment
36630ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
367609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
368609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
36930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n");
370609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
3712d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        // adjust based on gamma
3722d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        const char* textColorUniName = NULL;
3732d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        // width, height, 1/(3*width)
37430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fTextColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
3752d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                            kVec3f_GrSLType, "TextColor",
3762d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                            &textColorUniName);
3772d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
37830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
37930ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tvec4 gammaColor = ");
38030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
38130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
38230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tval.x = gammaColor.r;\n");
38330ba436f04e61d4505fb854d5fc56079636e0788joshualitt
38430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName);
38530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tgammaColor = ");
38630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
38730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
38830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tval.y = gammaColor.r;\n");
38930ba436f04e61d4505fb854d5fc56079636e0788joshualitt
39030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName);
39130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tgammaColor = ");
39230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
39330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend(";\n");
39430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\tval.z = gammaColor.r;\n");
39530ba436f04e61d4505fb854d5fc56079636e0788joshualitt
39630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
397609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                               (GrGLSLExpr4(inputColor) * GrGLSLExpr4("val")).c_str());
398609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
399609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
4007510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager& pdman,
401609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                         const GrDrawEffect& drawEffect) SK_OVERRIDE {
402609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkASSERT(fTextureSizeUni.isValid());
4032d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        SkASSERT(fTextColorUni.isValid());
404609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
4052d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        const GrDistanceFieldLCDTextureEffect& dfTexEffect =
4062d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                    drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>();
407f99f884cd82528684779e40413f1ceaf277dad2dbsalomon        GrTexture* texture = drawEffect.effect()->texture(0);
408609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        if (texture->width() != fTextureSize.width() ||
409609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            texture->height() != fTextureSize.height()) {
410609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            fTextureSize = SkISize::Make(texture->width(), texture->height());
411609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            float delta = 1.0f/(3.0f*texture->width());
41278f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth            if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
413609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                delta = -delta;
414609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org            }
4157510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen            pdman.set3f(fTextureSizeUni,
4167510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        SkIntToScalar(fTextureSize.width()),
4177510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        SkIntToScalar(fTextureSize.height()),
4187510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        delta);
419609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        }
4202d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
4212d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        GrColor textColor = dfTexEffect.getTextColor();
4222d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        if (textColor != fTextColor) {
4232d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth            static const float ONE_OVER_255 = 1.f / 255.f;
4247510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen            pdman.set3f(fTextColorUni,
4257510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        GrColorUnpackR(textColor) * ONE_OVER_255,
4267510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        GrColorUnpackG(textColor) * ONE_OVER_255,
4277510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen                        GrColorUnpackB(textColor) * ONE_OVER_255);
4282d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth            fTextColor = textColor;
4292d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        }
430609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
431609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
43263e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon    static inline void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&,
43363e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon                              GrEffectKeyBuilder* b) {
434609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        const GrDistanceFieldLCDTextureEffect& dfTexEffect =
435609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                                           drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>();
436609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
43778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth        b->add32(dfTexEffect.getFlags());
438609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
439609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
440609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgprivate:
4417510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fTextureSizeUni;
4427510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    SkISize                               fTextureSize;
4437510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fTextColorUni;
4447510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    SkColor                               fTextColor;
445609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
446609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    typedef GrGLVertexEffect INHERITED;
447609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org};
448609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
449609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
450609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
4512d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthGrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
4522d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                  GrTexture* texture, const GrTextureParams& params,
4532d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                  GrTexture* gamma, const GrTextureParams& gParams,
4542d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                  SkColor textColor,
45578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                  uint32_t flags)
456609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    : fTextureAccess(texture, params)
4572d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    , fGammaTextureAccess(gamma, gParams)
4582d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    , fTextColor(textColor)
45978f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    , fFlags(flags & kLCD_DistanceFieldEffectMask) {
46078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
46178f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth
462609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    this->addTextureAccess(&fTextureAccess);
4632d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    this->addTextureAccess(&fGammaTextureAccess);
464609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    this->addVertexAttrib(kVec2f_GrSLType);
465609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
466609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
467609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgbool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrEffect& other) const {
4682d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const GrDistanceFieldLCDTextureEffect& cte =
4692d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                            CastEffect<GrDistanceFieldLCDTextureEffect>(other);
47078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    return (fTextureAccess == cte.fTextureAccess &&
47178f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth            fGammaTextureAccess == cte.fGammaTextureAccess &&
47278f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth            fTextColor == cte.fTextColor &&
47378f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth            fFlags == cte.fFlags);
474609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
475609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
476609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgvoid GrDistanceFieldLCDTextureEffect::getConstantColorComponents(GrColor* color,
477609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                                                                 uint32_t* validFlags) const {
478609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    if ((*validFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(*color) &&
479609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        GrPixelConfigIsOpaque(this->texture(0)->config())) {
480609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        *validFlags = kA_GrColorComponentFlag;
481609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    } else {
482609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        *validFlags = 0;
483609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    }
484609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
485609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
486609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgconst GrBackendEffectFactory& GrDistanceFieldLCDTextureEffect::getFactory() const {
487609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    return GrTBackendEffectFactory<GrDistanceFieldLCDTextureEffect>::getInstance();
488609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}
489609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
490609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
491609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
492609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(GrDistanceFieldLCDTextureEffect);
493609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org
49483d081ae1d731b5039e99823620f5e287542ee39bsalomonGrEffect* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random,
49583d081ae1d731b5039e99823620f5e287542ee39bsalomon                                                      GrContext*,
49683d081ae1d731b5039e99823620f5e287542ee39bsalomon                                                      const GrDrawTargetCaps&,
49783d081ae1d731b5039e99823620f5e287542ee39bsalomon                                                      GrTexture* textures[]) {
498609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
4992d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                      GrEffectUnitTest::kAlphaTextureIdx;
5002d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    int texIdx2 = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
5012d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                       GrEffectUnitTest::kAlphaTextureIdx;
502609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    static const SkShader::TileMode kTileModes[] = {
503609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kClamp_TileMode,
504609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kRepeat_TileMode,
505609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        SkShader::kMirror_TileMode,
506609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    };
507609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    SkShader::TileMode tileModes[] = {
508609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
509609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
510609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    };
511609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
512609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org                           GrTextureParams::kNone_FilterMode);
5132d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
5142d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                           GrTextureParams::kNone_FilterMode);
5152d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    GrColor textColor = GrColorPackRGBA(random->nextULessThan(256),
5162d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                        random->nextULessThan(256),
5172d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                        random->nextULessThan(256),
5182d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                        random->nextULessThan(256));
51978f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
52078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
52178f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth    flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
522609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org    return GrDistanceFieldLCDTextureEffect::Create(textures[texIdx], params,
5232d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   textures[texIdx2], params2,
5242d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   textColor,
52578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth                                                   flags);
526d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}
527