OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2015 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 #include "GrGLSLBlend.h" | |
8 #include "glsl/GrGLSLFragmentShaderBuilder.h" | |
9 | |
10 ////////////////////////////////////////////////////////////////////////////// | |
11 // Advanced (non-coeff) blend helpers | |
12 ////////////////////////////////////////////////////////////////////////////// | |
13 | |
14 static void hard_light(GrGLSLFragmentBuilder* fsBuilder, | |
15 const char* final, | |
16 const char* src, | |
17 const char* dst) { | |
18 static const char kComponents[] = { 'r', 'g', 'b' }; | |
19 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { | |
20 char component = kComponents[i]; | |
21 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src
); | |
22 fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;", | |
23 final, component, src, component, dst, component)
; | |
24 fsBuilder->codeAppend("} else {"); | |
25 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s
.a - %s.%c);", | |
26 final, component, src, dst, dst, dst, component,
src, src, | |
27 component); | |
28 fsBuilder->codeAppend("}"); | |
29 } | |
30 fsBuilder->codeAppendf("%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s
.a);", | |
31 final, src, dst, dst, src); | |
32 } | |
33 | |
34 // Does one component of color-dodge | |
35 static void color_dodge_component(GrGLSLFragmentBuilder* fsBuilder, | |
36 const char* final, | |
37 const char* src, | |
38 const char* dst, | |
39 const char component) { | |
40 fsBuilder->codeAppendf("if (0.0 == %s.%c) {", dst, component); | |
41 fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", | |
42 final, component, src, component, dst); | |
43 fsBuilder->codeAppend("} else {"); | |
44 fsBuilder->codeAppendf("float d = %s.a - %s.%c;", src, src, component); | |
45 fsBuilder->codeAppend("if (0.0 == d) {"); | |
46 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c *
(1.0 - %s.a);", | |
47 final, component, src, dst, src, component, dst, dst,
component, | |
48 src); | |
49 fsBuilder->codeAppend("} else {"); | |
50 fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / d);", | |
51 dst, dst, component, src); | |
52 fsBuilder->codeAppendf("%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1
.0 - %s.a);", | |
53 final, component, src, src, component, dst, dst, comp
onent, src); | |
54 fsBuilder->codeAppend("}"); | |
55 fsBuilder->codeAppend("}"); | |
56 } | |
57 | |
58 // Does one component of color-burn | |
59 static void color_burn_component(GrGLSLFragmentBuilder* fsBuilder, | |
60 const char* final, | |
61 const char* src, | |
62 const char* dst, | |
63 const char component) { | |
64 fsBuilder->codeAppendf("if (%s.a == %s.%c) {", dst, dst, component); | |
65 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c *
(1.0 - %s.a);", | |
66 final, component, src, dst, src, component, dst, dst,
component, | |
67 src); | |
68 fsBuilder->codeAppendf("} else if (0.0 == %s.%c) {", src, component); | |
69 fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", | |
70 final, component, dst, component, src); | |
71 fsBuilder->codeAppend("} else {"); | |
72 fsBuilder->codeAppendf("float d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s
.%c);", | |
73 dst, dst, dst, component, src, src, component); | |
74 fsBuilder->codeAppendf("%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1
.0 - %s.a);", | |
75 final, component, src, src, component, dst, dst, comp
onent, src); | |
76 fsBuilder->codeAppend("}"); | |
77 } | |
78 | |
79 // Does one component of soft-light. Caller should have already checked that dst
alpha > 0. | |
80 static void soft_light_component_pos_dst_alpha(GrGLSLFragmentBuilder* fsBuilder, | |
81 const char* final, | |
82 const char* src, | |
83 const char* dst, | |
84 const char component) { | |
85 // if (2S < Sa) | |
86 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src); | |
87 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) | |
88 fsBuilder->codeAppendf("%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a +" | |
89 "(1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.
0);", | |
90 final, component, dst, component, dst, component, src
, src, | |
91 component, dst, dst, src, component, dst, component,
src, src, | |
92 component); | |
93 // else if (4D < Da) | |
94 fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {", | |
95 dst, component, dst); | |
96 fsBuilder->codeAppendf("float DSqd = %s.%c * %s.%c;", | |
97 dst, component, dst, component); | |
98 fsBuilder->codeAppendf("float DCub = DSqd * %s.%c;", dst, component); | |
99 fsBuilder->codeAppendf("float DaSqd = %s.a * %s.a;", dst, dst); | |
100 fsBuilder->codeAppendf("float DaCub = DaSqd * %s.a;", dst); | |
101 // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da
^2 | |
102 fsBuilder->codeAppendf("%s.%c =" | |
103 "(DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)
) +" | |
104 " 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s
.a - 2.0*%s.%c) -" | |
105 " DaCub*%s.%c) / DaSqd;", | |
106 final, component, src, component, dst, component, | |
107 src, src, component, dst, src, src, component, src, s
rc, | |
108 component, src, component); | |
109 fsBuilder->codeAppendf("} else {"); | |
110 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S | |
111 fsBuilder->codeAppendf("%s.%c = %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c -" | |
112 " sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c;", | |
113 final, component, dst, component, src, src, component
, src, component, | |
114 dst, dst, component, src, src, component, dst, src, c
omponent); | |
115 fsBuilder->codeAppendf("}"); | |
116 } | |
117 | |
118 // Adds a function that takes two colors and an alpha as input. It produces a co
lor with the | |
119 // hue and saturation of the first color, the luminosity of the second color, an
d the input | |
120 // alpha. It has this signature: | |
121 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). | |
122 static void add_lum_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setLumF
unction) { | |
123 // Emit a helper that gets the luminance of a color. | |
124 SkString getFunction; | |
125 GrGLSLShaderVar getLumArgs[] = { | |
126 GrGLSLShaderVar("color", kVec3f_GrSLType), | |
127 }; | |
128 SkString getLumBody("return dot(vec3(0.3, 0.59, 0.11), color);"); | |
129 fsBuilder->emitFunction(kFloat_GrSLType, | |
130 "luminance", | |
131 SK_ARRAY_COUNT(getLumArgs), getLumArgs, | |
132 getLumBody.c_str(), | |
133 &getFunction); | |
134 | |
135 // Emit the set luminance function. | |
136 GrGLSLShaderVar setLumArgs[] = { | |
137 GrGLSLShaderVar("hueSat", kVec3f_GrSLType), | |
138 GrGLSLShaderVar("alpha", kFloat_GrSLType), | |
139 GrGLSLShaderVar("lumColor", kVec3f_GrSLType), | |
140 }; | |
141 SkString setLumBody; | |
142 setLumBody.printf("float diff = %s(lumColor - hueSat);", getFunction.c_str()
); | |
143 setLumBody.append("vec3 outColor = hueSat + diff;"); | |
144 setLumBody.appendf("float outLum = %s(outColor);", getFunction.c_str()); | |
145 setLumBody.append("float minComp = min(min(outColor.r, outColor.g), outColor
.b);" | |
146 "float maxComp = max(max(outColor.r, outColor.g), outColor
.b);" | |
147 "if (minComp < 0.0 && outLum != minComp) {" | |
148 "outColor = outLum + ((outColor - vec3(outLum, outLum, out
Lum)) * outLum) /" | |
149 "(outLum - minComp);" | |
150 "}" | |
151 "if (maxComp > alpha && maxComp != outLum) {" | |
152 "outColor = outLum +" | |
153 "((outColor - vec3(outLum, outLum, outLum)) * (alpha - out
Lum)) /" | |
154 "(maxComp - outLum);" | |
155 "}" | |
156 "return outColor;"); | |
157 fsBuilder->emitFunction(kVec3f_GrSLType, | |
158 "set_luminance", | |
159 SK_ARRAY_COUNT(setLumArgs), setLumArgs, | |
160 setLumBody.c_str(), | |
161 setLumFunction); | |
162 } | |
163 | |
164 // Adds a function that creates a color with the hue and luminosity of one input
color and | |
165 // the saturation of another color. It will have this signature: | |
166 // float set_saturation(vec3 hueLumColor, vec3 satColor) | |
167 static void add_sat_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setSatF
unction) { | |
168 // Emit a helper that gets the saturation of a color | |
169 SkString getFunction; | |
170 GrGLSLShaderVar getSatArgs[] = { GrGLSLShaderVar("color", kVec3f_GrSLType) }
; | |
171 SkString getSatBody; | |
172 getSatBody.printf("return max(max(color.r, color.g), color.b) - " | |
173 "min(min(color.r, color.g), color.b);"); | |
174 fsBuilder->emitFunction(kFloat_GrSLType, | |
175 "saturation", | |
176 SK_ARRAY_COUNT(getSatArgs), getSatArgs, | |
177 getSatBody.c_str(), | |
178 &getFunction); | |
179 | |
180 // Emit a helper that sets the saturation given sorted input channels. This
used | |
181 // to use inout params for min, mid, and max components but that seems to ca
use | |
182 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b a
re the | |
183 // adjusted min, mid, and max inputs, respectively. | |
184 SkString helperFunction; | |
185 GrGLSLShaderVar helperArgs[] = { | |
186 GrGLSLShaderVar("minComp", kFloat_GrSLType), | |
187 GrGLSLShaderVar("midComp", kFloat_GrSLType), | |
188 GrGLSLShaderVar("maxComp", kFloat_GrSLType), | |
189 GrGLSLShaderVar("sat", kFloat_GrSLType), | |
190 }; | |
191 static const char kHelperBody[] = "if (minComp < maxComp) {" | |
192 "vec3 result;" | |
193 "result.r = 0.0;" | |
194 "result.g = sat * (midComp - minComp) / (maxComp - minComp);" | |
195 "result.b = sat;" | |
196 "return result;" | |
197 "} else {" | |
198 "return vec3(0, 0, 0);" | |
199 "}"; | |
200 fsBuilder->emitFunction(kVec3f_GrSLType, | |
201 "set_saturation_helper", | |
202 SK_ARRAY_COUNT(helperArgs), helperArgs, | |
203 kHelperBody, | |
204 &helperFunction); | |
205 | |
206 GrGLSLShaderVar setSatArgs[] = { | |
207 GrGLSLShaderVar("hueLumColor", kVec3f_GrSLType), | |
208 GrGLSLShaderVar("satColor", kVec3f_GrSLType), | |
209 }; | |
210 const char* helpFunc = helperFunction.c_str(); | |
211 SkString setSatBody; | |
212 setSatBody.appendf("float sat = %s(satColor);" | |
213 "if (hueLumColor.r <= hueLumColor.g) {" | |
214 "if (hueLumColor.g <= hueLumColor.b) {" | |
215 "hueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLu
mColor.b, sat);" | |
216 "} else if (hueLumColor.r <= hueLumColor.b) {" | |
217 "hueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLu
mColor.g, sat);" | |
218 "} else {" | |
219 "hueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLu
mColor.g, sat);" | |
220 "}" | |
221 "} else if (hueLumColor.r <= hueLumColor.b) {" | |
222 "hueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLu
mColor.b, sat);" | |
223 "} else if (hueLumColor.g <= hueLumColor.b) {" | |
224 "hueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLu
mColor.r, sat);" | |
225 "} else {" | |
226 "hueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLu
mColor.r, sat);" | |
227 "}" | |
228 "return hueLumColor;", | |
229 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFu
nc, | |
230 helpFunc, helpFunc); | |
231 fsBuilder->emitFunction(kVec3f_GrSLType, | |
232 "set_saturation", | |
233 SK_ARRAY_COUNT(setSatArgs), setSatArgs, | |
234 setSatBody.c_str(), | |
235 setSatFunction); | |
236 } | |
237 | |
238 static void emit_advanced_xfermode_code(GrGLSLFragmentBuilder* fsBuilder, const
char* srcColor, | |
239 const char* dstColor, const char* output
Color, | |
240 SkXfermode::Mode mode) { | |
241 SkASSERT(srcColor); | |
242 SkASSERT(dstColor); | |
243 SkASSERT(outputColor); | |
244 // These all perform src-over on the alpha channel. | |
245 fsBuilder->codeAppendf("%s.a = %s.a + (1.0 - %s.a) * %s.a;", | |
246 outputColor, srcColor, srcColor, dstColor); | |
247 | |
248 switch (mode) { | |
249 case SkXfermode::kOverlay_Mode: | |
250 // Overlay is Hard-Light with the src and dst reversed | |
251 hard_light(fsBuilder, outputColor, dstColor, srcColor); | |
252 break; | |
253 case SkXfermode::kDarken_Mode: | |
254 fsBuilder->codeAppendf("%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb,
" | |
255 "(1.0 - %s.a) * %s.rgb + %s.rgb);", | |
256 outputColor, | |
257 srcColor, dstColor, srcColor, | |
258 dstColor, srcColor, dstColor); | |
259 break; | |
260 case SkXfermode::kLighten_Mode: | |
261 fsBuilder->codeAppendf("%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb,
" | |
262 "(1.0 - %s.a) * %s.rgb + %s.rgb);", | |
263 outputColor, | |
264 srcColor, dstColor, srcColor, | |
265 dstColor, srcColor, dstColor); | |
266 break; | |
267 case SkXfermode::kColorDodge_Mode: | |
268 color_dodge_component(fsBuilder, outputColor, srcColor, dstColor, 'r
'); | |
269 color_dodge_component(fsBuilder, outputColor, srcColor, dstColor, 'g
'); | |
270 color_dodge_component(fsBuilder, outputColor, srcColor, dstColor, 'b
'); | |
271 break; | |
272 case SkXfermode::kColorBurn_Mode: | |
273 color_burn_component(fsBuilder, outputColor, srcColor, dstColor, 'r'
); | |
274 color_burn_component(fsBuilder, outputColor, srcColor, dstColor, 'g'
); | |
275 color_burn_component(fsBuilder, outputColor, srcColor, dstColor, 'b'
); | |
276 break; | |
277 case SkXfermode::kHardLight_Mode: | |
278 hard_light(fsBuilder, outputColor, srcColor, dstColor); | |
279 break; | |
280 case SkXfermode::kSoftLight_Mode: | |
281 fsBuilder->codeAppendf("if (0.0 == %s.a) {", dstColor); | |
282 fsBuilder->codeAppendf("%s.rgba = %s;", outputColor, srcColor); | |
283 fsBuilder->codeAppendf("} else {"); | |
284 soft_light_component_pos_dst_alpha(fsBuilder, outputColor, srcColor,
dstColor, 'r'); | |
285 soft_light_component_pos_dst_alpha(fsBuilder, outputColor, srcColor,
dstColor, 'g'); | |
286 soft_light_component_pos_dst_alpha(fsBuilder, outputColor, srcColor,
dstColor, 'b'); | |
287 fsBuilder->codeAppendf("}"); | |
288 break; | |
289 case SkXfermode::kDifference_Mode: | |
290 fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb -" | |
291 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);", | |
292 outputColor, srcColor, dstColor, srcColor, ds
tColor, | |
293 dstColor, srcColor); | |
294 break; | |
295 case SkXfermode::kExclusion_Mode: | |
296 fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb - " | |
297 "2.0 * %s.rgb * %s.rgb;", | |
298 outputColor, dstColor, srcColor, dstColor, sr
cColor); | |
299 break; | |
300 case SkXfermode::kMultiply_Mode: | |
301 fsBuilder->codeAppendf("%s.rgb = (1.0 - %s.a) * %s.rgb + " | |
302 "(1.0 - %s.a) * %s.rgb + " | |
303 "%s.rgb * %s.rgb;", | |
304 outputColor, srcColor, dstColor, dstColor, sr
cColor, | |
305 srcColor, dstColor); | |
306 break; | |
307 case SkXfermode::kHue_Mode: { | |
308 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D
+ (1 - Da) * S | |
309 SkString setSat, setLum; | |
310 add_sat_function(fsBuilder, &setSat); | |
311 add_lum_function(fsBuilder, &setLum); | |
312 fsBuilder->codeAppendf("vec4 dstSrcAlpha = %s * %s.a;", | |
313 dstColor, srcColor); | |
314 fsBuilder->codeAppendf("%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rg
b)," | |
315 "dstSrcAlpha.a, dstSrcAlpha.rgb);", | |
316 outputColor, setLum.c_str(), setSat.c_str(),
srcColor, | |
317 dstColor); | |
318 fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.
a) * %s.rgb;", | |
319 outputColor, srcColor, dstColor, dstColor, sr
cColor); | |
320 break; | |
321 } | |
322 case SkXfermode::kSaturation_Mode: { | |
323 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D
+ (1 - Da) * S | |
324 SkString setSat, setLum; | |
325 add_sat_function(fsBuilder, &setSat); | |
326 add_lum_function(fsBuilder, &setLum); | |
327 fsBuilder->codeAppendf("vec4 dstSrcAlpha = %s * %s.a;", | |
328 dstColor, srcColor); | |
329 fsBuilder->codeAppendf("%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.
a)," | |
330 "dstSrcAlpha.a, dstSrcAlpha.rgb);", | |
331 outputColor, setLum.c_str(), setSat.c_str(),
srcColor, | |
332 dstColor); | |
333 fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.
a) * %s.rgb;", | |
334 outputColor, srcColor, dstColor, dstColor, sr
cColor); | |
335 break; | |
336 } | |
337 case SkXfermode::kColor_Mode: { | |
338 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S | |
339 SkString setLum; | |
340 add_lum_function(fsBuilder, &setLum); | |
341 fsBuilder->codeAppendf("vec4 srcDstAlpha = %s * %s.a;", | |
342 srcColor, dstColor); | |
343 fsBuilder->codeAppendf("%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a,
%s.rgb * %s.a);", | |
344 outputColor, setLum.c_str(), dstColor, srcCol
or); | |
345 fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.
a) * %s.rgb;", | |
346 outputColor, srcColor, dstColor, dstColor, sr
cColor); | |
347 break; | |
348 } | |
349 case SkXfermode::kLuminosity_Mode: { | |
350 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S | |
351 SkString setLum; | |
352 add_lum_function(fsBuilder, &setLum); | |
353 fsBuilder->codeAppendf("vec4 srcDstAlpha = %s * %s.a;", | |
354 srcColor, dstColor); | |
355 fsBuilder->codeAppendf("%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, sr
cDstAlpha.rgb);", | |
356 outputColor, setLum.c_str(), dstColor, srcCol
or); | |
357 fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.
a) * %s.rgb;", | |
358 outputColor, srcColor, dstColor, dstColor, sr
cColor); | |
359 break; | |
360 } | |
361 default: | |
362 SkFAIL("Unknown Custom Xfer mode."); | |
363 break; | |
364 } | |
365 } | |
366 | |
367 ////////////////////////////////////////////////////////////////////////////// | |
368 // Porter-Duff blend helper | |
369 ////////////////////////////////////////////////////////////////////////////// | |
370 | |
371 static bool append_porterduff_term(GrGLSLFragmentBuilder* fsBuilder, SkXfermode:
:Coeff coeff, | |
372 const char* colorName, const char* srcColorNa
me, | |
373 const char* dstColorName, bool hasPrevious) { | |
374 if (SkXfermode::kZero_Coeff == coeff) { | |
375 return hasPrevious; | |
376 } else { | |
377 if (hasPrevious) { | |
378 fsBuilder->codeAppend(" + "); | |
379 } | |
380 fsBuilder->codeAppendf("%s", colorName); | |
381 switch (coeff) { | |
382 case SkXfermode::kOne_Coeff: | |
383 break; | |
384 case SkXfermode::kSC_Coeff: | |
385 fsBuilder->codeAppendf(" * %s", srcColorName); | |
386 break; | |
387 case SkXfermode::kISC_Coeff: | |
388 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", srcColorName); | |
389 break; | |
390 case SkXfermode::kDC_Coeff: | |
391 fsBuilder->codeAppendf(" * %s", dstColorName); | |
392 break; | |
393 case SkXfermode::kIDC_Coeff: | |
394 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", dstColorName); | |
395 break; | |
396 case SkXfermode::kSA_Coeff: | |
397 fsBuilder->codeAppendf(" * %s.a", srcColorName); | |
398 break; | |
399 case SkXfermode::kISA_Coeff: | |
400 fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName); | |
401 break; | |
402 case SkXfermode::kDA_Coeff: | |
403 fsBuilder->codeAppendf(" * %s.a", dstColorName); | |
404 break; | |
405 case SkXfermode::kIDA_Coeff: | |
406 fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName); | |
407 break; | |
408 default: | |
409 SkFAIL("Unsupported Blend Coeff"); | |
410 } | |
411 return true; | |
412 } | |
413 } | |
414 | |
415 ////////////////////////////////////////////////////////////////////////////// | |
416 | |
417 void GrGLSLBlend::AppendMode(GrGLSLFragmentBuilder* fsBuilder, const char* srcCo
lor, | |
418 const char* dstColor, const char* outColor, | |
419 SkXfermode::Mode mode) { | |
420 | |
421 SkXfermode::Coeff srcCoeff, dstCoeff; | |
422 if (SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) { | |
423 fsBuilder->codeAppendf("%s = ", outColor); | |
424 // append src blend | |
425 bool didAppend = append_porterduff_term(fsBuilder, srcCoeff, srcColor, s
rcColor, dstColor, | |
426 false); | |
427 // append dst blend | |
428 if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstC
olor, didAppend)) { | |
429 fsBuilder->codeAppend("vec4(0, 0, 0, 0)"); | |
430 } | |
431 fsBuilder->codeAppend(";"); | |
432 } else { | |
433 emit_advanced_xfermode_code(fsBuilder, srcColor, dstColor, outColor, mod
e); | |
434 } | |
435 } | |
OLD | NEW |