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