blob: 89ec238efd07d2624274eb74f26878905c72b0a8 [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"
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -05009
10#include "GrContext.h"
joshualitteb2a6762014-12-04 11:35:33 -080011#include "GrTexture.h"
12#include "SkDistanceFieldGen.h"
egdaniel2d721d32015-11-11 13:06:05 -080013#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniele659a582015-11-13 09:55:43 -080014#include "glsl/GrGLSLGeometryProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -070015#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080016#include "glsl/GrGLSLUniformHandler.h"
egdaniel64c47282015-11-13 06:54:19 -080017#include "glsl/GrGLSLUtil.h"
egdaniel0eafe792015-11-20 14:01:22 -080018#include "glsl/GrGLSLVarying.h"
19#include "glsl/GrGLSLVertexShaderBuilder.h"
jvanverth@google.comd830d132013-11-11 20:54:09 +000020
jvanverth21deace2015-04-01 12:43:48 -070021// Assuming a radius of a little less than the diagonal of the fragment
jvanverth24ba0082015-03-19 11:34:13 -070022#define SK_DistanceFieldAAFactor "0.65"
jvanverth2d2a68c2014-06-10 06:42:56 -070023
egdaniele659a582015-11-13 09:55:43 -080024class GrGLDistanceFieldA8TextGeoProc : public GrGLSLGeometryProcessor {
jvanverth@google.comd830d132013-11-11 20:54:09 +000025public:
joshualitt465283c2015-09-11 08:19:35 -070026 GrGLDistanceFieldA8TextGeoProc()
joshualitt5559ca22015-05-21 15:50:36 -070027 : fViewMatrix(SkMatrix::InvalidMatrix())
jvanverth9564ce62014-09-16 05:45:19 -070028#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth21deace2015-04-01 12:43:48 -070029 , fDistanceAdjust(-1.0f)
jvanverth9564ce62014-09-16 05:45:19 -070030#endif
31 {}
jvanverth@google.comd830d132013-11-11 20:54:09 +000032
mtklein36352bf2015-03-25 18:17:31 -070033 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
jvanverth502286d2015-04-08 12:37:51 -070034 const GrDistanceFieldA8TextGeoProc& dfTexEffect =
35 args.fGP.cast<GrDistanceFieldA8TextGeoProc>();
cdalton85285412016-02-18 12:37:07 -080036 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
jvanverth@google.comd830d132013-11-11 20:54:09 +000037
egdaniel4ca2e602015-11-18 08:01:26 -080038 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
egdaniel0eafe792015-11-20 14:01:22 -080039 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
egdaniel7ea439b2015-12-03 09:20:44 -080040 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
joshualittabb52a12015-01-13 15:02:10 -080041
42 // emit attributes
egdaniel0eafe792015-11-20 14:01:22 -080043 varyingHandler->emitAttributes(dfTexEffect);
joshualittabb52a12015-01-13 15:02:10 -080044
jvanverth21deace2015-04-01 12:43:48 -070045#ifdef SK_GAMMA_APPLY_TO_A8
46 // adjust based on gamma
halcanary96fcdcc2015-08-27 07:41:13 -070047 const char* distanceAdjustUniName = nullptr;
jvanverth21deace2015-04-01 12:43:48 -070048 // width, height, 1/(3*width)
cdalton5e58cee2016-02-11 12:49:47 -080049 fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -080050 kFloat_GrSLType, kDefault_GrSLPrecision,
51 "DistanceAdjust", &distanceAdjustUniName);
jvanverth21deace2015-04-01 12:43:48 -070052#endif
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000053
joshualitt9b989322014-12-15 14:16:27 -080054 // Setup pass through color
Brian Salomonbfd51832017-01-04 13:22:08 -050055 varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000056
joshualittabb52a12015-01-13 15:02:10 -080057 // Setup position
egdaniel7ea439b2015-12-03 09:20:44 -080058 this->setupPosition(vertBuilder,
59 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -080060 gpArgs,
61 dfTexEffect.inPosition()->fName,
62 dfTexEffect.viewMatrix(),
joshualitt5559ca22015-05-21 15:50:36 -070063 &fViewMatrixUniform);
joshualitt2dd1ae02014-12-03 06:24:10 -080064
joshualittabb52a12015-01-13 15:02:10 -080065 // emit transforms
egdaniel7ea439b2015-12-03 09:20:44 -080066 this->emitTransforms(vertBuilder,
egdaniel0eafe792015-11-20 14:01:22 -080067 varyingHandler,
egdaniel7ea439b2015-12-03 09:20:44 -080068 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -080069 gpArgs->fPositionVar,
70 dfTexEffect.inPosition()->fName,
bsalomona624bf32016-09-20 09:12:47 -070071 args.fFPCoordTransformHandler);
joshualitt4973d9d2014-11-08 09:24:25 -080072
jvanverthbb4a1cf2015-04-07 09:06:00 -070073 // add varyings
egdaniel8dcdedc2015-11-11 06:27:20 -080074 GrGLSLVertToFrag recipScale(kFloat_GrSLType);
jvanverth7023a002016-02-22 11:25:32 -080075 GrGLSLVertToFrag uv(kVec2f_GrSLType);
jvanverthcf371bb2016-03-10 11:10:43 -080076 bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
77 kUniformScale_DistanceFieldEffectMask;
jvanverthbb4a1cf2015-04-07 09:06:00 -070078 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
brianosmanb461d342016-04-13 13:10:14 -070079 bool isGammaCorrect =
80 SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
jvanverth7023a002016-02-22 11:25:32 -080081 varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
82 vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName);
jvanverthbb4a1cf2015-04-07 09:06:00 -070083
jvanverthcf371bb2016-03-10 11:10:43 -080084 // compute numbers to be hardcoded to convert texture coordinates from float to int
Brian Salomon0bbecb22016-11-17 11:38:22 -050085 SkASSERT(dfTexEffect.numTextureSamplers() == 1);
Brian Salomondb4183d2016-11-17 12:48:40 -050086 GrTexture* atlas = dfTexEffect.textureSampler(0).texture();
joshualitt7375d6b2015-08-07 13:36:44 -070087 SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
joshualitt922c8b12015-08-07 09:55:23 -070088
jvanverth7023a002016-02-22 11:25:32 -080089 GrGLSLVertToFrag st(kVec2f_GrSLType);
90 varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
91 vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(),
92 atlas->width(), atlas->height(),
egdaniel4ca2e602015-11-18 08:01:26 -080093 dfTexEffect.inTextureCoords()->fName);
halcanary9d524f22016-03-29 09:03:52 -070094
jvanverthfdf7ccc2015-01-27 08:19:33 -080095 // Use highp to work around aliasing issues
Ethan Nicholas1fc83b12016-11-22 09:31:35 -050096 fragBuilder->codeAppendf("highp vec2 uv = %s;\n", uv.fsIn());
jvanverthfdf7ccc2015-01-27 08:19:33 -080097
egdaniel4ca2e602015-11-18 08:01:26 -080098 fragBuilder->codeAppend("\tfloat texColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -070099 fragBuilder->appendTextureLookup(args.fTexSamplers[0],
egdaniel4ca2e602015-11-18 08:01:26 -0800100 "uv",
101 kVec2f_GrSLType);
102 fragBuilder->codeAppend(".r;\n");
103 fragBuilder->codeAppend("\tfloat distance = "
jvanverthfdf7ccc2015-01-27 08:19:33 -0800104 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
jvanverth21deace2015-04-01 12:43:48 -0700105#ifdef SK_GAMMA_APPLY_TO_A8
106 // adjust width based on gamma
egdaniel4ca2e602015-11-18 08:01:26 -0800107 fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
jvanverth21deace2015-04-01 12:43:48 -0700108#endif
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000109
egdaniel4ca2e602015-11-18 08:01:26 -0800110 fragBuilder->codeAppend("float afwidth;");
jvanverthcf371bb2016-03-10 11:10:43 -0800111 if (isUniformScale) {
jvanverth354eba52015-03-16 11:32:49 -0700112 // For uniform scale, we adjust for the effect of the transformation on the distance
halcanary9d524f22016-03-29 09:03:52 -0700113 // by using the length of the gradient of the t coordinate in the y direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800114 // 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 +0000115
jvanverth354eba52015-03-16 11:32:49 -0700116 // this gives us a smooth step across approximately one fragment
jvanverthe499adf2016-07-20 12:22:14 -0700117#ifdef SK_VULKAN
118 fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(%s.x));",
119 st.fsIn());
120#else
121 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
egdaniel4ca2e602015-11-18 08:01:26 -0800122 fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(%s.y));",
123 st.fsIn());
jvanverthe499adf2016-07-20 12:22:14 -0700124#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800125 } else if (isSimilarity) {
126 // For similarity transform, we adjust the effect of the transformation on the distance
127 // by using the length of the gradient of the texture coordinates. We use st coordinates
128 // to ensure we're mapping 1:1 from texel space to pixel space.
129 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
130
131 // this gives us a smooth step across approximately one fragment
jvanverthe499adf2016-07-20 12:22:14 -0700132#ifdef SK_VULKAN
133 fragBuilder->codeAppendf("float st_grad_len = length(dFdx(%s));", st.fsIn());
134#else
135 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800136 fragBuilder->codeAppendf("float st_grad_len = length(dFdy(%s));", st.fsIn());
jvanverthe499adf2016-07-20 12:22:14 -0700137#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800138 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
jvanverth354eba52015-03-16 11:32:49 -0700139 } else {
140 // For general transforms, to determine the amount of correction we multiply a unit
141 // vector pointing along the SDF gradient direction by the Jacobian of the st coords
142 // (which is the inverse transform for this fragment) and take the length of the result.
egdaniel4ca2e602015-11-18 08:01:26 -0800143 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
jvanverthd68a5502015-03-16 12:58:43 -0700144 // the length of the gradient may be 0, so we need to check for this
145 // this also compensates for the Adreno, which likes to drop tiles on division by 0
egdaniel4ca2e602015-11-18 08:01:26 -0800146 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
147 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
148 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
149 fragBuilder->codeAppend("} else {");
150 fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
151 fragBuilder->codeAppend("}");
jvanverthd68a5502015-03-16 12:58:43 -0700152
egdaniel4ca2e602015-11-18 08:01:26 -0800153 fragBuilder->codeAppendf("vec2 Jdx = dFdx(%s);", st.fsIn());
154 fragBuilder->codeAppendf("vec2 Jdy = dFdy(%s);", st.fsIn());
155 fragBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
156 fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000157
158 // this gives us a smooth step across approximately one fragment
egdaniel4ca2e602015-11-18 08:01:26 -0800159 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000160 }
brianosman0586f5c2016-04-12 12:48:21 -0700161
162 // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are
163 // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want distance
164 // mapped linearly to coverage, so use a linear step:
brianosmanb461d342016-04-13 13:10:14 -0700165 if (isGammaCorrect) {
brianosman0586f5c2016-04-12 12:48:21 -0700166 fragBuilder->codeAppend(
167 "float val = clamp(distance + afwidth / (2.0 * afwidth), 0.0, 1.0);");
168 } else {
169 fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
170 }
jvanverth@google.comd830d132013-11-11 20:54:09 +0000171
egdaniel4ca2e602015-11-18 08:01:26 -0800172 fragBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000173 }
174
bsalomona624bf32016-09-20 09:12:47 -0700175 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
176 FPCoordTransformIter&& transformIter) override {
jvanverth2d2a68c2014-06-10 06:42:56 -0700177#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth502286d2015-04-08 12:37:51 -0700178 const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>();
jvanverth21deace2015-04-01 12:43:48 -0700179 float distanceAdjust = dfTexEffect.getDistanceAdjust();
180 if (distanceAdjust != fDistanceAdjust) {
181 pdman.set1f(fDistanceAdjustUni, distanceAdjust);
182 fDistanceAdjust = distanceAdjust;
jvanverth2d2a68c2014-06-10 06:42:56 -0700183 }
184#endif
joshualitte578a952015-05-14 10:09:13 -0700185 const GrDistanceFieldA8TextGeoProc& dfa8gp = proc.cast<GrDistanceFieldA8TextGeoProc>();
joshualitt5559ca22015-05-21 15:50:36 -0700186
187 if (!dfa8gp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfa8gp.viewMatrix())) {
188 fViewMatrix = dfa8gp.viewMatrix();
egdaniel018fb622015-10-28 07:26:40 -0700189 float viewMatrix[3 * 3];
egdaniel64c47282015-11-13 06:54:19 -0800190 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
joshualitt5559ca22015-05-21 15:50:36 -0700191 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
192 }
bsalomona624bf32016-09-20 09:12:47 -0700193 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
commit-bot@chromium.org8fe2ee12014-03-26 18:03:05 +0000194 }
195
robertphillips46d36f02015-01-18 08:14:14 -0800196 static inline void GenKey(const GrGeometryProcessor& gp,
Brian Salomon94efbf52016-11-29 13:43:05 -0500197 const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700198 GrProcessorKeyBuilder* b) {
jvanverth502286d2015-04-08 12:37:51 -0700199 const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>();
joshualitt8fc6c2d2014-12-22 15:27:05 -0800200 uint32_t key = dfTexEffect.getFlags();
Brian Salomonbfd51832017-01-04 13:22:08 -0500201 key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
joshualitt8fc6c2d2014-12-22 15:27:05 -0800202 b->add32(key);
joshualitt922c8b12015-08-07 09:55:23 -0700203
204 // Currently we hardcode numbers to convert atlas coordinates to normalized floating point
Brian Salomon0bbecb22016-11-17 11:38:22 -0500205 SkASSERT(gp.numTextureSamplers() == 1);
Brian Salomondb4183d2016-11-17 12:48:40 -0500206 GrTexture* atlas = gp.textureSampler(0).texture();
joshualitt922c8b12015-08-07 09:55:23 -0700207 SkASSERT(atlas);
208 b->add32(atlas->width());
209 b->add32(atlas->height());
commit-bot@chromium.org4362a382014-03-26 19:49:03 +0000210 }
211
jvanverth@google.comd830d132013-11-11 20:54:09 +0000212private:
joshualitt5559ca22015-05-21 15:50:36 -0700213 SkMatrix fViewMatrix;
joshualitt5559ca22015-05-21 15:50:36 -0700214 UniformHandle fViewMatrixUniform;
mtklein50282b42015-01-22 07:59:52 -0800215#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth21deace2015-04-01 12:43:48 -0700216 float fDistanceAdjust;
217 UniformHandle fDistanceAdjustUni;
mtklein50282b42015-01-22 07:59:52 -0800218#endif
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000219
egdaniele659a582015-11-13 09:55:43 -0800220 typedef GrGLSLGeometryProcessor INHERITED;
jvanverth@google.comd830d132013-11-11 20:54:09 +0000221};
222
223///////////////////////////////////////////////////////////////////////////////
224
jvanverth502286d2015-04-08 12:37:51 -0700225GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800226 const SkMatrix& viewMatrix,
joshualitt2e3b3e32014-12-09 13:31:14 -0800227 GrTexture* texture,
Brian Salomon514baff2016-11-17 15:17:07 -0500228 const GrSamplerParams& params,
jvanverth2d2a68c2014-06-10 06:42:56 -0700229#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth21deace2015-04-01 12:43:48 -0700230 float distanceAdjust,
jvanverth2d2a68c2014-06-10 06:42:56 -0700231#endif
joshualittb8c241a2015-05-19 08:23:30 -0700232 uint32_t flags,
233 bool usesLocalCoords)
joshualitte3ababe2015-05-15 07:56:07 -0700234 : fColor(color)
joshualitte578a952015-05-14 10:09:13 -0700235 , fViewMatrix(viewMatrix)
Brian Salomon0bbecb22016-11-17 11:38:22 -0500236 , fTextureSampler(texture, params)
jvanverth2d2a68c2014-06-10 06:42:56 -0700237#ifdef SK_GAMMA_APPLY_TO_A8
jvanverth21deace2015-04-01 12:43:48 -0700238 , fDistanceAdjust(distanceAdjust)
jvanverth2d2a68c2014-06-10 06:42:56 -0700239#endif
joshualitt249af152014-09-15 11:41:13 -0700240 , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
halcanary96fcdcc2015-08-27 07:41:13 -0700241 , fInColor(nullptr)
joshualittb8c241a2015-05-19 08:23:30 -0700242 , fUsesLocalCoords(usesLocalCoords) {
jvanverth78f07182014-07-30 06:17:59 -0700243 SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
jvanverth502286d2015-04-08 12:37:51 -0700244 this->initClassID<GrDistanceFieldA8TextGeoProc>();
bsalomon6cb807b2016-08-17 11:33:39 -0700245 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
246 kHigh_GrSLPrecision);
247 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
248 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType,
249 kHigh_GrSLPrecision);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500250 this->addTextureSampler(&fTextureSampler);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000251}
252
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500253GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrContext* context,
254 GrColor color,
255 const SkMatrix& viewMatrix,
256 sk_sp<GrTextureProxy> proxy,
257 const GrSamplerParams& params,
258#ifdef SK_GAMMA_APPLY_TO_A8
259 float distanceAdjust,
260#endif
261 uint32_t flags,
262 bool usesLocalCoords)
263 : fColor(color)
264 , fViewMatrix(viewMatrix)
265 , fTextureSampler(context->textureProvider(), std::move(proxy), params)
266#ifdef SK_GAMMA_APPLY_TO_A8
267 , fDistanceAdjust(distanceAdjust)
268#endif
269 , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
270 , fInColor(nullptr)
271 , fUsesLocalCoords(usesLocalCoords) {
272 SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
273 this->initClassID<GrDistanceFieldA8TextGeoProc>();
274 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
275 kHigh_GrSLPrecision);
276 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
277 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType,
278 kHigh_GrSLPrecision);
279 this->addTextureSampler(&fTextureSampler);
280}
281
Brian Salomon94efbf52016-11-29 13:43:05 -0500282void GrDistanceFieldA8TextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800283 GrProcessorKeyBuilder* b) const {
joshualitt465283c2015-09-11 08:19:35 -0700284 GrGLDistanceFieldA8TextGeoProc::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800285}
286
Brian Salomon94efbf52016-11-29 13:43:05 -0500287GrGLSLPrimitiveProcessor*
288GrDistanceFieldA8TextGeoProc::createGLSLInstance(const GrShaderCaps&) const {
joshualitt465283c2015-09-11 08:19:35 -0700289 return new GrGLDistanceFieldA8TextGeoProc();
jvanverth@google.comd830d132013-11-11 20:54:09 +0000290}
291
292///////////////////////////////////////////////////////////////////////////////
293
jvanverth502286d2015-04-08 12:37:51 -0700294GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldA8TextGeoProc);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000295
Hal Canary6f6961e2017-01-31 13:50:44 -0500296#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700297sk_sp<GrGeometryProcessor> GrDistanceFieldA8TextGeoProc::TestCreate(GrProcessorTestData* d) {
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500298 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
299 : GrProcessorUnitTest::kAlphaTextureIdx;
300 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
301
jvanverth@google.comd830d132013-11-11 20:54:09 +0000302 static const SkShader::TileMode kTileModes[] = {
303 SkShader::kClamp_TileMode,
304 SkShader::kRepeat_TileMode,
305 SkShader::kMirror_TileMode,
306 };
307 SkShader::TileMode tileModes[] = {
joshualitt0067ff52015-07-08 14:26:19 -0700308 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
309 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
jvanverth@google.comd830d132013-11-11 20:54:09 +0000310 };
Brian Salomon514baff2016-11-17 15:17:07 -0500311 GrSamplerParams params(tileModes, d->fRandom->nextBool() ? GrSamplerParams::kBilerp_FilterMode
312 : GrSamplerParams::kNone_FilterMode);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000313
jvanverthcf371bb2016-03-10 11:10:43 -0800314 uint32_t flags = 0;
315 flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0;
316 if (flags & kSimilarity_DistanceFieldEffectFlag) {
317 flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0;
318 }
319
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500320 return GrDistanceFieldA8TextGeoProc::Make(d->context(),
321 GrRandomColor(d->fRandom),
bungeman06ca8ec2016-06-09 08:01:03 -0700322 GrTest::TestMatrix(d->fRandom),
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500323 std::move(proxy), params,
jvanverth2d2a68c2014-06-10 06:42:56 -0700324#ifdef SK_GAMMA_APPLY_TO_A8
bungeman06ca8ec2016-06-09 08:01:03 -0700325 d->fRandom->nextF(),
jvanverth2d2a68c2014-06-10 06:42:56 -0700326#endif
bungeman06ca8ec2016-06-09 08:01:03 -0700327 flags,
328 d->fRandom->nextBool());
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000329}
Hal Canary6f6961e2017-01-31 13:50:44 -0500330#endif
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000331
332///////////////////////////////////////////////////////////////////////////////
333
egdaniele659a582015-11-13 09:55:43 -0800334class GrGLDistanceFieldPathGeoProc : public GrGLSLGeometryProcessor {
jvanverthfa38a302014-10-06 05:59:05 -0700335public:
joshualitt465283c2015-09-11 08:19:35 -0700336 GrGLDistanceFieldPathGeoProc()
joshualitt5559ca22015-05-21 15:50:36 -0700337 : fViewMatrix(SkMatrix::InvalidMatrix())
joshualitt5559ca22015-05-21 15:50:36 -0700338 , fTextureSize(SkISize::Make(-1, -1)) {}
jvanverthfa38a302014-10-06 05:59:05 -0700339
mtklein36352bf2015-03-25 18:17:31 -0700340 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
jvanverth502286d2015-04-08 12:37:51 -0700341 const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>();
jvanverthfa38a302014-10-06 05:59:05 -0700342
cdalton85285412016-02-18 12:37:07 -0800343 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
jvanverthfa38a302014-10-06 05:59:05 -0700344
egdaniel4ca2e602015-11-18 08:01:26 -0800345 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
egdaniel0eafe792015-11-20 14:01:22 -0800346 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
egdaniel7ea439b2015-12-03 09:20:44 -0800347 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
joshualittabb52a12015-01-13 15:02:10 -0800348
349 // emit attributes
egdaniel0eafe792015-11-20 14:01:22 -0800350 varyingHandler->emitAttributes(dfTexEffect);
joshualittabb52a12015-01-13 15:02:10 -0800351
egdaniel8dcdedc2015-11-11 06:27:20 -0800352 GrGLSLVertToFrag v(kVec2f_GrSLType);
egdaniel0eafe792015-11-20 14:01:22 -0800353 varyingHandler->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
jvanverthfa38a302014-10-06 05:59:05 -0700354
joshualitt9b989322014-12-15 14:16:27 -0800355 // setup pass through color
Brian Salomonbfd51832017-01-04 13:22:08 -0500356 varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
egdaniel4ca2e602015-11-18 08:01:26 -0800357 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
reede4ef1ca2015-02-17 18:38:38 -0800358
joshualittabb52a12015-01-13 15:02:10 -0800359 // Setup position
egdaniel7ea439b2015-12-03 09:20:44 -0800360 this->setupPosition(vertBuilder,
361 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -0800362 gpArgs,
363 dfTexEffect.inPosition()->fName,
364 dfTexEffect.viewMatrix(),
joshualitt5559ca22015-05-21 15:50:36 -0700365 &fViewMatrixUniform);
joshualittabb52a12015-01-13 15:02:10 -0800366
367 // emit transforms
egdaniel7ea439b2015-12-03 09:20:44 -0800368 this->emitTransforms(vertBuilder,
egdaniel0eafe792015-11-20 14:01:22 -0800369 varyingHandler,
egdaniel7ea439b2015-12-03 09:20:44 -0800370 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -0800371 gpArgs->fPositionVar,
372 dfTexEffect.inPosition()->fName,
bsalomona624bf32016-09-20 09:12:47 -0700373 args.fFPCoordTransformHandler);
joshualitt4973d9d2014-11-08 09:24:25 -0800374
halcanary96fcdcc2015-08-27 07:41:13 -0700375 const char* textureSizeUniName = nullptr;
cdalton5e58cee2016-02-11 12:49:47 -0800376 fTextureSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800377 kVec2f_GrSLType, kDefault_GrSLPrecision,
378 "TextureSize", &textureSizeUniName);
reede4ef1ca2015-02-17 18:38:38 -0800379
jvanverthfdf7ccc2015-01-27 08:19:33 -0800380 // Use highp to work around aliasing issues
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500381 fragBuilder->codeAppendf("highp vec2 uv = %s;", v.fsIn());
jvanverthfdf7ccc2015-01-27 08:19:33 -0800382
egdaniel4ca2e602015-11-18 08:01:26 -0800383 fragBuilder->codeAppend("float texColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700384 fragBuilder->appendTextureLookup(args.fTexSamplers[0],
egdaniel4ca2e602015-11-18 08:01:26 -0800385 "uv",
386 kVec2f_GrSLType);
387 fragBuilder->codeAppend(".r;");
388 fragBuilder->codeAppend("float distance = "
jvanverthfdf7ccc2015-01-27 08:19:33 -0800389 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
jvanverthfa38a302014-10-06 05:59:05 -0700390
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500391 fragBuilder->codeAppendf("highp vec2 st = uv*%s;", textureSizeUniName);
egdaniel4ca2e602015-11-18 08:01:26 -0800392 fragBuilder->codeAppend("float afwidth;");
jvanverthcf371bb2016-03-10 11:10:43 -0800393 bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
394 kUniformScale_DistanceFieldEffectMask;
395 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
brianosman0e3c5542016-04-13 13:56:21 -0700396 bool isGammaCorrect =
397 SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
jvanverthcf371bb2016-03-10 11:10:43 -0800398 if (isUniformScale) {
jvanverth354eba52015-03-16 11:32:49 -0700399 // For uniform scale, we adjust for the effect of the transformation on the distance
halcanary9d524f22016-03-29 09:03:52 -0700400 // by using the length of the gradient of the t coordinate in the y direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800401 // We use st coordinates to ensure we're mapping 1:1 from texel space to pixel space.
jvanverth354eba52015-03-16 11:32:49 -0700402
jvanverthfa38a302014-10-06 05:59:05 -0700403 // this gives us a smooth step across approximately one fragment
jvanverthe499adf2016-07-20 12:22:14 -0700404#ifdef SK_VULKAN
405 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));");
406#else
407 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
egdaniel4ca2e602015-11-18 08:01:26 -0800408 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(st.y));");
jvanverthe499adf2016-07-20 12:22:14 -0700409#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800410 } else if (isSimilarity) {
411 // For similarity transform, we adjust the effect of the transformation on the distance
412 // by using the length of the gradient of the texture coordinates. We use st coordinates
413 // to ensure we're mapping 1:1 from texel space to pixel space.
jvanverthcf371bb2016-03-10 11:10:43 -0800414
415 // this gives us a smooth step across approximately one fragment
jvanverthe499adf2016-07-20 12:22:14 -0700416#ifdef SK_VULKAN
417 fragBuilder->codeAppend("float st_grad_len = length(dFdx(st));");
418#else
419 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800420 fragBuilder->codeAppend("float st_grad_len = length(dFdy(st));");
jvanverthe499adf2016-07-20 12:22:14 -0700421#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800422 fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
jvanverthfa38a302014-10-06 05:59:05 -0700423 } else {
jvanverth354eba52015-03-16 11:32:49 -0700424 // For general transforms, to determine the amount of correction we multiply a unit
425 // vector pointing along the SDF gradient direction by the Jacobian of the st coords
426 // (which is the inverse transform for this fragment) and take the length of the result.
egdaniel4ca2e602015-11-18 08:01:26 -0800427 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
jvanverthd68a5502015-03-16 12:58:43 -0700428 // the length of the gradient may be 0, so we need to check for this
429 // this also compensates for the Adreno, which likes to drop tiles on division by 0
egdaniel4ca2e602015-11-18 08:01:26 -0800430 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
431 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
432 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
433 fragBuilder->codeAppend("} else {");
434 fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
435 fragBuilder->codeAppend("}");
jvanverthd68a5502015-03-16 12:58:43 -0700436
egdaniel4ca2e602015-11-18 08:01:26 -0800437 fragBuilder->codeAppend("vec2 Jdx = dFdx(st);");
438 fragBuilder->codeAppend("vec2 Jdy = dFdy(st);");
439 fragBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
440 fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
jvanverthfa38a302014-10-06 05:59:05 -0700441
442 // this gives us a smooth step across approximately one fragment
egdaniel4ca2e602015-11-18 08:01:26 -0800443 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
jvanverthfa38a302014-10-06 05:59:05 -0700444 }
brianosman0e3c5542016-04-13 13:56:21 -0700445 // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are
446 // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want distance
447 // mapped linearly to coverage, so use a linear step:
448 if (isGammaCorrect) {
449 fragBuilder->codeAppend(
450 "float val = clamp(distance + afwidth / (2.0 * afwidth), 0.0, 1.0);");
451 } else {
452 fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
453 }
jvanverthfa38a302014-10-06 05:59:05 -0700454
egdaniel4ca2e602015-11-18 08:01:26 -0800455 fragBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
jvanverthfa38a302014-10-06 05:59:05 -0700456 }
457
bsalomona624bf32016-09-20 09:12:47 -0700458 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
459 FPCoordTransformIter&& transformIter) override {
reede4ef1ca2015-02-17 18:38:38 -0800460 SkASSERT(fTextureSizeUni.isValid());
jvanverthfa38a302014-10-06 05:59:05 -0700461
Brian Salomondb4183d2016-11-17 12:48:40 -0500462 GrTexture* texture = proc.textureSampler(0).texture();
halcanary9d524f22016-03-29 09:03:52 -0700463 if (texture->width() != fTextureSize.width() ||
jvanverthfa38a302014-10-06 05:59:05 -0700464 texture->height() != fTextureSize.height()) {
465 fTextureSize = SkISize::Make(texture->width(), texture->height());
reede4ef1ca2015-02-17 18:38:38 -0800466 pdman.set2f(fTextureSizeUni,
467 SkIntToScalar(fTextureSize.width()),
468 SkIntToScalar(fTextureSize.height()));
jvanverthfa38a302014-10-06 05:59:05 -0700469 }
joshualitt9b989322014-12-15 14:16:27 -0800470
joshualitte578a952015-05-14 10:09:13 -0700471 const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>();
joshualitt5559ca22015-05-21 15:50:36 -0700472
473 if (!dfpgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfpgp.viewMatrix())) {
474 fViewMatrix = dfpgp.viewMatrix();
egdaniel018fb622015-10-28 07:26:40 -0700475 float viewMatrix[3 * 3];
egdaniel64c47282015-11-13 06:54:19 -0800476 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
joshualitt5559ca22015-05-21 15:50:36 -0700477 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
478 }
bsalomona624bf32016-09-20 09:12:47 -0700479 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
jvanverthfa38a302014-10-06 05:59:05 -0700480 }
481
robertphillips46d36f02015-01-18 08:14:14 -0800482 static inline void GenKey(const GrGeometryProcessor& gp,
Brian Salomon94efbf52016-11-29 13:43:05 -0500483 const GrShaderCaps&,
jvanverthfa38a302014-10-06 05:59:05 -0700484 GrProcessorKeyBuilder* b) {
jvanverth502286d2015-04-08 12:37:51 -0700485 const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>();
jvanverthfa38a302014-10-06 05:59:05 -0700486
joshualitt8fc6c2d2014-12-22 15:27:05 -0800487 uint32_t key = dfTexEffect.getFlags();
Brian Salomonbfd51832017-01-04 13:22:08 -0500488 key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
joshualitt8fc6c2d2014-12-22 15:27:05 -0800489 b->add32(key);
jvanverthfa38a302014-10-06 05:59:05 -0700490 }
491
492private:
reede4ef1ca2015-02-17 18:38:38 -0800493 UniformHandle fTextureSizeUni;
joshualitt5559ca22015-05-21 15:50:36 -0700494 UniformHandle fViewMatrixUniform;
495 SkMatrix fViewMatrix;
joshualitt9b989322014-12-15 14:16:27 -0800496 SkISize fTextureSize;
jvanverthfa38a302014-10-06 05:59:05 -0700497
egdaniele659a582015-11-13 09:55:43 -0800498 typedef GrGLSLGeometryProcessor INHERITED;
jvanverthfa38a302014-10-06 05:59:05 -0700499};
500
501///////////////////////////////////////////////////////////////////////////////
502
jvanverth502286d2015-04-08 12:37:51 -0700503GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(
joshualitt2e3b3e32014-12-09 13:31:14 -0800504 GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800505 const SkMatrix& viewMatrix,
joshualitt2e3b3e32014-12-09 13:31:14 -0800506 GrTexture* texture,
Brian Salomon514baff2016-11-17 15:17:07 -0500507 const GrSamplerParams& params,
joshualittb8c241a2015-05-19 08:23:30 -0700508 uint32_t flags,
509 bool usesLocalCoords)
joshualitte3ababe2015-05-15 07:56:07 -0700510 : fColor(color)
joshualitte578a952015-05-14 10:09:13 -0700511 , fViewMatrix(viewMatrix)
Brian Salomon0bbecb22016-11-17 11:38:22 -0500512 , fTextureSampler(texture, params)
jvanverthfa38a302014-10-06 05:59:05 -0700513 , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
halcanary96fcdcc2015-08-27 07:41:13 -0700514 , fInColor(nullptr)
joshualittb8c241a2015-05-19 08:23:30 -0700515 , fUsesLocalCoords(usesLocalCoords) {
jvanverthfa38a302014-10-06 05:59:05 -0700516 SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
jvanverth502286d2015-04-08 12:37:51 -0700517 this->initClassID<GrDistanceFieldPathGeoProc>();
bsalomon6cb807b2016-08-17 11:33:39 -0700518 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
519 kHigh_GrSLPrecision);
520 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
521 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2f_GrVertexAttribType);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500522 this->addTextureSampler(&fTextureSampler);
jvanverthfa38a302014-10-06 05:59:05 -0700523}
524
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500525
526GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(
527 GrContext* context,
528 GrColor color,
529 const SkMatrix& viewMatrix,
530 sk_sp<GrTextureProxy> proxy,
531 const GrSamplerParams& params,
532 uint32_t flags,
533 bool usesLocalCoords)
534 : fColor(color)
535 , fViewMatrix(viewMatrix)
536 , fTextureSampler(context->textureProvider(), std::move(proxy), params)
537 , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
538 , fInColor(nullptr)
539 , fUsesLocalCoords(usesLocalCoords) {
540 SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
541 this->initClassID<GrDistanceFieldPathGeoProc>();
542 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
543 kHigh_GrSLPrecision);
544 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
545 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2f_GrVertexAttribType);
546 this->addTextureSampler(&fTextureSampler);
547}
548
Brian Salomon94efbf52016-11-29 13:43:05 -0500549void GrDistanceFieldPathGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800550 GrProcessorKeyBuilder* b) const {
joshualitt465283c2015-09-11 08:19:35 -0700551 GrGLDistanceFieldPathGeoProc::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800552}
553
Brian Salomon94efbf52016-11-29 13:43:05 -0500554GrGLSLPrimitiveProcessor*
555GrDistanceFieldPathGeoProc::createGLSLInstance(const GrShaderCaps&) const {
joshualitt465283c2015-09-11 08:19:35 -0700556 return new GrGLDistanceFieldPathGeoProc();
jvanverthfa38a302014-10-06 05:59:05 -0700557}
558
559///////////////////////////////////////////////////////////////////////////////
560
jvanverth502286d2015-04-08 12:37:51 -0700561GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc);
jvanverthfa38a302014-10-06 05:59:05 -0700562
Hal Canary6f6961e2017-01-31 13:50:44 -0500563#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700564sk_sp<GrGeometryProcessor> GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700565 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
566 : GrProcessorUnitTest::kAlphaTextureIdx;
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500567 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
568
jvanverthfa38a302014-10-06 05:59:05 -0700569 static const SkShader::TileMode kTileModes[] = {
570 SkShader::kClamp_TileMode,
571 SkShader::kRepeat_TileMode,
572 SkShader::kMirror_TileMode,
573 };
574 SkShader::TileMode tileModes[] = {
joshualitt0067ff52015-07-08 14:26:19 -0700575 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
576 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
jvanverthfa38a302014-10-06 05:59:05 -0700577 };
Brian Salomon514baff2016-11-17 15:17:07 -0500578 GrSamplerParams params(tileModes, d->fRandom->nextBool() ? GrSamplerParams::kBilerp_FilterMode
579 : GrSamplerParams::kNone_FilterMode);
jvanverthfa38a302014-10-06 05:59:05 -0700580
jvanverthcf371bb2016-03-10 11:10:43 -0800581 uint32_t flags = 0;
582 flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0;
583 if (flags & kSimilarity_DistanceFieldEffectFlag) {
584 flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0;
585 }
586
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500587 return GrDistanceFieldPathGeoProc::Make(d->context(),
588 GrRandomColor(d->fRandom),
bungeman06ca8ec2016-06-09 08:01:03 -0700589 GrTest::TestMatrix(d->fRandom),
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500590 std::move(proxy),
bungeman06ca8ec2016-06-09 08:01:03 -0700591 params,
592 flags,
593 d->fRandom->nextBool());
jvanverthfa38a302014-10-06 05:59:05 -0700594}
Hal Canary6f6961e2017-01-31 13:50:44 -0500595#endif
jvanverthfa38a302014-10-06 05:59:05 -0700596
597///////////////////////////////////////////////////////////////////////////////
598
egdaniele659a582015-11-13 09:55:43 -0800599class GrGLDistanceFieldLCDTextGeoProc : public GrGLSLGeometryProcessor {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000600public:
joshualitt465283c2015-09-11 08:19:35 -0700601 GrGLDistanceFieldLCDTextGeoProc()
joshualitt53f26aa2015-12-10 07:29:54 -0800602 : fViewMatrix(SkMatrix::InvalidMatrix()) {
jvanverth502286d2015-04-08 12:37:51 -0700603 fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
jvanverth21deace2015-04-01 12:43:48 -0700604 }
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000605
mtklein36352bf2015-03-25 18:17:31 -0700606 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
jvanverth502286d2015-04-08 12:37:51 -0700607 const GrDistanceFieldLCDTextGeoProc& dfTexEffect =
608 args.fGP.cast<GrDistanceFieldLCDTextGeoProc>();
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000609
egdaniel4ca2e602015-11-18 08:01:26 -0800610 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
egdaniel0eafe792015-11-20 14:01:22 -0800611 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
egdaniel7ea439b2015-12-03 09:20:44 -0800612 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
joshualittabb52a12015-01-13 15:02:10 -0800613
614 // emit attributes
egdaniel0eafe792015-11-20 14:01:22 -0800615 varyingHandler->emitAttributes(dfTexEffect);
egdaniel4ca2e602015-11-18 08:01:26 -0800616
cdalton85285412016-02-18 12:37:07 -0800617 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
joshualittabb52a12015-01-13 15:02:10 -0800618
joshualitt9b989322014-12-15 14:16:27 -0800619 // setup pass through color
Brian Salomonbfd51832017-01-04 13:22:08 -0500620 varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
joshualitt9b989322014-12-15 14:16:27 -0800621
joshualittabb52a12015-01-13 15:02:10 -0800622 // Setup position
egdaniel7ea439b2015-12-03 09:20:44 -0800623 this->setupPosition(vertBuilder,
624 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -0800625 gpArgs,
626 dfTexEffect.inPosition()->fName,
627 dfTexEffect.viewMatrix(),
joshualitt5559ca22015-05-21 15:50:36 -0700628 &fViewMatrixUniform);
joshualitt4973d9d2014-11-08 09:24:25 -0800629
joshualittabb52a12015-01-13 15:02:10 -0800630 // emit transforms
egdaniel7ea439b2015-12-03 09:20:44 -0800631 this->emitTransforms(vertBuilder,
egdaniel0eafe792015-11-20 14:01:22 -0800632 varyingHandler,
egdaniel7ea439b2015-12-03 09:20:44 -0800633 uniformHandler,
egdaniel4ca2e602015-11-18 08:01:26 -0800634 gpArgs->fPositionVar,
635 dfTexEffect.inPosition()->fName,
bsalomona624bf32016-09-20 09:12:47 -0700636 args.fFPCoordTransformHandler);
joshualittabb52a12015-01-13 15:02:10 -0800637
jvanverthbb4a1cf2015-04-07 09:06:00 -0700638 // set up varyings
jvanverthcf371bb2016-03-10 11:10:43 -0800639 bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
640 kUniformScale_DistanceFieldEffectMask;
641 bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
brianosmanb461d342016-04-13 13:10:14 -0700642 bool isGammaCorrect =
643 SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
egdaniel8dcdedc2015-11-11 06:27:20 -0800644 GrGLSLVertToFrag recipScale(kFloat_GrSLType);
jvanverth7023a002016-02-22 11:25:32 -0800645 GrGLSLVertToFrag uv(kVec2f_GrSLType);
646 varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
647 vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName);
jvanverthbb4a1cf2015-04-07 09:06:00 -0700648
jvanverthcf371bb2016-03-10 11:10:43 -0800649 // compute numbers to be hardcoded to convert texture coordinates from float to int
Brian Salomon0bbecb22016-11-17 11:38:22 -0500650 SkASSERT(dfTexEffect.numTextureSamplers() == 1);
Brian Salomondb4183d2016-11-17 12:48:40 -0500651 GrTexture* atlas = dfTexEffect.textureSampler(0).texture();
joshualitt7375d6b2015-08-07 13:36:44 -0700652 SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
joshualitt922c8b12015-08-07 09:55:23 -0700653
jvanverth7023a002016-02-22 11:25:32 -0800654 GrGLSLVertToFrag st(kVec2f_GrSLType);
655 varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
656 vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(),
657 atlas->width(), atlas->height(),
egdaniel4ca2e602015-11-18 08:01:26 -0800658 dfTexEffect.inTextureCoords()->fName);
jvanverthbb4a1cf2015-04-07 09:06:00 -0700659
660 // add frag shader code
joshualitt30ba4362014-08-21 20:18:45 -0700661
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000662 // create LCD offset adjusted by inverse of transform
jvanverthfdf7ccc2015-01-27 08:19:33 -0800663 // Use highp to work around aliasing issues
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500664 fragBuilder->codeAppendf("highp vec2 uv = %s;\n", uv.fsIn());
joshualitt922c8b12015-08-07 09:55:23 -0700665
666 SkScalar lcdDelta = 1.0f / (3.0f * atlas->width());
jvanverth5a105ff2015-02-18 11:36:35 -0800667 if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500668 fragBuilder->codeAppendf("highp float delta = -%.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta);
jvanverth5a105ff2015-02-18 11:36:35 -0800669 } else {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500670 fragBuilder->codeAppendf("highp float delta = %.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta);
jvanverth5a105ff2015-02-18 11:36:35 -0800671 }
jvanverth78f07182014-07-30 06:17:59 -0700672 if (isUniformScale) {
jvanverthe499adf2016-07-20 12:22:14 -0700673#ifdef SK_VULKAN
674 fragBuilder->codeAppendf("float st_grad_len = abs(dFdx(%s.x));", st.fsIn());
675#else
676 // We use the y gradient because there is a bug in the Mali 400 in the x direction.
jvanverthcf371bb2016-03-10 11:10:43 -0800677 fragBuilder->codeAppendf("float st_grad_len = abs(dFdy(%s.y));", st.fsIn());
jvanverthe499adf2016-07-20 12:22:14 -0700678#endif
jvanverthcf371bb2016-03-10 11:10:43 -0800679 fragBuilder->codeAppend("vec2 offset = vec2(st_grad_len*delta, 0.0);");
680 } else if (isSimilarity) {
681 // For a similarity matrix with rotation, the gradient will not be aligned
682 // with the texel coordinate axes, so we need to calculate it.
jvanverthe499adf2016-07-20 12:22:14 -0700683#ifdef SK_VULKAN
684 fragBuilder->codeAppendf("vec2 st_grad = dFdx(%s);", st.fsIn());
685 fragBuilder->codeAppend("vec2 offset = delta*st_grad;");
686#else
jvanverthcf371bb2016-03-10 11:10:43 -0800687 // We use dFdy because of a Mali 400 bug, and rotate -90 degrees to
688 // get the gradient in the x direction.
689 fragBuilder->codeAppendf("vec2 st_grad = dFdy(%s);", st.fsIn());
jvanverthcf371bb2016-03-10 11:10:43 -0800690 fragBuilder->codeAppend("vec2 offset = delta*vec2(st_grad.y, -st_grad.x);");
jvanverthe499adf2016-07-20 12:22:14 -0700691#endif
692 fragBuilder->codeAppend("float st_grad_len = length(st_grad);");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000693 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800694 fragBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn());
jvanverthbb4a1cf2015-04-07 09:06:00 -0700695
egdaniel4ca2e602015-11-18 08:01:26 -0800696 fragBuilder->codeAppend("vec2 Jdx = dFdx(st);");
697 fragBuilder->codeAppend("vec2 Jdy = dFdy(st);");
698 fragBuilder->codeAppend("vec2 offset = delta*Jdx;");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000699 }
700
701 // green is distance to uv center
egdaniel4ca2e602015-11-18 08:01:26 -0800702 fragBuilder->codeAppend("\tvec4 texColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700703 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv", kVec2f_GrSLType);
egdaniel4ca2e602015-11-18 08:01:26 -0800704 fragBuilder->codeAppend(";\n");
705 fragBuilder->codeAppend("\tvec3 distance;\n");
706 fragBuilder->codeAppend("\tdistance.y = texColor.r;\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000707 // red is distance to left offset
egdaniel4ca2e602015-11-18 08:01:26 -0800708 fragBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n");
709 fragBuilder->codeAppend("\ttexColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700710 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv_adjusted", kVec2f_GrSLType);
egdaniel4ca2e602015-11-18 08:01:26 -0800711 fragBuilder->codeAppend(";\n");
712 fragBuilder->codeAppend("\tdistance.x = texColor.r;\n");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000713 // blue is distance to right offset
egdaniel4ca2e602015-11-18 08:01:26 -0800714 fragBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
715 fragBuilder->codeAppend("\ttexColor = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700716 fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv_adjusted", kVec2f_GrSLType);
egdaniel4ca2e602015-11-18 08:01:26 -0800717 fragBuilder->codeAppend(";\n");
718 fragBuilder->codeAppend("\tdistance.z = texColor.r;\n");
jvanverth2d2a68c2014-06-10 06:42:56 -0700719
egdaniel4ca2e602015-11-18 08:01:26 -0800720 fragBuilder->codeAppend("\tdistance = "
jvanverthada68ef2014-11-03 14:00:24 -0800721 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
jvanverth2d2a68c2014-06-10 06:42:56 -0700722
jvanverth21deace2015-04-01 12:43:48 -0700723 // adjust width based on gamma
halcanary96fcdcc2015-08-27 07:41:13 -0700724 const char* distanceAdjustUniName = nullptr;
cdalton5e58cee2016-02-11 12:49:47 -0800725 fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800726 kVec3f_GrSLType, kDefault_GrSLPrecision,
727 "DistanceAdjust", &distanceAdjustUniName);
egdaniel4ca2e602015-11-18 08:01:26 -0800728 fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
jvanverth21deace2015-04-01 12:43:48 -0700729
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000730 // To be strictly correct, we should compute the anti-aliasing factor separately
731 // for each color component. However, this is only important when using perspective
732 // transformations, and even then using a single factor seems like a reasonable
733 // trade-off between quality and speed.
egdaniel4ca2e602015-11-18 08:01:26 -0800734 fragBuilder->codeAppend("float afwidth;");
jvanverthcf371bb2016-03-10 11:10:43 -0800735 if (isSimilarity) {
halcanary9d524f22016-03-29 09:03:52 -0700736 // For similarity transform (uniform scale-only is a subset of this), we adjust for the
737 // effect of the transformation on the distance by using the length of the gradient of
jvanverthcf371bb2016-03-10 11:10:43 -0800738 // the texture coordinates. We use st coordinates to ensure we're mapping 1:1 from texel
739 // space to pixel space.
jvanverth354eba52015-03-16 11:32:49 -0700740
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000741 // this gives us a smooth step across approximately one fragment
jvanverthcf371bb2016-03-10 11:10:43 -0800742 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*st_grad_len;");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000743 } else {
jvanverth354eba52015-03-16 11:32:49 -0700744 // For general transforms, to determine the amount of correction we multiply a unit
745 // vector pointing along the SDF gradient direction by the Jacobian of the st coords
746 // (which is the inverse transform for this fragment) and take the length of the result.
egdaniel4ca2e602015-11-18 08:01:26 -0800747 fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(distance.r));");
jvanverthd68a5502015-03-16 12:58:43 -0700748 // the length of the gradient may be 0, so we need to check for this
749 // this also compensates for the Adreno, which likes to drop tiles on division by 0
egdaniel4ca2e602015-11-18 08:01:26 -0800750 fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
751 fragBuilder->codeAppend("if (dg_len2 < 0.0001) {");
752 fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
753 fragBuilder->codeAppend("} else {");
754 fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
755 fragBuilder->codeAppend("}");
756 fragBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
757 fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000758
759 // this gives us a smooth step across approximately one fragment
egdaniel4ca2e602015-11-18 08:01:26 -0800760 fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000761 }
762
brianosman0586f5c2016-04-12 12:48:21 -0700763 // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are
764 // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want distance
765 // mapped linearly to coverage, so use a linear step:
brianosmanb461d342016-04-13 13:10:14 -0700766 if (isGammaCorrect) {
brianosman0586f5c2016-04-12 12:48:21 -0700767 fragBuilder->codeAppend("vec4 val = "
bsalomon32d1e952016-09-15 07:29:52 -0700768 "vec4(clamp(distance + vec3(afwidth) / vec3(2.0 * afwidth), 0.0, 1.0), 1.0);");
brianosman0586f5c2016-04-12 12:48:21 -0700769 } else {
770 fragBuilder->codeAppend(
771 "vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
772 }
773
egdaniel27b63352015-09-15 13:13:50 -0700774 // set alpha to be max of rgb coverage
egdaniel4ca2e602015-11-18 08:01:26 -0800775 fragBuilder->codeAppend("val.a = max(max(val.r, val.g), val.b);");
jvanverth2d2a68c2014-06-10 06:42:56 -0700776
egdaniel4ca2e602015-11-18 08:01:26 -0800777 fragBuilder->codeAppendf("%s = val;", args.fOutputCoverage);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000778 }
779
bsalomona624bf32016-09-20 09:12:47 -0700780 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& processor,
781 FPCoordTransformIter&& transformIter) override {
jvanverth21deace2015-04-01 12:43:48 -0700782 SkASSERT(fDistanceAdjustUni.isValid());
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000783
joshualitt5559ca22015-05-21 15:50:36 -0700784 const GrDistanceFieldLCDTextGeoProc& dflcd = processor.cast<GrDistanceFieldLCDTextGeoProc>();
785 GrDistanceFieldLCDTextGeoProc::DistanceAdjust wa = dflcd.getDistanceAdjust();
jvanverth21deace2015-04-01 12:43:48 -0700786 if (wa != fDistanceAdjust) {
787 pdman.set3f(fDistanceAdjustUni,
788 wa.fR,
789 wa.fG,
790 wa.fB);
791 fDistanceAdjust = wa;
jvanverth2d2a68c2014-06-10 06:42:56 -0700792 }
joshualitt9b989322014-12-15 14:16:27 -0800793
joshualitt5559ca22015-05-21 15:50:36 -0700794 if (!dflcd.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dflcd.viewMatrix())) {
795 fViewMatrix = dflcd.viewMatrix();
egdaniel018fb622015-10-28 07:26:40 -0700796 float viewMatrix[3 * 3];
egdaniel64c47282015-11-13 06:54:19 -0800797 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
joshualitt5559ca22015-05-21 15:50:36 -0700798 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
799 }
bsalomona624bf32016-09-20 09:12:47 -0700800 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000801 }
802
robertphillips46d36f02015-01-18 08:14:14 -0800803 static inline void GenKey(const GrGeometryProcessor& gp,
Brian Salomon94efbf52016-11-29 13:43:05 -0500804 const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700805 GrProcessorKeyBuilder* b) {
jvanverth502286d2015-04-08 12:37:51 -0700806 const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>();
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000807
joshualitt8fc6c2d2014-12-22 15:27:05 -0800808 uint32_t key = dfTexEffect.getFlags();
Brian Salomonbfd51832017-01-04 13:22:08 -0500809 key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
joshualitt8fc6c2d2014-12-22 15:27:05 -0800810 b->add32(key);
joshualitt922c8b12015-08-07 09:55:23 -0700811
812 // Currently we hardcode numbers to convert atlas coordinates to normalized floating point
Brian Salomon0bbecb22016-11-17 11:38:22 -0500813 SkASSERT(gp.numTextureSamplers() == 1);
Brian Salomondb4183d2016-11-17 12:48:40 -0500814 GrTexture* atlas = gp.textureSampler(0).texture();
joshualitt922c8b12015-08-07 09:55:23 -0700815 SkASSERT(atlas);
816 b->add32(atlas->width());
817 b->add32(atlas->height());
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000818 }
819
820private:
joshualitt5559ca22015-05-21 15:50:36 -0700821 SkMatrix fViewMatrix;
joshualitt5559ca22015-05-21 15:50:36 -0700822 UniformHandle fViewMatrixUniform;
jvanverth21deace2015-04-01 12:43:48 -0700823 UniformHandle fColorUniform;
jvanverth502286d2015-04-08 12:37:51 -0700824 GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust;
jvanverth21deace2015-04-01 12:43:48 -0700825 UniformHandle fDistanceAdjustUni;
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000826
egdaniele659a582015-11-13 09:55:43 -0800827 typedef GrGLSLGeometryProcessor INHERITED;
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000828};
829
830///////////////////////////////////////////////////////////////////////////////
831
jvanverth502286d2015-04-08 12:37:51 -0700832GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
joshualitt8059eb92014-12-29 15:10:07 -0800833 GrColor color, const SkMatrix& viewMatrix,
Brian Salomon514baff2016-11-17 15:17:07 -0500834 GrTexture* texture, const GrSamplerParams& params,
jvanverth21deace2015-04-01 12:43:48 -0700835 DistanceAdjust distanceAdjust,
joshualittb8c241a2015-05-19 08:23:30 -0700836 uint32_t flags, bool usesLocalCoords)
joshualitte3ababe2015-05-15 07:56:07 -0700837 : fColor(color)
joshualitte578a952015-05-14 10:09:13 -0700838 , fViewMatrix(viewMatrix)
Brian Salomon0bbecb22016-11-17 11:38:22 -0500839 , fTextureSampler(texture, params)
jvanverth21deace2015-04-01 12:43:48 -0700840 , fDistanceAdjust(distanceAdjust)
joshualittb8c241a2015-05-19 08:23:30 -0700841 , fFlags(flags & kLCD_DistanceFieldEffectMask)
842 , fUsesLocalCoords(usesLocalCoords) {
jvanverth78f07182014-07-30 06:17:59 -0700843 SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
jvanverth502286d2015-04-08 12:37:51 -0700844 this->initClassID<GrDistanceFieldLCDTextGeoProc>();
bsalomon6cb807b2016-08-17 11:33:39 -0700845 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
846 kHigh_GrSLPrecision);
847 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
848 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType,
849 kHigh_GrSLPrecision);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500850 this->addTextureSampler(&fTextureSampler);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000851}
852
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500853GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
854 GrContext* context,
855 GrColor color, const SkMatrix& viewMatrix,
856 sk_sp<GrTextureProxy> proxy,
857 const GrSamplerParams& params,
858 DistanceAdjust distanceAdjust,
859 uint32_t flags, bool usesLocalCoords)
860 : fColor(color)
861 , fViewMatrix(viewMatrix)
862 , fTextureSampler(context->textureProvider(), std::move(proxy), params)
863 , fDistanceAdjust(distanceAdjust)
864 , fFlags(flags & kLCD_DistanceFieldEffectMask)
865 , fUsesLocalCoords(usesLocalCoords) {
866 SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
867 this->initClassID<GrDistanceFieldLCDTextGeoProc>();
868 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
869 kHigh_GrSLPrecision);
870 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
871 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType,
872 kHigh_GrSLPrecision);
873 this->addTextureSampler(&fTextureSampler);
874}
875
Brian Salomon94efbf52016-11-29 13:43:05 -0500876void GrDistanceFieldLCDTextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800877 GrProcessorKeyBuilder* b) const {
joshualitt465283c2015-09-11 08:19:35 -0700878 GrGLDistanceFieldLCDTextGeoProc::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800879}
880
Brian Salomon94efbf52016-11-29 13:43:05 -0500881GrGLSLPrimitiveProcessor* GrDistanceFieldLCDTextGeoProc::createGLSLInstance(const GrShaderCaps&) const {
joshualitt465283c2015-09-11 08:19:35 -0700882 return new GrGLDistanceFieldLCDTextGeoProc();
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000883}
884
885///////////////////////////////////////////////////////////////////////////////
886
jvanverth502286d2015-04-08 12:37:51 -0700887GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc);
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000888
Hal Canary6f6961e2017-01-31 13:50:44 -0500889#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700890sk_sp<GrGeometryProcessor> GrDistanceFieldLCDTextGeoProc::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700891 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
892 GrProcessorUnitTest::kAlphaTextureIdx;
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500893 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
894
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000895 static const SkShader::TileMode kTileModes[] = {
896 SkShader::kClamp_TileMode,
897 SkShader::kRepeat_TileMode,
898 SkShader::kMirror_TileMode,
899 };
900 SkShader::TileMode tileModes[] = {
joshualitt0067ff52015-07-08 14:26:19 -0700901 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
902 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000903 };
Brian Salomon514baff2016-11-17 15:17:07 -0500904 GrSamplerParams params(tileModes, d->fRandom->nextBool() ? GrSamplerParams::kBilerp_FilterMode
905 : GrSamplerParams::kNone_FilterMode);
jvanverth21deace2015-04-01 12:43:48 -0700906 DistanceAdjust wa = { 0.0f, 0.1f, -0.1f };
jvanverth78f07182014-07-30 06:17:59 -0700907 uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
jvanverthcf371bb2016-03-10 11:10:43 -0800908 flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0;
909 if (flags & kSimilarity_DistanceFieldEffectFlag) {
910 flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0;
911 }
joshualitt0067ff52015-07-08 14:26:19 -0700912 flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500913 return GrDistanceFieldLCDTextGeoProc::Make(d->context(), GrRandomColor(d->fRandom),
bungeman06ca8ec2016-06-09 08:01:03 -0700914 GrTest::TestMatrix(d->fRandom),
Robert Phillipsdbc8eeb2017-02-21 10:04:31 -0500915 std::move(proxy), params,
bungeman06ca8ec2016-06-09 08:01:03 -0700916 wa,
917 flags,
918 d->fRandom->nextBool());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000919}
Hal Canary6f6961e2017-01-31 13:50:44 -0500920#endif