1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Blend.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h"
11*c8dee2aaSAndroid Build Coastguard Worker
12*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
14*c8dee2aaSAndroid Build Coastguard Worker #endif
15*c8dee2aaSAndroid Build Coastguard Worker
16*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu {
17*c8dee2aaSAndroid Build Coastguard Worker
BlendFuncName(SkBlendMode mode)18*c8dee2aaSAndroid Build Coastguard Worker const char* BlendFuncName(SkBlendMode mode) {
19*c8dee2aaSAndroid Build Coastguard Worker switch (mode) {
20*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kClear: return "blend_clear";
21*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrc: return "blend_src";
22*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDst: return "blend_dst";
23*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcOver: return "blend_src_over";
24*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstOver: return "blend_dst_over";
25*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcIn: return "blend_src_in";
26*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstIn: return "blend_dst_in";
27*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcOut: return "blend_src_out";
28*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstOut: return "blend_dst_out";
29*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcATop: return "blend_src_atop";
30*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstATop: return "blend_dst_atop";
31*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kXor: return "blend_xor";
32*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kPlus: return "blend_plus";
33*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kModulate: return "blend_modulate";
34*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kScreen: return "blend_screen";
35*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kOverlay: return "blend_overlay";
36*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDarken: return "blend_darken";
37*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kLighten: return "blend_lighten";
38*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kColorDodge: return "blend_color_dodge";
39*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kColorBurn: return "blend_color_burn";
40*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kHardLight: return "blend_hard_light";
41*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSoftLight: return "blend_soft_light";
42*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDifference: return "blend_difference";
43*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kExclusion: return "blend_exclusion";
44*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kMultiply: return "blend_multiply";
45*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kHue: return "blend_hue";
46*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSaturation: return "blend_saturation";
47*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kColor: return "blend_color";
48*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kLuminosity: return "blend_luminosity";
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker
GetPorterDuffBlendConstants(SkBlendMode mode)53*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const float> GetPorterDuffBlendConstants(SkBlendMode mode) {
54*c8dee2aaSAndroid Build Coastguard Worker // See sksl_gpu.sksl's blend_porter_duff function for explanation of values
55*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kClear[] = {0, 0, 0, 0};
56*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kSrc[] = {1, 0, 0, 0};
57*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kDst[] = {0, 1, 0, 0};
58*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kSrcOver[] = {1, 1, 0, -1};
59*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kDstOver[] = {1, 1, -1, 0};
60*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kSrcIn[] = {0, 0, 1, 0};
61*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kDstIn[] = {0, 0, 0, 1};
62*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kSrcOut[] = {1, 0, -1, 0};
63*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kDstOut[] = {0, 1, 0, -1};
64*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kSrcATop[] = {0, 1, 1, -1};
65*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kDstATop[] = {1, 0, -1, 1};
66*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kXor[] = {1, 1, -1, -1};
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker switch (mode) {
69*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kClear: return SkSpan(kClear);
70*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrc: return SkSpan(kSrc);
71*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDst: return SkSpan(kDst);
72*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcOver: return SkSpan(kSrcOver);
73*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstOver: return SkSpan(kDstOver);
74*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcIn: return SkSpan(kSrcIn);
75*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstIn: return SkSpan(kDstIn);
76*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcOut: return SkSpan(kSrcOut);
77*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstOut: return SkSpan(kDstOut);
78*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcATop: return SkSpan(kSrcATop);
79*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstATop: return SkSpan(kDstATop);
80*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kXor: return SkSpan(kXor);
81*c8dee2aaSAndroid Build Coastguard Worker default: return {};
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker
GetReducedBlendModeInfo(SkBlendMode mode)85*c8dee2aaSAndroid Build Coastguard Worker ReducedBlendModeInfo GetReducedBlendModeInfo(SkBlendMode mode) {
86*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kHue[] = {0, 1};
87*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kSaturation[] = {1, 1};
88*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kColor[] = {0, 0};
89*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kLuminosity[] = {1, 0};
90*c8dee2aaSAndroid Build Coastguard Worker
91*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kOverlay[] = {0};
92*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kHardLight[] = {1};
93*c8dee2aaSAndroid Build Coastguard Worker
94*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kDarken[] = {1};
95*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kLighten[] = {-1};
96*c8dee2aaSAndroid Build Coastguard Worker
97*c8dee2aaSAndroid Build Coastguard Worker // This switch must be kept in sync with BlendKey() in src/ganesh/glsl/GrGLSLBlend.cpp.
98*c8dee2aaSAndroid Build Coastguard Worker switch (mode) {
99*c8dee2aaSAndroid Build Coastguard Worker // Clear/src/dst are intentionally omitted; using the built-in blend_xxxxx functions is
100*c8dee2aaSAndroid Build Coastguard Worker // preferable, since that gives us an opportunity to eliminate the src/dst entirely.
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcOver:
103*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstOver:
104*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcIn:
105*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstIn:
106*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcOut:
107*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstOut:
108*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSrcATop:
109*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDstATop:
110*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kXor: return {"blend_porter_duff",
111*c8dee2aaSAndroid Build Coastguard Worker GetPorterDuffBlendConstants(mode)};
112*c8dee2aaSAndroid Build Coastguard Worker
113*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kHue: return {"blend_hslc", SkSpan(kHue)};
114*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kSaturation: return {"blend_hslc", SkSpan(kSaturation)};
115*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kColor: return {"blend_hslc", SkSpan(kColor)};
116*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kLuminosity: return {"blend_hslc", SkSpan(kLuminosity)};
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kOverlay: return {"blend_overlay", SkSpan(kOverlay)};
119*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kHardLight: return {"blend_overlay", SkSpan(kHardLight)};
120*c8dee2aaSAndroid Build Coastguard Worker
121*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kDarken: return {"blend_darken", SkSpan(kDarken)};
122*c8dee2aaSAndroid Build Coastguard Worker case SkBlendMode::kLighten: return {"blend_darken", SkSpan(kLighten)};
123*c8dee2aaSAndroid Build Coastguard Worker
124*c8dee2aaSAndroid Build Coastguard Worker default: return {BlendFuncName(mode), {}};
125*c8dee2aaSAndroid Build Coastguard Worker }
126*c8dee2aaSAndroid Build Coastguard Worker }
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker namespace {
131*c8dee2aaSAndroid Build Coastguard Worker
equation_string(skgpu::BlendEquation eq)132*c8dee2aaSAndroid Build Coastguard Worker const char *equation_string(skgpu::BlendEquation eq) {
133*c8dee2aaSAndroid Build Coastguard Worker switch (eq) {
134*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kAdd: return "add";
135*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kSubtract: return "subtract";
136*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kReverseSubtract: return "reverse_subtract";
137*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kScreen: return "screen";
138*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kOverlay: return "overlay";
139*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kDarken: return "darken";
140*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kLighten: return "lighten";
141*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kColorDodge: return "color_dodge";
142*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kColorBurn: return "color_burn";
143*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kHardLight: return "hard_light";
144*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kSoftLight: return "soft_light";
145*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kDifference: return "difference";
146*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kExclusion: return "exclusion";
147*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kMultiply: return "multiply";
148*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kHSLHue: return "hsl_hue";
149*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kHSLSaturation: return "hsl_saturation";
150*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kHSLColor: return "hsl_color";
151*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kHSLLuminosity: return "hsl_luminosity";
152*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendEquation::kIllegal:
153*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
154*c8dee2aaSAndroid Build Coastguard Worker return "<illegal>";
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker
157*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
158*c8dee2aaSAndroid Build Coastguard Worker }
159*c8dee2aaSAndroid Build Coastguard Worker
coeff_string(skgpu::BlendCoeff coeff)160*c8dee2aaSAndroid Build Coastguard Worker const char *coeff_string(skgpu::BlendCoeff coeff) {
161*c8dee2aaSAndroid Build Coastguard Worker switch (coeff) {
162*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kZero: return "zero";
163*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kOne: return "one";
164*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kSC: return "src_color";
165*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kISC: return "inv_src_color";
166*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kDC: return "dst_color";
167*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIDC: return "inv_dst_color";
168*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kSA: return "src_alpha";
169*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kISA: return "inv_src_alpha";
170*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kDA: return "dst_alpha";
171*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIDA: return "inv_dst_alpha";
172*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kConstC: return "const_color";
173*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIConstC: return "inv_const_color";
174*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kS2C: return "src2_color";
175*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIS2C: return "inv_src2_color";
176*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kS2A: return "src2_alpha";
177*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIS2A: return "inv_src2_alpha";
178*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIllegal:
179*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
180*c8dee2aaSAndroid Build Coastguard Worker return "<illegal>";
181*c8dee2aaSAndroid Build Coastguard Worker }
182*c8dee2aaSAndroid Build Coastguard Worker
183*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
184*c8dee2aaSAndroid Build Coastguard Worker }
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
187*c8dee2aaSAndroid Build Coastguard Worker
dump() const188*c8dee2aaSAndroid Build Coastguard Worker SkString BlendInfo::dump() const {
189*c8dee2aaSAndroid Build Coastguard Worker SkString out;
190*c8dee2aaSAndroid Build Coastguard Worker out.printf("writes_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)",
191*c8dee2aaSAndroid Build Coastguard Worker fWritesColor, equation_string(fEquation), coeff_string(fSrcBlend),
192*c8dee2aaSAndroid Build Coastguard Worker coeff_string(fDstBlend), fBlendConstant.toBytes_RGBA());
193*c8dee2aaSAndroid Build Coastguard Worker return out;
194*c8dee2aaSAndroid Build Coastguard Worker }
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker #endif // SK_DEBUG
197*c8dee2aaSAndroid Build Coastguard Worker
198*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu
199