Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(399)

Side by Side Diff: src/gpu/effects/GrDistanceFieldTextureEffect.cpp

Issue 258883002: Gamma correction for distance field text. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix SkAutoGlyphCache destructor Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/effects/GrDistanceFieldTextureEffect.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/GrGLEffect.h" 9 #include "gl/GrGLEffect.h"
10 #include "gl/GrGLSL.h" 10 #include "gl/GrGLSL.h"
11 #include "gl/GrGLTexture.h" 11 #include "gl/GrGLTexture.h"
12 #include "gl/GrGLVertexEffect.h" 12 #include "gl/GrGLVertexEffect.h"
13 #include "GrTBackendEffectFactory.h" 13 #include "GrTBackendEffectFactory.h"
14 #include "GrTexture.h" 14 #include "GrTexture.h"
15 15
16 #include "SkDistanceFieldGen.h" 16 #include "SkDistanceFieldGen.h"
17 17
18 // To get optical sizes people don't complain about when we blit correctly,
19 // we need to slightly bold each glyph. On the Mac, we need a larger bold value.
20 #if defined(SK_BUILD_FOR_MAC)
21 #define SK_DistanceFieldLCDFactor "0.33"
22 #define SK_DistanceFieldNonLCDFactor "0.25"
23 #else
24 #define SK_DistanceFieldLCDFactor "0.05"
25 #define SK_DistanceFieldNonLCDFactor "0.05"
26 #endif
27
28 // Assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/ 2
29 #define SK_DistanceFieldAAFactor "0.7071"
30
18 class GrGLDistanceFieldTextureEffect : public GrGLVertexEffect { 31 class GrGLDistanceFieldTextureEffect : public GrGLVertexEffect {
19 public: 32 public:
20 GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory, 33 GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory,
21 const GrDrawEffect& drawEffect) 34 const GrDrawEffect& drawEffect)
22 : INHERITED (factory) 35 : INHERITED (factory)
23 , fTextureSize(SkISize::Make(-1,-1)) {} 36 , fTextureSize(SkISize::Make(-1,-1)) {}
24 37
25 virtual void emitCode(GrGLFullShaderBuilder* builder, 38 virtual void emitCode(GrGLFullShaderBuilder* builder,
26 const GrDrawEffect& drawEffect, 39 const GrDrawEffect& drawEffect,
27 EffectKey key, 40 EffectKey key,
(...skipping 21 matching lines...) Expand all
49 fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visib ility, 62 fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visib ility,
50 kVec2f_GrSLType, "TextureSize", 63 kVec2f_GrSLType, "TextureSize",
51 &textureSizeUniName); 64 &textureSizeUniName);
52 65
53 builder->fsCodeAppend("\tvec4 texColor = "); 66 builder->fsCodeAppend("\tvec4 texColor = ");
54 builder->fsAppendTextureLookup(samplers[0], 67 builder->fsAppendTextureLookup(samplers[0],
55 fsCoordName.c_str(), 68 fsCoordName.c_str(),
56 kVec2f_GrSLType); 69 kVec2f_GrSLType);
57 builder->fsCodeAppend(";\n"); 70 builder->fsCodeAppend(";\n");
58 builder->fsCodeAppend("\tfloat distance = " 71 builder->fsCodeAppend("\tfloat distance = "
59 SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFie ldThreshold ");\n"); 72 SK_DistanceFieldMultiplier "*(texColor.r - " SK_Distan ceFieldThreshold ")"
73 "+ " SK_DistanceFieldNonLCDFactor ";\n");
60 74
61 // 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
62 // 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
63 // 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.
64 builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); 78 builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
65 builder->fsCodeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName); 79 builder->fsCodeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName);
66 builder->fsCodeAppend("\tfloat afwidth;\n"); 80 builder->fsCodeAppend("\tfloat afwidth;\n");
67 if (dfTexEffect.isSimilarity()) { 81 if (dfTexEffect.isSimilarity()) {
68 // this gives us a smooth step across approximately one fragment 82 // this gives us a smooth step across approximately one fragment
69 // (assuming a radius of the diagonal of the fragment, hence a facto r of sqrt(2)/2) 83 builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx (st.x);\n");
70 builder->fsCodeAppend("\tafwidth = 0.7071*dFdx(st.x);\n");
71 } else { 84 } else {
72 builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n"); 85 builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n");
73 builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n"); 86 builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n");
74 87
75 builder->fsCodeAppend("\tvec2 uv_grad;\n"); 88 builder->fsCodeAppend("\tvec2 uv_grad;\n");
76 if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { 89 if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
77 // 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
78 builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); 91 builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
79 builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n"); 92 builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n");
80 builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); 93 builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
81 builder->fsCodeAppend("\t} else {\n"); 94 builder->fsCodeAppend("\t} else {\n");
82 builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n" ); 95 builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n" );
83 builder->fsCodeAppend("\t}\n"); 96 builder->fsCodeAppend("\t}\n");
84 } else { 97 } else {
85 builder->fsCodeAppend("\tuv_grad = normalize(uv);\n"); 98 builder->fsCodeAppend("\tuv_grad = normalize(uv);\n");
86 } 99 }
87 builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad. y*Jdy.x,\n"); 100 builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad. y*Jdy.x,\n");
88 builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad. y*Jdy.y);\n"); 101 builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad. y*Jdy.y);\n");
89 102
90 // this gives us a smooth step across approximately one fragment 103 // this gives us a smooth step across approximately one fragment
91 // (assuming a radius of the diagonal of the fragment, hence a facto r of sqrt(2)/2) 104 builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng th(grad);\n");
92 builder->fsCodeAppend("\tafwidth = 0.7071*length(grad);\n");
93 } 105 }
106 builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, dista nce);\n");
94 107
95 builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, dista nce);\n"); 108 #ifdef SK_GAMMA_APPLY_TO_A8
109 // adjust based on gamma
110 const char* luminanceUniName = NULL;
111 // width, height, 1/(3*width)
112 fLuminanceUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity,
113 kFloat_GrSLType, "Luminance",
114 &luminanceUniName);
115
116 builder->fsCodeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
117 builder->fsCodeAppend("\tvec4 gammaColor = ");
118 builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
119 builder->fsCodeAppend(";\n");
120 builder->fsCodeAppend("\tval = gammaColor.r;\n");
121 #endif
96 122
97 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 123 builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
98 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("val") ).c_str()); 124 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("val") ).c_str());
99 } 125 }
100 126
101 virtual void setData(const GrGLUniformManager& uman, 127 virtual void setData(const GrGLUniformManager& uman,
102 const GrDrawEffect& drawEffect) SK_OVERRIDE { 128 const GrDrawEffect& drawEffect) SK_OVERRIDE {
103 SkASSERT(fTextureSizeUni.isValid()); 129 SkASSERT(fTextureSizeUni.isValid());
104 130
105 GrTexture* texture = drawEffect.effect()->get()->texture(0); 131 GrTexture* texture = drawEffect.effect()->get()->texture(0);
106 if (texture->width() != fTextureSize.width() || 132 if (texture->width() != fTextureSize.width() ||
107 texture->height() != fTextureSize.height()) { 133 texture->height() != fTextureSize.height()) {
108 fTextureSize = SkISize::Make(texture->width(), texture->height()); 134 fTextureSize = SkISize::Make(texture->width(), texture->height());
109 uman.set2f(fTextureSizeUni, 135 uman.set2f(fTextureSizeUni,
110 SkIntToScalar(fTextureSize.width()), 136 SkIntToScalar(fTextureSize.width()),
111 SkIntToScalar(fTextureSize.height())); 137 SkIntToScalar(fTextureSize.height()));
112 } 138 }
139 #ifdef SK_GAMMA_APPLY_TO_A8
140 const GrDistanceFieldTextureEffect& dfTexEffect =
141 drawEffect.castEffect<GrDistanceFi eldTextureEffect>();
142 float luminance = dfTexEffect.getLuminance();
143 if (luminance != fLuminance) {
144 uman.set1f(fLuminanceUni, luminance);
145 fLuminance = luminance;
146 }
147 #endif
113 } 148 }
114 149
115 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCap s&) { 150 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCap s&) {
116 const GrDistanceFieldTextureEffect& dfTexEffect = 151 const GrDistanceFieldTextureEffect& dfTexEffect =
117 drawEffect.castEffect<GrDistanceFi eldTextureEffect>(); 152 drawEffect.castEffect<GrDistanceFi eldTextureEffect>();
118 153
119 return dfTexEffect.isSimilarity() ? 0x1 : 0x0; 154 return dfTexEffect.isSimilarity() ? 0x1 : 0x0;
120 } 155 }
121 156
122 private: 157 private:
123 GrGLUniformManager::UniformHandle fTextureSizeUni; 158 GrGLUniformManager::UniformHandle fTextureSizeUni;
124 SkISize fTextureSize; 159 SkISize fTextureSize;
160 GrGLUniformManager::UniformHandle fLuminanceUni;
161 float fLuminance;
125 162
126 typedef GrGLVertexEffect INHERITED; 163 typedef GrGLVertexEffect INHERITED;
127 }; 164 };
128 165
129 /////////////////////////////////////////////////////////////////////////////// 166 ///////////////////////////////////////////////////////////////////////////////
130 167
131 GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture, 168 GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture,
132 const GrTextureParams & params, 169 const GrTextureParams & params,
170 #ifdef SK_GAMMA_APPLY_TO_A8
171 GrTexture* gamma,
172 const GrTextureParams & gammaParams,
173 float luminance,
174 #endif
133 bool similarity) 175 bool similarity)
134 : fTextureAccess(texture, params) 176 : fTextureAccess(texture, params)
177 #ifdef SK_GAMMA_APPLY_TO_A8
178 , fGammaTextureAccess(gamma, gammaParams)
179 , fLuminance(luminance)
180 #endif
135 , fIsSimilarity(similarity) { 181 , fIsSimilarity(similarity) {
136 this->addTextureAccess(&fTextureAccess); 182 this->addTextureAccess(&fTextureAccess);
183 #ifdef SK_GAMMA_APPLY_TO_A8
184 this->addTextureAccess(&fGammaTextureAccess);
185 #endif
137 this->addVertexAttrib(kVec2f_GrSLType); 186 this->addVertexAttrib(kVec2f_GrSLType);
138 } 187 }
139 188
140 bool GrDistanceFieldTextureEffect::onIsEqual(const GrEffect& other) const { 189 bool GrDistanceFieldTextureEffect::onIsEqual(const GrEffect& other) const {
141 const GrDistanceFieldTextureEffect& cte = CastEffect<GrDistanceFieldTextureE ffect>(other); 190 const GrDistanceFieldTextureEffect& cte = CastEffect<GrDistanceFieldTextureE ffect>(other);
142 return fTextureAccess == cte.fTextureAccess; 191 return fTextureAccess == cte.fTextureAccess;
143 } 192 }
144 193
145 void GrDistanceFieldTextureEffect::getConstantColorComponents(GrColor* color, 194 void GrDistanceFieldTextureEffect::getConstantColorComponents(GrColor* color,
146 uint32_t* validFlag s) const { 195 uint32_t* validFlag s) const {
(...skipping 12 matching lines...) Expand all
159 /////////////////////////////////////////////////////////////////////////////// 208 ///////////////////////////////////////////////////////////////////////////////
160 209
161 GR_DEFINE_EFFECT_TEST(GrDistanceFieldTextureEffect); 210 GR_DEFINE_EFFECT_TEST(GrDistanceFieldTextureEffect);
162 211
163 GrEffectRef* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random, 212 GrEffectRef* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
164 GrContext*, 213 GrContext*,
165 const GrDrawTargetCaps&, 214 const GrDrawTargetCaps&,
166 GrTexture* textures[]) { 215 GrTexture* textures[]) {
167 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : 216 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
168 GrEffectUnitTest::kAlphaTextureIdx; 217 GrEffectUnitTest::kAlphaTextureIdx;
218 #ifdef SK_GAMMA_APPLY_TO_A8
219 int texIdx2 = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
220 GrEffectUnitTest::kAlphaTextureIdx;
221 #endif
169 static const SkShader::TileMode kTileModes[] = { 222 static const SkShader::TileMode kTileModes[] = {
170 SkShader::kClamp_TileMode, 223 SkShader::kClamp_TileMode,
171 SkShader::kRepeat_TileMode, 224 SkShader::kRepeat_TileMode,
172 SkShader::kMirror_TileMode, 225 SkShader::kMirror_TileMode,
173 }; 226 };
174 SkShader::TileMode tileModes[] = { 227 SkShader::TileMode tileModes[] = {
175 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 228 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
176 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 229 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
177 }; 230 };
178 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBil erp_FilterMode : 231 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBil erp_FilterMode :
179 GrTextureParams::kNon e_FilterMode); 232 GrTextureParams::kNon e_FilterMode);
233 #ifdef SK_GAMMA_APPLY_TO_A8
234 GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBi lerp_FilterMode :
235 GrTextureParams::kNo ne_FilterMode);
236 #endif
180 237
181 return GrDistanceFieldTextureEffect::Create(textures[texIdx], params, 238 return GrDistanceFieldTextureEffect::Create(textures[texIdx], params,
239 #ifdef SK_GAMMA_APPLY_TO_A8
240 textures[texIdx2], params2,
241 random->nextF(),
242 #endif
182 random->nextBool()); 243 random->nextBool());
183 } 244 }
184 245
185 /////////////////////////////////////////////////////////////////////////////// 246 ///////////////////////////////////////////////////////////////////////////////
186 247
187 class GrGLDistanceFieldLCDTextureEffect : public GrGLVertexEffect { 248 class GrGLDistanceFieldLCDTextureEffect : public GrGLVertexEffect {
188 public: 249 public:
189 GrGLDistanceFieldLCDTextureEffect(const GrBackendEffectFactory& factory, 250 GrGLDistanceFieldLCDTextureEffect(const GrBackendEffectFactory& factory,
190 const GrDrawEffect& drawEffect) 251 const GrDrawEffect& drawEffect)
191 : INHERITED (factory) 252 : INHERITED (factory)
(...skipping 12 matching lines...) Expand all
204 const GrDistanceFieldLCDTextureEffect& dfTexEffect = 265 const GrDistanceFieldLCDTextureEffect& dfTexEffect =
205 drawEffect.castEffect<GrDistanceField LCDTextureEffect>(); 266 drawEffect.castEffect<GrDistanceField LCDTextureEffect>();
206 267
207 SkString fsCoordName; 268 SkString fsCoordName;
208 const char* vsCoordName; 269 const char* vsCoordName;
209 const char* fsCoordNamePtr; 270 const char* fsCoordNamePtr;
210 builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsC oordNamePtr); 271 builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsC oordNamePtr);
211 fsCoordName = fsCoordNamePtr; 272 fsCoordName = fsCoordNamePtr;
212 273
213 const char* attrName0 = 274 const char* attrName0 =
214 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])- >c_str(); 275 builder->getEffectAttributeName(drawEffect.getVertexAttribInd ices()[0])->c_str();
215 builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0); 276 builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0);
216 277
217 const char* textureSizeUniName = NULL; 278 const char* textureSizeUniName = NULL;
218 // width, height, 1/(3*width) 279 // width, height, 1/(3*width)
219 fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visib ility, 280 fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visib ility,
220 kVec3f_GrSLType, "TextureSize", 281 kVec3f_GrSLType, "TextureSize",
221 &textureSizeUniName); 282 &textureSizeUniName);
222 283
223 // create LCD offset adjusted by inverse of transform 284 // create LCD offset adjusted by inverse of transform
224 builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str()); 285 builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
225 builder->fsCodeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName); 286 builder->fsCodeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName);
226 if (dfTexEffect.isUniformScale()) { 287 if (dfTexEffect.isUniformScale()) {
227 builder->fsCodeAppend("\tfloat dx = dFdx(st.x);\n"); 288 builder->fsCodeAppend("\tfloat dx = dFdx(st.x);\n");
228 builder->fsCodeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", text ureSizeUniName); 289 builder->fsCodeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", text ureSizeUniName);
229 } else { 290 } else {
230 builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n"); 291 builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n");
231 builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n"); 292 builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n");
232 builder->fsCodeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUni Name); 293 builder->fsCodeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUni Name);
233 } 294 }
234 295
235 // green is distance to uv center 296 // green is distance to uv center
236 builder->fsCodeAppend("\tvec4 texColor = "); 297 builder->fsCodeAppend("\tvec4 texColor = ");
237 builder->fsAppendTextureLookup(samplers[0], "uv", kVec2f_GrSLType); 298 builder->fsAppendTextureLookup(samplers[0], "uv", kVec2f_GrSLType);
238 builder->fsCodeAppend(";\n"); 299 builder->fsCodeAppend(";\n");
239 builder->fsCodeAppend("\tvec3 distance;\n"); 300 builder->fsCodeAppend("\tvec3 distance;\n");
240 builder->fsCodeAppend("\tdistance.y = " 301 builder->fsCodeAppend("\tdistance.y = texColor.r;\n");
241 SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFie ldThreshold ");\n");
242 // red is distance to left offset 302 // red is distance to left offset
243 builder->fsCodeAppend("\tvec2 uv_adjusted = uv - offset;\n"); 303 builder->fsCodeAppend("\tvec2 uv_adjusted = uv - offset;\n");
244 builder->fsCodeAppend("\ttexColor = "); 304 builder->fsCodeAppend("\ttexColor = ");
245 builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLTy pe); 305 builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLTy pe);
246 builder->fsCodeAppend(";\n"); 306 builder->fsCodeAppend(";\n");
247 builder->fsCodeAppend("\tdistance.x = " 307 builder->fsCodeAppend("\tdistance.x = texColor.r;\n");
248 SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFie ldThreshold ");\n");
249 // blue is distance to right offset 308 // blue is distance to right offset
250 builder->fsCodeAppend("\tuv_adjusted = uv + offset;\n"); 309 builder->fsCodeAppend("\tuv_adjusted = uv + offset;\n");
251 builder->fsCodeAppend("\ttexColor = "); 310 builder->fsCodeAppend("\ttexColor = ");
252 builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLTy pe); 311 builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLTy pe);
253 builder->fsCodeAppend(";\n"); 312 builder->fsCodeAppend(";\n");
254 builder->fsCodeAppend("\tdistance.z = " 313 builder->fsCodeAppend("\tdistance.z = texColor.r;\n");
255 SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFie ldThreshold ");\n"); 314
315 builder->fsCodeAppend("\tdistance = "
316 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_Distance FieldThreshold"))"
317 "+ vec3(" SK_DistanceFieldLCDFactor ");\n");
318
256 // we adjust for the effect of the transformation on the distance by usi ng 319 // we adjust for the effect of the transformation on the distance by usi ng
257 // the length of the gradient of the texture coordinates. We use st coor dinates 320 // the length of the gradient of the texture coordinates. We use st coor dinates
258 // to ensure we're mapping 1:1 from texel space to pixel space. 321 // to ensure we're mapping 1:1 from texel space to pixel space.
259 322
260 // To be strictly correct, we should compute the anti-aliasing factor se parately 323 // To be strictly correct, we should compute the anti-aliasing factor se parately
261 // for each color component. However, this is only important when using perspective 324 // for each color component. However, this is only important when using perspective
262 // transformations, and even then using a single factor seems like a rea sonable 325 // transformations, and even then using a single factor seems like a rea sonable
263 // trade-off between quality and speed. 326 // trade-off between quality and speed.
264 builder->fsCodeAppend("\tfloat afwidth;\n"); 327 builder->fsCodeAppend("\tfloat afwidth;\n");
265 if (dfTexEffect.isUniformScale()) { 328 if (dfTexEffect.isUniformScale()) {
266 // this gives us a smooth step across approximately one fragment 329 // this gives us a smooth step across approximately one fragment
267 // (assuming a radius of the diagonal of the fragment, hence a facto r of sqrt(2)/2) 330 builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\ n");
268 builder->fsCodeAppend("\tafwidth = 0.7071*dx;\n");
269 } else { 331 } else {
270 builder->fsCodeAppend("\tvec2 uv_grad;\n"); 332 builder->fsCodeAppend("\tvec2 uv_grad;\n");
271 if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) { 333 if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
272 // this is to compensate for the Adreno, which likes to drop til es on division by 0 334 // this is to compensate for the Adreno, which likes to drop til es on division by 0
273 builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); 335 builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
274 builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n"); 336 builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n");
275 builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); 337 builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
276 builder->fsCodeAppend("\t} else {\n"); 338 builder->fsCodeAppend("\t} else {\n");
277 builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n" ); 339 builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n" );
278 builder->fsCodeAppend("\t}\n"); 340 builder->fsCodeAppend("\t}\n");
279 } else { 341 } else {
280 builder->fsCodeAppend("\tuv_grad = normalize(uv);\n"); 342 builder->fsCodeAppend("\tuv_grad = normalize(uv);\n");
281 } 343 }
282 builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad. y*Jdy.x,\n"); 344 builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad. y*Jdy.x,\n");
283 builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad. y*Jdy.y);\n"); 345 builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad. y*Jdy.y);\n");
284 346
285 // this gives us a smooth step across approximately one fragment 347 // this gives us a smooth step across approximately one fragment
286 // (assuming a radius of the diagonal of the fragment, hence a facto r of sqrt(2)/2) 348 builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng th(grad);\n");
287 builder->fsCodeAppend("\tafwidth = 0.7071*length(grad);\n");
288 } 349 }
289 350
290 builder->fsCodeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3 (afwidth), distance), 1.0);\n"); 351 builder->fsCodeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3 (afwidth), distance), 1.0);\n");
291 352
353 // adjust based on gamma
354 const char* textColorUniName = NULL;
355 // width, height, 1/(3*width)
356 fTextColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity,
357 kVec3f_GrSLType, "TextColor",
358 &textColorUniName);
359
360 builder->fsCodeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
361 builder->fsCodeAppend("\tvec4 gammaColor = ");
362 builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
363 builder->fsCodeAppend(";\n");
364 builder->fsCodeAppend("\tval.x = gammaColor.r;\n");
365
366 builder->fsCodeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName);
367 builder->fsCodeAppend("\tgammaColor = ");
368 builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
369 builder->fsCodeAppend(";\n");
370 builder->fsCodeAppend("\tval.y = gammaColor.r;\n");
371
372 builder->fsCodeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName);
373 builder->fsCodeAppend("\tgammaColor = ");
374 builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
375 builder->fsCodeAppend(";\n");
376 builder->fsCodeAppend("\tval.z = gammaColor.r;\n");
377
292 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 378 builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
293 (GrGLSLExpr4(inputColor) * GrGLSLExpr4("val")).c_ str()); 379 (GrGLSLExpr4(inputColor) * GrGLSLExpr4("val")).c_ str());
294 } 380 }
295 381
296 virtual void setData(const GrGLUniformManager& uman, 382 virtual void setData(const GrGLUniformManager& uman,
297 const GrDrawEffect& drawEffect) SK_OVERRIDE { 383 const GrDrawEffect& drawEffect) SK_OVERRIDE {
298 SkASSERT(fTextureSizeUni.isValid()); 384 SkASSERT(fTextureSizeUni.isValid());
385 SkASSERT(fTextColorUni.isValid());
299 386
387 const GrDistanceFieldLCDTextureEffect& dfTexEffect =
388 drawEffect.castEffect<GrDistanceFieldLCDText ureEffect>();
300 GrTexture* texture = drawEffect.effect()->get()->texture(0); 389 GrTexture* texture = drawEffect.effect()->get()->texture(0);
301 if (texture->width() != fTextureSize.width() || 390 if (texture->width() != fTextureSize.width() ||
302 texture->height() != fTextureSize.height()) { 391 texture->height() != fTextureSize.height()) {
303 const GrDistanceFieldLCDTextureEffect& dfTexEffect =
304 drawEffect.castEffect<GrDistanceField LCDTextureEffect>();
305 fTextureSize = SkISize::Make(texture->width(), texture->height()); 392 fTextureSize = SkISize::Make(texture->width(), texture->height());
306 float delta = 1.0f/(3.0f*texture->width()); 393 float delta = 1.0f/(3.0f*texture->width());
307 if (dfTexEffect.useBGR()) { 394 if (dfTexEffect.useBGR()) {
308 delta = -delta; 395 delta = -delta;
309 } 396 }
310 uman.set3f(fTextureSizeUni, 397 uman.set3f(fTextureSizeUni,
311 SkIntToScalar(fTextureSize.width()), 398 SkIntToScalar(fTextureSize.width()),
312 SkIntToScalar(fTextureSize.height()), 399 SkIntToScalar(fTextureSize.height()),
313 delta); 400 delta);
314 } 401 }
402
403 GrColor textColor = dfTexEffect.getTextColor();
404 if (textColor != fTextColor) {
405 static const float ONE_OVER_255 = 1.f / 255.f;
406 uman.set3f(fTextColorUni,
407 GrColorUnpackR(textColor) * ONE_OVER_255,
408 GrColorUnpackG(textColor) * ONE_OVER_255,
409 GrColorUnpackB(textColor) * ONE_OVER_255);
410 fTextColor = textColor;
411 }
315 } 412 }
316 413
317 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCap s&) { 414 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCap s&) {
318 const GrDistanceFieldLCDTextureEffect& dfTexEffect = 415 const GrDistanceFieldLCDTextureEffect& dfTexEffect =
319 drawEffect.castEffect<GrDistanceField LCDTextureEffect>(); 416 drawEffect.castEffect<GrDistanceField LCDTextureEffect>();
320 417
321 int uniformScale = dfTexEffect.isUniformScale() ? 0x01 : 0x00; 418 return dfTexEffect.isUniformScale() ? 0x01 : 0x00;;
322 int useBGR = dfTexEffect.useBGR() ? 0x10 : 0x00;
323 return uniformScale | useBGR;
324 } 419 }
325 420
326 private: 421 private:
327 GrGLUniformManager::UniformHandle fTextureSizeUni; 422 GrGLUniformManager::UniformHandle fTextureSizeUni;
328 SkISize fTextureSize; 423 SkISize fTextureSize;
424 GrGLUniformManager::UniformHandle fTextColorUni;
425 SkColor fTextColor;
329 426
330 typedef GrGLVertexEffect INHERITED; 427 typedef GrGLVertexEffect INHERITED;
331 }; 428 };
332 429
333 /////////////////////////////////////////////////////////////////////////////// 430 ///////////////////////////////////////////////////////////////////////////////
334 431
335 GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(GrTexture* text ure, 432 GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
336 const GrTexture Params& params, 433 GrTexture* texture, const GrTe xtureParams& params,
337 bool uniformSca le, 434 GrTexture* gamma, const GrText ureParams& gParams,
338 bool useBGR) 435 SkColor textColor,
436 bool uniformScale, bool useBGR )
339 : fTextureAccess(texture, params) 437 : fTextureAccess(texture, params)
438 , fGammaTextureAccess(gamma, gParams)
439 , fTextColor(textColor)
340 , fUniformScale(uniformScale) 440 , fUniformScale(uniformScale)
341 , fUseBGR(useBGR) { 441 , fUseBGR(useBGR) {
342 this->addTextureAccess(&fTextureAccess); 442 this->addTextureAccess(&fTextureAccess);
443 this->addTextureAccess(&fGammaTextureAccess);
343 this->addVertexAttrib(kVec2f_GrSLType); 444 this->addVertexAttrib(kVec2f_GrSLType);
344 } 445 }
345 446
346 bool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrEffect& other) const { 447 bool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrEffect& other) const {
347 const GrDistanceFieldLCDTextureEffect& cte = CastEffect<GrDistanceFieldLCDTe xtureEffect>(other); 448 const GrDistanceFieldLCDTextureEffect& cte =
348 return fTextureAccess == cte.fTextureAccess; 449 CastEffect<GrDistanceFieldLCDTexture Effect>(other);
450 return (fTextureAccess == cte.fTextureAccess && fGammaTextureAccess == cte.f GammaTextureAccess);
349 } 451 }
350 452
351 void GrDistanceFieldLCDTextureEffect::getConstantColorComponents(GrColor* color, 453 void GrDistanceFieldLCDTextureEffect::getConstantColorComponents(GrColor* color,
352 uint32_t* valid Flags) const { 454 uint32_t* valid Flags) const {
353 if ((*validFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(*color ) && 455 if ((*validFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(*color ) &&
354 GrPixelConfigIsOpaque(this->texture(0)->config())) { 456 GrPixelConfigIsOpaque(this->texture(0)->config())) {
355 *validFlags = kA_GrColorComponentFlag; 457 *validFlags = kA_GrColorComponentFlag;
356 } else { 458 } else {
357 *validFlags = 0; 459 *validFlags = 0;
358 } 460 }
359 } 461 }
360 462
361 const GrBackendEffectFactory& GrDistanceFieldLCDTextureEffect::getFactory() cons t { 463 const GrBackendEffectFactory& GrDistanceFieldLCDTextureEffect::getFactory() cons t {
362 return GrTBackendEffectFactory<GrDistanceFieldLCDTextureEffect>::getInstance (); 464 return GrTBackendEffectFactory<GrDistanceFieldLCDTextureEffect>::getInstance ();
363 } 465 }
364 466
365 /////////////////////////////////////////////////////////////////////////////// 467 ///////////////////////////////////////////////////////////////////////////////
366 468
367 GR_DEFINE_EFFECT_TEST(GrDistanceFieldLCDTextureEffect); 469 GR_DEFINE_EFFECT_TEST(GrDistanceFieldLCDTextureEffect);
368 470
369 GrEffectRef* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random, 471 GrEffectRef* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random,
370 GrContext*, 472 GrContext*,
371 const GrDrawTargetCaps& , 473 const GrDrawTargetCaps& ,
372 GrTexture* textures[]) { 474 GrTexture* textures[]) {
373 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : 475 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
374 GrEffectUnitTest::kAlphaTextureIdx; 476 GrEffectUnitTest::kAlphaTextureIdx;
477 int texIdx2 = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
478 GrEffectUnitTest::kAlphaTextureIdx;
375 static const SkShader::TileMode kTileModes[] = { 479 static const SkShader::TileMode kTileModes[] = {
376 SkShader::kClamp_TileMode, 480 SkShader::kClamp_TileMode,
377 SkShader::kRepeat_TileMode, 481 SkShader::kRepeat_TileMode,
378 SkShader::kMirror_TileMode, 482 SkShader::kMirror_TileMode,
379 }; 483 };
380 SkShader::TileMode tileModes[] = { 484 SkShader::TileMode tileModes[] = {
381 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 485 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
382 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 486 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
383 }; 487 };
384 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBil erp_FilterMode : 488 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBil erp_FilterMode :
385 GrTextureParams::kNone_FilterMode); 489 GrTextureParams::kNone_FilterMode);
386 490 GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBi lerp_FilterMode :
491 GrTextureParams::kNone_FilterMode);
492 GrColor textColor = GrColorPackRGBA(random->nextULessThan(256),
493 random->nextULessThan(256),
494 random->nextULessThan(256),
495 random->nextULessThan(256));
387 return GrDistanceFieldLCDTextureEffect::Create(textures[texIdx], params, 496 return GrDistanceFieldLCDTextureEffect::Create(textures[texIdx], params,
497 textures[texIdx2], params2,
498 textColor,
388 random->nextBool(), random->n extBool()); 499 random->nextBool(), random->n extBool());
389 } 500 }
OLDNEW
« no previous file with comments | « src/gpu/effects/GrDistanceFieldTextureEffect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698