Apply coverage in XP base class when using dst reads
[platform/upstream/libSkiaSharp.git] / src / gpu / effects / GrCustomXfermode.cpp
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
8 #include "effects/GrCustomXfermode.h"
9 #include "effects/GrCustomXfermodePriv.h"
10
11 #include "GrCoordTransform.h"
12 #include "GrContext.h"
13 #include "GrFragmentProcessor.h"
14 #include "GrInvariantOutput.h"
15 #include "GrProcessor.h"
16 #include "GrTexture.h"
17 #include "GrTextureAccess.h"
18 #include "SkXfermode.h"
19 #include "gl/GrGLCaps.h"
20 #include "gl/GrGLGpu.h"
21 #include "gl/GrGLProcessor.h"
22 #include "gl/GrGLProgramDataManager.h"
23 #include "gl/builders/GrGLProgramBuilder.h"
24
25 bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) {
26     return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
27 }
28
29 ///////////////////////////////////////////////////////////////////////////////
30 // Static helpers
31 ///////////////////////////////////////////////////////////////////////////////
32
33 static GrBlendEquation hw_blend_equation(SkXfermode::Mode mode) {
34     enum { kOffset = kOverlay_GrBlendEquation - SkXfermode::kOverlay_Mode };
35     return static_cast<GrBlendEquation>(mode + kOffset);
36
37     GR_STATIC_ASSERT(kOverlay_GrBlendEquation == SkXfermode::kOverlay_Mode + kOffset);
38     GR_STATIC_ASSERT(kDarken_GrBlendEquation == SkXfermode::kDarken_Mode + kOffset);
39     GR_STATIC_ASSERT(kLighten_GrBlendEquation == SkXfermode::kLighten_Mode + kOffset);
40     GR_STATIC_ASSERT(kColorDodge_GrBlendEquation == SkXfermode::kColorDodge_Mode + kOffset);
41     GR_STATIC_ASSERT(kColorBurn_GrBlendEquation == SkXfermode::kColorBurn_Mode + kOffset);
42     GR_STATIC_ASSERT(kHardLight_GrBlendEquation == SkXfermode::kHardLight_Mode + kOffset);
43     GR_STATIC_ASSERT(kSoftLight_GrBlendEquation == SkXfermode::kSoftLight_Mode + kOffset);
44     GR_STATIC_ASSERT(kDifference_GrBlendEquation == SkXfermode::kDifference_Mode + kOffset);
45     GR_STATIC_ASSERT(kExclusion_GrBlendEquation == SkXfermode::kExclusion_Mode + kOffset);
46     GR_STATIC_ASSERT(kMultiply_GrBlendEquation == SkXfermode::kMultiply_Mode + kOffset);
47     GR_STATIC_ASSERT(kHSLHue_GrBlendEquation == SkXfermode::kHue_Mode + kOffset);
48     GR_STATIC_ASSERT(kHSLSaturation_GrBlendEquation == SkXfermode::kSaturation_Mode + kOffset);
49     GR_STATIC_ASSERT(kHSLColor_GrBlendEquation == SkXfermode::kColor_Mode + kOffset);
50     GR_STATIC_ASSERT(kHSLLuminosity_GrBlendEquation == SkXfermode::kLuminosity_Mode + kOffset);
51     GR_STATIC_ASSERT(kGrBlendEquationCnt == SkXfermode::kLastMode + 1 + kOffset);
52 }
53
54 static bool can_use_hw_blend_equation(const GrProcOptInfo& coveragePOI, const GrCaps& caps) {
55     if (!caps.advancedBlendEquationSupport()) {
56         return false;
57     }
58     if (coveragePOI.isFourChannelOutput()) {
59         return false; // LCD coverage must be applied after the blend equation.
60     }
61     return true;
62 }
63
64 static void hard_light(GrGLFragmentBuilder* fsBuilder,
65                        const char* final,
66                        const char* src,
67                        const char* dst) {
68     static const char kComponents[] = {'r', 'g', 'b'};
69     for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
70         char component = kComponents[i];
71         fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src);
72         fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;",
73                                final, component, src, component, dst, component);
74         fsBuilder->codeAppend("} else {");
75         fsBuilder->codeAppendf("%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);",
76                                final, component, src, dst, dst, dst, component, src, src,
77                                component);
78         fsBuilder->codeAppend("}");
79     }
80     fsBuilder->codeAppendf("%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);",
81                            final, src, dst, dst, src);
82 }
83
84 // Does one component of color-dodge
85 static void color_dodge_component(GrGLFragmentBuilder* fsBuilder,
86                                   const char* final,
87                                   const char* src,
88                                   const char* dst,
89                                   const char component) {
90     fsBuilder->codeAppendf("if (0.0 == %s.%c) {", dst, component);
91     fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
92                            final, component, src, component, dst);
93     fsBuilder->codeAppend("} else {");
94     fsBuilder->codeAppendf("float d = %s.a - %s.%c;", src, src, component);
95     fsBuilder->codeAppend("if (0.0 == d) {");
96     fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
97                            final, component, src, dst, src, component, dst, dst, component,
98                            src);
99     fsBuilder->codeAppend("} else {");
100     fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / d);",
101                            dst, dst, component, src);
102     fsBuilder->codeAppendf("%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
103                            final, component, src, src, component, dst, dst, component, src);
104     fsBuilder->codeAppend("}");
105     fsBuilder->codeAppend("}");
106 }
107
108 // Does one component of color-burn
109 static void color_burn_component(GrGLFragmentBuilder* fsBuilder,
110                                  const char* final,
111                                  const char* src,
112                                  const char* dst,
113                                  const char component) {
114     fsBuilder->codeAppendf("if (%s.a == %s.%c) {", dst, dst, component);
115     fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
116                            final, component, src, dst, src, component, dst, dst, component,
117                            src);
118     fsBuilder->codeAppendf("} else if (0.0 == %s.%c) {", src, component);
119     fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
120                            final, component, dst, component, src);
121     fsBuilder->codeAppend("} else {");
122     fsBuilder->codeAppendf("float d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);",
123                            dst, dst, dst, component, src, src, component);
124     fsBuilder->codeAppendf("%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
125                            final, component, src, src, component, dst, dst, component, src);
126     fsBuilder->codeAppend("}");
127 }
128
129 // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
130 static void soft_light_component_pos_dst_alpha(GrGLFragmentBuilder* fsBuilder,
131                                                const char* final,
132                                                const char* src,
133                                                const char* dst,
134                                                const char component) {
135     // if (2S < Sa)
136     fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src);
137     // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
138     fsBuilder->codeAppendf("%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a +"
139                                    "(1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);",
140                            final, component, dst, component, dst, component, src, src,
141                            component, dst, dst, src, component, dst, component, src, src,
142                            component);
143     // else if (4D < Da)
144     fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {",
145                            dst, component, dst);
146     fsBuilder->codeAppendf("float DSqd = %s.%c * %s.%c;",
147                            dst, component, dst, component);
148     fsBuilder->codeAppendf("float DCub = DSqd * %s.%c;", dst, component);
149     fsBuilder->codeAppendf("float DaSqd = %s.a * %s.a;", dst, dst);
150     fsBuilder->codeAppendf("float DaCub = DaSqd * %s.a;", dst);
151     // (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
152     fsBuilder->codeAppendf("%s.%c ="
153                            "(-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) +"
154                            " 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) /"
155                            "DaSqd;",
156                            final, component, src, component, src, component, dst, component,
157                            src, src, component, dst, src, src, component, src, src,
158                            component);
159     fsBuilder->codeAppendf("} else {");
160     // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
161     fsBuilder->codeAppendf("%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c +"
162                                    "%s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;",
163                            final, component, dst, dst, component, src, src, component, dst,
164                            src, component, dst, component, src, src, component, src,
165                            component);
166     fsBuilder->codeAppendf("}");
167 }
168
169 // Adds a function that takes two colors and an alpha as input. It produces a color with the
170 // hue and saturation of the first color, the luminosity of the second color, and the input
171 // alpha. It has this signature:
172 //      vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
173 static void add_lum_function(GrGLFragmentBuilder* fsBuilder, SkString* setLumFunction) {
174     // Emit a helper that gets the luminance of a color.
175     SkString getFunction;
176     GrGLShaderVar getLumArgs[] = {
177         GrGLShaderVar("color", kVec3f_GrSLType),
178     };
179     SkString getLumBody("return dot(vec3(0.3, 0.59, 0.11), color);");
180     fsBuilder->emitFunction(kFloat_GrSLType,
181                             "luminance",
182                             SK_ARRAY_COUNT(getLumArgs), getLumArgs,
183                             getLumBody.c_str(),
184                             &getFunction);
185
186     // Emit the set luminance function.
187     GrGLShaderVar setLumArgs[] = {
188         GrGLShaderVar("hueSat", kVec3f_GrSLType),
189         GrGLShaderVar("alpha", kFloat_GrSLType),
190         GrGLShaderVar("lumColor", kVec3f_GrSLType),
191     };
192     SkString setLumBody;
193     setLumBody.printf("float diff = %s(lumColor - hueSat);", getFunction.c_str());
194     setLumBody.append("vec3 outColor = hueSat + diff;");
195     setLumBody.appendf("float outLum = %s(outColor);", getFunction.c_str());
196     setLumBody.append("float minComp = min(min(outColor.r, outColor.g), outColor.b);"
197                       "float maxComp = max(max(outColor.r, outColor.g), outColor.b);"
198                       "if (minComp < 0.0 && outLum != minComp) {"
199                       "outColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) /"
200                                           "(outLum - minComp);"
201                       "}"
202                       "if (maxComp > alpha && maxComp != outLum) {"
203                       "outColor = outLum +"
204                                  "((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) /"
205                                  "(maxComp - outLum);"
206                       "}"
207                       "return outColor;");
208     fsBuilder->emitFunction(kVec3f_GrSLType,
209                             "set_luminance",
210                             SK_ARRAY_COUNT(setLumArgs), setLumArgs,
211                             setLumBody.c_str(),
212                             setLumFunction);
213 }
214
215 // Adds a function that creates a color with the hue and luminosity of one input color and
216 // the saturation of another color. It will have this signature:
217 //      float set_saturation(vec3 hueLumColor, vec3 satColor)
218 static void add_sat_function(GrGLFragmentBuilder* fsBuilder, SkString* setSatFunction) {
219     // Emit a helper that gets the saturation of a color
220     SkString getFunction;
221     GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
222     SkString getSatBody;
223     getSatBody.printf("return max(max(color.r, color.g), color.b) - "
224                       "min(min(color.r, color.g), color.b);");
225     fsBuilder->emitFunction(kFloat_GrSLType,
226                             "saturation",
227                             SK_ARRAY_COUNT(getSatArgs), getSatArgs,
228                             getSatBody.c_str(),
229                             &getFunction);
230
231     // Emit a helper that sets the saturation given sorted input channels. This used
232     // to use inout params for min, mid, and max components but that seems to cause
233     // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
234     // adjusted min, mid, and max inputs, respectively.
235     SkString helperFunction;
236     GrGLShaderVar helperArgs[] = {
237         GrGLShaderVar("minComp", kFloat_GrSLType),
238         GrGLShaderVar("midComp", kFloat_GrSLType),
239         GrGLShaderVar("maxComp", kFloat_GrSLType),
240         GrGLShaderVar("sat", kFloat_GrSLType),
241     };
242     static const char kHelperBody[] = "if (minComp < maxComp) {"
243         "vec3 result;"
244         "result.r = 0.0;"
245         "result.g = sat * (midComp - minComp) / (maxComp - minComp);"
246         "result.b = sat;"
247         "return result;"
248         "} else {"
249         "return vec3(0, 0, 0);"
250         "}";
251     fsBuilder->emitFunction(kVec3f_GrSLType,
252                             "set_saturation_helper",
253                             SK_ARRAY_COUNT(helperArgs), helperArgs,
254                             kHelperBody,
255                             &helperFunction);
256
257     GrGLShaderVar setSatArgs[] = {
258         GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
259         GrGLShaderVar("satColor", kVec3f_GrSLType),
260     };
261     const char* helpFunc = helperFunction.c_str();
262     SkString setSatBody;
263     setSatBody.appendf("float sat = %s(satColor);"
264                        "if (hueLumColor.r <= hueLumColor.g) {"
265                        "if (hueLumColor.g <= hueLumColor.b) {"
266                        "hueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);"
267                        "} else if (hueLumColor.r <= hueLumColor.b) {"
268                        "hueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);"
269                        "} else {"
270                        "hueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);"
271                        "}"
272                        "} else if (hueLumColor.r <= hueLumColor.b) {"
273                        "hueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);"
274                        "} else if (hueLumColor.g <= hueLumColor.b) {"
275                        "hueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);"
276                        "} else {"
277                        "hueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);"
278                        "}"
279                        "return hueLumColor;",
280                        getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
281                        helpFunc, helpFunc);
282     fsBuilder->emitFunction(kVec3f_GrSLType,
283                             "set_saturation",
284                             SK_ARRAY_COUNT(setSatArgs), setSatArgs,
285                             setSatBody.c_str(),
286                             setSatFunction);
287
288 }
289
290 static void emit_custom_xfermode_code(SkXfermode::Mode mode,
291                                       GrGLFragmentBuilder* fsBuilder,
292                                       const char* outputColor,
293                                       const char* inputColor,
294                                       const char* dstColor) {
295     // We don't try to optimize for this case at all
296     if (NULL == inputColor) {
297         fsBuilder->codeAppendf("const vec4 ones = vec4(1);");
298         inputColor = "ones";
299     }
300     fsBuilder->codeAppendf("// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
301
302     // These all perform src-over on the alpha channel.
303     fsBuilder->codeAppendf("%s.a = %s.a + (1.0 - %s.a) * %s.a;",
304                            outputColor, inputColor, inputColor, dstColor);
305
306     switch (mode) {
307         case SkXfermode::kOverlay_Mode:
308             // Overlay is Hard-Light with the src and dst reversed
309             hard_light(fsBuilder, outputColor, dstColor, inputColor);
310             break;
311         case SkXfermode::kDarken_Mode:
312             fsBuilder->codeAppendf("%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
313                                    "(1.0 - %s.a) * %s.rgb + %s.rgb);",
314                                    outputColor,
315                                    inputColor, dstColor, inputColor,
316                                    dstColor, inputColor, dstColor);
317             break;
318         case SkXfermode::kLighten_Mode:
319             fsBuilder->codeAppendf("%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
320                                    "(1.0 - %s.a) * %s.rgb + %s.rgb);",
321                                    outputColor,
322                                    inputColor, dstColor, inputColor,
323                                    dstColor, inputColor, dstColor);
324             break;
325         case SkXfermode::kColorDodge_Mode:
326             color_dodge_component(fsBuilder, outputColor, inputColor, dstColor, 'r');
327             color_dodge_component(fsBuilder, outputColor, inputColor, dstColor, 'g');
328             color_dodge_component(fsBuilder, outputColor, inputColor, dstColor, 'b');
329             break;
330         case SkXfermode::kColorBurn_Mode:
331             color_burn_component(fsBuilder, outputColor, inputColor, dstColor, 'r');
332             color_burn_component(fsBuilder, outputColor, inputColor, dstColor, 'g');
333             color_burn_component(fsBuilder, outputColor, inputColor, dstColor, 'b');
334             break;
335         case SkXfermode::kHardLight_Mode:
336             hard_light(fsBuilder, outputColor, inputColor, dstColor);
337             break;
338         case SkXfermode::kSoftLight_Mode:
339             fsBuilder->codeAppendf("if (0.0 == %s.a) {", dstColor);
340             fsBuilder->codeAppendf("%s.rgba = %s;", outputColor, inputColor);
341             fsBuilder->codeAppendf("} else {");
342             soft_light_component_pos_dst_alpha(fsBuilder, outputColor, inputColor, dstColor, 'r');
343             soft_light_component_pos_dst_alpha(fsBuilder, outputColor, inputColor, dstColor, 'g');
344             soft_light_component_pos_dst_alpha(fsBuilder, outputColor, inputColor, dstColor, 'b');
345             fsBuilder->codeAppendf("}");
346             break;
347         case SkXfermode::kDifference_Mode:
348             fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb -"
349                                    "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);",
350                                    outputColor, inputColor, dstColor, inputColor, dstColor,
351                                    dstColor, inputColor);
352             break;
353         case SkXfermode::kExclusion_Mode:
354             fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb - "
355                                    "2.0 * %s.rgb * %s.rgb;",
356                                    outputColor, dstColor, inputColor, dstColor, inputColor);
357             break;
358         case SkXfermode::kMultiply_Mode:
359             fsBuilder->codeAppendf("%s.rgb = (1.0 - %s.a) * %s.rgb + "
360                                    "(1.0 - %s.a) * %s.rgb + "
361                                    "%s.rgb * %s.rgb;",
362                                    outputColor, inputColor, dstColor, dstColor, inputColor,
363                                    inputColor, dstColor);
364             break;
365         case SkXfermode::kHue_Mode: {
366             //  SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
367             SkString setSat, setLum;
368             add_sat_function(fsBuilder, &setSat);
369             add_lum_function(fsBuilder, &setLum);
370             fsBuilder->codeAppendf("vec4 dstSrcAlpha = %s * %s.a;",
371                                    dstColor, inputColor);
372             fsBuilder->codeAppendf("%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb),"
373                                                "dstSrcAlpha.a, dstSrcAlpha.rgb);",
374                                    outputColor, setLum.c_str(), setSat.c_str(), inputColor,
375                                    dstColor);
376             fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;",
377                                    outputColor, inputColor, dstColor, dstColor, inputColor);
378             break;
379         }
380         case SkXfermode::kSaturation_Mode: {
381             // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
382             SkString setSat, setLum;
383             add_sat_function(fsBuilder, &setSat);
384             add_lum_function(fsBuilder, &setLum);
385             fsBuilder->codeAppendf("vec4 dstSrcAlpha = %s * %s.a;",
386                                    dstColor, inputColor);
387             fsBuilder->codeAppendf("%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a),"
388                                                "dstSrcAlpha.a, dstSrcAlpha.rgb);",
389                                    outputColor, setLum.c_str(), setSat.c_str(), inputColor,
390                                    dstColor);
391             fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;",
392                                    outputColor, inputColor, dstColor, dstColor, inputColor);
393             break;
394         }
395         case SkXfermode::kColor_Mode: {
396             //  SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
397             SkString setLum;
398             add_lum_function(fsBuilder, &setLum);
399             fsBuilder->codeAppendf("vec4 srcDstAlpha = %s * %s.a;",
400                                    inputColor, dstColor);
401             fsBuilder->codeAppendf("%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);",
402                                    outputColor, setLum.c_str(), dstColor, inputColor);
403             fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;",
404                                    outputColor, inputColor, dstColor, dstColor, inputColor);
405             break;
406         }
407         case SkXfermode::kLuminosity_Mode: {
408             //  SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
409             SkString setLum;
410             add_lum_function(fsBuilder, &setLum);
411             fsBuilder->codeAppendf("vec4 srcDstAlpha = %s * %s.a;",
412                                    inputColor, dstColor);
413             fsBuilder->codeAppendf("%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);",
414                                    outputColor, setLum.c_str(), dstColor, inputColor);
415             fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;",
416                                    outputColor, inputColor, dstColor, dstColor, inputColor);
417             break;
418         }
419         default:
420             SkFAIL("Unknown Custom Xfer mode.");
421             break;
422     }
423 }
424
425 ///////////////////////////////////////////////////////////////////////////////
426 // Fragment Processor
427 ///////////////////////////////////////////////////////////////////////////////
428
429 GrFragmentProcessor* GrCustomXfermode::CreateFP(SkXfermode::Mode mode, GrTexture* background) {
430     if (!GrCustomXfermode::IsSupportedMode(mode)) {
431         return NULL;
432     } else {
433         return SkNEW_ARGS(GrCustomXferFP, (mode, background));
434     }
435 }
436
437 ///////////////////////////////////////////////////////////////////////////////
438
439 class GLCustomXferFP : public GrGLFragmentProcessor {
440 public:
441     GLCustomXferFP(const GrFragmentProcessor&) {}
442     ~GLCustomXferFP() override {};
443
444     void emitCode(GrGLFPBuilder* builder,
445                   const GrFragmentProcessor& fp,
446                   const char* outputColor,
447                   const char* inputColor,
448                   const TransformedCoordsArray& coords,
449                   const TextureSamplerArray& samplers) override {
450         SkXfermode::Mode mode = fp.cast<GrCustomXferFP>().mode();
451         GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
452         const char* dstColor = "bgColor";
453         fsBuilder->codeAppendf("vec4 %s = ", dstColor);
454         fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
455         fsBuilder->codeAppendf(";");
456
457         emit_custom_xfermode_code(mode, fsBuilder, outputColor, inputColor, dstColor); 
458     }
459
460     void setData(const GrGLProgramDataManager&, const GrProcessor&) override {}
461
462     static void GenKey(const GrFragmentProcessor& proc, const GrGLSLCaps&, GrProcessorKeyBuilder* 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 private:
471     typedef GrGLFragmentProcessor INHERITED;
472 };
473
474 ///////////////////////////////////////////////////////////////////////////////
475
476 GrCustomXferFP::GrCustomXferFP(SkXfermode::Mode mode, GrTexture* background)
477     : fMode(mode) {
478     this->initClassID<GrCustomXferFP>();
479
480     SkASSERT(background);
481     fBackgroundTransform.reset(kLocal_GrCoordSet, background, 
482                                GrTextureParams::kNone_FilterMode);
483     this->addCoordTransform(&fBackgroundTransform);
484     fBackgroundAccess.reset(background);
485     this->addTextureAccess(&fBackgroundAccess);
486 }
487
488 void GrCustomXferFP::getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
489     GLCustomXferFP::GenKey(*this, caps, b);
490 }
491
492 GrGLFragmentProcessor* GrCustomXferFP::createGLInstance() const {
493     return SkNEW_ARGS(GLCustomXferFP, (*this));
494 }
495
496 bool GrCustomXferFP::onIsEqual(const GrFragmentProcessor& other) const {
497     const GrCustomXferFP& s = other.cast<GrCustomXferFP>();
498     return fMode == s.fMode;
499 }
500
501 void GrCustomXferFP::onComputeInvariantOutput(GrInvariantOutput* inout) const {
502     inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
503 }
504
505 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrCustomXferFP);
506 GrFragmentProcessor* GrCustomXferFP::TestCreate(SkRandom* rand,
507                                                 GrContext*,
508                                                 const GrCaps&,
509                                                 GrTexture* textures[]) {
510     int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
511
512     return SkNEW_ARGS(GrCustomXferFP, (static_cast<SkXfermode::Mode>(mode), textures[0]));
513 }
514
515 ///////////////////////////////////////////////////////////////////////////////
516 // Xfer Processor
517 ///////////////////////////////////////////////////////////////////////////////
518
519 class CustomXP : public GrXferProcessor {
520 public:
521     CustomXP(SkXfermode::Mode mode, GrBlendEquation hwBlendEquation)
522         : fMode(mode),
523           fHWBlendEquation(hwBlendEquation) {
524         this->initClassID<CustomXP>();
525     }
526
527     CustomXP(SkXfermode::Mode mode, const DstTexture* dstTexture)
528         : INHERITED(dstTexture, true),
529           fMode(mode),
530           fHWBlendEquation(static_cast<GrBlendEquation>(-1)) {
531         this->initClassID<CustomXP>();
532     }
533
534     const char* name() const override { return "Custom Xfermode"; }
535
536     GrGLXferProcessor* createGLInstance() const override;
537
538     SkXfermode::Mode mode() const { return fMode; }
539     bool hasHWBlendEquation() const { return -1 != static_cast<int>(fHWBlendEquation); }
540
541     GrBlendEquation hwBlendEquation() const {
542         SkASSERT(this->hasHWBlendEquation());
543         return fHWBlendEquation;
544     }
545
546 private:
547     GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
548                                                  const GrProcOptInfo& coveragePOI,
549                                                  bool doesStencilWrite,
550                                                  GrColor* overrideColor,
551                                                  const GrCaps& caps) override;
552
553     void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
554
555     bool onWillNeedXferBarrier(const GrRenderTarget* rt,
556                                const GrCaps& caps,
557                                GrXferBarrierType* outBarrierType) const override;
558
559     void onGetBlendInfo(BlendInfo*) const override;
560
561     bool onIsEqual(const GrXferProcessor& xpBase) const override;
562
563     const SkXfermode::Mode fMode;
564     const GrBlendEquation  fHWBlendEquation;
565
566     typedef GrXferProcessor INHERITED;
567 };
568
569 ///////////////////////////////////////////////////////////////////////////////
570
571 GrXPFactory* GrCustomXfermode::CreateXPFactory(SkXfermode::Mode mode) {
572     if (!GrCustomXfermode::IsSupportedMode(mode)) {
573         return NULL;
574     } else {
575         return SkNEW_ARGS(GrCustomXPFactory, (mode));
576     }
577 }
578
579 ///////////////////////////////////////////////////////////////////////////////
580
581 class GLCustomXP : public GrGLXferProcessor {
582 public:
583     GLCustomXP(const GrXferProcessor&) {}
584     ~GLCustomXP() override {}
585
586     static void GenKey(const GrXferProcessor& p, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) {
587         const CustomXP& xp = p.cast<CustomXP>();
588         uint32_t key = 0;
589         if (xp.hasHWBlendEquation()) {
590             SkASSERT(caps.advBlendEqInteraction() > 0);  // 0 will mean !xp.hasHWBlendEquation().
591             key |= caps.advBlendEqInteraction();
592             key |= xp.readsCoverage() << 2;
593             GR_STATIC_ASSERT(GrGLSLCaps::kLast_AdvBlendEqInteraction < 4);
594         }
595         if (!xp.hasHWBlendEquation() || caps.mustEnableSpecificAdvBlendEqs()) {
596             key |= xp.mode() << 3;
597         }
598         b->add32(key);
599     }
600
601 private:
602     void emitOutputsForBlendState(const EmitArgs& args) override {
603         const CustomXP& xp = args.fXP.cast<CustomXP>();
604         SkASSERT(xp.hasHWBlendEquation());
605
606         GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
607         fsBuilder->enableAdvancedBlendEquationIfNeeded(xp.hwBlendEquation());
608
609         // Apply coverage by multiplying it into the src color before blending.
610         // (See onGetOptimizations())
611         if (xp.readsCoverage()) {
612             fsBuilder->codeAppendf("%s = %s * %s;",
613                                    args.fOutputPrimary, args.fInputCoverage, args.fInputColor);
614         } else {
615             fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputColor);
616         }
617     }
618
619     void emitBlendCodeForDstRead(GrGLXPBuilder* pb, const char* srcColor, const char* dstColor,
620                                  const char* outColor, const GrXferProcessor& proc) override {
621         const CustomXP& xp = proc.cast<CustomXP>();
622         SkASSERT(!xp.hasHWBlendEquation());
623
624         GrGLXPFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder();
625         emit_custom_xfermode_code(xp.mode(), fsBuilder, outColor, srcColor, dstColor);
626     }
627
628     void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) override {}
629
630     typedef GrGLFragmentProcessor INHERITED;
631 };
632
633 ///////////////////////////////////////////////////////////////////////////////
634
635 void CustomXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
636     GLCustomXP::GenKey(*this, caps, b);
637 }
638
639 GrGLXferProcessor* CustomXP::createGLInstance() const {
640     SkASSERT(this->willReadDstColor() != this->hasHWBlendEquation());
641     return SkNEW_ARGS(GLCustomXP, (*this));
642 }
643
644 bool CustomXP::onIsEqual(const GrXferProcessor& other) const {
645     const CustomXP& s = other.cast<CustomXP>();
646     return fMode == s.fMode && fHWBlendEquation == s.fHWBlendEquation;
647 }
648
649 GrXferProcessor::OptFlags CustomXP::onGetOptimizations(const GrProcOptInfo& colorPOI,
650                                                        const GrProcOptInfo& coveragePOI,
651                                                        bool doesStencilWrite,
652                                                        GrColor* overrideColor,
653                                                        const GrCaps& caps) {
654   /*
655     Most the optimizations we do here are based on tweaking alpha for coverage.
656
657     The general SVG blend equation is defined in the spec as follows:
658
659       Dca' = B(Sc, Dc) * Sa * Da + Y * Sca * (1-Da) + Z * Dca * (1-Sa)
660       Da'  = X * Sa * Da + Y * Sa * (1-Da) + Z * Da * (1-Sa)
661
662     (Note that Sca, Dca indicate RGB vectors that are premultiplied by alpha,
663      and that B(Sc, Dc) is a mode-specific function that accepts non-multiplied
664      RGB colors.)
665
666     For every blend mode supported by this class, i.e. the "advanced" blend
667     modes, X=Y=Z=1 and this equation reduces to the PDF blend equation.
668
669     It can be shown that when X=Y=Z=1, these equations can modulate alpha for
670     coverage.
671
672
673     == Color ==
674
675     We substitute Y=Z=1 and define a blend() function that calculates Dca' in
676     terms of premultiplied alpha only:
677
678       blend(Sca, Dca, Sa, Da) = {Dca : if Sa == 0,
679                                  Sca : if Da == 0,
680                                  B(Sca/Sa, Dca/Da) * Sa * Da + Sca * (1-Da) + Dca * (1-Sa) : if Sa,Da != 0}
681
682     And for coverage modulation, we use a post blend src-over model:
683
684       Dca'' = f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
685
686     (Where f is the fractional coverage.)
687
688     Next we show that canTweakAlphaForCoverage() is true by proving the
689     following relationship:
690
691       blend(f*Sca, Dca, f*Sa, Da) == f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
692
693     General case (f,Sa,Da != 0):
694
695       f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
696         = f * (B(Sca/Sa, Dca/Da) * Sa * Da + Sca * (1-Da) + Dca * (1-Sa)) + (1-f) * Dca  [Sa,Da != 0, definition of blend()]
697         = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) + f*Dca * (1-Sa) + Dca - f*Dca
698         = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca - f*Sca * Da + f*Dca - f*Dca * Sa + Dca - f*Dca
699         = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca - f*Sca * Da - f*Dca * Sa + Dca
700         = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) - f*Dca * Sa + Dca
701         = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) + Dca * (1 - f*Sa)
702         = B(f*Sca/f*Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) + Dca * (1 - f*Sa)  [f!=0]
703         = blend(f*Sca, Dca, f*Sa, Da)  [definition of blend()]
704
705     Corner cases (Sa=0, Da=0, and f=0):
706
707       Sa=0: f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
708               = f * Dca + (1-f) * Dca  [Sa=0, definition of blend()]
709               = Dca
710               = blend(0, Dca, 0, Da)  [definition of blend()]
711               = blend(f*Sca, Dca, f*Sa, Da)  [Sa=0]
712
713       Da=0: f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
714               = f * Sca + (1-f) * Dca  [Da=0, definition of blend()]
715               = f * Sca  [Da=0]
716               = blend(f*Sca, 0, f*Sa, 0)  [definition of blend()]
717               = blend(f*Sca, Dca, f*Sa, Da)  [Da=0]
718
719       f=0: f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
720              = Dca  [f=0]
721              = blend(0, Dca, 0, Da)  [definition of blend()]
722              = blend(f*Sca, Dca, f*Sa, Da)  [f=0]
723
724     == Alpha ==
725
726     We substitute X=Y=Z=1 and define a blend() function that calculates Da':
727
728       blend(Sa, Da) = Sa * Da + Sa * (1-Da) + Da * (1-Sa)
729                     = Sa * Da + Sa - Sa * Da + Da - Da * Sa
730                     = Sa + Da - Sa * Da
731
732     We use the same model for coverage modulation as we did with color:
733
734       Da'' = f * blend(Sa, Da) + (1-f) * Da
735
736     And show that canTweakAlphaForCoverage() is true by proving the following
737     relationship:
738
739       blend(f*Sa, Da) == f * blend(Sa, Da) + (1-f) * Da
740
741
742       f * blend(Sa, Da) + (1-f) * Da
743         = f * (Sa + Da - Sa * Da) + (1-f) * Da
744         = f*Sa + f*Da - f*Sa * Da + Da - f*Da
745         = f*Sa - f*Sa * Da + Da
746         = f*Sa + Da - f*Sa * Da
747         = blend(f*Sa, Da)
748    */
749
750     OptFlags flags = kNone_Opt;
751     if (colorPOI.allStagesMultiplyInput()) {
752         flags |= kCanTweakAlphaForCoverage_OptFlag;
753     }
754     if (this->hasHWBlendEquation() && coveragePOI.isSolidWhite()) {
755         flags |= kIgnoreCoverage_OptFlag;
756     }
757     return flags;
758 }
759
760 bool CustomXP::onWillNeedXferBarrier(const GrRenderTarget* rt,
761                                      const GrCaps& caps,
762                                      GrXferBarrierType* outBarrierType) const {
763     if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport()) {
764         *outBarrierType = kBlend_GrXferBarrierType;
765         return true;
766     }
767     return false;
768 }
769
770 void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const {
771     if (this->hasHWBlendEquation()) {
772         blendInfo->fEquation = this->hwBlendEquation();
773     }
774 }
775
776 ///////////////////////////////////////////////////////////////////////////////
777
778 GrCustomXPFactory::GrCustomXPFactory(SkXfermode::Mode mode)
779     : fMode(mode),
780       fHWBlendEquation(hw_blend_equation(mode)) {
781     SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
782     this->initClassID<GrCustomXPFactory>();
783 }
784
785 GrXferProcessor*
786 GrCustomXPFactory::onCreateXferProcessor(const GrCaps& caps,
787                                          const GrProcOptInfo& colorPOI,
788                                          const GrProcOptInfo& coveragePOI,
789                                          const DstTexture* dstTexture) const {
790     if (can_use_hw_blend_equation(coveragePOI, caps)) {
791         SkASSERT(!dstTexture || !dstTexture->texture());
792         return SkNEW_ARGS(CustomXP, (fMode, fHWBlendEquation));
793     }
794     return SkNEW_ARGS(CustomXP, (fMode, dstTexture));
795 }
796
797 bool GrCustomXPFactory::willReadDstColor(const GrCaps& caps,
798                                          const GrProcOptInfo& colorPOI,
799                                          const GrProcOptInfo& coveragePOI) const {
800     return !can_use_hw_blend_equation(coveragePOI, caps);
801 }
802
803 void GrCustomXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
804                                                  InvariantBlendedColor* blendedColor) const {
805     blendedColor->fWillBlendWithDst = true;
806     blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
807 }
808
809 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory);
810 GrXPFactory* GrCustomXPFactory::TestCreate(SkRandom* rand,
811                                            GrContext*,
812                                            const GrCaps&,
813                                            GrTexture*[]) {
814     int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
815
816     return SkNEW_ARGS(GrCustomXPFactory, (static_cast<SkXfermode::Mode>(mode)));
817 }
818