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

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

Powered by Google App Engine
This is Rietveld 408576698