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

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: fix 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
« no previous file with comments | « src/gpu/SkGr.cpp ('k') | src/gpu/effects/GrCustomXfermodePriv.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/gpu/SkGr.cpp ('k') | src/gpu/effects/GrCustomXfermodePriv.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698