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