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