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 uint32_t hardware; 35}; 36 37#define RGBA(key, value) \ 38 .rgb_ ## key = value, \ 39 .alpha_ ## key = value 40 41static 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 276int 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