blob: 9a7e78757776c290f1a1078d4d6658ae381194ed [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
jvanverth8ed3b9a2015-04-09 08:00:49 -07008#include "GrDistanceFieldGeoProc.h"
joshualitteb2a6762014-12-04 11:35:33 -08009#include "GrTexture.h"
10#include "SkDistanceFieldGen.h"
egdaniel2d721d32015-11-11 13:06:05 -080011#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniele659a582015-11-13 09:55:43 -080012#include "glsl/GrGLSLGeometryProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -070013#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080014#include "glsl/GrGLSLUniformHandler.h"
egdaniel64c47282015-11-13 06:54:19 -080015#include "glsl/GrGLSLUtil.h"
egdaniel0eafe792015-11-20 14:01:22 -080016#include "glsl/GrGLSLVarying.h"
17#include "glsl/GrGLSLVertexShaderBuilder.h"
jvanverth@google.comd830d132013-11-11 20:54:09 +000018
jvanverth21deace2015-04-01 12:43:48 -070019// Assuming a radius of a little less than the diagonal of the fragment
jvanverth24ba0082015-03-19 11:34:13 -070020#define SK_DistanceFieldAAFactor "0.65"
jvanverth2d2a68c2014-06-10 06:42:56 -070021
egdaniele659a582015-11-13 09:55:43 -080022class GrGLDistanceFieldA8TextGeoProc : public GrGLSLGeometryProcessor {
jvanverth@google.comd830d132013-11-11 20:54:09 +000023public:
joshualitt465283c2015-09-11 08:19:35 -070024 GrGLDistanceFieldA8TextGeoProc()
joshualitt5559ca22015-05-21 15:50:36 -070025 : fViewMatrix(SkMatrix::InvalidMatrix())
jvanverth9564ce62014-09-16 05:45:19 -070026#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth21deace2015-04-01 12:43:48 -070027 , fDistanceAdjust(-1.0f)
jvanverth9564ce62014-09-16 05:45:19 -070028#endif
29 {}
jvanverth@google.comd830d132013-11-11 20:54:09 +000030
mtklein36352bf2015-03-25 18:17:31 -070031 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
jvanverth502286d2015-04-08 12:37:51 -070032 const GrDistanceFieldA8TextGeoProc& dfTexEffect =
33 args.fGP.cast<GrDistanceFieldA8TextGeoProc>();
cdalton85285412016-02-18 12:37:07 -080034 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
jvanverth@google.comd830d132013-11-11 20:54:09 +000035
egdaniel4ca2e602015-11-18 08:01:26 -080036 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
egdaniel0eafe792015-11-20 14:01:22 -080037 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
egdaniel7ea439b2015-12-03 09:20:44 -080038 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
joshualittabb52a12015-01-13 15:02:10 -080039
40 // emit attributes
egdaniel0eafe792015-11-20 14:01:22 -080041 varyingHandler->emitAttributes(dfTexEffect);
joshualittabb52a12015-01-13 15:02:10 -080042
jvanverth21deace2015-04-01 12:43:48 -070043#ifdef SK_GAMMA_APPLY_TO_A8
44 // adjust based on gamma
halcanary96fcdcc2015-08-27 07:41:13 -070045 const char* distanceAdjustUniName = nullptr;
jvanverth21deace2015-04-01 12:43:48 -070046 // width, height, 1/(3*width)
cdalton5e58cee2016-02-11 12:49:47 -080047 fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -080048 kFloat_GrSLType, kDefault_GrSLPrecision,
49 "DistanceAdjust", &distanceAdjustUniName);
jvanverth21deace2015-04-01 12:43:48 -070050#endif
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000051
joshualitt9b989322014-12-15 14:16:27 -080052 // Setup pass through color
Brian Salomonbfd51832017-01-04 13:22:08 -050053 varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000054
joshualittabb52a12015-01-13 15:02:10 -080055 // Setup position
egdaniel7ea439b2015-12-03 09:20:44 -080056 this->setupPosition(vertBuilder,
57 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -080058 gpArgs,
59 dfTexEffect.inPosition()->fName,
60 dfTexEffect.viewMatrix(),
joshualitt5559ca22015-05-21 15:50:36 -070061 &fViewMatrixUniform);
joshualitt2dd1ae02014-12-03 06:24:10 -080062
joshualittabb52a12015-01-13 15:02:10 -080063 // emit transforms
egdaniel7ea439b2015-12-03 09:20:44 -080064 this->emitTransforms(vertBuilder,
egdaniel0eafe792015-11-20 14:01:22 -080065 varyingHandler,
egdaniel7ea439b2015-12-03 09:20:44 -080066 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -080067 gpArgs->fPositionVar,
68 dfTexEffect.inPosition()->fName,
bsalomona624bf32016-09-20 09:12:47 -070069 args.fFPCoordTransformHandler);
joshualitt4973d9d2014-11-08 09:24:25 -080070
jvanverthbb4a1cf2015-04-07 09:06:00 -070071 // add varyings
egdaniel8dcdedc2015-11-11 06:27:20 -080072 GrGLSLVertToFrag recipScale(kFloat_GrSLType);
jvanverth7023a002016-02-22 11:25:32 -080073 GrGLSLVertToFrag uv(kVec2f_GrSLType);
jvanverthcf371bb2016-03-10 11:10:43 -080074 bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
75 kUniformScale_DistanceFieldEffectMask;
jvanverthbb4a1cf2015-04-07 09:06:00 -070076 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
brianosmanb461d342016-04-13 13:10:14 -070077 bool isGammaCorrect =
78 SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
jvanverth7023a002016-02-22 11:25:32 -080079 varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
80 vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName);
jvanverthbb4a1cf2015-04-07 09:06:00 -070081
jvanverthcf371bb2016-03-10 11:10:43 -080082 // compute numbers to be hardcoded to convert texture coordinates from float to int
Brian Salomon0bbecb22016-11-17 11:38:22 -050083 SkASSERT(dfTexEffect.numTextureSamplers() == 1);
Brian Salomondb4183d2016-11-17 12:48:40 -050084 GrTexture* atlas = dfTexEffect.textureSampler(0).texture();
joshualitt7375d6b2015-08-07 13:36:44 -070085 SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
joshualitt922c8b12015-08-07 09:55:23 -070086
jvanverth7023a002016-02-22 11:25:32 -080087 GrGLSLVertToFrag st(kVec2f_GrSLType);
88 varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
89 vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(),
90 atlas->width(), atlas->height(),
egdaniel4ca2e602015-11-18 08:01:26 -080091 dfTexEffect.inTextureCoords()->fName);
halcanary9d524f22016-03-29 09:03:52 -070092
jvanverthfdf7ccc2015-01-27 08:19:33 -080093 // Use highp to work around aliasing issues
Ethan Nicholas1fc83b12016-11-22 09:31:35 -050094 fragBuilder->codeAppendf("highp vec2 uv = %s;\n", uv.fsIn());
jvanverthfdf7ccc2015-01-27 08:19:33 -080095
egdaniel4ca2e602015-11-18 08:01:26 -080096 fragBuilder->codeAppend("\tfloat texColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -070097 fragBuilder->appendTextureLookup(args.fTexSamplers[0],
egdaniel4ca2e602015-11-18 08:01:26 -080098 "uv",
99 kVec2f_GrSLType);
100 fragBuilder->codeAppend(".r;\n");
101 fragBuilder->codeAppend("\tfloat distance = "
jvanverthfdf7ccc2015-01-27 08:19:33 -0800102 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
jvanverth21deace2015-04-01 12:43:48 -0700103#ifdef SK_GAMMA_APPLY_TO_A8
104 // adjust width based on gamma
egdaniel4ca2e602015-11-18 08:01:26 -0800105 fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
jvanverth21deace2015-04-01 12:43:48 -0700106#endif
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000107
egdaniel4ca2e602015-11-18 08:01:26 -0800108 fragBuilder->codeAppend("float afwidth;");
jvanverthcf371bb2016-03-10 11:10:43 -0800109 if (isUniformScale) {
jvanverth354eba52015-03-16 11:32:49 -0700110 // For uniform scale, we adjust for the effect of the transformation on the distance
halcanary9d524f22016-03-29 09:03:52 -0700111 // by using the length of the gradient of the t coordinate in the y direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800112 // We use st coordinates to ensure we're mapping 1:1 from texel space to pixel space.
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000113
jvanverth354eba52015-03-16 11:32:49 -0700114 // this gives us a smooth step across approximately one fragment
jvanverthe499adf2016-07-20 12:22:14 -0700115#ifdef SK_VULKAN
116 fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(%s.x));",
117 st.fsIn());
118#else
119 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
egdaniel4ca2e602015-11-18 08:01:26 -0800120 fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(%s.y));",
121 st.fsIn());
jvanverthe499adf2016-07-20 12:22:14 -0700122#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800123 } else if (isSimilarity) {
124 // For similarity transform, we adjust the effect of the transformation on the distance
125 // by using the length of the gradient of the texture coordinates. We use st coordinates
126 // to ensure we're mapping 1:1 from texel space to pixel space.
127 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
128
129 // this gives us a smooth step across approximately one fragment
jvanverthe499adf2016-07-20 12:22:14 -0700130#ifdef SK_VULKAN
131 fragBuilder->codeAppendf("float st_grad_len = length(dFdx(%s));", st.fsIn());
132#else
133 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800134 fragBuilder->codeAppendf("float st_grad_len = length(dFdy(%s));", st.fsIn());
jvanverthe499adf2016-07-20 12:22:14 -0700135#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800136 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
jvanverth354eba52015-03-16 11:32:49 -0700137 } else {
138 // For general transforms, to determine the amount of correction we multiply a unit
139 // vector pointing along the SDF gradient direction by the Jacobian of the st coords
140 // (which is the inverse transform for this fragment) and take the length of the result.
egdaniel4ca2e602015-11-18 08:01:26 -0800141 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
jvanverthd68a5502015-03-16 12:58:43 -0700142 // the length of the gradient may be 0, so we need to check for this
143 // this also compensates for the Adreno, which likes to drop tiles on division by 0
egdaniel4ca2e602015-11-18 08:01:26 -0800144 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
145 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
146 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
147 fragBuilder->codeAppend("} else {");
148 fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
149 fragBuilder->codeAppend("}");
jvanverthd68a5502015-03-16 12:58:43 -0700150
egdaniel4ca2e602015-11-18 08:01:26 -0800151 fragBuilder->codeAppendf("vec2 Jdx = dFdx(%s);", st.fsIn());
152 fragBuilder->codeAppendf("vec2 Jdy = dFdy(%s);", st.fsIn());
153 fragBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
154 fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000155
156 // this gives us a smooth step across approximately one fragment
egdaniel4ca2e602015-11-18 08:01:26 -0800157 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000158 }
brianosman0586f5c2016-04-12 12:48:21 -0700159
160 // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are
161 // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want distance
162 // mapped linearly to coverage, so use a linear step:
brianosmanb461d342016-04-13 13:10:14 -0700163 if (isGammaCorrect) {
brianosman0586f5c2016-04-12 12:48:21 -0700164 fragBuilder->codeAppend(
165 "float val = clamp(distance + afwidth / (2.0 * afwidth), 0.0, 1.0);");
166 } else {
167 fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
168 }
jvanverth@google.comd830d132013-11-11 20:54:09 +0000169
egdaniel4ca2e602015-11-18 08:01:26 -0800170 fragBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000171 }
172
bsalomona624bf32016-09-20 09:12:47 -0700173 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
174 FPCoordTransformIter&& transformIter) override {
jvanverth2d2a68c2014-06-10 06:42:56 -0700175#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth502286d2015-04-08 12:37:51 -0700176 const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>();
jvanverth21deace2015-04-01 12:43:48 -0700177 float distanceAdjust = dfTexEffect.getDistanceAdjust();
178 if (distanceAdjust != fDistanceAdjust) {
179 pdman.set1f(fDistanceAdjustUni, distanceAdjust);
180 fDistanceAdjust = distanceAdjust;
jvanverth2d2a68c2014-06-10 06:42:56 -0700181 }
182#endif
joshualitte578a952015-05-14 10:09:13 -0700183 const GrDistanceFieldA8TextGeoProc& dfa8gp = proc.cast<GrDistanceFieldA8TextGeoProc>();
joshualitt5559ca22015-05-21 15:50:36 -0700184
185 if (!dfa8gp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfa8gp.viewMatrix())) {
186 fViewMatrix = dfa8gp.viewMatrix();
egdaniel018fb622015-10-28 07:26:40 -0700187 float viewMatrix[3 * 3];
egdaniel64c47282015-11-13 06:54:19 -0800188 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
joshualitt5559ca22015-05-21 15:50:36 -0700189 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
190 }
bsalomona624bf32016-09-20 09:12:47 -0700191 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
commit-bot@chromium.org8fe2ee12014-03-26 18:03:05 +0000192 }
193
robertphillips46d36f02015-01-18 08:14:14 -0800194 static inline void GenKey(const GrGeometryProcessor& gp,
Brian Salomon94efbf52016-11-29 13:43:05 -0500195 const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700196 GrProcessorKeyBuilder* b) {
jvanverth502286d2015-04-08 12:37:51 -0700197 const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>();
joshualitt8fc6c2d2014-12-22 15:27:05 -0800198 uint32_t key = dfTexEffect.getFlags();
Brian Salomonbfd51832017-01-04 13:22:08 -0500199 key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
joshualitt8fc6c2d2014-12-22 15:27:05 -0800200 b->add32(key);
joshualitt922c8b12015-08-07 09:55:23 -0700201
202 // Currently we hardcode numbers to convert atlas coordinates to normalized floating point
Brian Salomon0bbecb22016-11-17 11:38:22 -0500203 SkASSERT(gp.numTextureSamplers() == 1);
Brian Salomondb4183d2016-11-17 12:48:40 -0500204 GrTexture* atlas = gp.textureSampler(0).texture();
joshualitt922c8b12015-08-07 09:55:23 -0700205 SkASSERT(atlas);
206 b->add32(atlas->width());
207 b->add32(atlas->height());
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000208 }
209
jvanverth@google.comd830d132013-11-11 20:54:09 +0000210private:
joshualitt5559ca22015-05-21 15:50:36 -0700211 SkMatrix fViewMatrix;
joshualitt5559ca22015-05-21 15:50:36 -0700212 UniformHandle fViewMatrixUniform;
mtklein50282b42015-01-22 07:59:52 -0800213#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth21deace2015-04-01 12:43:48 -0700214 float fDistanceAdjust;
215 UniformHandle fDistanceAdjustUni;
mtklein50282b42015-01-22 07:59:52 -0800216#endif
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000217
egdaniele659a582015-11-13 09:55:43 -0800218 typedef GrGLSLGeometryProcessor INHERITED;
jvanverth@google.comd830d132013-11-11 20:54:09 +0000219};
220
221///////////////////////////////////////////////////////////////////////////////
222
jvanverth502286d2015-04-08 12:37:51 -0700223GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800224 const SkMatrix& viewMatrix,
joshualitt2e3b3e32014-12-09 13:31:14 -0800225 GrTexture* texture,
Brian Salomon514baff2016-11-17 15:17:07 -0500226 const GrSamplerParams& params,
jvanverth2d2a68c2014-06-10 06:42:56 -0700227#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth21deace2015-04-01 12:43:48 -0700228 float distanceAdjust,
jvanverth2d2a68c2014-06-10 06:42:56 -0700229#endif
joshualittb8c241a2015-05-19 08:23:30 -0700230 uint32_t flags,
231 bool usesLocalCoords)
joshualitte3ababe2015-05-15 07:56:07 -0700232 : fColor(color)
joshualitte578a952015-05-14 10:09:13 -0700233 , fViewMatrix(viewMatrix)
Brian Salomon0bbecb22016-11-17 11:38:22 -0500234 , fTextureSampler(texture, params)
jvanverth2d2a68c2014-06-10 06:42:56 -0700235#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth21deace2015-04-01 12:43:48 -0700236 , fDistanceAdjust(distanceAdjust)
jvanverth2d2a68c2014-06-10 06:42:56 -0700237#endif
joshualitt249af152014-09-15 11:41:13 -0700238 , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
halcanary96fcdcc2015-08-27 07:41:13 -0700239 , fInColor(nullptr)
joshualittb8c241a2015-05-19 08:23:30 -0700240 , fUsesLocalCoords(usesLocalCoords) {
jvanverth78f07182014-07-30 06:17:59 -0700241 SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
jvanverth502286d2015-04-08 12:37:51 -0700242 this->initClassID<GrDistanceFieldA8TextGeoProc>();
bsalomon6cb807b2016-08-17 11:33:39 -0700243 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
244 kHigh_GrSLPrecision);
245 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
246 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType,
247 kHigh_GrSLPrecision);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500248 this->addTextureSampler(&fTextureSampler);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000249}
250
Brian Salomon94efbf52016-11-29 13:43:05 -0500251void GrDistanceFieldA8TextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800252 GrProcessorKeyBuilder* b) const {
joshualitt465283c2015-09-11 08:19:35 -0700253 GrGLDistanceFieldA8TextGeoProc::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800254}
255
Brian Salomon94efbf52016-11-29 13:43:05 -0500256GrGLSLPrimitiveProcessor*
257GrDistanceFieldA8TextGeoProc::createGLSLInstance(const GrShaderCaps&) const {
joshualitt465283c2015-09-11 08:19:35 -0700258 return new GrGLDistanceFieldA8TextGeoProc();
jvanverth@google.comd830d132013-11-11 20:54:09 +0000259}
260
261///////////////////////////////////////////////////////////////////////////////
262
jvanverth502286d2015-04-08 12:37:51 -0700263GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldA8TextGeoProc);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000264
Hal Canary6f6961e2017-01-31 13:50:44 -0500265#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700266sk_sp<GrGeometryProcessor> GrDistanceFieldA8TextGeoProc::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700267 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
268 GrProcessorUnitTest::kAlphaTextureIdx;
jvanverth@google.comd830d132013-11-11 20:54:09 +0000269 static const SkShader::TileMode kTileModes[] = {
270 SkShader::kClamp_TileMode,
271 SkShader::kRepeat_TileMode,
272 SkShader::kMirror_TileMode,
273 };
274 SkShader::TileMode tileModes[] = {
joshualitt0067ff52015-07-08 14:26:19 -0700275 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
276 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
jvanverth@google.comd830d132013-11-11 20:54:09 +0000277 };
Brian Salomon514baff2016-11-17 15:17:07 -0500278 GrSamplerParams params(tileModes, d->fRandom->nextBool() ? GrSamplerParams::kBilerp_FilterMode
279 : GrSamplerParams::kNone_FilterMode);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000280
jvanverthcf371bb2016-03-10 11:10:43 -0800281 uint32_t flags = 0;
282 flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0;
283 if (flags & kSimilarity_DistanceFieldEffectFlag) {
284 flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0;
285 }
286
bungeman06ca8ec2016-06-09 08:01:03 -0700287 return GrDistanceFieldA8TextGeoProc::Make(GrRandomColor(d->fRandom),
288 GrTest::TestMatrix(d->fRandom),
289 d->fTextures[texIdx], params,
jvanverth2d2a68c2014-06-10 06:42:56 -0700290#ifdef SK_GAMMA_APPLY_TO_A8
bungeman06ca8ec2016-06-09 08:01:03 -0700291 d->fRandom->nextF(),
jvanverth2d2a68c2014-06-10 06:42:56 -0700292#endif
bungeman06ca8ec2016-06-09 08:01:03 -0700293 flags,
294 d->fRandom->nextBool());
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000295}
Hal Canary6f6961e2017-01-31 13:50:44 -0500296#endif
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000297
298///////////////////////////////////////////////////////////////////////////////
299
egdaniele659a582015-11-13 09:55:43 -0800300class GrGLDistanceFieldPathGeoProc : public GrGLSLGeometryProcessor {
jvanverthfa38a302014-10-06 05:59:05 -0700301public:
joshualitt465283c2015-09-11 08:19:35 -0700302 GrGLDistanceFieldPathGeoProc()
joshualitt5559ca22015-05-21 15:50:36 -0700303 : fViewMatrix(SkMatrix::InvalidMatrix())
joshualitt5559ca22015-05-21 15:50:36 -0700304 , fTextureSize(SkISize::Make(-1, -1)) {}
jvanverthfa38a302014-10-06 05:59:05 -0700305
mtklein36352bf2015-03-25 18:17:31 -0700306 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
jvanverth502286d2015-04-08 12:37:51 -0700307 const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>();
jvanverthfa38a302014-10-06 05:59:05 -0700308
cdalton85285412016-02-18 12:37:07 -0800309 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
jvanverthfa38a302014-10-06 05:59:05 -0700310
egdaniel4ca2e602015-11-18 08:01:26 -0800311 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
egdaniel0eafe792015-11-20 14:01:22 -0800312 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
egdaniel7ea439b2015-12-03 09:20:44 -0800313 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
joshualittabb52a12015-01-13 15:02:10 -0800314
315 // emit attributes
egdaniel0eafe792015-11-20 14:01:22 -0800316 varyingHandler->emitAttributes(dfTexEffect);
joshualittabb52a12015-01-13 15:02:10 -0800317
egdaniel8dcdedc2015-11-11 06:27:20 -0800318 GrGLSLVertToFrag v(kVec2f_GrSLType);
egdaniel0eafe792015-11-20 14:01:22 -0800319 varyingHandler->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
jvanverthfa38a302014-10-06 05:59:05 -0700320
joshualitt9b989322014-12-15 14:16:27 -0800321 // setup pass through color
Brian Salomonbfd51832017-01-04 13:22:08 -0500322 varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
egdaniel4ca2e602015-11-18 08:01:26 -0800323 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
reede4ef1ca2015-02-17 18:38:38 -0800324
joshualittabb52a12015-01-13 15:02:10 -0800325 // Setup position
egdaniel7ea439b2015-12-03 09:20:44 -0800326 this->setupPosition(vertBuilder,
327 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -0800328 gpArgs,
329 dfTexEffect.inPosition()->fName,
330 dfTexEffect.viewMatrix(),
joshualitt5559ca22015-05-21 15:50:36 -0700331 &fViewMatrixUniform);
joshualittabb52a12015-01-13 15:02:10 -0800332
333 // emit transforms
egdaniel7ea439b2015-12-03 09:20:44 -0800334 this->emitTransforms(vertBuilder,
egdaniel0eafe792015-11-20 14:01:22 -0800335 varyingHandler,
egdaniel7ea439b2015-12-03 09:20:44 -0800336 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -0800337 gpArgs->fPositionVar,
338 dfTexEffect.inPosition()->fName,
bsalomona624bf32016-09-20 09:12:47 -0700339 args.fFPCoordTransformHandler);
joshualitt4973d9d2014-11-08 09:24:25 -0800340
halcanary96fcdcc2015-08-27 07:41:13 -0700341 const char* textureSizeUniName = nullptr;
cdalton5e58cee2016-02-11 12:49:47 -0800342 fTextureSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800343 kVec2f_GrSLType, kDefault_GrSLPrecision,
344 "TextureSize", &textureSizeUniName);
reede4ef1ca2015-02-17 18:38:38 -0800345
jvanverthfdf7ccc2015-01-27 08:19:33 -0800346 // Use highp to work around aliasing issues
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500347 fragBuilder->codeAppendf("highp vec2 uv = %s;", v.fsIn());
jvanverthfdf7ccc2015-01-27 08:19:33 -0800348
egdaniel4ca2e602015-11-18 08:01:26 -0800349 fragBuilder->codeAppend("float texColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700350 fragBuilder->appendTextureLookup(args.fTexSamplers[0],
egdaniel4ca2e602015-11-18 08:01:26 -0800351 "uv",
352 kVec2f_GrSLType);
353 fragBuilder->codeAppend(".r;");
354 fragBuilder->codeAppend("float distance = "
jvanverthfdf7ccc2015-01-27 08:19:33 -0800355 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
jvanverthfa38a302014-10-06 05:59:05 -0700356
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500357 fragBuilder->codeAppendf("highp vec2 st = uv*%s;", textureSizeUniName);
egdaniel4ca2e602015-11-18 08:01:26 -0800358 fragBuilder->codeAppend("float afwidth;");
jvanverthcf371bb2016-03-10 11:10:43 -0800359 bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
360 kUniformScale_DistanceFieldEffectMask;
361 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
brianosman0e3c5542016-04-13 13:56:21 -0700362 bool isGammaCorrect =
363 SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
jvanverthcf371bb2016-03-10 11:10:43 -0800364 if (isUniformScale) {
jvanverth354eba52015-03-16 11:32:49 -0700365 // For uniform scale, we adjust for the effect of the transformation on the distance
halcanary9d524f22016-03-29 09:03:52 -0700366 // by using the length of the gradient of the t coordinate in the y direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800367 // We use st coordinates to ensure we're mapping 1:1 from texel space to pixel space.
jvanverth354eba52015-03-16 11:32:49 -0700368
jvanverthfa38a302014-10-06 05:59:05 -0700369 // this gives us a smooth step across approximately one fragment
jvanverthe499adf2016-07-20 12:22:14 -0700370#ifdef SK_VULKAN
371 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));");
372#else
373 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
egdaniel4ca2e602015-11-18 08:01:26 -0800374 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(st.y));");
jvanverthe499adf2016-07-20 12:22:14 -0700375#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800376 } else if (isSimilarity) {
377 // For similarity transform, we adjust the effect of the transformation on the distance
378 // by using the length of the gradient of the texture coordinates. We use st coordinates
379 // to ensure we're mapping 1:1 from texel space to pixel space.
jvanverthcf371bb2016-03-10 11:10:43 -0800380
381 // this gives us a smooth step across approximately one fragment
jvanverthe499adf2016-07-20 12:22:14 -0700382#ifdef SK_VULKAN
383 fragBuilder->codeAppend("float st_grad_len = length(dFdx(st));");
384#else
385 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800386 fragBuilder->codeAppend("float st_grad_len = length(dFdy(st));");
jvanverthe499adf2016-07-20 12:22:14 -0700387#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800388 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
jvanverthfa38a302014-10-06 05:59:05 -0700389 } else {
jvanverth354eba52015-03-16 11:32:49 -0700390 // For general transforms, to determine the amount of correction we multiply a unit
391 // vector pointing along the SDF gradient direction by the Jacobian of the st coords
392 // (which is the inverse transform for this fragment) and take the length of the result.
egdaniel4ca2e602015-11-18 08:01:26 -0800393 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
jvanverthd68a5502015-03-16 12:58:43 -0700394 // the length of the gradient may be 0, so we need to check for this
395 // this also compensates for the Adreno, which likes to drop tiles on division by 0
egdaniel4ca2e602015-11-18 08:01:26 -0800396 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
397 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
398 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
399 fragBuilder->codeAppend("} else {");
400 fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
401 fragBuilder->codeAppend("}");
jvanverthd68a5502015-03-16 12:58:43 -0700402
egdaniel4ca2e602015-11-18 08:01:26 -0800403 fragBuilder->codeAppend("vec2 Jdx = dFdx(st);");
404 fragBuilder->codeAppend("vec2 Jdy = dFdy(st);");
405 fragBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
406 fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
jvanverthfa38a302014-10-06 05:59:05 -0700407
408 // this gives us a smooth step across approximately one fragment
egdaniel4ca2e602015-11-18 08:01:26 -0800409 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
jvanverthfa38a302014-10-06 05:59:05 -0700410 }
brianosman0e3c5542016-04-13 13:56:21 -0700411 // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are
412 // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want distance
413 // mapped linearly to coverage, so use a linear step:
414 if (isGammaCorrect) {
415 fragBuilder->codeAppend(
416 "float val = clamp(distance + afwidth / (2.0 * afwidth), 0.0, 1.0);");
417 } else {
418 fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
419 }
jvanverthfa38a302014-10-06 05:59:05 -0700420
egdaniel4ca2e602015-11-18 08:01:26 -0800421 fragBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
jvanverthfa38a302014-10-06 05:59:05 -0700422 }
423
bsalomona624bf32016-09-20 09:12:47 -0700424 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
425 FPCoordTransformIter&& transformIter) override {
reede4ef1ca2015-02-17 18:38:38 -0800426 SkASSERT(fTextureSizeUni.isValid());
jvanverthfa38a302014-10-06 05:59:05 -0700427
Brian Salomondb4183d2016-11-17 12:48:40 -0500428 GrTexture* texture = proc.textureSampler(0).texture();
halcanary9d524f22016-03-29 09:03:52 -0700429 if (texture->width() != fTextureSize.width() ||
jvanverthfa38a302014-10-06 05:59:05 -0700430 texture->height() != fTextureSize.height()) {
431 fTextureSize = SkISize::Make(texture->width(), texture->height());
reede4ef1ca2015-02-17 18:38:38 -0800432 pdman.set2f(fTextureSizeUni,
433 SkIntToScalar(fTextureSize.width()),
434 SkIntToScalar(fTextureSize.height()));
jvanverthfa38a302014-10-06 05:59:05 -0700435 }
joshualitt9b989322014-12-15 14:16:27 -0800436
joshualitte578a952015-05-14 10:09:13 -0700437 const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>();
joshualitt5559ca22015-05-21 15:50:36 -0700438
439 if (!dfpgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfpgp.viewMatrix())) {
440 fViewMatrix = dfpgp.viewMatrix();
egdaniel018fb622015-10-28 07:26:40 -0700441 float viewMatrix[3 * 3];
egdaniel64c47282015-11-13 06:54:19 -0800442 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
joshualitt5559ca22015-05-21 15:50:36 -0700443 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
444 }
bsalomona624bf32016-09-20 09:12:47 -0700445 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
jvanverthfa38a302014-10-06 05:59:05 -0700446 }
447
robertphillips46d36f02015-01-18 08:14:14 -0800448 static inline void GenKey(const GrGeometryProcessor& gp,
Brian Salomon94efbf52016-11-29 13:43:05 -0500449 const GrShaderCaps&,
jvanverthfa38a302014-10-06 05:59:05 -0700450 GrProcessorKeyBuilder* b) {
jvanverth502286d2015-04-08 12:37:51 -0700451 const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>();
jvanverthfa38a302014-10-06 05:59:05 -0700452
joshualitt8fc6c2d2014-12-22 15:27:05 -0800453 uint32_t key = dfTexEffect.getFlags();
Brian Salomonbfd51832017-01-04 13:22:08 -0500454 key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
joshualitt8fc6c2d2014-12-22 15:27:05 -0800455 b->add32(key);
jvanverthfa38a302014-10-06 05:59:05 -0700456 }
457
458private:
reede4ef1ca2015-02-17 18:38:38 -0800459 UniformHandle fTextureSizeUni;
joshualitt5559ca22015-05-21 15:50:36 -0700460 UniformHandle fViewMatrixUniform;
461 SkMatrix fViewMatrix;
joshualitt9b989322014-12-15 14:16:27 -0800462 SkISize fTextureSize;
jvanverthfa38a302014-10-06 05:59:05 -0700463
egdaniele659a582015-11-13 09:55:43 -0800464 typedef GrGLSLGeometryProcessor INHERITED;
jvanverthfa38a302014-10-06 05:59:05 -0700465};
466
467///////////////////////////////////////////////////////////////////////////////
468
jvanverth502286d2015-04-08 12:37:51 -0700469GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(
joshualitt2e3b3e32014-12-09 13:31:14 -0800470 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800471 const SkMatrix& viewMatrix,
joshualitt2e3b3e32014-12-09 13:31:14 -0800472 GrTexture* texture,
Brian Salomon514baff2016-11-17 15:17:07 -0500473 const GrSamplerParams& params,
joshualittb8c241a2015-05-19 08:23:30 -0700474 uint32_t flags,
475 bool usesLocalCoords)
joshualitte3ababe2015-05-15 07:56:07 -0700476 : fColor(color)
joshualitte578a952015-05-14 10:09:13 -0700477 , fViewMatrix(viewMatrix)
Brian Salomon0bbecb22016-11-17 11:38:22 -0500478 , fTextureSampler(texture, params)
jvanverthfa38a302014-10-06 05:59:05 -0700479 , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
halcanary96fcdcc2015-08-27 07:41:13 -0700480 , fInColor(nullptr)
joshualittb8c241a2015-05-19 08:23:30 -0700481 , fUsesLocalCoords(usesLocalCoords) {
jvanverthfa38a302014-10-06 05:59:05 -0700482 SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
jvanverth502286d2015-04-08 12:37:51 -0700483 this->initClassID<GrDistanceFieldPathGeoProc>();
bsalomon6cb807b2016-08-17 11:33:39 -0700484 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
485 kHigh_GrSLPrecision);
486 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
487 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2f_GrVertexAttribType);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500488 this->addTextureSampler(&fTextureSampler);
jvanverthfa38a302014-10-06 05:59:05 -0700489}
490
Brian Salomon94efbf52016-11-29 13:43:05 -0500491void GrDistanceFieldPathGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800492 GrProcessorKeyBuilder* b) const {
joshualitt465283c2015-09-11 08:19:35 -0700493 GrGLDistanceFieldPathGeoProc::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800494}
495
Brian Salomon94efbf52016-11-29 13:43:05 -0500496GrGLSLPrimitiveProcessor*
497GrDistanceFieldPathGeoProc::createGLSLInstance(const GrShaderCaps&) const {
joshualitt465283c2015-09-11 08:19:35 -0700498 return new GrGLDistanceFieldPathGeoProc();
jvanverthfa38a302014-10-06 05:59:05 -0700499}
500
501///////////////////////////////////////////////////////////////////////////////
502
jvanverth502286d2015-04-08 12:37:51 -0700503GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc);
jvanverthfa38a302014-10-06 05:59:05 -0700504
Hal Canary6f6961e2017-01-31 13:50:44 -0500505#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700506sk_sp<GrGeometryProcessor> GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700507 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
508 : GrProcessorUnitTest::kAlphaTextureIdx;
jvanverthfa38a302014-10-06 05:59:05 -0700509 static const SkShader::TileMode kTileModes[] = {
510 SkShader::kClamp_TileMode,
511 SkShader::kRepeat_TileMode,
512 SkShader::kMirror_TileMode,
513 };
514 SkShader::TileMode tileModes[] = {
joshualitt0067ff52015-07-08 14:26:19 -0700515 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
516 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
jvanverthfa38a302014-10-06 05:59:05 -0700517 };
Brian Salomon514baff2016-11-17 15:17:07 -0500518 GrSamplerParams params(tileModes, d->fRandom->nextBool() ? GrSamplerParams::kBilerp_FilterMode
519 : GrSamplerParams::kNone_FilterMode);
jvanverthfa38a302014-10-06 05:59:05 -0700520
jvanverthcf371bb2016-03-10 11:10:43 -0800521 uint32_t flags = 0;
522 flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0;
523 if (flags & kSimilarity_DistanceFieldEffectFlag) {
524 flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0;
525 }
526
bungeman06ca8ec2016-06-09 08:01:03 -0700527 return GrDistanceFieldPathGeoProc::Make(GrRandomColor(d->fRandom),
528 GrTest::TestMatrix(d->fRandom),
529 d->fTextures[texIdx],
530 params,
531 flags,
532 d->fRandom->nextBool());
jvanverthfa38a302014-10-06 05:59:05 -0700533}
Hal Canary6f6961e2017-01-31 13:50:44 -0500534#endif
jvanverthfa38a302014-10-06 05:59:05 -0700535
536///////////////////////////////////////////////////////////////////////////////
537
egdaniele659a582015-11-13 09:55:43 -0800538class GrGLDistanceFieldLCDTextGeoProc : public GrGLSLGeometryProcessor {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000539public:
joshualitt465283c2015-09-11 08:19:35 -0700540 GrGLDistanceFieldLCDTextGeoProc()
joshualitt53f26aa2015-12-10 07:29:54 -0800541 : fViewMatrix(SkMatrix::InvalidMatrix()) {
jvanverth502286d2015-04-08 12:37:51 -0700542 fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
jvanverth21deace2015-04-01 12:43:48 -0700543 }
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000544
mtklein36352bf2015-03-25 18:17:31 -0700545 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
jvanverth502286d2015-04-08 12:37:51 -0700546 const GrDistanceFieldLCDTextGeoProc& dfTexEffect =
547 args.fGP.cast<GrDistanceFieldLCDTextGeoProc>();
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000548
egdaniel4ca2e602015-11-18 08:01:26 -0800549 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
egdaniel0eafe792015-11-20 14:01:22 -0800550 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
egdaniel7ea439b2015-12-03 09:20:44 -0800551 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
joshualittabb52a12015-01-13 15:02:10 -0800552
553 // emit attributes
egdaniel0eafe792015-11-20 14:01:22 -0800554 varyingHandler->emitAttributes(dfTexEffect);
egdaniel4ca2e602015-11-18 08:01:26 -0800555
cdalton85285412016-02-18 12:37:07 -0800556 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
joshualittabb52a12015-01-13 15:02:10 -0800557
joshualitt9b989322014-12-15 14:16:27 -0800558 // setup pass through color
Brian Salomonbfd51832017-01-04 13:22:08 -0500559 varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
joshualitt9b989322014-12-15 14:16:27 -0800560
joshualittabb52a12015-01-13 15:02:10 -0800561 // Setup position
egdaniel7ea439b2015-12-03 09:20:44 -0800562 this->setupPosition(vertBuilder,
563 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -0800564 gpArgs,
565 dfTexEffect.inPosition()->fName,
566 dfTexEffect.viewMatrix(),
joshualitt5559ca22015-05-21 15:50:36 -0700567 &fViewMatrixUniform);
joshualitt4973d9d2014-11-08 09:24:25 -0800568
joshualittabb52a12015-01-13 15:02:10 -0800569 // emit transforms
egdaniel7ea439b2015-12-03 09:20:44 -0800570 this->emitTransforms(vertBuilder,
egdaniel0eafe792015-11-20 14:01:22 -0800571 varyingHandler,
egdaniel7ea439b2015-12-03 09:20:44 -0800572 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -0800573 gpArgs->fPositionVar,
574 dfTexEffect.inPosition()->fName,
bsalomona624bf32016-09-20 09:12:47 -0700575 args.fFPCoordTransformHandler);
joshualittabb52a12015-01-13 15:02:10 -0800576
jvanverthbb4a1cf2015-04-07 09:06:00 -0700577 // set up varyings
jvanverthcf371bb2016-03-10 11:10:43 -0800578 bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
579 kUniformScale_DistanceFieldEffectMask;
580 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
brianosmanb461d342016-04-13 13:10:14 -0700581 bool isGammaCorrect =
582 SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
egdaniel8dcdedc2015-11-11 06:27:20 -0800583 GrGLSLVertToFrag recipScale(kFloat_GrSLType);
jvanverth7023a002016-02-22 11:25:32 -0800584 GrGLSLVertToFrag uv(kVec2f_GrSLType);
585 varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
586 vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName);
jvanverthbb4a1cf2015-04-07 09:06:00 -0700587
jvanverthcf371bb2016-03-10 11:10:43 -0800588 // compute numbers to be hardcoded to convert texture coordinates from float to int
Brian Salomon0bbecb22016-11-17 11:38:22 -0500589 SkASSERT(dfTexEffect.numTextureSamplers() == 1);
Brian Salomondb4183d2016-11-17 12:48:40 -0500590 GrTexture* atlas = dfTexEffect.textureSampler(0).texture();
joshualitt7375d6b2015-08-07 13:36:44 -0700591 SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
joshualitt922c8b12015-08-07 09:55:23 -0700592
jvanverth7023a002016-02-22 11:25:32 -0800593 GrGLSLVertToFrag st(kVec2f_GrSLType);
594 varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
595 vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(),
596 atlas->width(), atlas->height(),
egdaniel4ca2e602015-11-18 08:01:26 -0800597 dfTexEffect.inTextureCoords()->fName);
jvanverthbb4a1cf2015-04-07 09:06:00 -0700598
599 // add frag shader code
joshualitt30ba4362014-08-21 20:18:45 -0700600
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000601 // create LCD offset adjusted by inverse of transform
jvanverthfdf7ccc2015-01-27 08:19:33 -0800602 // Use highp to work around aliasing issues
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500603 fragBuilder->codeAppendf("highp vec2 uv = %s;\n", uv.fsIn());
joshualitt922c8b12015-08-07 09:55:23 -0700604
605 SkScalar lcdDelta = 1.0f / (3.0f * atlas->width());
jvanverth5a105ff2015-02-18 11:36:35 -0800606 if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500607 fragBuilder->codeAppendf("highp float delta = -%.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta);
jvanverth5a105ff2015-02-18 11:36:35 -0800608 } else {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500609 fragBuilder->codeAppendf("highp float delta = %.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta);
jvanverth5a105ff2015-02-18 11:36:35 -0800610 }
jvanverth78f07182014-07-30 06:17:59 -0700611 if (isUniformScale) {
jvanverthe499adf2016-07-20 12:22:14 -0700612#ifdef SK_VULKAN
613 fragBuilder->codeAppendf("float st_grad_len = abs(dFdx(%s.x));", st.fsIn());
614#else
615 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800616 fragBuilder->codeAppendf("float st_grad_len = abs(dFdy(%s.y));", st.fsIn());
jvanverthe499adf2016-07-20 12:22:14 -0700617#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800618 fragBuilder->codeAppend("vec2 offset = vec2(st_grad_len*delta, 0.0);");
619 } else if (isSimilarity) {
620 // For a similarity matrix with rotation, the gradient will not be aligned
621 // with the texel coordinate axes, so we need to calculate it.
jvanverthe499adf2016-07-20 12:22:14 -0700622#ifdef SK_VULKAN
623 fragBuilder->codeAppendf("vec2 st_grad = dFdx(%s);", st.fsIn());
624 fragBuilder->codeAppend("vec2 offset = delta*st_grad;");
625#else
jvanverthcf371bb2016-03-10 11:10:43 -0800626 // We use dFdy because of a Mali 400 bug, and rotate -90 degrees to
627 // get the gradient in the x direction.
628 fragBuilder->codeAppendf("vec2 st_grad = dFdy(%s);", st.fsIn());
jvanverthcf371bb2016-03-10 11:10:43 -0800629 fragBuilder->codeAppend("vec2 offset = delta*vec2(st_grad.y, -st_grad.x);");
jvanverthe499adf2016-07-20 12:22:14 -0700630#endif
631 fragBuilder->codeAppend("float st_grad_len = length(st_grad);");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000632 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800633 fragBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn());
jvanverthbb4a1cf2015-04-07 09:06:00 -0700634
egdaniel4ca2e602015-11-18 08:01:26 -0800635 fragBuilder->codeAppend("vec2 Jdx = dFdx(st);");
636 fragBuilder->codeAppend("vec2 Jdy = dFdy(st);");
637 fragBuilder->codeAppend("vec2 offset = delta*Jdx;");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000638 }
639
640 // green is distance to uv center
egdaniel4ca2e602015-11-18 08:01:26 -0800641 fragBuilder->codeAppend("\tvec4 texColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700642 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv", kVec2f_GrSLType);
egdaniel4ca2e602015-11-18 08:01:26 -0800643 fragBuilder->codeAppend(";\n");
644 fragBuilder->codeAppend("\tvec3 distance;\n");
645 fragBuilder->codeAppend("\tdistance.y = texColor.r;\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000646 // red is distance to left offset
egdaniel4ca2e602015-11-18 08:01:26 -0800647 fragBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n");
648 fragBuilder->codeAppend("\ttexColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700649 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv_adjusted", kVec2f_GrSLType);
egdaniel4ca2e602015-11-18 08:01:26 -0800650 fragBuilder->codeAppend(";\n");
651 fragBuilder->codeAppend("\tdistance.x = texColor.r;\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000652 // blue is distance to right offset
egdaniel4ca2e602015-11-18 08:01:26 -0800653 fragBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
654 fragBuilder->codeAppend("\ttexColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700655 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv_adjusted", kVec2f_GrSLType);
egdaniel4ca2e602015-11-18 08:01:26 -0800656 fragBuilder->codeAppend(";\n");
657 fragBuilder->codeAppend("\tdistance.z = texColor.r;\n");
jvanverth2d2a68c2014-06-10 06:42:56 -0700658
egdaniel4ca2e602015-11-18 08:01:26 -0800659 fragBuilder->codeAppend("\tdistance = "
jvanverthada68ef2014-11-03 14:00:24 -0800660 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
jvanverth2d2a68c2014-06-10 06:42:56 -0700661
jvanverth21deace2015-04-01 12:43:48 -0700662 // adjust width based on gamma
halcanary96fcdcc2015-08-27 07:41:13 -0700663 const char* distanceAdjustUniName = nullptr;
cdalton5e58cee2016-02-11 12:49:47 -0800664 fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800665 kVec3f_GrSLType, kDefault_GrSLPrecision,
666 "DistanceAdjust", &distanceAdjustUniName);
egdaniel4ca2e602015-11-18 08:01:26 -0800667 fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
jvanverth21deace2015-04-01 12:43:48 -0700668
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000669 // To be strictly correct, we should compute the anti-aliasing factor separately
670 // for each color component. However, this is only important when using perspective
671 // transformations, and even then using a single factor seems like a reasonable
672 // trade-off between quality and speed.
egdaniel4ca2e602015-11-18 08:01:26 -0800673 fragBuilder->codeAppend("float afwidth;");
jvanverthcf371bb2016-03-10 11:10:43 -0800674 if (isSimilarity) {
halcanary9d524f22016-03-29 09:03:52 -0700675 // For similarity transform (uniform scale-only is a subset of this), we adjust for the
676 // effect of the transformation on the distance by using the length of the gradient of
jvanverthcf371bb2016-03-10 11:10:43 -0800677 // the texture coordinates. We use st coordinates to ensure we're mapping 1:1 from texel
678 // space to pixel space.
jvanverth354eba52015-03-16 11:32:49 -0700679
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000680 // this gives us a smooth step across approximately one fragment
jvanverthcf371bb2016-03-10 11:10:43 -0800681 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*st_grad_len;");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000682 } else {
jvanverth354eba52015-03-16 11:32:49 -0700683 // For general transforms, to determine the amount of correction we multiply a unit
684 // vector pointing along the SDF gradient direction by the Jacobian of the st coords
685 // (which is the inverse transform for this fragment) and take the length of the result.
egdaniel4ca2e602015-11-18 08:01:26 -0800686 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(distance.r));");
jvanverthd68a5502015-03-16 12:58:43 -0700687 // the length of the gradient may be 0, so we need to check for this
688 // this also compensates for the Adreno, which likes to drop tiles on division by 0
egdaniel4ca2e602015-11-18 08:01:26 -0800689 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
690 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
691 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
692 fragBuilder->codeAppend("} else {");
693 fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
694 fragBuilder->codeAppend("}");
695 fragBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
696 fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000697
698 // this gives us a smooth step across approximately one fragment
egdaniel4ca2e602015-11-18 08:01:26 -0800699 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000700 }
701
brianosman0586f5c2016-04-12 12:48:21 -0700702 // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are
703 // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want distance
704 // mapped linearly to coverage, so use a linear step:
brianosmanb461d342016-04-13 13:10:14 -0700705 if (isGammaCorrect) {
brianosman0586f5c2016-04-12 12:48:21 -0700706 fragBuilder->codeAppend("vec4 val = "
bsalomon32d1e952016-09-15 07:29:52 -0700707 "vec4(clamp(distance + vec3(afwidth) / vec3(2.0 * afwidth), 0.0, 1.0), 1.0);");
brianosman0586f5c2016-04-12 12:48:21 -0700708 } else {
709 fragBuilder->codeAppend(
710 "vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
711 }
712
egdaniel27b63352015-09-15 13:13:50 -0700713 // set alpha to be max of rgb coverage
egdaniel4ca2e602015-11-18 08:01:26 -0800714 fragBuilder->codeAppend("val.a = max(max(val.r, val.g), val.b);");
jvanverth2d2a68c2014-06-10 06:42:56 -0700715
egdaniel4ca2e602015-11-18 08:01:26 -0800716 fragBuilder->codeAppendf("%s = val;", args.fOutputCoverage);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000717 }
718
bsalomona624bf32016-09-20 09:12:47 -0700719 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& processor,
720 FPCoordTransformIter&& transformIter) override {
jvanverth21deace2015-04-01 12:43:48 -0700721 SkASSERT(fDistanceAdjustUni.isValid());
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000722
joshualitt5559ca22015-05-21 15:50:36 -0700723 const GrDistanceFieldLCDTextGeoProc& dflcd = processor.cast<GrDistanceFieldLCDTextGeoProc>();
724 GrDistanceFieldLCDTextGeoProc::DistanceAdjust wa = dflcd.getDistanceAdjust();
jvanverth21deace2015-04-01 12:43:48 -0700725 if (wa != fDistanceAdjust) {
726 pdman.set3f(fDistanceAdjustUni,
727 wa.fR,
728 wa.fG,
729 wa.fB);
730 fDistanceAdjust = wa;
jvanverth2d2a68c2014-06-10 06:42:56 -0700731 }
joshualitt9b989322014-12-15 14:16:27 -0800732
joshualitt5559ca22015-05-21 15:50:36 -0700733 if (!dflcd.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dflcd.viewMatrix())) {
734 fViewMatrix = dflcd.viewMatrix();
egdaniel018fb622015-10-28 07:26:40 -0700735 float viewMatrix[3 * 3];
egdaniel64c47282015-11-13 06:54:19 -0800736 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
joshualitt5559ca22015-05-21 15:50:36 -0700737 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
738 }
bsalomona624bf32016-09-20 09:12:47 -0700739 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000740 }
741
robertphillips46d36f02015-01-18 08:14:14 -0800742 static inline void GenKey(const GrGeometryProcessor& gp,
Brian Salomon94efbf52016-11-29 13:43:05 -0500743 const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700744 GrProcessorKeyBuilder* b) {
jvanverth502286d2015-04-08 12:37:51 -0700745 const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>();
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000746
joshualitt8fc6c2d2014-12-22 15:27:05 -0800747 uint32_t key = dfTexEffect.getFlags();
Brian Salomonbfd51832017-01-04 13:22:08 -0500748 key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
joshualitt8fc6c2d2014-12-22 15:27:05 -0800749 b->add32(key);
joshualitt922c8b12015-08-07 09:55:23 -0700750
751 // Currently we hardcode numbers to convert atlas coordinates to normalized floating point
Brian Salomon0bbecb22016-11-17 11:38:22 -0500752 SkASSERT(gp.numTextureSamplers() == 1);
Brian Salomondb4183d2016-11-17 12:48:40 -0500753 GrTexture* atlas = gp.textureSampler(0).texture();
joshualitt922c8b12015-08-07 09:55:23 -0700754 SkASSERT(atlas);
755 b->add32(atlas->width());
756 b->add32(atlas->height());
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000757 }
758
759private:
joshualitt5559ca22015-05-21 15:50:36 -0700760 SkMatrix fViewMatrix;
joshualitt5559ca22015-05-21 15:50:36 -0700761 UniformHandle fViewMatrixUniform;
jvanverth21deace2015-04-01 12:43:48 -0700762 UniformHandle fColorUniform;
jvanverth502286d2015-04-08 12:37:51 -0700763 GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust;
jvanverth21deace2015-04-01 12:43:48 -0700764 UniformHandle fDistanceAdjustUni;
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000765
egdaniele659a582015-11-13 09:55:43 -0800766 typedef GrGLSLGeometryProcessor INHERITED;
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000767};
768
769///////////////////////////////////////////////////////////////////////////////
770
jvanverth502286d2015-04-08 12:37:51 -0700771GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
joshualitt8059eb92014-12-29 15:10:07 -0800772 GrColor color, const SkMatrix& viewMatrix,
Brian Salomon514baff2016-11-17 15:17:07 -0500773 GrTexture* texture, const GrSamplerParams& params,
jvanverth21deace2015-04-01 12:43:48 -0700774 DistanceAdjust distanceAdjust,
joshualittb8c241a2015-05-19 08:23:30 -0700775 uint32_t flags, bool usesLocalCoords)
joshualitte3ababe2015-05-15 07:56:07 -0700776 : fColor(color)
joshualitte578a952015-05-14 10:09:13 -0700777 , fViewMatrix(viewMatrix)
Brian Salomon0bbecb22016-11-17 11:38:22 -0500778 , fTextureSampler(texture, params)
jvanverth21deace2015-04-01 12:43:48 -0700779 , fDistanceAdjust(distanceAdjust)
joshualittb8c241a2015-05-19 08:23:30 -0700780 , fFlags(flags & kLCD_DistanceFieldEffectMask)
781 , fUsesLocalCoords(usesLocalCoords) {
jvanverth78f07182014-07-30 06:17:59 -0700782 SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
jvanverth502286d2015-04-08 12:37:51 -0700783 this->initClassID<GrDistanceFieldLCDTextGeoProc>();
bsalomon6cb807b2016-08-17 11:33:39 -0700784 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
785 kHigh_GrSLPrecision);
786 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
787 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType,
788 kHigh_GrSLPrecision);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500789 this->addTextureSampler(&fTextureSampler);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000790}
791
Brian Salomon94efbf52016-11-29 13:43:05 -0500792void GrDistanceFieldLCDTextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800793 GrProcessorKeyBuilder* b) const {
joshualitt465283c2015-09-11 08:19:35 -0700794 GrGLDistanceFieldLCDTextGeoProc::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800795}
796
Brian Salomon94efbf52016-11-29 13:43:05 -0500797GrGLSLPrimitiveProcessor* GrDistanceFieldLCDTextGeoProc::createGLSLInstance(const GrShaderCaps&) const {
joshualitt465283c2015-09-11 08:19:35 -0700798 return new GrGLDistanceFieldLCDTextGeoProc();
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000799}
800
801///////////////////////////////////////////////////////////////////////////////
802
jvanverth502286d2015-04-08 12:37:51 -0700803GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000804
Hal Canary6f6961e2017-01-31 13:50:44 -0500805#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700806sk_sp<GrGeometryProcessor> GrDistanceFieldLCDTextGeoProc::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700807 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
808 GrProcessorUnitTest::kAlphaTextureIdx;
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000809 static const SkShader::TileMode kTileModes[] = {
810 SkShader::kClamp_TileMode,
811 SkShader::kRepeat_TileMode,
812 SkShader::kMirror_TileMode,
813 };
814 SkShader::TileMode tileModes[] = {
joshualitt0067ff52015-07-08 14:26:19 -0700815 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
816 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000817 };
Brian Salomon514baff2016-11-17 15:17:07 -0500818 GrSamplerParams params(tileModes, d->fRandom->nextBool() ? GrSamplerParams::kBilerp_FilterMode
819 : GrSamplerParams::kNone_FilterMode);
jvanverth21deace2015-04-01 12:43:48 -0700820 DistanceAdjust wa = { 0.0f, 0.1f, -0.1f };
jvanverth78f07182014-07-30 06:17:59 -0700821 uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
jvanverthcf371bb2016-03-10 11:10:43 -0800822 flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0;
823 if (flags & kSimilarity_DistanceFieldEffectFlag) {
824 flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0;
825 }
joshualitt0067ff52015-07-08 14:26:19 -0700826 flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
bungeman06ca8ec2016-06-09 08:01:03 -0700827 return GrDistanceFieldLCDTextGeoProc::Make(GrRandomColor(d->fRandom),
828 GrTest::TestMatrix(d->fRandom),
829 d->fTextures[texIdx], params,
830 wa,
831 flags,
832 d->fRandom->nextBool());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000833}
Hal Canary6f6961e2017-01-31 13:50:44 -0500834#endif