1 /*
2 * Copyright (C) 2021 Collabora, Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include "pan_blend.h"
25
26 /* A test consists of a given blend mode and its translated form */
27 struct test {
28 const char *label;
29 struct pan_blend_equation eq;
30 unsigned constant_mask;
31 bool reads_dest;
32 bool opaque;
33 bool fixed_function;
34 uint32_t hardware;
35 };
36
37 #define RGBA(key, value) \
38 .rgb_ ## key = value, \
39 .alpha_ ## key = value
40
41 static const struct test blend_tests[] = {
42 {
43 "Replace",
44 {
45 .blend_enable = false,
46 .color_mask = 0xF,
47 },
48 .constant_mask = 0x0,
49 .reads_dest = false,
50 .opaque = true,
51 .fixed_function = true,
52 .hardware = 0xF0122122
53 },
54 {
55 "Alpha",
56 {
57 .blend_enable = true,
58 .color_mask = 0xF,
59
60 RGBA(func, BLEND_FUNC_ADD),
61 RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA),
62 RGBA(dst_factor, BLEND_FACTOR_SRC_ALPHA),
63 RGBA(invert_dst_factor, true),
64 },
65 .constant_mask = 0x0,
66 .reads_dest = true,
67 .opaque = false,
68 .fixed_function = true,
69 .hardware = 0xF0503503
70 },
71 {
72 "Additive",
73 {
74 .blend_enable = true,
75 .color_mask = 0xF,
76
77 RGBA(func, BLEND_FUNC_ADD),
78 RGBA(src_factor, BLEND_FACTOR_ZERO),
79 RGBA(dst_factor, BLEND_FACTOR_ZERO),
80 RGBA(invert_src_factor, true),
81 RGBA(invert_dst_factor, true),
82 },
83 .constant_mask = 0x0,
84 .reads_dest = true,
85 .opaque = false,
86 .fixed_function = true,
87 .hardware = 0xF0932932 /* equivalently 0xF0923923 */
88 },
89 {
90 "Additive-Alpha",
91 {
92 .blend_enable = true,
93 .color_mask = 0xF,
94
95 RGBA(func, BLEND_FUNC_ADD),
96 RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA),
97 RGBA(dst_factor, BLEND_FACTOR_ZERO),
98 RGBA(invert_dst_factor, true),
99 },
100 .constant_mask = 0x0,
101 .reads_dest = true,
102 .opaque = false,
103 .fixed_function = true,
104 .hardware = 0xF0523523
105 },
106 {
107 "Subtractive",
108 {
109 .blend_enable = true,
110 .color_mask = 0xF,
111
112 RGBA(func, BLEND_FUNC_SUBTRACT),
113 RGBA(src_factor, BLEND_FACTOR_ZERO),
114 RGBA(dst_factor, BLEND_FACTOR_ZERO),
115 RGBA(invert_src_factor, true),
116 RGBA(invert_dst_factor, true),
117 },
118 .constant_mask = 0x0,
119 .reads_dest = true,
120 .opaque = false,
121 .fixed_function = true,
122 .hardware = 0xF09B29B2 /* equivalently 0xF09A39A3 */
123 },
124 {
125 "Subtractive-Alpha",
126 {
127 .blend_enable = true,
128 .color_mask = 0xF,
129
130 RGBA(func, BLEND_FUNC_SUBTRACT),
131 RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA),
132 RGBA(dst_factor, BLEND_FACTOR_ZERO),
133 RGBA(invert_dst_factor, true),
134 },
135 .constant_mask = 0x0,
136 .reads_dest = true,
137 .opaque = false,
138 .fixed_function = true,
139 .hardware = 0xF052B52b /* equivalently 0xF05A35A3 */
140 },
141 {
142 "Modulate",
143 {
144 .blend_enable = true,
145 .color_mask = 0xF,
146
147 RGBA(func, BLEND_FUNC_ADD),
148 RGBA(src_factor, BLEND_FACTOR_ZERO),
149 RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR),
150 },
151 .constant_mask = 0x0,
152 .reads_dest = true,
153 .opaque = false,
154 .fixed_function = true,
155 .hardware = 0xF0231231 /* equivalently 0xF0321321 */
156 },
157 {
158 "Replace masked",
159 {
160 .blend_enable = false,
161 .color_mask = 0x3,
162 },
163 .constant_mask = 0x0,
164 .reads_dest = true,
165 .opaque = false,
166 .fixed_function = true,
167 .hardware = 0x30122122
168 },
169 {
170 "Modulate masked",
171 {
172 .blend_enable = true,
173 .color_mask = 0xA,
174
175 RGBA(func, BLEND_FUNC_ADD),
176 RGBA(src_factor, BLEND_FACTOR_ZERO),
177 RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR),
178 },
179 .constant_mask = 0x0,
180 .reads_dest = true,
181 .opaque = false,
182 .fixed_function = true,
183 .hardware = 0xA0231231 /* equivalently 0xA0321321 */
184 },
185 {
186 "src*dst + dst*src",
187 {
188 .blend_enable = true,
189 .color_mask = 0xF,
190
191 RGBA(func, BLEND_FUNC_ADD),
192 RGBA(src_factor, BLEND_FACTOR_DST_COLOR),
193 RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR),
194 },
195 .constant_mask = 0x0,
196 .reads_dest = true,
197 .opaque = false,
198 .fixed_function = true,
199 .hardware = 0xF0431431 /* 0 + dest * (2*src) */
200 },
201 {
202 "Mixed src*dst + dst*src masked I",
203 {
204 .blend_enable = true,
205 .color_mask = 0xC,
206
207 .rgb_func = BLEND_FUNC_ADD,
208 .rgb_src_factor = BLEND_FACTOR_ZERO,
209 .rgb_invert_src_factor = true,
210 .rgb_dst_factor= BLEND_FACTOR_ZERO,
211
212 .alpha_func = BLEND_FUNC_ADD,
213 .alpha_src_factor = BLEND_FACTOR_DST_COLOR,
214 .alpha_dst_factor= BLEND_FACTOR_SRC_COLOR,
215 },
216 .constant_mask = 0x0,
217 .reads_dest = true,
218 .opaque = false,
219 .fixed_function = true,
220 .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */
221 },
222 {
223 "Mixed src*dst + dst*src masked II",
224 {
225 .blend_enable = true,
226 .color_mask = 0xC,
227
228 .rgb_func = BLEND_FUNC_ADD,
229 .rgb_src_factor = BLEND_FACTOR_ZERO,
230 .rgb_invert_src_factor = true,
231 .rgb_dst_factor= BLEND_FACTOR_ZERO,
232
233 .alpha_func = BLEND_FUNC_ADD,
234 .alpha_src_factor = BLEND_FACTOR_DST_ALPHA,
235 .alpha_dst_factor= BLEND_FACTOR_SRC_COLOR,
236 },
237 .constant_mask = 0x0,
238 .reads_dest = true,
239 .opaque = false,
240 .fixed_function = true,
241 .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */
242 },
243 {
244 "Mixed src*dst + dst*src masked III",
245 {
246 .blend_enable = true,
247 .color_mask = 0xC,
248
249 .rgb_func = BLEND_FUNC_ADD,
250 .rgb_src_factor = BLEND_FACTOR_ZERO,
251 .rgb_invert_src_factor = true,
252 .rgb_dst_factor= BLEND_FACTOR_ZERO,
253
254 .alpha_func = BLEND_FUNC_ADD,
255 .alpha_src_factor = BLEND_FACTOR_DST_ALPHA,
256 .alpha_dst_factor= BLEND_FACTOR_SRC_ALPHA,
257 },
258 .constant_mask = 0x0,
259 .reads_dest = true,
260 .opaque = false,
261 .fixed_function = true,
262 .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */
263 }
264 };
265
266 #define ASSERT_EQ(x, y) do { \
267 if (x == y) { \
268 nr_pass++; \
269 } else { \
270 nr_fail++; \
271 fprintf(stderr, "%s: Assertion failed %s (%x) != %s (%x)\n", \
272 T.label, #x, x, #y, y); \
273 } \
274 } while(0)
275
main(int argc,const char ** argv)276 int main(int argc, const char **argv)
277 {
278 unsigned nr_pass = 0, nr_fail = 0;
279
280 for (unsigned i = 0; i < ARRAY_SIZE(blend_tests); ++i) {
281 struct test T = blend_tests[i];
282 ASSERT_EQ(T.constant_mask, pan_blend_constant_mask(T.eq));
283 ASSERT_EQ(T.reads_dest, pan_blend_reads_dest(T.eq));
284 ASSERT_EQ(T.opaque, pan_blend_is_opaque(T.eq));
285 ASSERT_EQ(T.fixed_function, pan_blend_can_fixed_function(T.eq, true));
286
287 if (pan_blend_can_fixed_function(T.eq, true)) {
288 ASSERT_EQ(T.hardware, pan_pack_blend(T.eq));
289 }
290 }
291
292 printf("Passed %u/%u\n", nr_pass, nr_pass + nr_fail);
293 return nr_fail ? 1 : 0;
294 }
295