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 */ 27struct 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 bool alpha_zero_nop; 35 bool alpha_one_store; 36 uint32_t hardware; 37}; 38 39#define RGBA(key, value) \ 40 .rgb_ ## key = value, \ 41 .alpha_ ## key = value 42 43static const struct test blend_tests[] = { 44 { 45 "Replace", 46 { 47 .blend_enable = false, 48 .color_mask = 0xF, 49 }, 50 .constant_mask = 0x0, 51 .reads_dest = false, 52 .opaque = true, 53 .fixed_function = true, 54 .alpha_zero_nop = false, 55 .alpha_one_store = false, 56 .hardware = 0xF0122122 57 }, 58 { 59 "Alpha", 60 { 61 .blend_enable = true, 62 .color_mask = 0xF, 63 64 RGBA(func, BLEND_FUNC_ADD), 65 RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA), 66 RGBA(dst_factor, BLEND_FACTOR_SRC_ALPHA), 67 RGBA(invert_dst_factor, true), 68 }, 69 .constant_mask = 0x0, 70 .reads_dest = true, 71 .opaque = false, 72 .fixed_function = true, 73 .alpha_zero_nop = true, 74 .alpha_one_store = true, 75 .hardware = 0xF0503503 76 }, 77 { 78 "Additive", 79 { 80 .blend_enable = true, 81 .color_mask = 0xF, 82 83 RGBA(func, BLEND_FUNC_ADD), 84 RGBA(src_factor, BLEND_FACTOR_ZERO), 85 RGBA(dst_factor, BLEND_FACTOR_ZERO), 86 RGBA(invert_src_factor, true), 87 RGBA(invert_dst_factor, true), 88 }, 89 .constant_mask = 0x0, 90 .reads_dest = true, 91 .opaque = false, 92 .fixed_function = true, 93 .alpha_zero_nop = false, 94 .alpha_one_store = false, 95 .hardware = 0xF0932932 /* equivalently 0xF0923923 */ 96 }, 97 { 98 "Additive-Alpha", 99 { 100 .blend_enable = true, 101 .color_mask = 0xF, 102 103 RGBA(func, BLEND_FUNC_ADD), 104 RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA), 105 RGBA(dst_factor, BLEND_FACTOR_ZERO), 106 RGBA(invert_dst_factor, true), 107 }, 108 .constant_mask = 0x0, 109 .reads_dest = true, 110 .opaque = false, 111 .fixed_function = true, 112 .alpha_zero_nop = true, 113 .alpha_one_store = false, 114 .hardware = 0xF0523523 115 }, 116 { 117 "Subtractive", 118 { 119 .blend_enable = true, 120 .color_mask = 0xF, 121 122 RGBA(func, BLEND_FUNC_SUBTRACT), 123 RGBA(src_factor, BLEND_FACTOR_ZERO), 124 RGBA(dst_factor, BLEND_FACTOR_ZERO), 125 RGBA(invert_src_factor, true), 126 RGBA(invert_dst_factor, true), 127 }, 128 .constant_mask = 0x0, 129 .reads_dest = true, 130 .opaque = false, 131 .fixed_function = true, 132 .alpha_zero_nop = false, 133 .alpha_one_store = false, 134 .hardware = 0xF09B29B2 /* equivalently 0xF09A39A3 */ 135 }, 136 { 137 "Subtractive-Alpha", 138 { 139 .blend_enable = true, 140 .color_mask = 0xF, 141 142 RGBA(func, BLEND_FUNC_SUBTRACT), 143 RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA), 144 RGBA(dst_factor, BLEND_FACTOR_ZERO), 145 RGBA(invert_dst_factor, true), 146 }, 147 .constant_mask = 0x0, 148 .reads_dest = true, 149 .opaque = false, 150 .fixed_function = true, 151 .alpha_zero_nop = false, 152 .alpha_one_store = false, 153 .hardware = 0xF052B52b /* equivalently 0xF05A35A3 */ 154 }, 155 { 156 "Modulate", 157 { 158 .blend_enable = true, 159 .color_mask = 0xF, 160 161 RGBA(func, BLEND_FUNC_ADD), 162 RGBA(src_factor, BLEND_FACTOR_ZERO), 163 RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR), 164 }, 165 .constant_mask = 0x0, 166 .reads_dest = true, 167 .opaque = false, 168 .fixed_function = true, 169 .alpha_zero_nop = false, 170 .alpha_one_store = false, 171 .hardware = 0xF0231231 /* equivalently 0xF0321321 */ 172 }, 173 { 174 "Replace masked", 175 { 176 .blend_enable = false, 177 .color_mask = 0x3, 178 }, 179 .constant_mask = 0x0, 180 .reads_dest = true, 181 .opaque = false, 182 .fixed_function = true, 183 .alpha_zero_nop = false, 184 .alpha_one_store = false, 185 .hardware = 0x30122122 186 }, 187 { 188 "Modulate masked", 189 { 190 .blend_enable = true, 191 .color_mask = 0xA, 192 193 RGBA(func, BLEND_FUNC_ADD), 194 RGBA(src_factor, BLEND_FACTOR_ZERO), 195 RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR), 196 }, 197 .constant_mask = 0x0, 198 .reads_dest = true, 199 .opaque = false, 200 .fixed_function = true, 201 .alpha_zero_nop = false, 202 .alpha_one_store = false, 203 .hardware = 0xA0231231 /* equivalently 0xA0321321 */ 204 }, 205 { 206 "src*dst + dst*src", 207 { 208 .blend_enable = true, 209 .color_mask = 0xF, 210 211 RGBA(func, BLEND_FUNC_ADD), 212 RGBA(src_factor, BLEND_FACTOR_DST_COLOR), 213 RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR), 214 }, 215 .constant_mask = 0x0, 216 .reads_dest = true, 217 .opaque = false, 218 .fixed_function = true, 219 .alpha_zero_nop = false, 220 .alpha_one_store = false, 221 .hardware = 0xF0431431 /* 0 + dest * (2*src) */ 222 }, 223 { 224 "Mixed src*dst + dst*src masked I", 225 { 226 .blend_enable = true, 227 .color_mask = 0xC, 228 229 .rgb_func = BLEND_FUNC_ADD, 230 .rgb_src_factor = BLEND_FACTOR_ZERO, 231 .rgb_invert_src_factor = true, 232 .rgb_dst_factor= BLEND_FACTOR_ZERO, 233 234 .alpha_func = BLEND_FUNC_ADD, 235 .alpha_src_factor = BLEND_FACTOR_DST_COLOR, 236 .alpha_dst_factor= BLEND_FACTOR_SRC_COLOR, 237 }, 238 .constant_mask = 0x0, 239 .reads_dest = true, 240 .opaque = false, 241 .fixed_function = true, 242 .alpha_zero_nop = false, 243 .alpha_one_store = false, 244 .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */ 245 }, 246 { 247 "Mixed src*dst + dst*src masked II", 248 { 249 .blend_enable = true, 250 .color_mask = 0xC, 251 252 .rgb_func = BLEND_FUNC_ADD, 253 .rgb_src_factor = BLEND_FACTOR_ZERO, 254 .rgb_invert_src_factor = true, 255 .rgb_dst_factor= BLEND_FACTOR_ZERO, 256 257 .alpha_func = BLEND_FUNC_ADD, 258 .alpha_src_factor = BLEND_FACTOR_DST_ALPHA, 259 .alpha_dst_factor= BLEND_FACTOR_SRC_COLOR, 260 }, 261 .constant_mask = 0x0, 262 .reads_dest = true, 263 .opaque = false, 264 .fixed_function = true, 265 .alpha_zero_nop = false, 266 .alpha_one_store = false, 267 .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */ 268 }, 269 { 270 "Mixed src*dst + dst*src masked III", 271 { 272 .blend_enable = true, 273 .color_mask = 0xC, 274 275 .rgb_func = BLEND_FUNC_ADD, 276 .rgb_src_factor = BLEND_FACTOR_ZERO, 277 .rgb_invert_src_factor = true, 278 .rgb_dst_factor= BLEND_FACTOR_ZERO, 279 280 .alpha_func = BLEND_FUNC_ADD, 281 .alpha_src_factor = BLEND_FACTOR_DST_ALPHA, 282 .alpha_dst_factor= BLEND_FACTOR_SRC_ALPHA, 283 }, 284 .constant_mask = 0x0, 285 .reads_dest = true, 286 .opaque = false, 287 .fixed_function = true, 288 .alpha_zero_nop = false, 289 .alpha_one_store = false, 290 .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */ 291 } 292}; 293 294#define ASSERT_EQ(x, y) do { \ 295 if (x == y) { \ 296 nr_pass++; \ 297 } else { \ 298 nr_fail++; \ 299 fprintf(stderr, "%s: Assertion failed %s (%x) != %s (%x)\n", \ 300 T.label, #x, x, #y, y); \ 301 } \ 302} while(0) 303 304int main(int argc, const char **argv) 305{ 306 unsigned nr_pass = 0, nr_fail = 0; 307 308 for (unsigned i = 0; i < ARRAY_SIZE(blend_tests); ++i) { 309 struct test T = blend_tests[i]; 310 ASSERT_EQ(T.constant_mask, pan_blend_constant_mask(T.eq)); 311 ASSERT_EQ(T.reads_dest, pan_blend_reads_dest(T.eq)); 312 ASSERT_EQ(T.opaque, pan_blend_is_opaque(T.eq)); 313 ASSERT_EQ(T.fixed_function, pan_blend_can_fixed_function(T.eq, true)); 314 ASSERT_EQ(T.alpha_zero_nop, pan_blend_alpha_zero_nop(T.eq)); 315 ASSERT_EQ(T.alpha_one_store, pan_blend_alpha_one_store(T.eq)); 316 317 if (pan_blend_can_fixed_function(T.eq, true)) { 318 ASSERT_EQ(T.hardware, pan_pack_blend(T.eq)); 319 } 320 } 321 322 printf("Passed %u/%u\n", nr_pass, nr_pass + nr_fail); 323 return nr_fail ? 1 : 0; 324} 325