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

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

Issue 1334293003: Create fragment processor for performing input color blend with child processor (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: working Created 5 years, 3 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 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" 9 #include "effects/GrCustomXfermodePriv.h"
10 10
11 #include "GrCoordTransform.h" 11 #include "GrCoordTransform.h"
12 #include "GrContext.h" 12 #include "GrContext.h"
13 #include "GrFragmentProcessor.h" 13 #include "GrFragmentProcessor.h"
14 #include "GrInvariantOutput.h" 14 #include "GrInvariantOutput.h"
15 #include "GrProcessor.h" 15 #include "GrProcessor.h"
16 #include "GrTexture.h" 16 #include "GrTexture.h"
17 #include "GrTextureAccess.h" 17 #include "GrTextureAccess.h"
18 #include "SkXfermode.h" 18 #include "SkXfermode.h"
19 #include "gl/GrGLCaps.h" 19 #include "gl/GrGLCaps.h"
20 #include "gl/GrGLGpu.h" 20 #include "gl/GrGLGpu.h"
21 #include "gl/GrGLSLBlend.h"
21 #include "gl/GrGLFragmentProcessor.h" 22 #include "gl/GrGLFragmentProcessor.h"
22 #include "gl/GrGLProgramDataManager.h" 23 #include "gl/GrGLProgramDataManager.h"
23 #include "gl/builders/GrGLProgramBuilder.h" 24 #include "gl/builders/GrGLProgramBuilder.h"
24 #include "glsl/GrGLSLCaps.h" 25 #include "glsl/GrGLSLCaps.h"
25 26
26 bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) { 27 bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) {
27 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; 28 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
28 } 29 }
29 30
30 /////////////////////////////////////////////////////////////////////////////// 31 ///////////////////////////////////////////////////////////////////////////////
(...skipping 29 matching lines...) Expand all
60 } 61 }
61 if (coveragePOI.isFourChannelOutput()) { 62 if (coveragePOI.isFourChannelOutput()) {
62 return false; // LCD coverage must be applied after the blend equation. 63 return false; // LCD coverage must be applied after the blend equation.
63 } 64 }
64 if (caps.canUseAdvancedBlendEquation(equation)) { 65 if (caps.canUseAdvancedBlendEquation(equation)) {
65 return false; 66 return false;
66 } 67 }
67 return true; 68 return true;
68 } 69 }
69 70
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 /////////////////////////////////////////////////////////////////////////////// 71 ///////////////////////////////////////////////////////////////////////////////
517 // Xfer Processor 72 // Xfer Processor
518 /////////////////////////////////////////////////////////////////////////////// 73 ///////////////////////////////////////////////////////////////////////////////
519 74
520 class CustomXP : public GrXferProcessor { 75 class CustomXP : public GrXferProcessor {
521 public: 76 public:
522 CustomXP(SkXfermode::Mode mode, GrBlendEquation hwBlendEquation) 77 CustomXP(SkXfermode::Mode mode, GrBlendEquation hwBlendEquation)
523 : fMode(mode), 78 : fMode(mode),
524 fHWBlendEquation(hwBlendEquation) { 79 fHWBlendEquation(hwBlendEquation) {
525 this->initClassID<CustomXP>(); 80 this->initClassID<CustomXP>();
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputC olor); 169 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputC olor);
615 } 170 }
616 } 171 }
617 172
618 void emitBlendCodeForDstRead(GrGLXPBuilder* pb, const char* srcColor, const char* dstColor, 173 void emitBlendCodeForDstRead(GrGLXPBuilder* pb, const char* srcColor, const char* dstColor,
619 const char* outColor, const GrXferProcessor& pr oc) override { 174 const char* outColor, const GrXferProcessor& pr oc) override {
620 const CustomXP& xp = proc.cast<CustomXP>(); 175 const CustomXP& xp = proc.cast<CustomXP>();
621 SkASSERT(!xp.hasHWBlendEquation()); 176 SkASSERT(!xp.hasHWBlendEquation());
622 177
623 GrGLXPFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); 178 GrGLXPFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder();
624 emit_custom_xfermode_code(xp.mode(), fsBuilder, outColor, srcColor, dstC olor); 179 GrGLSLBlend::AppendMode(fsBuilder, srcColor, dstColor, outColor, xp.mode ());
625 } 180 }
626 181
627 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri de {} 182 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri de {}
628 183
629 typedef GrGLXferProcessor INHERITED; 184 typedef GrGLXferProcessor INHERITED;
630 }; 185 };
631 186
632 /////////////////////////////////////////////////////////////////////////////// 187 ///////////////////////////////////////////////////////////////////////////////
633 188
634 void CustomXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder * b) const { 189 void CustomXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder * b) const {
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 } 360 }
806 361
807 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory); 362 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory);
808 const GrXPFactory* GrCustomXPFactory::TestCreate(GrProcessorTestData* d) { 363 const GrXPFactory* GrCustomXPFactory::TestCreate(GrProcessorTestData* d) {
809 int mode = d->fRandom->nextRangeU(SkXfermode::kLastCoeffMode + 1, 364 int mode = d->fRandom->nextRangeU(SkXfermode::kLastCoeffMode + 1,
810 SkXfermode::kLastSeparableMode); 365 SkXfermode::kLastSeparableMode);
811 366
812 return new GrCustomXPFactory(static_cast<SkXfermode::Mode>(mode)); 367 return new GrCustomXPFactory(static_cast<SkXfermode::Mode>(mode));
813 } 368 }
814 369
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698