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 |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "gl/builders/GrGLProgramBuilder.h" | 22 #include "gl/builders/GrGLProgramBuilder.h" |
23 | 23 |
24 bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) { | 24 bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) { |
25 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; | 25 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; |
26 } | 26 } |
27 | 27 |
28 /////////////////////////////////////////////////////////////////////////////// | 28 /////////////////////////////////////////////////////////////////////////////// |
29 // Static helpers | 29 // Static helpers |
30 /////////////////////////////////////////////////////////////////////////////// | 30 /////////////////////////////////////////////////////////////////////////////// |
31 | 31 |
32 static void hard_light(GrGLFPFragmentBuilder* fsBuilder, | 32 static void hard_light(GrGLFragmentBuilder* fsBuilder, |
33 const char* final, | 33 const char* final, |
34 const char* src, | 34 const char* src, |
35 const char* dst) { | 35 const char* dst) { |
36 static const char kComponents[] = {'r', 'g', 'b'}; | 36 static const char kComponents[] = {'r', 'g', 'b'}; |
37 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { | 37 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { |
38 char component = kComponents[i]; | 38 char component = kComponents[i]; |
39 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src
); | 39 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src
); |
40 fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;", | 40 fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;", |
41 final, component, src, component, dst, component)
; | 41 final, component, src, component, dst, component)
; |
42 fsBuilder->codeAppend("} else {"); | 42 fsBuilder->codeAppend("} else {"); |
43 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s
.a - %s.%c);", | 43 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s
.a - %s.%c);", |
44 final, component, src, dst, dst, dst, component,
src, src, | 44 final, component, src, dst, dst, dst, component,
src, src, |
45 component); | 45 component); |
46 fsBuilder->codeAppend("}"); | 46 fsBuilder->codeAppend("}"); |
47 } | 47 } |
48 fsBuilder->codeAppendf("%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s
.a);", | 48 fsBuilder->codeAppendf("%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s
.a);", |
49 final, src, dst, dst, src); | 49 final, src, dst, dst, src); |
50 } | 50 } |
51 | 51 |
52 // Does one component of color-dodge | 52 // Does one component of color-dodge |
53 static void color_dodge_component(GrGLFPFragmentBuilder* fsBuilder, | 53 static void color_dodge_component(GrGLFragmentBuilder* fsBuilder, |
54 const char* final, | 54 const char* final, |
55 const char* src, | 55 const char* src, |
56 const char* dst, | 56 const char* dst, |
57 const char component) { | 57 const char component) { |
58 fsBuilder->codeAppendf("if (0.0 == %s.%c) {", dst, component); | 58 fsBuilder->codeAppendf("if (0.0 == %s.%c) {", dst, component); |
59 fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", | 59 fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", |
60 final, component, src, component, dst); | 60 final, component, src, component, dst); |
61 fsBuilder->codeAppend("} else {"); | 61 fsBuilder->codeAppend("} else {"); |
62 fsBuilder->codeAppendf("float d = %s.a - %s.%c;", src, src, component); | 62 fsBuilder->codeAppendf("float d = %s.a - %s.%c;", src, src, component); |
63 fsBuilder->codeAppend("if (0.0 == d) {"); | 63 fsBuilder->codeAppend("if (0.0 == d) {"); |
64 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c *
(1.0 - %s.a);", | 64 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c *
(1.0 - %s.a);", |
65 final, component, src, dst, src, component, dst, dst,
component, | 65 final, component, src, dst, src, component, dst, dst,
component, |
66 src); | 66 src); |
67 fsBuilder->codeAppend("} else {"); | 67 fsBuilder->codeAppend("} else {"); |
68 fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / d);", | 68 fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / d);", |
69 dst, dst, component, src); | 69 dst, dst, component, src); |
70 fsBuilder->codeAppendf("%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1
.0 - %s.a);", | 70 fsBuilder->codeAppendf("%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1
.0 - %s.a);", |
71 final, component, src, src, component, dst, dst, comp
onent, src); | 71 final, component, src, src, component, dst, dst, comp
onent, src); |
72 fsBuilder->codeAppend("}"); | 72 fsBuilder->codeAppend("}"); |
73 fsBuilder->codeAppend("}"); | 73 fsBuilder->codeAppend("}"); |
74 } | 74 } |
75 | 75 |
76 // Does one component of color-burn | 76 // Does one component of color-burn |
77 static void color_burn_component(GrGLFPFragmentBuilder* fsBuilder, | 77 static void color_burn_component(GrGLFragmentBuilder* fsBuilder, |
78 const char* final, | 78 const char* final, |
79 const char* src, | 79 const char* src, |
80 const char* dst, | 80 const char* dst, |
81 const char component) { | 81 const char component) { |
82 fsBuilder->codeAppendf("if (%s.a == %s.%c) {", dst, dst, component); | 82 fsBuilder->codeAppendf("if (%s.a == %s.%c) {", dst, dst, component); |
83 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c *
(1.0 - %s.a);", | 83 fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c *
(1.0 - %s.a);", |
84 final, component, src, dst, src, component, dst, dst,
component, | 84 final, component, src, dst, src, component, dst, dst,
component, |
85 src); | 85 src); |
86 fsBuilder->codeAppendf("} else if (0.0 == %s.%c) {", src, component); | 86 fsBuilder->codeAppendf("} else if (0.0 == %s.%c) {", src, component); |
87 fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", | 87 fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", |
88 final, component, dst, component, src); | 88 final, component, dst, component, src); |
89 fsBuilder->codeAppend("} else {"); | 89 fsBuilder->codeAppend("} else {"); |
90 fsBuilder->codeAppendf("float d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s
.%c);", | 90 fsBuilder->codeAppendf("float d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s
.%c);", |
91 dst, dst, dst, component, src, src, component); | 91 dst, dst, dst, component, src, src, component); |
92 fsBuilder->codeAppendf("%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1
.0 - %s.a);", | 92 fsBuilder->codeAppendf("%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1
.0 - %s.a);", |
93 final, component, src, src, component, dst, dst, comp
onent, src); | 93 final, component, src, src, component, dst, dst, comp
onent, src); |
94 fsBuilder->codeAppend("}"); | 94 fsBuilder->codeAppend("}"); |
95 } | 95 } |
96 | 96 |
97 // Does one component of soft-light. Caller should have already checked that dst
alpha > 0. | 97 // Does one component of soft-light. Caller should have already checked that dst
alpha > 0. |
98 static void soft_light_component_pos_dst_alpha(GrGLFPFragmentBuilder* fsBuilder, | 98 static void soft_light_component_pos_dst_alpha(GrGLFragmentBuilder* fsBuilder, |
99 const char* final, | 99 const char* final, |
100 const char* src, | 100 const char* src, |
101 const char* dst, | 101 const char* dst, |
102 const char component) { | 102 const char component) { |
103 // if (2S < Sa) | 103 // if (2S < Sa) |
104 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src); | 104 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src); |
105 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) | 105 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) |
106 fsBuilder->codeAppendf("%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a +" | 106 fsBuilder->codeAppendf("%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a +" |
107 "(1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s
.%c + 1.0);", | 107 "(1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s
.%c + 1.0);", |
108 final, component, dst, component, dst, component, src
, src, | 108 final, component, dst, component, dst, component, src
, src, |
(...skipping 22 matching lines...) Expand all Loading... |
131 final, component, dst, dst, component, src, src, comp
onent, dst, | 131 final, component, dst, dst, component, src, src, comp
onent, dst, |
132 src, component, dst, component, src, src, component,
src, | 132 src, component, dst, component, src, src, component,
src, |
133 component); | 133 component); |
134 fsBuilder->codeAppendf("}"); | 134 fsBuilder->codeAppendf("}"); |
135 } | 135 } |
136 | 136 |
137 // Adds a function that takes two colors and an alpha as input. It produces a co
lor with the | 137 // Adds a function that takes two colors and an alpha as input. It produces a co
lor with the |
138 // hue and saturation of the first color, the luminosity of the second color, an
d the input | 138 // hue and saturation of the first color, the luminosity of the second color, an
d the input |
139 // alpha. It has this signature: | 139 // alpha. It has this signature: |
140 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). | 140 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). |
141 static void add_lum_function(GrGLFPFragmentBuilder* fsBuilder, SkString* setLumF
unction) { | 141 static void add_lum_function(GrGLFragmentBuilder* fsBuilder, SkString* setLumFun
ction) { |
142 // Emit a helper that gets the luminance of a color. | 142 // Emit a helper that gets the luminance of a color. |
143 SkString getFunction; | 143 SkString getFunction; |
144 GrGLShaderVar getLumArgs[] = { | 144 GrGLShaderVar getLumArgs[] = { |
145 GrGLShaderVar("color", kVec3f_GrSLType), | 145 GrGLShaderVar("color", kVec3f_GrSLType), |
146 }; | 146 }; |
147 SkString getLumBody("return dot(vec3(0.3, 0.59, 0.11), color);"); | 147 SkString getLumBody("return dot(vec3(0.3, 0.59, 0.11), color);"); |
148 fsBuilder->emitFunction(kFloat_GrSLType, | 148 fsBuilder->emitFunction(kFloat_GrSLType, |
149 "luminance", | 149 "luminance", |
150 SK_ARRAY_COUNT(getLumArgs), getLumArgs, | 150 SK_ARRAY_COUNT(getLumArgs), getLumArgs, |
151 getLumBody.c_str(), | 151 getLumBody.c_str(), |
(...skipping 24 matching lines...) Expand all Loading... |
176 fsBuilder->emitFunction(kVec3f_GrSLType, | 176 fsBuilder->emitFunction(kVec3f_GrSLType, |
177 "set_luminance", | 177 "set_luminance", |
178 SK_ARRAY_COUNT(setLumArgs), setLumArgs, | 178 SK_ARRAY_COUNT(setLumArgs), setLumArgs, |
179 setLumBody.c_str(), | 179 setLumBody.c_str(), |
180 setLumFunction); | 180 setLumFunction); |
181 } | 181 } |
182 | 182 |
183 // Adds a function that creates a color with the hue and luminosity of one input
color and | 183 // Adds a function that creates a color with the hue and luminosity of one input
color and |
184 // the saturation of another color. It will have this signature: | 184 // the saturation of another color. It will have this signature: |
185 // float set_saturation(vec3 hueLumColor, vec3 satColor) | 185 // float set_saturation(vec3 hueLumColor, vec3 satColor) |
186 static void add_sat_function(GrGLFPFragmentBuilder* fsBuilder, SkString* setSatF
unction) { | 186 static void add_sat_function(GrGLFragmentBuilder* fsBuilder, SkString* setSatFun
ction) { |
187 // Emit a helper that gets the saturation of a color | 187 // Emit a helper that gets the saturation of a color |
188 SkString getFunction; | 188 SkString getFunction; |
189 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) }; | 189 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) }; |
190 SkString getSatBody; | 190 SkString getSatBody; |
191 getSatBody.printf("return max(max(color.r, color.g), color.b) - " | 191 getSatBody.printf("return max(max(color.r, color.g), color.b) - " |
192 "min(min(color.r, color.g), color.b);"); | 192 "min(min(color.r, color.g), color.b);"); |
193 fsBuilder->emitFunction(kFloat_GrSLType, | 193 fsBuilder->emitFunction(kFloat_GrSLType, |
194 "saturation", | 194 "saturation", |
195 SK_ARRAY_COUNT(getSatArgs), getSatArgs, | 195 SK_ARRAY_COUNT(getSatArgs), getSatArgs, |
196 getSatBody.c_str(), | 196 getSatBody.c_str(), |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 helpFunc, helpFunc); | 249 helpFunc, helpFunc); |
250 fsBuilder->emitFunction(kVec3f_GrSLType, | 250 fsBuilder->emitFunction(kVec3f_GrSLType, |
251 "set_saturation", | 251 "set_saturation", |
252 SK_ARRAY_COUNT(setSatArgs), setSatArgs, | 252 SK_ARRAY_COUNT(setSatArgs), setSatArgs, |
253 setSatBody.c_str(), | 253 setSatBody.c_str(), |
254 setSatFunction); | 254 setSatFunction); |
255 | 255 |
256 } | 256 } |
257 | 257 |
258 static void emit_custom_xfermode_code(SkXfermode::Mode mode, | 258 static void emit_custom_xfermode_code(SkXfermode::Mode mode, |
259 GrGLFPFragmentBuilder* fsBuilder, | 259 GrGLFragmentBuilder* fsBuilder, |
260 const char* outputColor, | 260 const char* outputColor, |
261 const char* inputColor, | 261 const char* inputColor, |
262 const char* dstColor) { | 262 const char* dstColor) { |
263 // We don't try to optimize for this case at all | 263 // We don't try to optimize for this case at all |
264 if (NULL == inputColor) { | 264 if (NULL == inputColor) { |
265 fsBuilder->codeAppendf("const vec4 ones = vec4(1);"); | 265 fsBuilder->codeAppendf("const vec4 ones = vec4(1);"); |
266 inputColor = "ones"; | 266 inputColor = "ones"; |
267 } | 267 } |
268 fsBuilder->codeAppendf("// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mod
e)); | 268 fsBuilder->codeAppendf("// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mod
e)); |
269 | 269 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 GLCustomXferFP(const GrFragmentProcessor&) {} | 409 GLCustomXferFP(const GrFragmentProcessor&) {} |
410 ~GLCustomXferFP() override {}; | 410 ~GLCustomXferFP() override {}; |
411 | 411 |
412 void emitCode(GrGLFPBuilder* builder, | 412 void emitCode(GrGLFPBuilder* builder, |
413 const GrFragmentProcessor& fp, | 413 const GrFragmentProcessor& fp, |
414 const char* outputColor, | 414 const char* outputColor, |
415 const char* inputColor, | 415 const char* inputColor, |
416 const TransformedCoordsArray& coords, | 416 const TransformedCoordsArray& coords, |
417 const TextureSamplerArray& samplers) override { | 417 const TextureSamplerArray& samplers) override { |
418 SkXfermode::Mode mode = fp.cast<GrCustomXferFP>().mode(); | 418 SkXfermode::Mode mode = fp.cast<GrCustomXferFP>().mode(); |
419 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); | 419 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); |
420 const char* dstColor = "bgColor"; | 420 const char* dstColor = "bgColor"; |
421 fsBuilder->codeAppendf("vec4 %s = ", dstColor); | 421 fsBuilder->codeAppendf("vec4 %s = ", dstColor); |
422 fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0]
.getType()); | 422 fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0]
.getType()); |
423 fsBuilder->codeAppendf(";"); | 423 fsBuilder->codeAppendf(";"); |
424 | 424 |
425 emit_custom_xfermode_code(mode, fsBuilder, outputColor, inputColor, dstC
olor); | 425 emit_custom_xfermode_code(mode, fsBuilder, outputColor, inputColor, dstC
olor); |
426 } | 426 } |
427 | 427 |
428 void setData(const GrGLProgramDataManager&, const GrProcessor&) override {} | 428 void setData(const GrGLProgramDataManager&, const GrProcessor&) override {} |
429 | 429 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 static void GenKey(const GrXferProcessor& proc, const GrGLSLCaps&, GrProcess
orKeyBuilder* b) { | 543 static void GenKey(const GrXferProcessor& proc, const GrGLSLCaps&, GrProcess
orKeyBuilder* b) { |
544 uint32_t key = proc.numTextures(); | 544 uint32_t key = proc.numTextures(); |
545 SkASSERT(key <= 1); | 545 SkASSERT(key <= 1); |
546 key |= proc.cast<CustomXP>().mode() << 1; | 546 key |= proc.cast<CustomXP>().mode() << 1; |
547 b->add32(key); | 547 b->add32(key); |
548 } | 548 } |
549 | 549 |
550 private: | 550 private: |
551 void onEmitCode(const EmitArgs& args) override { | 551 void onEmitCode(const EmitArgs& args) override { |
552 SkXfermode::Mode mode = args.fXP.cast<CustomXP>().mode(); | 552 SkXfermode::Mode mode = args.fXP.cast<CustomXP>().mode(); |
553 GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); | 553 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
554 const char* dstColor = fsBuilder->dstColor(); | 554 const char* dstColor = fsBuilder->dstColor(); |
555 | 555 |
556 emit_custom_xfermode_code(mode, fsBuilder, args.fOutputPrimary, args.fIn
putColor, dstColor); | 556 emit_custom_xfermode_code(mode, fsBuilder, args.fOutputPrimary, args.fIn
putColor, dstColor); |
557 | 557 |
558 fsBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;", | 558 fsBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;", |
559 args.fOutputPrimary, args.fOutputPrimary, args.fI
nputCoverage, | 559 args.fOutputPrimary, args.fOutputPrimary, args.fI
nputCoverage, |
560 args.fInputCoverage, dstColor); | 560 args.fInputCoverage, dstColor); |
561 } | 561 } |
562 | 562 |
563 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri
de {} | 563 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri
de {} |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory); | 620 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory); |
621 GrXPFactory* GrCustomXPFactory::TestCreate(SkRandom* rand, | 621 GrXPFactory* GrCustomXPFactory::TestCreate(SkRandom* rand, |
622 GrContext*, | 622 GrContext*, |
623 const GrDrawTargetCaps&, | 623 const GrDrawTargetCaps&, |
624 GrTexture*[]) { | 624 GrTexture*[]) { |
625 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLas
tSeparableMode); | 625 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLas
tSeparableMode); |
626 | 626 |
627 return SkNEW_ARGS(GrCustomXPFactory, (static_cast<SkXfermode::Mode>(mode))); | 627 return SkNEW_ARGS(GrCustomXPFactory, (static_cast<SkXfermode::Mode>(mode))); |
628 } | 628 } |
629 | 629 |
OLD | NEW |