xref: /aosp_15_r20/external/skia/src/gpu/Blend.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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