OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "effects/GrCustomXfermode.h" | 8 #include "effects/GrCustomXfermode.h" |
9 #include "effects/GrCustomXfermodePriv.h" | |
10 | 9 |
11 #include "GrCoordTransform.h" | 10 #include "GrCoordTransform.h" |
12 #include "GrContext.h" | 11 #include "GrContext.h" |
13 #include "GrFragmentProcessor.h" | 12 #include "GrFragmentProcessor.h" |
14 #include "GrInvariantOutput.h" | 13 #include "GrInvariantOutput.h" |
15 #include "GrProcessor.h" | 14 #include "GrProcessor.h" |
16 #include "GrTexture.h" | 15 #include "GrTexture.h" |
17 #include "GrTextureAccess.h" | 16 #include "GrTextureAccess.h" |
18 #include "SkXfermode.h" | 17 #include "SkXfermode.h" |
19 #include "gl/GrGLCaps.h" | 18 #include "gl/GrGLCaps.h" |
20 #include "gl/GrGLGpu.h" | 19 #include "gl/GrGLGpu.h" |
| 20 #include "gl/GrGLSLBlend.h" |
21 #include "gl/GrGLFragmentProcessor.h" | 21 #include "gl/GrGLFragmentProcessor.h" |
22 #include "gl/GrGLProgramDataManager.h" | 22 #include "gl/GrGLProgramDataManager.h" |
23 #include "gl/builders/GrGLProgramBuilder.h" | 23 #include "gl/builders/GrGLProgramBuilder.h" |
24 #include "glsl/GrGLSLCaps.h" | 24 #include "glsl/GrGLSLCaps.h" |
25 | 25 |
26 bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) { | 26 bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) { |
27 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; | 27 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; |
28 } | 28 } |
29 | 29 |
30 /////////////////////////////////////////////////////////////////////////////// | 30 /////////////////////////////////////////////////////////////////////////////// |
(...skipping 29 matching lines...) Expand all Loading... |
60 } | 60 } |
61 if (coveragePOI.isFourChannelOutput()) { | 61 if (coveragePOI.isFourChannelOutput()) { |
62 return false; // LCD coverage must be applied after the blend equation. | 62 return false; // LCD coverage must be applied after the blend equation. |
63 } | 63 } |
64 if (caps.canUseAdvancedBlendEquation(equation)) { | 64 if (caps.canUseAdvancedBlendEquation(equation)) { |
65 return false; | 65 return false; |
66 } | 66 } |
67 return true; | 67 return true; |
68 } | 68 } |
69 | 69 |
70 static void hard_light(GrGLFragmentBuilder* fsBuilder, | |
71 const char* final, | |
72 const char* src, | |
73 const char* dst) { | |
74 static const char kComponents[] = {'r', 'g', 'b'}; | |
75 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { | |
76 char component = kComponents[i]; | |
77 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src
); | |
78 fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;", | |
79 final, component, src, component, dst, component)
; | |
80 fsBuilder->codeAppend("} else {"); | |
81 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s
.a - %s.%c);", | |
82 final, component, src, dst, dst, dst, component,
src, src, | |
83 component); | |
84 fsBuilder->codeAppend("}"); | |
85 } | |
86 fsBuilder->codeAppendf("%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s
.a);", | |
87 final, src, dst, dst, src); | |
88 } | |
89 | |
90 // Does one component of color-dodge | |
91 static void color_dodge_component(GrGLFragmentBuilder* fsBuilder, | |
92 const char* final, | |
93 const char* src, | |
94 const char* dst, | |
95 const char component) { | |
96 fsBuilder->codeAppendf("if (0.0 == %s.%c) {", dst, component); | |
97 fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", | |
98 final, component, src, component, dst); | |
99 fsBuilder->codeAppend("} else {"); | |
100 fsBuilder->codeAppendf("float d = %s.a - %s.%c;", src, src, component); | |
101 fsBuilder->codeAppend("if (0.0 == d) {"); | |
102 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c *
(1.0 - %s.a);", | |
103 final, component, src, dst, src, component, dst, dst,
component, | |
104 src); | |
105 fsBuilder->codeAppend("} else {"); | |
106 fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / d);", | |
107 dst, dst, component, src); | |
108 fsBuilder->codeAppendf("%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1
.0 - %s.a);", | |
109 final, component, src, src, component, dst, dst, comp
onent, src); | |
110 fsBuilder->codeAppend("}"); | |
111 fsBuilder->codeAppend("}"); | |
112 } | |
113 | |
114 // Does one component of color-burn | |
115 static void color_burn_component(GrGLFragmentBuilder* fsBuilder, | |
116 const char* final, | |
117 const char* src, | |
118 const char* dst, | |
119 const char component) { | |
120 fsBuilder->codeAppendf("if (%s.a == %s.%c) {", dst, dst, component); | |
121 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c *
(1.0 - %s.a);", | |
122 final, component, src, dst, src, component, dst, dst,
component, | |
123 src); | |
124 fsBuilder->codeAppendf("} else if (0.0 == %s.%c) {", src, component); | |
125 fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", | |
126 final, component, dst, component, src); | |
127 fsBuilder->codeAppend("} else {"); | |
128 fsBuilder->codeAppendf("float d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s
.%c);", | |
129 dst, dst, dst, component, src, src, component); | |
130 fsBuilder->codeAppendf("%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1
.0 - %s.a);", | |
131 final, component, src, src, component, dst, dst, comp
onent, src); | |
132 fsBuilder->codeAppend("}"); | |
133 } | |
134 | |
135 // Does one component of soft-light. Caller should have already checked that dst
alpha > 0. | |
136 static void soft_light_component_pos_dst_alpha(GrGLFragmentBuilder* fsBuilder, | |
137 const char* final, | |
138 const char* src, | |
139 const char* dst, | |
140 const char component) { | |
141 // if (2S < Sa) | |
142 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src); | |
143 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) | |
144 fsBuilder->codeAppendf("%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a +" | |
145 "(1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s
.%c + 1.0);", | |
146 final, component, dst, component, dst, component, src
, src, | |
147 component, dst, dst, src, component, dst, component,
src, src, | |
148 component); | |
149 // else if (4D < Da) | |
150 fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {", | |
151 dst, component, dst); | |
152 fsBuilder->codeAppendf("float DSqd = %s.%c * %s.%c;", | |
153 dst, component, dst, component); | |
154 fsBuilder->codeAppendf("float DCub = DSqd * %s.%c;", dst, component); | |
155 fsBuilder->codeAppendf("float DaSqd = %s.a * %s.a;", dst, dst); | |
156 fsBuilder->codeAppendf("float DaCub = DaSqd * %s.a;", dst); | |
157 // (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 | |
158 fsBuilder->codeAppendf("%s.%c =" | |
159 "(DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)
) +" | |
160 " 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s
.a - 2.0*%s.%c) -" | |
161 " DaCub*%s.%c) / DaSqd;", | |
162 final, component, src, component, dst, component, | |
163 src, src, component, dst, src, src, component, src, s
rc, | |
164 component, src, component); | |
165 fsBuilder->codeAppendf("} else {"); | |
166 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S | |
167 fsBuilder->codeAppendf("%s.%c = %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c -" | |
168 " sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c;", | |
169 final, component, dst, component, src, src, component
, src, component, | |
170 dst, dst, component, src, src, component, dst, src, c
omponent); | |
171 fsBuilder->codeAppendf("}"); | |
172 } | |
173 | |
174 // Adds a function that takes two colors and an alpha as input. It produces a co
lor with the | |
175 // hue and saturation of the first color, the luminosity of the second color, an
d the input | |
176 // alpha. It has this signature: | |
177 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). | |
178 static void add_lum_function(GrGLFragmentBuilder* fsBuilder, SkString* setLumFun
ction) { | |
179 // Emit a helper that gets the luminance of a color. | |
180 SkString getFunction; | |
181 GrGLShaderVar getLumArgs[] = { | |
182 GrGLShaderVar("color", kVec3f_GrSLType), | |
183 }; | |
184 SkString getLumBody("return dot(vec3(0.3, 0.59, 0.11), color);"); | |
185 fsBuilder->emitFunction(kFloat_GrSLType, | |
186 "luminance", | |
187 SK_ARRAY_COUNT(getLumArgs), getLumArgs, | |
188 getLumBody.c_str(), | |
189 &getFunction); | |
190 | |
191 // Emit the set luminance function. | |
192 GrGLShaderVar setLumArgs[] = { | |
193 GrGLShaderVar("hueSat", kVec3f_GrSLType), | |
194 GrGLShaderVar("alpha", kFloat_GrSLType), | |
195 GrGLShaderVar("lumColor", kVec3f_GrSLType), | |
196 }; | |
197 SkString setLumBody; | |
198 setLumBody.printf("float diff = %s(lumColor - hueSat);", getFunction.c_str()
); | |
199 setLumBody.append("vec3 outColor = hueSat + diff;"); | |
200 setLumBody.appendf("float outLum = %s(outColor);", getFunction.c_str()); | |
201 setLumBody.append("float minComp = min(min(outColor.r, outColor.g), outColor
.b);" | |
202 "float maxComp = max(max(outColor.r, outColor.g), outColor
.b);" | |
203 "if (minComp < 0.0 && outLum != minComp) {" | |
204 "outColor = outLum + ((outColor - vec3(outLum, outLum, out
Lum)) * outLum) /" | |
205 "(outLum - minComp);" | |
206 "}" | |
207 "if (maxComp > alpha && maxComp != outLum) {" | |
208 "outColor = outLum +" | |
209 "((outColor - vec3(outLum, outLum, outLum)) * (
alpha - outLum)) /" | |
210 "(maxComp - outLum);" | |
211 "}" | |
212 "return outColor;"); | |
213 fsBuilder->emitFunction(kVec3f_GrSLType, | |
214 "set_luminance", | |
215 SK_ARRAY_COUNT(setLumArgs), setLumArgs, | |
216 setLumBody.c_str(), | |
217 setLumFunction); | |
218 } | |
219 | |
220 // Adds a function that creates a color with the hue and luminosity of one input
color and | |
221 // the saturation of another color. It will have this signature: | |
222 // float set_saturation(vec3 hueLumColor, vec3 satColor) | |
223 static void add_sat_function(GrGLFragmentBuilder* fsBuilder, SkString* setSatFun
ction) { | |
224 // Emit a helper that gets the saturation of a color | |
225 SkString getFunction; | |
226 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) }; | |
227 SkString getSatBody; | |
228 getSatBody.printf("return max(max(color.r, color.g), color.b) - " | |
229 "min(min(color.r, color.g), color.b);"); | |
230 fsBuilder->emitFunction(kFloat_GrSLType, | |
231 "saturation", | |
232 SK_ARRAY_COUNT(getSatArgs), getSatArgs, | |
233 getSatBody.c_str(), | |
234 &getFunction); | |
235 | |
236 // Emit a helper that sets the saturation given sorted input channels. This
used | |
237 // to use inout params for min, mid, and max components but that seems to ca
use | |
238 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b a
re the | |
239 // adjusted min, mid, and max inputs, respectively. | |
240 SkString helperFunction; | |
241 GrGLShaderVar helperArgs[] = { | |
242 GrGLShaderVar("minComp", kFloat_GrSLType), | |
243 GrGLShaderVar("midComp", kFloat_GrSLType), | |
244 GrGLShaderVar("maxComp", kFloat_GrSLType), | |
245 GrGLShaderVar("sat", kFloat_GrSLType), | |
246 }; | |
247 static const char kHelperBody[] = "if (minComp < maxComp) {" | |
248 "vec3 result;" | |
249 "result.r = 0.0;" | |
250 "result.g = sat * (midComp - minComp) / (maxComp - minComp);" | |
251 "result.b = sat;" | |
252 "return result;" | |
253 "} else {" | |
254 "return vec3(0, 0, 0);" | |
255 "}"; | |
256 fsBuilder->emitFunction(kVec3f_GrSLType, | |
257 "set_saturation_helper", | |
258 SK_ARRAY_COUNT(helperArgs), helperArgs, | |
259 kHelperBody, | |
260 &helperFunction); | |
261 | |
262 GrGLShaderVar setSatArgs[] = { | |
263 GrGLShaderVar("hueLumColor", kVec3f_GrSLType), | |
264 GrGLShaderVar("satColor", kVec3f_GrSLType), | |
265 }; | |
266 const char* helpFunc = helperFunction.c_str(); | |
267 SkString setSatBody; | |
268 setSatBody.appendf("float sat = %s(satColor);" | |
269 "if (hueLumColor.r <= hueLumColor.g) {" | |
270 "if (hueLumColor.g <= hueLumColor.b) {" | |
271 "hueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLu
mColor.b, sat);" | |
272 "} else if (hueLumColor.r <= hueLumColor.b) {" | |
273 "hueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLu
mColor.g, sat);" | |
274 "} else {" | |
275 "hueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLu
mColor.g, sat);" | |
276 "}" | |
277 "} else if (hueLumColor.r <= hueLumColor.b) {" | |
278 "hueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLu
mColor.b, sat);" | |
279 "} else if (hueLumColor.g <= hueLumColor.b) {" | |
280 "hueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLu
mColor.r, sat);" | |
281 "} else {" | |
282 "hueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLu
mColor.r, sat);" | |
283 "}" | |
284 "return hueLumColor;", | |
285 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFu
nc, | |
286 helpFunc, helpFunc); | |
287 fsBuilder->emitFunction(kVec3f_GrSLType, | |
288 "set_saturation", | |
289 SK_ARRAY_COUNT(setSatArgs), setSatArgs, | |
290 setSatBody.c_str(), | |
291 setSatFunction); | |
292 | |
293 } | |
294 | |
295 static void emit_custom_xfermode_code(SkXfermode::Mode mode, | |
296 GrGLFragmentBuilder* fsBuilder, | |
297 const char* outputColor, | |
298 const char* inputColor, | |
299 const char* dstColor) { | |
300 // We don't try to optimize for this case at all | |
301 if (nullptr == inputColor) { | |
302 fsBuilder->codeAppendf("const vec4 ones = vec4(1);"); | |
303 inputColor = "ones"; | |
304 } | |
305 fsBuilder->codeAppendf("// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mod
e)); | |
306 | |
307 // These all perform src-over on the alpha channel. | |
308 fsBuilder->codeAppendf("%s.a = %s.a + (1.0 - %s.a) * %s.a;", | |
309 outputColor, inputColor, inputColor, dstColor); | |
310 | |
311 switch (mode) { | |
312 case SkXfermode::kOverlay_Mode: | |
313 // Overlay is Hard-Light with the src and dst reversed | |
314 hard_light(fsBuilder, outputColor, dstColor, inputColor); | |
315 break; | |
316 case SkXfermode::kDarken_Mode: | |
317 fsBuilder->codeAppendf("%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb,
" | |
318 "(1.0 - %s.a) * %s.rgb + %s.rgb);", | |
319 outputColor, | |
320 inputColor, dstColor, inputColor, | |
321 dstColor, inputColor, dstColor); | |
322 break; | |
323 case SkXfermode::kLighten_Mode: | |
324 fsBuilder->codeAppendf("%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb,
" | |
325 "(1.0 - %s.a) * %s.rgb + %s.rgb);", | |
326 outputColor, | |
327 inputColor, dstColor, inputColor, | |
328 dstColor, inputColor, dstColor); | |
329 break; | |
330 case SkXfermode::kColorDodge_Mode: | |
331 color_dodge_component(fsBuilder, outputColor, inputColor, dstColor,
'r'); | |
332 color_dodge_component(fsBuilder, outputColor, inputColor, dstColor,
'g'); | |
333 color_dodge_component(fsBuilder, outputColor, inputColor, dstColor,
'b'); | |
334 break; | |
335 case SkXfermode::kColorBurn_Mode: | |
336 color_burn_component(fsBuilder, outputColor, inputColor, dstColor, '
r'); | |
337 color_burn_component(fsBuilder, outputColor, inputColor, dstColor, '
g'); | |
338 color_burn_component(fsBuilder, outputColor, inputColor, dstColor, '
b'); | |
339 break; | |
340 case SkXfermode::kHardLight_Mode: | |
341 hard_light(fsBuilder, outputColor, inputColor, dstColor); | |
342 break; | |
343 case SkXfermode::kSoftLight_Mode: | |
344 fsBuilder->codeAppendf("if (0.0 == %s.a) {", dstColor); | |
345 fsBuilder->codeAppendf("%s.rgba = %s;", outputColor, inputColor); | |
346 fsBuilder->codeAppendf("} else {"); | |
347 soft_light_component_pos_dst_alpha(fsBuilder, outputColor, inputColo
r, dstColor, 'r'); | |
348 soft_light_component_pos_dst_alpha(fsBuilder, outputColor, inputColo
r, dstColor, 'g'); | |
349 soft_light_component_pos_dst_alpha(fsBuilder, outputColor, inputColo
r, dstColor, 'b'); | |
350 fsBuilder->codeAppendf("}"); | |
351 break; | |
352 case SkXfermode::kDifference_Mode: | |
353 fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb -" | |
354 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);", | |
355 outputColor, inputColor, dstColor, inputColor
, dstColor, | |
356 dstColor, inputColor); | |
357 break; | |
358 case SkXfermode::kExclusion_Mode: | |
359 fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb - " | |
360 "2.0 * %s.rgb * %s.rgb;", | |
361 outputColor, dstColor, inputColor, dstColor,
inputColor); | |
362 break; | |
363 case SkXfermode::kMultiply_Mode: | |
364 fsBuilder->codeAppendf("%s.rgb = (1.0 - %s.a) * %s.rgb + " | |
365 "(1.0 - %s.a) * %s.rgb + " | |
366 "%s.rgb * %s.rgb;", | |
367 outputColor, inputColor, dstColor, dstColor,
inputColor, | |
368 inputColor, dstColor); | |
369 break; | |
370 case SkXfermode::kHue_Mode: { | |
371 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D
+ (1 - Da) * S | |
372 SkString setSat, setLum; | |
373 add_sat_function(fsBuilder, &setSat); | |
374 add_lum_function(fsBuilder, &setLum); | |
375 fsBuilder->codeAppendf("vec4 dstSrcAlpha = %s * %s.a;", | |
376 dstColor, inputColor); | |
377 fsBuilder->codeAppendf("%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rg
b)," | |
378 "dstSrcAlpha.a, dstSrcAlpha.rgb);
", | |
379 outputColor, setLum.c_str(), setSat.c_str(),
inputColor, | |
380 dstColor); | |
381 fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.
a) * %s.rgb;", | |
382 outputColor, inputColor, dstColor, dstColor,
inputColor); | |
383 break; | |
384 } | |
385 case SkXfermode::kSaturation_Mode: { | |
386 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D
+ (1 - Da) * S | |
387 SkString setSat, setLum; | |
388 add_sat_function(fsBuilder, &setSat); | |
389 add_lum_function(fsBuilder, &setLum); | |
390 fsBuilder->codeAppendf("vec4 dstSrcAlpha = %s * %s.a;", | |
391 dstColor, inputColor); | |
392 fsBuilder->codeAppendf("%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.
a)," | |
393 "dstSrcAlpha.a, dstSrcAlpha.rgb);
", | |
394 outputColor, setLum.c_str(), setSat.c_str(),
inputColor, | |
395 dstColor); | |
396 fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.
a) * %s.rgb;", | |
397 outputColor, inputColor, dstColor, dstColor,
inputColor); | |
398 break; | |
399 } | |
400 case SkXfermode::kColor_Mode: { | |
401 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S | |
402 SkString setLum; | |
403 add_lum_function(fsBuilder, &setLum); | |
404 fsBuilder->codeAppendf("vec4 srcDstAlpha = %s * %s.a;", | |
405 inputColor, dstColor); | |
406 fsBuilder->codeAppendf("%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a,
%s.rgb * %s.a);", | |
407 outputColor, setLum.c_str(), dstColor, inputC
olor); | |
408 fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.
a) * %s.rgb;", | |
409 outputColor, inputColor, dstColor, dstColor,
inputColor); | |
410 break; | |
411 } | |
412 case SkXfermode::kLuminosity_Mode: { | |
413 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S | |
414 SkString setLum; | |
415 add_lum_function(fsBuilder, &setLum); | |
416 fsBuilder->codeAppendf("vec4 srcDstAlpha = %s * %s.a;", | |
417 inputColor, dstColor); | |
418 fsBuilder->codeAppendf("%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, sr
cDstAlpha.rgb);", | |
419 outputColor, setLum.c_str(), dstColor, inputC
olor); | |
420 fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.
a) * %s.rgb;", | |
421 outputColor, inputColor, dstColor, dstColor,
inputColor); | |
422 break; | |
423 } | |
424 default: | |
425 SkFAIL("Unknown Custom Xfer mode."); | |
426 break; | |
427 } | |
428 } | |
429 | |
430 /////////////////////////////////////////////////////////////////////////////// | |
431 // Fragment Processor | |
432 /////////////////////////////////////////////////////////////////////////////// | |
433 | |
434 GrFragmentProcessor* GrCustomXfermode::CreateFP(GrProcessorDataManager* procData
Manager, | |
435 SkXfermode::Mode mode, GrTexture
* background) { | |
436 if (!GrCustomXfermode::IsSupportedMode(mode)) { | |
437 return nullptr; | |
438 } else { | |
439 return new GrCustomXferFP(procDataManager, mode, background); | |
440 } | |
441 } | |
442 | |
443 /////////////////////////////////////////////////////////////////////////////// | |
444 | |
445 class GLCustomXferFP : public GrGLFragmentProcessor { | |
446 public: | |
447 GLCustomXferFP(const GrFragmentProcessor&) {} | |
448 ~GLCustomXferFP() override {}; | |
449 | |
450 void emitCode(EmitArgs& args) override { | |
451 SkXfermode::Mode mode = args.fFp.cast<GrCustomXferFP>().mode(); | |
452 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder
(); | |
453 const char* dstColor = "bgColor"; | |
454 fsBuilder->codeAppendf("vec4 %s = ", dstColor); | |
455 fsBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(
), | |
456 args.fCoords[0].getType()); | |
457 fsBuilder->codeAppendf(";"); | |
458 | |
459 emit_custom_xfermode_code(mode, fsBuilder, args.fOutputColor, args.fInpu
tColor, dstColor); | |
460 } | |
461 | |
462 static void GenKey(const GrFragmentProcessor& proc, const GrGLSLCaps&, GrPro
cessorKeyBuilder* b) { | |
463 // The background may come from the dst or from a texture. | |
464 uint32_t key = proc.numTextures(); | |
465 SkASSERT(key <= 1); | |
466 key |= proc.cast<GrCustomXferFP>().mode() << 1; | |
467 b->add32(key); | |
468 } | |
469 | |
470 protected: | |
471 void onSetData(const GrGLProgramDataManager&, const GrProcessor&) override {
} | |
472 | |
473 private: | |
474 typedef GrGLFragmentProcessor INHERITED; | |
475 }; | |
476 | |
477 /////////////////////////////////////////////////////////////////////////////// | |
478 | |
479 GrCustomXferFP::GrCustomXferFP(GrProcessorDataManager*, SkXfermode::Mode mode, G
rTexture* background) | |
480 : fMode(mode) { | |
481 this->initClassID<GrCustomXferFP>(); | |
482 | |
483 SkASSERT(background); | |
484 fBackgroundTransform.reset(kLocal_GrCoordSet, background, | |
485 GrTextureParams::kNone_FilterMode); | |
486 this->addCoordTransform(&fBackgroundTransform); | |
487 fBackgroundAccess.reset(background); | |
488 this->addTextureAccess(&fBackgroundAccess); | |
489 } | |
490 | |
491 void GrCustomXferFP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyB
uilder* b) const { | |
492 GLCustomXferFP::GenKey(*this, caps, b); | |
493 } | |
494 | |
495 GrGLFragmentProcessor* GrCustomXferFP::onCreateGLInstance() const { | |
496 return new GLCustomXferFP(*this); | |
497 } | |
498 | |
499 bool GrCustomXferFP::onIsEqual(const GrFragmentProcessor& other) const { | |
500 const GrCustomXferFP& s = other.cast<GrCustomXferFP>(); | |
501 return fMode == s.fMode; | |
502 } | |
503 | |
504 void GrCustomXferFP::onComputeInvariantOutput(GrInvariantOutput* inout) const { | |
505 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | |
506 } | |
507 | |
508 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrCustomXferFP); | |
509 const GrFragmentProcessor* GrCustomXferFP::TestCreate(GrProcessorTestData* d) { | |
510 int mode = d->fRandom->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode
::kLastSeparableMode); | |
511 | |
512 return new GrCustomXferFP(d->fProcDataManager, static_cast<SkXfermode::Mode>
(mode), | |
513 d->fTextures[0]); | |
514 } | |
515 | |
516 /////////////////////////////////////////////////////////////////////////////// | 70 /////////////////////////////////////////////////////////////////////////////// |
517 // Xfer Processor | 71 // Xfer Processor |
518 /////////////////////////////////////////////////////////////////////////////// | 72 /////////////////////////////////////////////////////////////////////////////// |
519 | 73 |
520 class CustomXP : public GrXferProcessor { | 74 class CustomXP : public GrXferProcessor { |
521 public: | 75 public: |
522 CustomXP(SkXfermode::Mode mode, GrBlendEquation hwBlendEquation) | 76 CustomXP(SkXfermode::Mode mode, GrBlendEquation hwBlendEquation) |
523 : fMode(mode), | 77 : fMode(mode), |
524 fHWBlendEquation(hwBlendEquation) { | 78 fHWBlendEquation(hwBlendEquation) { |
525 this->initClassID<CustomXP>(); | 79 this->initClassID<CustomXP>(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 bool onIsEqual(const GrXferProcessor& xpBase) const override; | 114 bool onIsEqual(const GrXferProcessor& xpBase) const override; |
561 | 115 |
562 const SkXfermode::Mode fMode; | 116 const SkXfermode::Mode fMode; |
563 const GrBlendEquation fHWBlendEquation; | 117 const GrBlendEquation fHWBlendEquation; |
564 | 118 |
565 typedef GrXferProcessor INHERITED; | 119 typedef GrXferProcessor INHERITED; |
566 }; | 120 }; |
567 | 121 |
568 /////////////////////////////////////////////////////////////////////////////// | 122 /////////////////////////////////////////////////////////////////////////////// |
569 | 123 |
570 GrXPFactory* GrCustomXfermode::CreateXPFactory(SkXfermode::Mode mode) { | |
571 if (!GrCustomXfermode::IsSupportedMode(mode)) { | |
572 return nullptr; | |
573 } else { | |
574 return new GrCustomXPFactory(mode); | |
575 } | |
576 } | |
577 | |
578 /////////////////////////////////////////////////////////////////////////////// | |
579 | |
580 class GLCustomXP : public GrGLXferProcessor { | 124 class GLCustomXP : public GrGLXferProcessor { |
581 public: | 125 public: |
582 GLCustomXP(const GrXferProcessor&) {} | 126 GLCustomXP(const GrXferProcessor&) {} |
583 ~GLCustomXP() override {} | 127 ~GLCustomXP() override {} |
584 | 128 |
585 static void GenKey(const GrXferProcessor& p, const GrGLSLCaps& caps, GrProce
ssorKeyBuilder* b) { | 129 static void GenKey(const GrXferProcessor& p, const GrGLSLCaps& caps, GrProce
ssorKeyBuilder* b) { |
586 const CustomXP& xp = p.cast<CustomXP>(); | 130 const CustomXP& xp = p.cast<CustomXP>(); |
587 uint32_t key = 0; | 131 uint32_t key = 0; |
588 if (xp.hasHWBlendEquation()) { | 132 if (xp.hasHWBlendEquation()) { |
589 SkASSERT(caps.advBlendEqInteraction() > 0); // 0 will mean !xp.hasH
WBlendEquation(). | 133 SkASSERT(caps.advBlendEqInteraction() > 0); // 0 will mean !xp.hasH
WBlendEquation(). |
(...skipping 24 matching lines...) Expand all Loading... |
614 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputC
olor); | 158 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputC
olor); |
615 } | 159 } |
616 } | 160 } |
617 | 161 |
618 void emitBlendCodeForDstRead(GrGLXPBuilder* pb, const char* srcColor, const
char* dstColor, | 162 void emitBlendCodeForDstRead(GrGLXPBuilder* pb, const char* srcColor, const
char* dstColor, |
619 const char* outColor, const GrXferProcessor& pr
oc) override { | 163 const char* outColor, const GrXferProcessor& pr
oc) override { |
620 const CustomXP& xp = proc.cast<CustomXP>(); | 164 const CustomXP& xp = proc.cast<CustomXP>(); |
621 SkASSERT(!xp.hasHWBlendEquation()); | 165 SkASSERT(!xp.hasHWBlendEquation()); |
622 | 166 |
623 GrGLXPFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); | 167 GrGLXPFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); |
624 emit_custom_xfermode_code(xp.mode(), fsBuilder, outColor, srcColor, dstC
olor); | 168 GrGLSLBlend::AppendMode(fsBuilder, srcColor, dstColor, outColor, xp.mode
()); |
625 } | 169 } |
626 | 170 |
627 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri
de {} | 171 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri
de {} |
628 | 172 |
629 typedef GrGLXferProcessor INHERITED; | 173 typedef GrGLXferProcessor INHERITED; |
630 }; | 174 }; |
631 | 175 |
632 /////////////////////////////////////////////////////////////////////////////// | 176 /////////////////////////////////////////////////////////////////////////////// |
633 | 177 |
634 void CustomXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder
* b) const { | 178 void CustomXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder
* b) const { |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 return kNone_GrXferBarrierType; | 307 return kNone_GrXferBarrierType; |
764 } | 308 } |
765 | 309 |
766 void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const { | 310 void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const { |
767 if (this->hasHWBlendEquation()) { | 311 if (this->hasHWBlendEquation()) { |
768 blendInfo->fEquation = this->hwBlendEquation(); | 312 blendInfo->fEquation = this->hwBlendEquation(); |
769 } | 313 } |
770 } | 314 } |
771 | 315 |
772 /////////////////////////////////////////////////////////////////////////////// | 316 /////////////////////////////////////////////////////////////////////////////// |
| 317 class CustomXPFactory : public GrXPFactory { |
| 318 public: |
| 319 CustomXPFactory(SkXfermode::Mode mode); |
773 | 320 |
774 GrCustomXPFactory::GrCustomXPFactory(SkXfermode::Mode mode) | 321 bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const
override { |
| 322 return true; |
| 323 } |
| 324 |
| 325 void getInvariantBlendedColor(const GrProcOptInfo& colorPOI, |
| 326 GrXPFactory::InvariantBlendedColor*) const ove
rride; |
| 327 |
| 328 private: |
| 329 GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, |
| 330 const GrProcOptInfo& colorPOI, |
| 331 const GrProcOptInfo& coveragePOI, |
| 332 bool hasMixedSamples, |
| 333 const DstTexture*) const override; |
| 334 |
| 335 bool willReadDstColor(const GrCaps& caps, |
| 336 const GrProcOptInfo& colorPOI, |
| 337 const GrProcOptInfo& coveragePOI, |
| 338 bool hasMixedSamples) const override; |
| 339 |
| 340 bool onIsEqual(const GrXPFactory& xpfBase) const override { |
| 341 const CustomXPFactory& xpf = xpfBase.cast<CustomXPFactory>(); |
| 342 return fMode == xpf.fMode; |
| 343 } |
| 344 |
| 345 GR_DECLARE_XP_FACTORY_TEST; |
| 346 |
| 347 SkXfermode::Mode fMode; |
| 348 GrBlendEquation fHWBlendEquation; |
| 349 |
| 350 typedef GrXPFactory INHERITED; |
| 351 }; |
| 352 |
| 353 CustomXPFactory::CustomXPFactory(SkXfermode::Mode mode) |
775 : fMode(mode), | 354 : fMode(mode), |
776 fHWBlendEquation(hw_blend_equation(mode)) { | 355 fHWBlendEquation(hw_blend_equation(mode)) { |
777 SkASSERT(GrCustomXfermode::IsSupportedMode(fMode)); | 356 SkASSERT(GrCustomXfermode::IsSupportedMode(fMode)); |
778 this->initClassID<GrCustomXPFactory>(); | 357 this->initClassID<CustomXPFactory>(); |
779 } | 358 } |
780 | 359 |
781 GrXferProcessor* | 360 GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps, |
782 GrCustomXPFactory::onCreateXferProcessor(const GrCaps& caps, | 361 const GrProcOptInfo& col
orPOI, |
783 const GrProcOptInfo& colorPOI, | 362 const GrProcOptInfo& cov
eragePOI, |
784 const GrProcOptInfo& coveragePOI, | 363 bool hasMixedSamples, |
785 bool hasMixedSamples, | 364 const DstTexture* dstTex
ture) const { |
786 const DstTexture* dstTexture) const { | |
787 if (can_use_hw_blend_equation(fHWBlendEquation, coveragePOI, caps)) { | 365 if (can_use_hw_blend_equation(fHWBlendEquation, coveragePOI, caps)) { |
788 SkASSERT(!dstTexture || !dstTexture->texture()); | 366 SkASSERT(!dstTexture || !dstTexture->texture()); |
789 return new CustomXP(fMode, fHWBlendEquation); | 367 return new CustomXP(fMode, fHWBlendEquation); |
790 } | 368 } |
791 return new CustomXP(dstTexture, hasMixedSamples, fMode); | 369 return new CustomXP(dstTexture, hasMixedSamples, fMode); |
792 } | 370 } |
793 | 371 |
794 bool GrCustomXPFactory::willReadDstColor(const GrCaps& caps, | 372 bool CustomXPFactory::willReadDstColor(const GrCaps& caps, |
795 const GrProcOptInfo& colorPOI, | 373 const GrProcOptInfo& colorPOI, |
796 const GrProcOptInfo& coveragePOI, | 374 const GrProcOptInfo& coveragePOI, |
797 bool hasMixedSamples) const { | 375 bool hasMixedSamples) const { |
798 return !can_use_hw_blend_equation(fHWBlendEquation, coveragePOI, caps); | 376 return !can_use_hw_blend_equation(fHWBlendEquation, coveragePOI, caps); |
799 } | 377 } |
800 | 378 |
801 void GrCustomXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI, | 379 void CustomXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI, |
802 InvariantBlendedColor* blendedC
olor) const { | 380 InvariantBlendedColor* blendedCol
or) const { |
803 blendedColor->fWillBlendWithDst = true; | 381 blendedColor->fWillBlendWithDst = true; |
804 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; | 382 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; |
805 } | 383 } |
806 | 384 |
807 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory); | 385 GR_DEFINE_XP_FACTORY_TEST(CustomXPFactory); |
808 const GrXPFactory* GrCustomXPFactory::TestCreate(GrProcessorTestData* d) { | 386 const GrXPFactory* CustomXPFactory::TestCreate(GrProcessorTestData* d) { |
809 int mode = d->fRandom->nextRangeU(SkXfermode::kLastCoeffMode + 1, | 387 int mode = d->fRandom->nextRangeU(SkXfermode::kLastCoeffMode + 1, |
810 SkXfermode::kLastSeparableMode); | 388 SkXfermode::kLastSeparableMode); |
811 | 389 |
812 return new GrCustomXPFactory(static_cast<SkXfermode::Mode>(mode)); | 390 return new CustomXPFactory(static_cast<SkXfermode::Mode>(mode)); |
813 } | 391 } |
814 | 392 |
| 393 /////////////////////////////////////////////////////////////////////////////// |
| 394 |
| 395 GrXPFactory* GrCustomXfermode::CreateXPFactory(SkXfermode::Mode mode) { |
| 396 if (!GrCustomXfermode::IsSupportedMode(mode)) { |
| 397 return nullptr; |
| 398 } else { |
| 399 return new CustomXPFactory(mode); |
| 400 } |
| 401 } |
OLD | NEW |