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