blob: f408d2dfec51800d3c664fbf96e716ee444ed428 [file] [log] [blame]
jvanverth@google.comd830d132013-11-11 20:54:09 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrDistanceFieldTextureEffect.h"
egdaniel605dd0f2014-11-12 08:35:25 -08009#include "GrInvariantOutput.h"
joshualitteb2a6762014-12-04 11:35:33 -080010#include "GrTexture.h"
11#include "SkDistanceFieldGen.h"
joshualittb0a8a372014-09-23 09:50:21 -070012#include "gl/GrGLProcessor.h"
jvanverth@google.comd830d132013-11-11 20:54:09 +000013#include "gl/GrGLSL.h"
14#include "gl/GrGLTexture.h"
joshualitt249af152014-09-15 11:41:13 -070015#include "gl/GrGLGeometryProcessor.h"
joshualitteb2a6762014-12-04 11:35:33 -080016#include "gl/builders/GrGLProgramBuilder.h"
jvanverth@google.comd830d132013-11-11 20:54:09 +000017
jvanverth2d2a68c2014-06-10 06:42:56 -070018// Assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2
19#define SK_DistanceFieldAAFactor "0.7071"
20
joshualitt249af152014-09-15 11:41:13 -070021class GrGLDistanceFieldTextureEffect : public GrGLGeometryProcessor {
jvanverth@google.comd830d132013-11-11 20:54:09 +000022public:
joshualitteb2a6762014-12-04 11:35:33 -080023 GrGLDistanceFieldTextureEffect(const GrGeometryProcessor&,
joshualitt87f48d92014-12-04 10:41:40 -080024 const GrBatchTracker&)
joshualitteb2a6762014-12-04 11:35:33 -080025 : fTextureSize(SkISize::Make(-1,-1))
jvanverth9564ce62014-09-16 05:45:19 -070026#ifdef SK_GAMMA_APPLY_TO_A8
27 , fLuminance(-1.0f)
28#endif
29 {}
jvanverth@google.comd830d132013-11-11 20:54:09 +000030
joshualittc369e7c2014-10-22 10:56:26 -070031 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
joshualitt249af152014-09-15 11:41:13 -070032 const GrDistanceFieldTextureEffect& dfTexEffect =
joshualittc369e7c2014-10-22 10:56:26 -070033 args.fGP.cast<GrDistanceFieldTextureEffect>();
jvanverth@google.comd830d132013-11-11 20:54:09 +000034
joshualittc369e7c2014-10-22 10:56:26 -070035 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
joshualitt30ba4362014-08-21 20:18:45 -070036 SkAssertResult(fsBuilder->enableFeature(
37 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
jvanverth@google.comd830d132013-11-11 20:54:09 +000038
joshualitt2dd1ae02014-12-03 06:24:10 -080039 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
joshualitt74077b92014-10-24 11:26:03 -070040 GrGLVertToFrag v(kVec2f_GrSLType);
41 args.fPB->addVarying("TextureCoords", &v);
joshualitt2dd1ae02014-12-03 06:24:10 -080042 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000043
joshualitt2dd1ae02014-12-03 06:24:10 -080044 // setup color attribute
45 if(dfTexEffect.inColor()) {
46 args.fPB->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
47 }
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000048
joshualitt4973d9d2014-11-08 09:24:25 -080049 // setup position varying
50 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(),
joshualitt2dd1ae02014-12-03 06:24:10 -080051 vsBuilder->uViewM(), dfTexEffect.inPosition()->fName);
52
53 // setup output coords
54 vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(),
55 dfTexEffect.inPosition()->fName);
56 vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(),
57 dfTexEffect.inPosition()->fName);
joshualitt4973d9d2014-11-08 09:24:25 -080058
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000059 const char* textureSizeUniName = NULL;
joshualittc369e7c2014-10-22 10:56:26 -070060 fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -080061 kVec2f_GrSLType, kDefault_GrSLPrecision,
62 "TextureSize", &textureSizeUniName);
jvanverth@google.comd830d132013-11-11 20:54:09 +000063
joshualitt30ba4362014-08-21 20:18:45 -070064 fsBuilder->codeAppend("\tvec4 texColor = ");
joshualittc369e7c2014-10-22 10:56:26 -070065 fsBuilder->appendTextureLookup(args.fSamplers[0],
joshualitt74077b92014-10-24 11:26:03 -070066 v.fsIn(),
jvanverth@google.comd830d132013-11-11 20:54:09 +000067 kVec2f_GrSLType);
joshualitt30ba4362014-08-21 20:18:45 -070068 fsBuilder->codeAppend(";\n");
69 fsBuilder->codeAppend("\tfloat distance = "
jvanverthada68ef2014-11-03 14:00:24 -080070 SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000071
72 // we adjust for the effect of the transformation on the distance by using
73 // the length of the gradient of the texture coordinates. We use st coordinates
74 // to ensure we're mapping 1:1 from texel space to pixel space.
joshualitt74077b92014-10-24 11:26:03 -070075 fsBuilder->codeAppendf("\tvec2 uv = %s;\n", v.fsIn());
joshualitt30ba4362014-08-21 20:18:45 -070076 fsBuilder->codeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName);
77 fsBuilder->codeAppend("\tfloat afwidth;\n");
jvanverth78f07182014-07-30 06:17:59 -070078 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
commit-bot@chromium.org4362a382014-03-26 19:49:03 +000079 // this gives us a smooth step across approximately one fragment
jvanverthfa38a302014-10-06 05:59:05 -070080 fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));\n");
commit-bot@chromium.org4362a382014-03-26 19:49:03 +000081 } else {
joshualitt30ba4362014-08-21 20:18:45 -070082 fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n");
83 fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n");
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000084
joshualitt30ba4362014-08-21 20:18:45 -070085 fsBuilder->codeAppend("\tvec2 uv_grad;\n");
joshualittc369e7c2014-10-22 10:56:26 -070086 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
commit-bot@chromium.org4362a382014-03-26 19:49:03 +000087 // this is to compensate for the Adreno, which likes to drop tiles on division by 0
joshualitt30ba4362014-08-21 20:18:45 -070088 fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
89 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
90 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
91 fsBuilder->codeAppend("\t} else {\n");
92 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
93 fsBuilder->codeAppend("\t}\n");
commit-bot@chromium.org4362a382014-03-26 19:49:03 +000094 } else {
joshualitt30ba4362014-08-21 20:18:45 -070095 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
commit-bot@chromium.org4362a382014-03-26 19:49:03 +000096 }
joshualitt30ba4362014-08-21 20:18:45 -070097 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
98 fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
commit-bot@chromium.org4362a382014-03-26 19:49:03 +000099
100 // this gives us a smooth step across approximately one fragment
joshualitt30ba4362014-08-21 20:18:45 -0700101 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000102 }
joshualitt30ba4362014-08-21 20:18:45 -0700103 fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n");
jvanverth@google.comd830d132013-11-11 20:54:09 +0000104
jvanverth2d2a68c2014-06-10 06:42:56 -0700105#ifdef SK_GAMMA_APPLY_TO_A8
106 // adjust based on gamma
107 const char* luminanceUniName = NULL;
108 // width, height, 1/(3*width)
joshualittc369e7c2014-10-22 10:56:26 -0700109 fLuminanceUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800110 kFloat_GrSLType, kDefault_GrSLPrecision,
111 "Luminance", &luminanceUniName);
jvanverth2d2a68c2014-06-10 06:42:56 -0700112
joshualitt30ba4362014-08-21 20:18:45 -0700113 fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
114 fsBuilder->codeAppend("\tvec4 gammaColor = ");
joshualittc369e7c2014-10-22 10:56:26 -0700115 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
joshualitt30ba4362014-08-21 20:18:45 -0700116 fsBuilder->codeAppend(";\n");
117 fsBuilder->codeAppend("\tval = gammaColor.r;\n");
jvanverth2d2a68c2014-06-10 06:42:56 -0700118#endif
119
joshualitt2dd1ae02014-12-03 06:24:10 -0800120 fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000121 }
122
kkinnunen7510b222014-07-30 00:04:16 -0700123 virtual void setData(const GrGLProgramDataManager& pdman,
joshualitt87f48d92014-12-04 10:41:40 -0800124 const GrGeometryProcessor& proc,
125 const GrBatchTracker&) SK_OVERRIDE {
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000126 SkASSERT(fTextureSizeUni.isValid());
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000127
joshualitt87f48d92014-12-04 10:41:40 -0800128 GrTexture* texture = proc.texture(0);
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000129 if (texture->width() != fTextureSize.width() ||
130 texture->height() != fTextureSize.height()) {
131 fTextureSize = SkISize::Make(texture->width(), texture->height());
kkinnunen7510b222014-07-30 00:04:16 -0700132 pdman.set2f(fTextureSizeUni,
133 SkIntToScalar(fTextureSize.width()),
134 SkIntToScalar(fTextureSize.height()));
commit-bot@chromium.org66beaf02014-03-26 18:21:55 +0000135 }
jvanverth2d2a68c2014-06-10 06:42:56 -0700136#ifdef SK_GAMMA_APPLY_TO_A8
137 const GrDistanceFieldTextureEffect& dfTexEffect =
joshualitt87f48d92014-12-04 10:41:40 -0800138 proc.cast<GrDistanceFieldTextureEffect>();
jvanverth2d2a68c2014-06-10 06:42:56 -0700139 float luminance = dfTexEffect.getLuminance();
140 if (luminance != fLuminance) {
kkinnunen7510b222014-07-30 00:04:16 -0700141 pdman.set1f(fLuminanceUni, luminance);
jvanverth2d2a68c2014-06-10 06:42:56 -0700142 fLuminance = luminance;
143 }
144#endif
commit-bot@chromium.org8fe2ee12014-03-26 18:03:05 +0000145 }
146
joshualitt87f48d92014-12-04 10:41:40 -0800147 static inline void GenKey(const GrGeometryProcessor& processor,
148 const GrBatchTracker&,
149 const GrGLCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700150 GrProcessorKeyBuilder* b) {
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000151 const GrDistanceFieldTextureEffect& dfTexEffect =
joshualittb0a8a372014-09-23 09:50:21 -0700152 processor.cast<GrDistanceFieldTextureEffect>();
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000153
jvanverth78f07182014-07-30 06:17:59 -0700154 b->add32(dfTexEffect.getFlags());
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000155 }
156
jvanverth@google.comd830d132013-11-11 20:54:09 +0000157private:
kkinnunen7510b222014-07-30 00:04:16 -0700158 GrGLProgramDataManager::UniformHandle fTextureSizeUni;
159 SkISize fTextureSize;
160 GrGLProgramDataManager::UniformHandle fLuminanceUni;
161 float fLuminance;
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000162
joshualitt249af152014-09-15 11:41:13 -0700163 typedef GrGLGeometryProcessor INHERITED;
jvanverth@google.comd830d132013-11-11 20:54:09 +0000164};
165
166///////////////////////////////////////////////////////////////////////////////
167
joshualitt2e3b3e32014-12-09 13:31:14 -0800168GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrColor color,
169 GrTexture* texture,
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000170 const GrTextureParams& params,
jvanverth2d2a68c2014-06-10 06:42:56 -0700171#ifdef SK_GAMMA_APPLY_TO_A8
172 GrTexture* gamma,
173 const GrTextureParams& gammaParams,
174 float luminance,
175#endif
jvanverth78f07182014-07-30 06:17:59 -0700176 uint32_t flags)
joshualitt2e3b3e32014-12-09 13:31:14 -0800177 : INHERITED(color)
178 , fTextureAccess(texture, params)
jvanverth2d2a68c2014-06-10 06:42:56 -0700179#ifdef SK_GAMMA_APPLY_TO_A8
180 , fGammaTextureAccess(gamma, gammaParams)
181 , fLuminance(luminance)
182#endif
joshualitt249af152014-09-15 11:41:13 -0700183 , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
joshualitt2dd1ae02014-12-03 06:24:10 -0800184 , fInColor(NULL) {
jvanverth78f07182014-07-30 06:17:59 -0700185 SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
joshualitteb2a6762014-12-04 11:35:33 -0800186 this->initClassID<GrDistanceFieldTextureEffect>();
joshualitt2dd1ae02014-12-03 06:24:10 -0800187 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType));
188 if (flags & kColorAttr_DistanceFieldEffectFlag) {
189 fInColor = &this->addVertexAttrib(GrAttribute("inColor", kVec4ub_GrVertexAttribType));
190 this->setHasVertexColor();
191 }
192 fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords",
193 kVec2f_GrVertexAttribType));
jvanverth@google.comd830d132013-11-11 20:54:09 +0000194 this->addTextureAccess(&fTextureAccess);
jvanverth2d2a68c2014-06-10 06:42:56 -0700195#ifdef SK_GAMMA_APPLY_TO_A8
196 this->addTextureAccess(&fGammaTextureAccess);
197#endif
jvanverth@google.comd830d132013-11-11 20:54:09 +0000198}
199
bsalomon0e08fc12014-10-15 08:19:04 -0700200bool GrDistanceFieldTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
joshualitt49586be2014-09-16 08:21:41 -0700201 const GrDistanceFieldTextureEffect& cte = other.cast<GrDistanceFieldTextureEffect>();
bsalomon420d7e92014-10-16 09:18:09 -0700202 return
jvanverth78f07182014-07-30 06:17:59 -0700203#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth78f07182014-07-30 06:17:59 -0700204 fLuminance == cte.fLuminance &&
205#endif
206 fFlags == cte.fFlags;
jvanverth@google.comd830d132013-11-11 20:54:09 +0000207}
208
egdaniel605dd0f2014-11-12 08:35:25 -0800209void GrDistanceFieldTextureEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
egdanielccb2e382014-10-13 12:53:46 -0700210 inout->mulByUnknownAlpha();
jvanverth@google.comd830d132013-11-11 20:54:09 +0000211}
212
joshualitteb2a6762014-12-04 11:35:33 -0800213void GrDistanceFieldTextureEffect::getGLProcessorKey(const GrBatchTracker& bt,
214 const GrGLCaps& caps,
215 GrProcessorKeyBuilder* b) const {
216 GrGLDistanceFieldTextureEffect::GenKey(*this, bt, caps, b);
217}
218
219GrGLGeometryProcessor*
220GrDistanceFieldTextureEffect::createGLInstance(const GrBatchTracker& bt) const {
221 return SkNEW_ARGS(GrGLDistanceFieldTextureEffect, (*this, bt));
jvanverth@google.comd830d132013-11-11 20:54:09 +0000222}
223
224///////////////////////////////////////////////////////////////////////////////
225
joshualittb0a8a372014-09-23 09:50:21 -0700226GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldTextureEffect);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000227
joshualittb0a8a372014-09-23 09:50:21 -0700228GrGeometryProcessor* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
229 GrContext*,
230 const GrDrawTargetCaps&,
231 GrTexture* textures[]) {
232 int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
233 GrProcessorUnitTest::kAlphaTextureIdx;
jvanverth2d2a68c2014-06-10 06:42:56 -0700234#ifdef SK_GAMMA_APPLY_TO_A8
joshualittb0a8a372014-09-23 09:50:21 -0700235 int texIdx2 = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
236 GrProcessorUnitTest::kAlphaTextureIdx;
jvanverth2d2a68c2014-06-10 06:42:56 -0700237#endif
jvanverth@google.comd830d132013-11-11 20:54:09 +0000238 static const SkShader::TileMode kTileModes[] = {
239 SkShader::kClamp_TileMode,
240 SkShader::kRepeat_TileMode,
241 SkShader::kMirror_TileMode,
242 };
243 SkShader::TileMode tileModes[] = {
244 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
245 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
246 };
247 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
248 GrTextureParams::kNone_FilterMode);
jvanverth2d2a68c2014-06-10 06:42:56 -0700249#ifdef SK_GAMMA_APPLY_TO_A8
250 GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
251 GrTextureParams::kNone_FilterMode);
252#endif
jvanverth@google.comd830d132013-11-11 20:54:09 +0000253
joshualitt2e3b3e32014-12-09 13:31:14 -0800254 return GrDistanceFieldTextureEffect::Create(GrRandomColor(random), textures[texIdx], params,
jvanverth2d2a68c2014-06-10 06:42:56 -0700255#ifdef SK_GAMMA_APPLY_TO_A8
256 textures[texIdx2], params2,
257 random->nextF(),
258#endif
jvanverth78f07182014-07-30 06:17:59 -0700259 random->nextBool() ?
260 kSimilarity_DistanceFieldEffectFlag : 0);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000261}
262
263///////////////////////////////////////////////////////////////////////////////
264
jvanverthfa38a302014-10-06 05:59:05 -0700265class GrGLDistanceFieldNoGammaTextureEffect : public GrGLGeometryProcessor {
266public:
joshualitteb2a6762014-12-04 11:35:33 -0800267 GrGLDistanceFieldNoGammaTextureEffect(const GrGeometryProcessor&,
joshualitt87f48d92014-12-04 10:41:40 -0800268 const GrBatchTracker&)
joshualitteb2a6762014-12-04 11:35:33 -0800269 : fTextureSize(SkISize::Make(-1, -1)) {}
jvanverthfa38a302014-10-06 05:59:05 -0700270
joshualittc369e7c2014-10-22 10:56:26 -0700271 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
jvanverthfa38a302014-10-06 05:59:05 -0700272 const GrDistanceFieldNoGammaTextureEffect& dfTexEffect =
joshualittc369e7c2014-10-22 10:56:26 -0700273 args.fGP.cast<GrDistanceFieldNoGammaTextureEffect>();
jvanverthfa38a302014-10-06 05:59:05 -0700274
joshualittc369e7c2014-10-22 10:56:26 -0700275 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
jvanverthfa38a302014-10-06 05:59:05 -0700276 SkAssertResult(fsBuilder->enableFeature(
277 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
278
joshualitt2dd1ae02014-12-03 06:24:10 -0800279 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
joshualitt74077b92014-10-24 11:26:03 -0700280 GrGLVertToFrag v(kVec2f_GrSLType);
281 args.fPB->addVarying("TextureCoords", &v);
jvanverthfa38a302014-10-06 05:59:05 -0700282
joshualitt2dd1ae02014-12-03 06:24:10 -0800283 // setup color attribute
284 if(dfTexEffect.inColor()) {
285 args.fPB->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
286 }
287
288 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
289
290 // setup coord outputs
291 vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(),
292 dfTexEffect.inPosition()->fName);
293 vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(),
294 dfTexEffect.inPosition()->fName);
jvanverthfa38a302014-10-06 05:59:05 -0700295
joshualitt4973d9d2014-11-08 09:24:25 -0800296 // setup position varying
297 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(),
joshualitt2dd1ae02014-12-03 06:24:10 -0800298 vsBuilder->uViewM(), dfTexEffect.inPosition()->fName);
joshualitt4973d9d2014-11-08 09:24:25 -0800299
jvanverthfa38a302014-10-06 05:59:05 -0700300 const char* textureSizeUniName = NULL;
joshualittc369e7c2014-10-22 10:56:26 -0700301 fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800302 kVec2f_GrSLType, kDefault_GrSLPrecision,
303 "TextureSize", &textureSizeUniName);
jvanverthfa38a302014-10-06 05:59:05 -0700304
305 fsBuilder->codeAppend("vec4 texColor = ");
joshualittc369e7c2014-10-22 10:56:26 -0700306 fsBuilder->appendTextureLookup(args.fSamplers[0],
joshualitt74077b92014-10-24 11:26:03 -0700307 v.fsIn(),
jvanverthfa38a302014-10-06 05:59:05 -0700308 kVec2f_GrSLType);
309 fsBuilder->codeAppend(";");
310 fsBuilder->codeAppend("float distance = "
311 SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");");
312
313 // we adjust for the effect of the transformation on the distance by using
314 // the length of the gradient of the texture coordinates. We use st coordinates
315 // to ensure we're mapping 1:1 from texel space to pixel space.
joshualitt74077b92014-10-24 11:26:03 -0700316 fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn());
jvanverthfa38a302014-10-06 05:59:05 -0700317 fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName);
318 fsBuilder->codeAppend("float afwidth;");
319 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
320 // this gives us a smooth step across approximately one fragment
321 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));");
322 } else {
323 fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
324 fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
325
326 fsBuilder->codeAppend("vec2 uv_grad;");
joshualittc369e7c2014-10-22 10:56:26 -0700327 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
jvanverthfa38a302014-10-06 05:59:05 -0700328 // this is to compensate for the Adreno, which likes to drop tiles on division by 0
329 fsBuilder->codeAppend("float uv_len2 = dot(uv, uv);");
330 fsBuilder->codeAppend("if (uv_len2 < 0.0001) {");
331 fsBuilder->codeAppend("uv_grad = vec2(0.7071, 0.7071);");
332 fsBuilder->codeAppend("} else {");
333 fsBuilder->codeAppend("uv_grad = uv*inversesqrt(uv_len2);");
334 fsBuilder->codeAppend("}");
335 } else {
336 fsBuilder->codeAppend("uv_grad = normalize(uv);");
337 }
338 fsBuilder->codeAppend("vec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,");
339 fsBuilder->codeAppend(" uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);");
340
341 // this gives us a smooth step across approximately one fragment
342 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
343 }
344 fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
345
joshualitt2dd1ae02014-12-03 06:24:10 -0800346 fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
jvanverthfa38a302014-10-06 05:59:05 -0700347 }
348
349 virtual void setData(const GrGLProgramDataManager& pdman,
joshualitt87f48d92014-12-04 10:41:40 -0800350 const GrGeometryProcessor& proc,
351 const GrBatchTracker&) SK_OVERRIDE {
jvanverthfa38a302014-10-06 05:59:05 -0700352 SkASSERT(fTextureSizeUni.isValid());
353
joshualitt87f48d92014-12-04 10:41:40 -0800354 GrTexture* texture = proc.texture(0);
jvanverthfa38a302014-10-06 05:59:05 -0700355 if (texture->width() != fTextureSize.width() ||
356 texture->height() != fTextureSize.height()) {
357 fTextureSize = SkISize::Make(texture->width(), texture->height());
358 pdman.set2f(fTextureSizeUni,
359 SkIntToScalar(fTextureSize.width()),
360 SkIntToScalar(fTextureSize.height()));
361 }
362 }
363
joshualitt87f48d92014-12-04 10:41:40 -0800364 static inline void GenKey(const GrGeometryProcessor& proc,
365 const GrBatchTracker&,
366 const GrGLCaps&,
jvanverthfa38a302014-10-06 05:59:05 -0700367 GrProcessorKeyBuilder* b) {
368 const GrDistanceFieldNoGammaTextureEffect& dfTexEffect =
joshualitt87f48d92014-12-04 10:41:40 -0800369 proc.cast<GrDistanceFieldNoGammaTextureEffect>();
jvanverthfa38a302014-10-06 05:59:05 -0700370
371 b->add32(dfTexEffect.getFlags());
372 }
373
374private:
375 GrGLProgramDataManager::UniformHandle fTextureSizeUni;
376 SkISize fTextureSize;
377
378 typedef GrGLGeometryProcessor INHERITED;
379};
380
381///////////////////////////////////////////////////////////////////////////////
382
joshualitt2e3b3e32014-12-09 13:31:14 -0800383GrDistanceFieldNoGammaTextureEffect::GrDistanceFieldNoGammaTextureEffect(
384 GrColor color,
385 GrTexture* texture,
386 const GrTextureParams& params,
387 uint32_t flags)
388 : INHERITED(color)
389 , fTextureAccess(texture, params)
jvanverthfa38a302014-10-06 05:59:05 -0700390 , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
joshualitt2dd1ae02014-12-03 06:24:10 -0800391 , fInColor(NULL) {
jvanverthfa38a302014-10-06 05:59:05 -0700392 SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
joshualitteb2a6762014-12-04 11:35:33 -0800393 this->initClassID<GrDistanceFieldNoGammaTextureEffect>();
joshualitt2dd1ae02014-12-03 06:24:10 -0800394 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType));
395 if (flags & kColorAttr_DistanceFieldEffectFlag) {
396 fInColor = &this->addVertexAttrib(GrAttribute("inColor", kVec4ub_GrVertexAttribType));
397 this->setHasVertexColor();
398 }
399 fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords",
400 kVec2f_GrVertexAttribType));
jvanverthfa38a302014-10-06 05:59:05 -0700401 this->addTextureAccess(&fTextureAccess);
402}
403
bsalomon0e08fc12014-10-15 08:19:04 -0700404bool GrDistanceFieldNoGammaTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
jvanverthfa38a302014-10-06 05:59:05 -0700405 const GrDistanceFieldNoGammaTextureEffect& cte =
406 other.cast<GrDistanceFieldNoGammaTextureEffect>();
bsalomon420d7e92014-10-16 09:18:09 -0700407 return fFlags == cte.fFlags;
jvanverthfa38a302014-10-06 05:59:05 -0700408}
409
egdaniel605dd0f2014-11-12 08:35:25 -0800410void GrDistanceFieldNoGammaTextureEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
egdanielccb2e382014-10-13 12:53:46 -0700411 inout->mulByUnknownAlpha();
jvanverthfa38a302014-10-06 05:59:05 -0700412}
413
joshualitteb2a6762014-12-04 11:35:33 -0800414void GrDistanceFieldNoGammaTextureEffect::getGLProcessorKey(const GrBatchTracker& bt,
415 const GrGLCaps& caps,
416 GrProcessorKeyBuilder* b) const {
417 GrGLDistanceFieldNoGammaTextureEffect::GenKey(*this, bt, caps, b);
418}
419
420GrGLGeometryProcessor*
421GrDistanceFieldNoGammaTextureEffect::createGLInstance(const GrBatchTracker& bt) const {
422 return SkNEW_ARGS(GrGLDistanceFieldNoGammaTextureEffect, (*this, bt));
jvanverthfa38a302014-10-06 05:59:05 -0700423}
424
425///////////////////////////////////////////////////////////////////////////////
426
427GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldNoGammaTextureEffect);
428
429GrGeometryProcessor* GrDistanceFieldNoGammaTextureEffect::TestCreate(SkRandom* random,
430 GrContext*,
431 const GrDrawTargetCaps&,
432 GrTexture* textures[]) {
433 int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
434 : GrProcessorUnitTest::kAlphaTextureIdx;
435 static const SkShader::TileMode kTileModes[] = {
436 SkShader::kClamp_TileMode,
437 SkShader::kRepeat_TileMode,
438 SkShader::kMirror_TileMode,
439 };
440 SkShader::TileMode tileModes[] = {
441 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
442 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
443 };
444 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode
445 : GrTextureParams::kNone_FilterMode);
446
joshualitt2e3b3e32014-12-09 13:31:14 -0800447 return GrDistanceFieldNoGammaTextureEffect::Create(GrRandomColor(random), textures[texIdx],
448 params,
jvanverthfa38a302014-10-06 05:59:05 -0700449 random->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0);
450}
451
452///////////////////////////////////////////////////////////////////////////////
453
joshualitt249af152014-09-15 11:41:13 -0700454class GrGLDistanceFieldLCDTextureEffect : public GrGLGeometryProcessor {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000455public:
joshualitteb2a6762014-12-04 11:35:33 -0800456 GrGLDistanceFieldLCDTextureEffect(const GrGeometryProcessor&,
joshualitt87f48d92014-12-04 10:41:40 -0800457 const GrBatchTracker&)
joshualitteb2a6762014-12-04 11:35:33 -0800458 : fTextureSize(SkISize::Make(-1,-1))
jvanverth9564ce62014-09-16 05:45:19 -0700459 , fTextColor(GrColor_ILLEGAL) {}
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000460
joshualittc369e7c2014-10-22 10:56:26 -0700461 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000462 const GrDistanceFieldLCDTextureEffect& dfTexEffect =
joshualittc369e7c2014-10-22 10:56:26 -0700463 args.fGP.cast<GrDistanceFieldLCDTextureEffect>();
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000464
joshualittc369e7c2014-10-22 10:56:26 -0700465 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
joshualitt2dd1ae02014-12-03 06:24:10 -0800466 GrGLVertToFrag v(kVec2f_GrSLType);
467 args.fPB->addVarying("TextureCoords", &v);
468 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
469
470 // setup coord outputs
471 vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(),
472 dfTexEffect.inPosition()->fName);
473 vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(),
474 dfTexEffect.inPosition()->fName);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000475
joshualitt4973d9d2014-11-08 09:24:25 -0800476 // setup position varying
477 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(),
joshualitt2dd1ae02014-12-03 06:24:10 -0800478 vsBuilder->uViewM(), dfTexEffect.inPosition()->fName);
joshualitt4973d9d2014-11-08 09:24:25 -0800479
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000480 const char* textureSizeUniName = NULL;
481 // width, height, 1/(3*width)
joshualittc369e7c2014-10-22 10:56:26 -0700482 fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800483 kVec3f_GrSLType, kDefault_GrSLPrecision,
484 "TextureSize", &textureSizeUniName);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000485
joshualittc369e7c2014-10-22 10:56:26 -0700486 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
joshualitt30ba4362014-08-21 20:18:45 -0700487
488 SkAssertResult(fsBuilder->enableFeature(
489 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
490
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000491 // create LCD offset adjusted by inverse of transform
joshualitt74077b92014-10-24 11:26:03 -0700492 fsBuilder->codeAppendf("\tvec2 uv = %s;\n", v.fsIn());
joshualitt30ba4362014-08-21 20:18:45 -0700493 fsBuilder->codeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName);
jvanverth78f07182014-07-30 06:17:59 -0700494 bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
495 if (isUniformScale) {
joshualitt30ba4362014-08-21 20:18:45 -0700496 fsBuilder->codeAppend("\tfloat dx = dFdx(st.x);\n");
497 fsBuilder->codeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", textureSizeUniName);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000498 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700499 fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n");
500 fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n");
501 fsBuilder->codeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUniName);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000502 }
503
504 // green is distance to uv center
joshualitt30ba4362014-08-21 20:18:45 -0700505 fsBuilder->codeAppend("\tvec4 texColor = ");
joshualittc369e7c2014-10-22 10:56:26 -0700506 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv", kVec2f_GrSLType);
joshualitt30ba4362014-08-21 20:18:45 -0700507 fsBuilder->codeAppend(";\n");
508 fsBuilder->codeAppend("\tvec3 distance;\n");
509 fsBuilder->codeAppend("\tdistance.y = texColor.r;\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000510 // red is distance to left offset
joshualitt30ba4362014-08-21 20:18:45 -0700511 fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n");
512 fsBuilder->codeAppend("\ttexColor = ");
joshualittc369e7c2014-10-22 10:56:26 -0700513 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
joshualitt30ba4362014-08-21 20:18:45 -0700514 fsBuilder->codeAppend(";\n");
515 fsBuilder->codeAppend("\tdistance.x = texColor.r;\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000516 // blue is distance to right offset
joshualitt30ba4362014-08-21 20:18:45 -0700517 fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
518 fsBuilder->codeAppend("\ttexColor = ");
joshualittc369e7c2014-10-22 10:56:26 -0700519 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType);
joshualitt30ba4362014-08-21 20:18:45 -0700520 fsBuilder->codeAppend(";\n");
521 fsBuilder->codeAppend("\tdistance.z = texColor.r;\n");
jvanverth2d2a68c2014-06-10 06:42:56 -0700522
joshualitt30ba4362014-08-21 20:18:45 -0700523 fsBuilder->codeAppend("\tdistance = "
jvanverthada68ef2014-11-03 14:00:24 -0800524 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
jvanverth2d2a68c2014-06-10 06:42:56 -0700525
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000526 // we adjust for the effect of the transformation on the distance by using
527 // the length of the gradient of the texture coordinates. We use st coordinates
528 // to ensure we're mapping 1:1 from texel space to pixel space.
529
530 // To be strictly correct, we should compute the anti-aliasing factor separately
531 // for each color component. However, this is only important when using perspective
532 // transformations, and even then using a single factor seems like a reasonable
533 // trade-off between quality and speed.
joshualitt30ba4362014-08-21 20:18:45 -0700534 fsBuilder->codeAppend("\tfloat afwidth;\n");
jvanverth78f07182014-07-30 06:17:59 -0700535 if (isUniformScale) {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000536 // this gives us a smooth step across approximately one fragment
jvanverthfa38a302014-10-06 05:59:05 -0700537 fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*dx);\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000538 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700539 fsBuilder->codeAppend("\tvec2 uv_grad;\n");
joshualittc369e7c2014-10-22 10:56:26 -0700540 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000541 // this is to compensate for the Adreno, which likes to drop tiles on division by 0
joshualitt30ba4362014-08-21 20:18:45 -0700542 fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
543 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
544 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
545 fsBuilder->codeAppend("\t} else {\n");
546 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
547 fsBuilder->codeAppend("\t}\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000548 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700549 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000550 }
joshualitt30ba4362014-08-21 20:18:45 -0700551 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
552 fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000553
554 // this gives us a smooth step across approximately one fragment
joshualitt30ba4362014-08-21 20:18:45 -0700555 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000556 }
557
joshualitt30ba4362014-08-21 20:18:45 -0700558 fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000559
jvanverth2d2a68c2014-06-10 06:42:56 -0700560 // adjust based on gamma
561 const char* textColorUniName = NULL;
562 // width, height, 1/(3*width)
joshualittc369e7c2014-10-22 10:56:26 -0700563 fTextColorUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800564 kVec3f_GrSLType, kDefault_GrSLPrecision,
565 "TextColor", &textColorUniName);
jvanverth2d2a68c2014-06-10 06:42:56 -0700566
joshualitt30ba4362014-08-21 20:18:45 -0700567 fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
568 fsBuilder->codeAppend("\tvec4 gammaColor = ");
joshualittc369e7c2014-10-22 10:56:26 -0700569 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
joshualitt30ba4362014-08-21 20:18:45 -0700570 fsBuilder->codeAppend(";\n");
571 fsBuilder->codeAppend("\tval.x = gammaColor.r;\n");
jvanverth2d2a68c2014-06-10 06:42:56 -0700572
joshualitt30ba4362014-08-21 20:18:45 -0700573 fsBuilder->codeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName);
574 fsBuilder->codeAppend("\tgammaColor = ");
joshualittc369e7c2014-10-22 10:56:26 -0700575 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
joshualitt30ba4362014-08-21 20:18:45 -0700576 fsBuilder->codeAppend(";\n");
577 fsBuilder->codeAppend("\tval.y = gammaColor.r;\n");
jvanverth2d2a68c2014-06-10 06:42:56 -0700578
joshualitt30ba4362014-08-21 20:18:45 -0700579 fsBuilder->codeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName);
580 fsBuilder->codeAppend("\tgammaColor = ");
joshualittc369e7c2014-10-22 10:56:26 -0700581 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
joshualitt30ba4362014-08-21 20:18:45 -0700582 fsBuilder->codeAppend(";\n");
583 fsBuilder->codeAppend("\tval.z = gammaColor.r;\n");
jvanverth2d2a68c2014-06-10 06:42:56 -0700584
joshualitt2dd1ae02014-12-03 06:24:10 -0800585 fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000586 }
587
kkinnunen7510b222014-07-30 00:04:16 -0700588 virtual void setData(const GrGLProgramDataManager& pdman,
joshualitt87f48d92014-12-04 10:41:40 -0800589 const GrGeometryProcessor& processor,
590 const GrBatchTracker&) SK_OVERRIDE {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000591 SkASSERT(fTextureSizeUni.isValid());
jvanverth2d2a68c2014-06-10 06:42:56 -0700592 SkASSERT(fTextColorUni.isValid());
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000593
jvanverth2d2a68c2014-06-10 06:42:56 -0700594 const GrDistanceFieldLCDTextureEffect& dfTexEffect =
joshualittb0a8a372014-09-23 09:50:21 -0700595 processor.cast<GrDistanceFieldLCDTextureEffect>();
596 GrTexture* texture = processor.texture(0);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000597 if (texture->width() != fTextureSize.width() ||
598 texture->height() != fTextureSize.height()) {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000599 fTextureSize = SkISize::Make(texture->width(), texture->height());
600 float delta = 1.0f/(3.0f*texture->width());
jvanverth78f07182014-07-30 06:17:59 -0700601 if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000602 delta = -delta;
603 }
kkinnunen7510b222014-07-30 00:04:16 -0700604 pdman.set3f(fTextureSizeUni,
605 SkIntToScalar(fTextureSize.width()),
606 SkIntToScalar(fTextureSize.height()),
607 delta);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000608 }
jvanverth2d2a68c2014-06-10 06:42:56 -0700609
610 GrColor textColor = dfTexEffect.getTextColor();
611 if (textColor != fTextColor) {
612 static const float ONE_OVER_255 = 1.f / 255.f;
kkinnunen7510b222014-07-30 00:04:16 -0700613 pdman.set3f(fTextColorUni,
614 GrColorUnpackR(textColor) * ONE_OVER_255,
615 GrColorUnpackG(textColor) * ONE_OVER_255,
616 GrColorUnpackB(textColor) * ONE_OVER_255);
jvanverth2d2a68c2014-06-10 06:42:56 -0700617 fTextColor = textColor;
618 }
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000619 }
620
joshualitt87f48d92014-12-04 10:41:40 -0800621 static inline void GenKey(const GrGeometryProcessor& processor,
622 const GrBatchTracker&,
623 const GrGLCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700624 GrProcessorKeyBuilder* b) {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000625 const GrDistanceFieldLCDTextureEffect& dfTexEffect =
joshualittb0a8a372014-09-23 09:50:21 -0700626 processor.cast<GrDistanceFieldLCDTextureEffect>();
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000627
jvanverth78f07182014-07-30 06:17:59 -0700628 b->add32(dfTexEffect.getFlags());
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000629 }
630
631private:
kkinnunen7510b222014-07-30 00:04:16 -0700632 GrGLProgramDataManager::UniformHandle fTextureSizeUni;
633 SkISize fTextureSize;
634 GrGLProgramDataManager::UniformHandle fTextColorUni;
635 SkColor fTextColor;
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000636
joshualitt249af152014-09-15 11:41:13 -0700637 typedef GrGLGeometryProcessor INHERITED;
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000638};
639
640///////////////////////////////////////////////////////////////////////////////
641
jvanverth2d2a68c2014-06-10 06:42:56 -0700642GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
joshualitt2e3b3e32014-12-09 13:31:14 -0800643 GrColor color,
jvanverth2d2a68c2014-06-10 06:42:56 -0700644 GrTexture* texture, const GrTextureParams& params,
645 GrTexture* gamma, const GrTextureParams& gParams,
646 SkColor textColor,
jvanverth78f07182014-07-30 06:17:59 -0700647 uint32_t flags)
joshualitt2e3b3e32014-12-09 13:31:14 -0800648 : INHERITED(color)
649 , fTextureAccess(texture, params)
jvanverth2d2a68c2014-06-10 06:42:56 -0700650 , fGammaTextureAccess(gamma, gParams)
651 , fTextColor(textColor)
joshualitt2dd1ae02014-12-03 06:24:10 -0800652 , fFlags(flags & kLCD_DistanceFieldEffectMask){
jvanverth78f07182014-07-30 06:17:59 -0700653 SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
joshualitteb2a6762014-12-04 11:35:33 -0800654 this->initClassID<GrDistanceFieldLCDTextureEffect>();
joshualitt2dd1ae02014-12-03 06:24:10 -0800655 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType));
656 fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords",
657 kVec2f_GrVertexAttribType));
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000658 this->addTextureAccess(&fTextureAccess);
jvanverth2d2a68c2014-06-10 06:42:56 -0700659 this->addTextureAccess(&fGammaTextureAccess);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000660}
661
bsalomon0e08fc12014-10-15 08:19:04 -0700662bool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
joshualitt49586be2014-09-16 08:21:41 -0700663 const GrDistanceFieldLCDTextureEffect& cte = other.cast<GrDistanceFieldLCDTextureEffect>();
bsalomon420d7e92014-10-16 09:18:09 -0700664 return (fTextColor == cte.fTextColor &&
jvanverth78f07182014-07-30 06:17:59 -0700665 fFlags == cte.fFlags);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000666}
667
egdaniel605dd0f2014-11-12 08:35:25 -0800668void GrDistanceFieldLCDTextureEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
egdanielccb2e382014-10-13 12:53:46 -0700669 inout->mulByUnknownColor();
egdaniel309e3462014-12-09 10:35:58 -0800670 inout->setUsingLCDCoverage();
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000671}
672
joshualitteb2a6762014-12-04 11:35:33 -0800673void GrDistanceFieldLCDTextureEffect::getGLProcessorKey(const GrBatchTracker& bt,
674 const GrGLCaps& caps,
675 GrProcessorKeyBuilder* b) const {
676 GrGLDistanceFieldLCDTextureEffect::GenKey(*this, bt, caps, b);
677}
678
679GrGLGeometryProcessor*
680GrDistanceFieldLCDTextureEffect::createGLInstance(const GrBatchTracker& bt) const {
681 return SkNEW_ARGS(GrGLDistanceFieldLCDTextureEffect, (*this, bt));
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000682}
683
684///////////////////////////////////////////////////////////////////////////////
685
joshualittb0a8a372014-09-23 09:50:21 -0700686GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextureEffect);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000687
joshualittb0a8a372014-09-23 09:50:21 -0700688GrGeometryProcessor* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random,
689 GrContext*,
690 const GrDrawTargetCaps&,
691 GrTexture* textures[]) {
692 int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
693 GrProcessorUnitTest::kAlphaTextureIdx;
694 int texIdx2 = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
695 GrProcessorUnitTest::kAlphaTextureIdx;
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000696 static const SkShader::TileMode kTileModes[] = {
697 SkShader::kClamp_TileMode,
698 SkShader::kRepeat_TileMode,
699 SkShader::kMirror_TileMode,
700 };
701 SkShader::TileMode tileModes[] = {
702 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
703 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
704 };
705 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
706 GrTextureParams::kNone_FilterMode);
jvanverth2d2a68c2014-06-10 06:42:56 -0700707 GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
708 GrTextureParams::kNone_FilterMode);
709 GrColor textColor = GrColorPackRGBA(random->nextULessThan(256),
710 random->nextULessThan(256),
711 random->nextULessThan(256),
712 random->nextULessThan(256));
jvanverth78f07182014-07-30 06:17:59 -0700713 uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
714 flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
715 flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
joshualitt2e3b3e32014-12-09 13:31:14 -0800716 return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random), textures[texIdx], params,
jvanverth2d2a68c2014-06-10 06:42:56 -0700717 textures[texIdx2], params2,
718 textColor,
jvanverth78f07182014-07-30 06:17:59 -0700719 flags);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000720}