OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrDistanceFieldTextureEffect.h" | 8 #include "GrDistanceFieldTextureEffect.h" |
9 #include "gl/builders/GrGLProgramBuilder.h" | 9 #include "gl/builders/GrGLProgramBuilder.h" |
10 #include "gl/GrGLProcessor.h" | 10 #include "gl/GrGLProcessor.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 public: | 33 public: |
34 GrGLDistanceFieldTextureEffect(const GrBackendProcessorFactory& factory, | 34 GrGLDistanceFieldTextureEffect(const GrBackendProcessorFactory& factory, |
35 const GrProcessor&) | 35 const GrProcessor&) |
36 : INHERITED (factory) | 36 : INHERITED (factory) |
37 , fTextureSize(SkISize::Make(-1,-1)) | 37 , fTextureSize(SkISize::Make(-1,-1)) |
38 #ifdef SK_GAMMA_APPLY_TO_A8 | 38 #ifdef SK_GAMMA_APPLY_TO_A8 |
39 , fLuminance(-1.0f) | 39 , fLuminance(-1.0f) |
40 #endif | 40 #endif |
41 {} | 41 {} |
42 | 42 |
43 virtual void emitCode(GrGLGPBuilder* builder, | 43 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
44 const GrGeometryProcessor& geometryProcessor, | |
45 const GrProcessorKey& key, | |
46 const char* outputColor, | |
47 const char* inputColor, | |
48 const TransformedCoordsArray&, | |
49 const TextureSamplerArray& samplers) SK_OVERRIDE { | |
50 const GrDistanceFieldTextureEffect& dfTexEffect = | 44 const GrDistanceFieldTextureEffect& dfTexEffect = |
51 geometryProcessor.cast<GrDistanceFieldTextureEffect>(); | 45 args.fGP.cast<GrDistanceFieldTextureEffect>(); |
52 SkASSERT(1 == dfTexEffect.getVertexAttribs().count()); | 46 SkASSERT(1 == dfTexEffect.getVertexAttribs().count()); |
53 | 47 |
54 GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); | 48 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
55 SkAssertResult(fsBuilder->enableFeature( | 49 SkAssertResult(fsBuilder->enableFeature( |
56 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); | 50 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); |
57 | 51 |
58 SkString fsCoordName; | 52 SkString fsCoordName; |
59 const char* vsCoordName; | 53 const char* vsCoordName; |
60 const char* fsCoordNamePtr; | 54 const char* fsCoordNamePtr; |
61 builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsC
oordNamePtr); | 55 args.fPB->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fs
CoordNamePtr); |
62 fsCoordName = fsCoordNamePtr; | 56 fsCoordName = fsCoordNamePtr; |
63 | 57 |
64 GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder(); | 58 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); |
65 vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextur
eCoords().c_str()); | 59 vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextur
eCoords().c_str()); |
66 | 60 |
67 const char* textureSizeUniName = NULL; | 61 const char* textureSizeUniName = NULL; |
68 fTextureSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visi
bility, | 62 fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Vis
ibility, |
69 kVec2f_GrSLType, "TextureSize", | 63 kVec2f_GrSLType, "TextureSize", |
70 &textureSizeUniName); | 64 &textureSizeUniName); |
71 | 65 |
72 fsBuilder->codeAppend("\tvec4 texColor = "); | 66 fsBuilder->codeAppend("\tvec4 texColor = "); |
73 fsBuilder->appendTextureLookup(samplers[0], | 67 fsBuilder->appendTextureLookup(args.fSamplers[0], |
74 fsCoordName.c_str(), | 68 fsCoordName.c_str(), |
75 kVec2f_GrSLType); | 69 kVec2f_GrSLType); |
76 fsBuilder->codeAppend(";\n"); | 70 fsBuilder->codeAppend(";\n"); |
77 fsBuilder->codeAppend("\tfloat distance = " | 71 fsBuilder->codeAppend("\tfloat distance = " |
78 SK_DistanceFieldMultiplier "*(texColor.r - " SK_Distan
ceFieldThreshold ")" | 72 SK_DistanceFieldMultiplier "*(texColor.r - " SK_Distan
ceFieldThreshold ")" |
79 "+ " SK_DistanceFieldNonLCDFactor ";\n"); | 73 "+ " SK_DistanceFieldNonLCDFactor ";\n"); |
80 | 74 |
81 // we adjust for the effect of the transformation on the distance by usi
ng | 75 // we adjust for the effect of the transformation on the distance by usi
ng |
82 // the length of the gradient of the texture coordinates. We use st coor
dinates | 76 // the length of the gradient of the texture coordinates. We use st coor
dinates |
83 // to ensure we're mapping 1:1 from texel space to pixel space. | 77 // to ensure we're mapping 1:1 from texel space to pixel space. |
84 fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); | 78 fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); |
85 fsBuilder->codeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName); | 79 fsBuilder->codeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName); |
86 fsBuilder->codeAppend("\tfloat afwidth;\n"); | 80 fsBuilder->codeAppend("\tfloat afwidth;\n"); |
87 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { | 81 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { |
88 // this gives us a smooth step across approximately one fragment | 82 // this gives us a smooth step across approximately one fragment |
89 fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*
dFdx(st.x));\n"); | 83 fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*
dFdx(st.x));\n"); |
90 } else { | 84 } else { |
91 fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); | 85 fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); |
92 fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); | 86 fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); |
93 | 87 |
94 fsBuilder->codeAppend("\tvec2 uv_grad;\n"); | 88 fsBuilder->codeAppend("\tvec2 uv_grad;\n"); |
95 if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { | 89 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { |
96 // this is to compensate for the Adreno, which likes to drop til
es on division by 0 | 90 // this is to compensate for the Adreno, which likes to drop til
es on division by 0 |
97 fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); | 91 fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); |
98 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); | 92 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); |
99 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); | 93 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); |
100 fsBuilder->codeAppend("\t} else {\n"); | 94 fsBuilder->codeAppend("\t} else {\n"); |
101 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"
); | 95 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"
); |
102 fsBuilder->codeAppend("\t}\n"); | 96 fsBuilder->codeAppend("\t}\n"); |
103 } else { | 97 } else { |
104 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); | 98 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); |
105 } | 99 } |
106 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.
y*Jdy.x,\n"); | 100 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.
y*Jdy.x,\n"); |
107 fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.
y*Jdy.y);\n"); | 101 fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.
y*Jdy.y);\n"); |
108 | 102 |
109 // this gives us a smooth step across approximately one fragment | 103 // this gives us a smooth step across approximately one fragment |
110 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng
th(grad);\n"); | 104 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng
th(grad);\n"); |
111 } | 105 } |
112 fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, dista
nce);\n"); | 106 fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, dista
nce);\n"); |
113 | 107 |
114 #ifdef SK_GAMMA_APPLY_TO_A8 | 108 #ifdef SK_GAMMA_APPLY_TO_A8 |
115 // adjust based on gamma | 109 // adjust based on gamma |
116 const char* luminanceUniName = NULL; | 110 const char* luminanceUniName = NULL; |
117 // width, height, 1/(3*width) | 111 // width, height, 1/(3*width) |
118 fLuminanceUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibi
lity, | 112 fLuminanceUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib
ility, |
119 kFloat_GrSLType, "Luminance", | 113 kFloat_GrSLType, "Luminance", |
120 &luminanceUniName); | 114 &luminanceUniName); |
121 | 115 |
122 fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName); | 116 fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName); |
123 fsBuilder->codeAppend("\tvec4 gammaColor = "); | 117 fsBuilder->codeAppend("\tvec4 gammaColor = "); |
124 fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); | 118 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType)
; |
125 fsBuilder->codeAppend(";\n"); | 119 fsBuilder->codeAppend(";\n"); |
126 fsBuilder->codeAppend("\tval = gammaColor.r;\n"); | 120 fsBuilder->codeAppend("\tval = gammaColor.r;\n"); |
127 #endif | 121 #endif |
128 | 122 |
129 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, | 123 fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutput, |
130 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("val")
).c_str()); | 124 (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("val"
)).c_str()); |
131 } | 125 } |
132 | 126 |
133 virtual void setData(const GrGLProgramDataManager& pdman, | 127 virtual void setData(const GrGLProgramDataManager& pdman, |
134 const GrProcessor& effect) SK_OVERRIDE { | 128 const GrProcessor& effect) SK_OVERRIDE { |
135 SkASSERT(fTextureSizeUni.isValid()); | 129 SkASSERT(fTextureSizeUni.isValid()); |
136 | 130 |
137 GrTexture* texture = effect.texture(0); | 131 GrTexture* texture = effect.texture(0); |
138 if (texture->width() != fTextureSize.width() || | 132 if (texture->width() != fTextureSize.width() || |
139 texture->height() != fTextureSize.height()) { | 133 texture->height() != fTextureSize.height()) { |
140 fTextureSize = SkISize::Make(texture->width(), texture->height()); | 134 fTextureSize = SkISize::Make(texture->width(), texture->height()); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 | 248 |
255 /////////////////////////////////////////////////////////////////////////////// | 249 /////////////////////////////////////////////////////////////////////////////// |
256 | 250 |
257 class GrGLDistanceFieldNoGammaTextureEffect : public GrGLGeometryProcessor { | 251 class GrGLDistanceFieldNoGammaTextureEffect : public GrGLGeometryProcessor { |
258 public: | 252 public: |
259 GrGLDistanceFieldNoGammaTextureEffect(const GrBackendProcessorFactory& facto
ry, | 253 GrGLDistanceFieldNoGammaTextureEffect(const GrBackendProcessorFactory& facto
ry, |
260 const GrProcessor& effect) | 254 const GrProcessor& effect) |
261 : INHERITED(factory) | 255 : INHERITED(factory) |
262 , fTextureSize(SkISize::Make(-1, -1)) {} | 256 , fTextureSize(SkISize::Make(-1, -1)) {} |
263 | 257 |
264 virtual void emitCode(GrGLGPBuilder* builder, | 258 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
265 const GrGeometryProcessor& effect, | |
266 const GrProcessorKey& key, | |
267 const char* outputColor, | |
268 const char* inputColor, | |
269 const TransformedCoordsArray&, | |
270 const TextureSamplerArray& samplers) SK_OVERRIDE { | |
271 const GrDistanceFieldNoGammaTextureEffect& dfTexEffect = | 259 const GrDistanceFieldNoGammaTextureEffect& dfTexEffect = |
272 effect.cast<GrDistanceFieldNoGam
maTextureEffect>(); | 260 args.fGP.cast<GrDistanceFieldNoGammaTextureEffect>(); |
273 SkASSERT(1 == dfTexEffect.getVertexAttribs().count()); | 261 SkASSERT(1 == dfTexEffect.getVertexAttribs().count()); |
274 | 262 |
275 GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); | 263 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
276 SkAssertResult(fsBuilder->enableFeature( | 264 SkAssertResult(fsBuilder->enableFeature( |
277 GrGLFragmentShaderBuilder::kStandardDerivat
ives_GLSLFeature)); | 265 GrGLFragmentShaderBuilder::kStandardDerivat
ives_GLSLFeature)); |
278 | 266 |
279 SkString fsCoordName; | 267 SkString fsCoordName; |
280 const char* vsCoordName; | 268 const char* vsCoordName; |
281 const char* fsCoordNamePtr; | 269 const char* fsCoordNamePtr; |
282 builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsC
oordNamePtr); | 270 args.fPB->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fs
CoordNamePtr); |
283 fsCoordName = fsCoordNamePtr; | 271 fsCoordName = fsCoordNamePtr; |
284 | 272 |
285 GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder(); | 273 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); |
286 vsBuilder->codeAppendf("%s = %s;", vsCoordName, dfTexEffect.inTextureCoo
rds().c_str()); | 274 vsBuilder->codeAppendf("%s = %s;", vsCoordName, dfTexEffect.inTextureCoo
rds().c_str()); |
287 | 275 |
288 const char* textureSizeUniName = NULL; | 276 const char* textureSizeUniName = NULL; |
289 fTextureSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visi
bility, | 277 fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Vis
ibility, |
290 kVec2f_GrSLType, "TextureSize", | 278 kVec2f_GrSLType, "TextureSize", |
291 &textureSizeUniName); | 279 &textureSizeUniName); |
292 | 280 |
293 fsBuilder->codeAppend("vec4 texColor = "); | 281 fsBuilder->codeAppend("vec4 texColor = "); |
294 fsBuilder->appendTextureLookup(samplers[0], | 282 fsBuilder->appendTextureLookup(args.fSamplers[0], |
295 fsCoordName.c_str(), | 283 fsCoordName.c_str(), |
296 kVec2f_GrSLType); | 284 kVec2f_GrSLType); |
297 fsBuilder->codeAppend(";"); | 285 fsBuilder->codeAppend(";"); |
298 fsBuilder->codeAppend("float distance = " | 286 fsBuilder->codeAppend("float distance = " |
299 SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThresho
ld ");"); | 287 SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThresho
ld ");"); |
300 | 288 |
301 // we adjust for the effect of the transformation on the distance by usi
ng | 289 // we adjust for the effect of the transformation on the distance by usi
ng |
302 // the length of the gradient of the texture coordinates. We use st coor
dinates | 290 // the length of the gradient of the texture coordinates. We use st coor
dinates |
303 // to ensure we're mapping 1:1 from texel space to pixel space. | 291 // to ensure we're mapping 1:1 from texel space to pixel space. |
304 fsBuilder->codeAppendf("vec2 uv = %s;", fsCoordName.c_str()); | 292 fsBuilder->codeAppendf("vec2 uv = %s;", fsCoordName.c_str()); |
305 fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); | 293 fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); |
306 fsBuilder->codeAppend("float afwidth;"); | 294 fsBuilder->codeAppend("float afwidth;"); |
307 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { | 295 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { |
308 // this gives us a smooth step across approximately one fragment | 296 // this gives us a smooth step across approximately one fragment |
309 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dF
dx(st.x));"); | 297 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dF
dx(st.x));"); |
310 } else { | 298 } else { |
311 fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); | 299 fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); |
312 fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); | 300 fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); |
313 | 301 |
314 fsBuilder->codeAppend("vec2 uv_grad;"); | 302 fsBuilder->codeAppend("vec2 uv_grad;"); |
315 if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { | 303 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { |
316 // this is to compensate for the Adreno, which likes to drop til
es on division by 0 | 304 // this is to compensate for the Adreno, which likes to drop til
es on division by 0 |
317 fsBuilder->codeAppend("float uv_len2 = dot(uv, uv);"); | 305 fsBuilder->codeAppend("float uv_len2 = dot(uv, uv);"); |
318 fsBuilder->codeAppend("if (uv_len2 < 0.0001) {"); | 306 fsBuilder->codeAppend("if (uv_len2 < 0.0001) {"); |
319 fsBuilder->codeAppend("uv_grad = vec2(0.7071, 0.7071);"); | 307 fsBuilder->codeAppend("uv_grad = vec2(0.7071, 0.7071);"); |
320 fsBuilder->codeAppend("} else {"); | 308 fsBuilder->codeAppend("} else {"); |
321 fsBuilder->codeAppend("uv_grad = uv*inversesqrt(uv_len2);"); | 309 fsBuilder->codeAppend("uv_grad = uv*inversesqrt(uv_len2);"); |
322 fsBuilder->codeAppend("}"); | 310 fsBuilder->codeAppend("}"); |
323 } else { | 311 } else { |
324 fsBuilder->codeAppend("uv_grad = normalize(uv);"); | 312 fsBuilder->codeAppend("uv_grad = normalize(uv);"); |
325 } | 313 } |
326 fsBuilder->codeAppend("vec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*
Jdy.x,"); | 314 fsBuilder->codeAppend("vec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*
Jdy.x,"); |
327 fsBuilder->codeAppend(" uv_grad.x*Jdx.y + uv_grad.y*
Jdy.y);"); | 315 fsBuilder->codeAppend(" uv_grad.x*Jdx.y + uv_grad.y*
Jdy.y);"); |
328 | 316 |
329 // this gives us a smooth step across approximately one fragment | 317 // this gives us a smooth step across approximately one fragment |
330 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length
(grad);"); | 318 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length
(grad);"); |
331 } | 319 } |
332 fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distanc
e);"); | 320 fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distanc
e);"); |
333 | 321 |
334 fsBuilder->codeAppendf("%s = %s;", outputColor, | 322 fsBuilder->codeAppendf("%s = %s;", args.fOutput, |
335 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("val")).c_str()); | 323 (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("val")).c_str()); |
336 } | 324 } |
337 | 325 |
338 virtual void setData(const GrGLProgramDataManager& pdman, | 326 virtual void setData(const GrGLProgramDataManager& pdman, |
339 const GrProcessor& effect) SK_OVERRIDE { | 327 const GrProcessor& effect) SK_OVERRIDE { |
340 SkASSERT(fTextureSizeUni.isValid()); | 328 SkASSERT(fTextureSizeUni.isValid()); |
341 | 329 |
342 GrTexture* texture = effect.texture(0); | 330 GrTexture* texture = effect.texture(0); |
343 if (texture->width() != fTextureSize.width() || | 331 if (texture->width() != fTextureSize.width() || |
344 texture->height() != fTextureSize.height()) { | 332 texture->height() != fTextureSize.height()) { |
345 fTextureSize = SkISize::Make(texture->width(), texture->height()); | 333 fTextureSize = SkISize::Make(texture->width(), texture->height()); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 /////////////////////////////////////////////////////////////////////////////// | 409 /////////////////////////////////////////////////////////////////////////////// |
422 | 410 |
423 class GrGLDistanceFieldLCDTextureEffect : public GrGLGeometryProcessor { | 411 class GrGLDistanceFieldLCDTextureEffect : public GrGLGeometryProcessor { |
424 public: | 412 public: |
425 GrGLDistanceFieldLCDTextureEffect(const GrBackendProcessorFactory& factory, | 413 GrGLDistanceFieldLCDTextureEffect(const GrBackendProcessorFactory& factory, |
426 const GrProcessor&) | 414 const GrProcessor&) |
427 : INHERITED (factory) | 415 : INHERITED (factory) |
428 , fTextureSize(SkISize::Make(-1,-1)) | 416 , fTextureSize(SkISize::Make(-1,-1)) |
429 , fTextColor(GrColor_ILLEGAL) {} | 417 , fTextColor(GrColor_ILLEGAL) {} |
430 | 418 |
431 virtual void emitCode(GrGLGPBuilder* builder, | 419 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
432 const GrGeometryProcessor& geometryProcessor, | |
433 const GrProcessorKey& key, | |
434 const char* outputColor, | |
435 const char* inputColor, | |
436 const TransformedCoordsArray&, | |
437 const TextureSamplerArray& samplers) SK_OVERRIDE { | |
438 const GrDistanceFieldLCDTextureEffect& dfTexEffect = | 420 const GrDistanceFieldLCDTextureEffect& dfTexEffect = |
439 geometryProcessor.cast<GrDistanceFieldLCDTextureEffect>(); | 421 args.fGP.cast<GrDistanceFieldLCDTextureEffect>(); |
440 SkASSERT(1 == dfTexEffect.getVertexAttribs().count()); | 422 SkASSERT(1 == dfTexEffect.getVertexAttribs().count()); |
441 | 423 |
442 SkString fsCoordName; | 424 SkString fsCoordName; |
443 const char* vsCoordName; | 425 const char* vsCoordName; |
444 const char* fsCoordNamePtr; | 426 const char* fsCoordNamePtr; |
445 builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsC
oordNamePtr); | 427 args.fPB->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fs
CoordNamePtr); |
446 fsCoordName = fsCoordNamePtr; | 428 fsCoordName = fsCoordNamePtr; |
447 | 429 |
448 GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder(); | 430 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); |
449 vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextur
eCoords().c_str()); | 431 vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextur
eCoords().c_str()); |
450 | 432 |
451 const char* textureSizeUniName = NULL; | 433 const char* textureSizeUniName = NULL; |
452 // width, height, 1/(3*width) | 434 // width, height, 1/(3*width) |
453 fTextureSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visi
bility, | 435 fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Vis
ibility, |
454 kVec3f_GrSLType, "TextureSize", | 436 kVec3f_GrSLType, "TextureSize", |
455 &textureSizeUniName); | 437 &textureSizeUniName); |
456 | 438 |
457 GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); | 439 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
458 | 440 |
459 SkAssertResult(fsBuilder->enableFeature( | 441 SkAssertResult(fsBuilder->enableFeature( |
460 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); | 442 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); |
461 | 443 |
462 // create LCD offset adjusted by inverse of transform | 444 // create LCD offset adjusted by inverse of transform |
463 fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); | 445 fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); |
464 fsBuilder->codeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName); | 446 fsBuilder->codeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName); |
465 bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_Distance
FieldEffectMask); | 447 bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_Distance
FieldEffectMask); |
466 if (isUniformScale) { | 448 if (isUniformScale) { |
467 fsBuilder->codeAppend("\tfloat dx = dFdx(st.x);\n"); | 449 fsBuilder->codeAppend("\tfloat dx = dFdx(st.x);\n"); |
468 fsBuilder->codeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", text
ureSizeUniName); | 450 fsBuilder->codeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", text
ureSizeUniName); |
469 } else { | 451 } else { |
470 fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); | 452 fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); |
471 fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); | 453 fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); |
472 fsBuilder->codeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUni
Name); | 454 fsBuilder->codeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUni
Name); |
473 } | 455 } |
474 | 456 |
475 // green is distance to uv center | 457 // green is distance to uv center |
476 fsBuilder->codeAppend("\tvec4 texColor = "); | 458 fsBuilder->codeAppend("\tvec4 texColor = "); |
477 fsBuilder->appendTextureLookup(samplers[0], "uv", kVec2f_GrSLType); | 459 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv", kVec2f_GrSLType)
; |
478 fsBuilder->codeAppend(";\n"); | 460 fsBuilder->codeAppend(";\n"); |
479 fsBuilder->codeAppend("\tvec3 distance;\n"); | 461 fsBuilder->codeAppend("\tvec3 distance;\n"); |
480 fsBuilder->codeAppend("\tdistance.y = texColor.r;\n"); | 462 fsBuilder->codeAppend("\tdistance.y = texColor.r;\n"); |
481 // red is distance to left offset | 463 // red is distance to left offset |
482 fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n"); | 464 fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n"); |
483 fsBuilder->codeAppend("\ttexColor = "); | 465 fsBuilder->codeAppend("\ttexColor = "); |
484 fsBuilder->appendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLTy
pe); | 466 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_
GrSLType); |
485 fsBuilder->codeAppend(";\n"); | 467 fsBuilder->codeAppend(";\n"); |
486 fsBuilder->codeAppend("\tdistance.x = texColor.r;\n"); | 468 fsBuilder->codeAppend("\tdistance.x = texColor.r;\n"); |
487 // blue is distance to right offset | 469 // blue is distance to right offset |
488 fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n"); | 470 fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n"); |
489 fsBuilder->codeAppend("\ttexColor = "); | 471 fsBuilder->codeAppend("\ttexColor = "); |
490 fsBuilder->appendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLTy
pe); | 472 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_
GrSLType); |
491 fsBuilder->codeAppend(";\n"); | 473 fsBuilder->codeAppend(";\n"); |
492 fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); | 474 fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); |
493 | 475 |
494 fsBuilder->codeAppend("\tdistance = " | 476 fsBuilder->codeAppend("\tdistance = " |
495 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_Distance
FieldThreshold"))" | 477 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_Distance
FieldThreshold"))" |
496 "+ vec3(" SK_DistanceFieldLCDFactor ");\n"); | 478 "+ vec3(" SK_DistanceFieldLCDFactor ");\n"); |
497 | 479 |
498 // we adjust for the effect of the transformation on the distance by usi
ng | 480 // we adjust for the effect of the transformation on the distance by usi
ng |
499 // the length of the gradient of the texture coordinates. We use st coor
dinates | 481 // the length of the gradient of the texture coordinates. We use st coor
dinates |
500 // to ensure we're mapping 1:1 from texel space to pixel space. | 482 // to ensure we're mapping 1:1 from texel space to pixel space. |
501 | 483 |
502 // To be strictly correct, we should compute the anti-aliasing factor se
parately | 484 // To be strictly correct, we should compute the anti-aliasing factor se
parately |
503 // for each color component. However, this is only important when using
perspective | 485 // for each color component. However, this is only important when using
perspective |
504 // transformations, and even then using a single factor seems like a rea
sonable | 486 // transformations, and even then using a single factor seems like a rea
sonable |
505 // trade-off between quality and speed. | 487 // trade-off between quality and speed. |
506 fsBuilder->codeAppend("\tfloat afwidth;\n"); | 488 fsBuilder->codeAppend("\tfloat afwidth;\n"); |
507 if (isUniformScale) { | 489 if (isUniformScale) { |
508 // this gives us a smooth step across approximately one fragment | 490 // this gives us a smooth step across approximately one fragment |
509 fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*
dx);\n"); | 491 fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*
dx);\n"); |
510 } else { | 492 } else { |
511 fsBuilder->codeAppend("\tvec2 uv_grad;\n"); | 493 fsBuilder->codeAppend("\tvec2 uv_grad;\n"); |
512 if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { | 494 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { |
513 // this is to compensate for the Adreno, which likes to drop til
es on division by 0 | 495 // this is to compensate for the Adreno, which likes to drop til
es on division by 0 |
514 fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); | 496 fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); |
515 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); | 497 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); |
516 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); | 498 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); |
517 fsBuilder->codeAppend("\t} else {\n"); | 499 fsBuilder->codeAppend("\t} else {\n"); |
518 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"
); | 500 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"
); |
519 fsBuilder->codeAppend("\t}\n"); | 501 fsBuilder->codeAppend("\t}\n"); |
520 } else { | 502 } else { |
521 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); | 503 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); |
522 } | 504 } |
523 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.
y*Jdy.x,\n"); | 505 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.
y*Jdy.x,\n"); |
524 fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.
y*Jdy.y);\n"); | 506 fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.
y*Jdy.y);\n"); |
525 | 507 |
526 // this gives us a smooth step across approximately one fragment | 508 // this gives us a smooth step across approximately one fragment |
527 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng
th(grad);\n"); | 509 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng
th(grad);\n"); |
528 } | 510 } |
529 | 511 |
530 fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3
(afwidth), distance), 1.0);\n"); | 512 fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3
(afwidth), distance), 1.0);\n"); |
531 | 513 |
532 // adjust based on gamma | 514 // adjust based on gamma |
533 const char* textColorUniName = NULL; | 515 const char* textColorUniName = NULL; |
534 // width, height, 1/(3*width) | 516 // width, height, 1/(3*width) |
535 fTextColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibi
lity, | 517 fTextColorUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib
ility, |
536 kVec3f_GrSLType, "TextColor", | 518 kVec3f_GrSLType, "TextColor", |
537 &textColorUniName); | 519 &textColorUniName); |
538 | 520 |
539 fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName); | 521 fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName); |
540 fsBuilder->codeAppend("\tvec4 gammaColor = "); | 522 fsBuilder->codeAppend("\tvec4 gammaColor = "); |
541 fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); | 523 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType)
; |
542 fsBuilder->codeAppend(";\n"); | 524 fsBuilder->codeAppend(";\n"); |
543 fsBuilder->codeAppend("\tval.x = gammaColor.r;\n"); | 525 fsBuilder->codeAppend("\tval.x = gammaColor.r;\n"); |
544 | 526 |
545 fsBuilder->codeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName); | 527 fsBuilder->codeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName); |
546 fsBuilder->codeAppend("\tgammaColor = "); | 528 fsBuilder->codeAppend("\tgammaColor = "); |
547 fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); | 529 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType)
; |
548 fsBuilder->codeAppend(";\n"); | 530 fsBuilder->codeAppend(";\n"); |
549 fsBuilder->codeAppend("\tval.y = gammaColor.r;\n"); | 531 fsBuilder->codeAppend("\tval.y = gammaColor.r;\n"); |
550 | 532 |
551 fsBuilder->codeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName); | 533 fsBuilder->codeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName); |
552 fsBuilder->codeAppend("\tgammaColor = "); | 534 fsBuilder->codeAppend("\tgammaColor = "); |
553 fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType); | 535 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType)
; |
554 fsBuilder->codeAppend(";\n"); | 536 fsBuilder->codeAppend(";\n"); |
555 fsBuilder->codeAppend("\tval.z = gammaColor.r;\n"); | 537 fsBuilder->codeAppend("\tval.z = gammaColor.r;\n"); |
556 | 538 |
557 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, | 539 fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutput, |
558 (GrGLSLExpr4(inputColor) * GrGLSLExpr4("val")).c_
str()); | 540 (GrGLSLExpr4(args.fInput) * GrGLSLExpr4("val")).c
_str()); |
559 } | 541 } |
560 | 542 |
561 virtual void setData(const GrGLProgramDataManager& pdman, | 543 virtual void setData(const GrGLProgramDataManager& pdman, |
562 const GrProcessor& processor) SK_OVERRIDE { | 544 const GrProcessor& processor) SK_OVERRIDE { |
563 SkASSERT(fTextureSizeUni.isValid()); | 545 SkASSERT(fTextureSizeUni.isValid()); |
564 SkASSERT(fTextColorUni.isValid()); | 546 SkASSERT(fTextColorUni.isValid()); |
565 | 547 |
566 const GrDistanceFieldLCDTextureEffect& dfTexEffect = | 548 const GrDistanceFieldLCDTextureEffect& dfTexEffect = |
567 processor.cast<GrDistanceFieldLCDTextureEffect>(); | 549 processor.cast<GrDistanceFieldLCDTextureEffect>(); |
568 GrTexture* texture = processor.texture(0); | 550 GrTexture* texture = processor.texture(0); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 random->nextULessThan(256), | 653 random->nextULessThan(256), |
672 random->nextULessThan(256)); | 654 random->nextULessThan(256)); |
673 uint32_t flags = kUseLCD_DistanceFieldEffectFlag; | 655 uint32_t flags = kUseLCD_DistanceFieldEffectFlag; |
674 flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; | 656 flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; |
675 flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; | 657 flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; |
676 return GrDistanceFieldLCDTextureEffect::Create(textures[texIdx], params, | 658 return GrDistanceFieldLCDTextureEffect::Create(textures[texIdx], params, |
677 textures[texIdx2], params2, | 659 textures[texIdx2], params2, |
678 textColor, | 660 textColor, |
679 flags); | 661 flags); |
680 } | 662 } |
OLD | NEW |