17ec681f3Smrg/* 27ec681f3Smrg * Copyright (C) 2021 Collabora, Ltd. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 217ec681f3Smrg * SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include "pan_blend.h" 257ec681f3Smrg 267ec681f3Smrg/* A test consists of a given blend mode and its translated form */ 277ec681f3Smrgstruct test { 287ec681f3Smrg const char *label; 297ec681f3Smrg struct pan_blend_equation eq; 307ec681f3Smrg unsigned constant_mask; 317ec681f3Smrg bool reads_dest; 327ec681f3Smrg bool opaque; 337ec681f3Smrg bool fixed_function; 347ec681f3Smrg uint32_t hardware; 357ec681f3Smrg}; 367ec681f3Smrg 377ec681f3Smrg#define RGBA(key, value) \ 387ec681f3Smrg .rgb_ ## key = value, \ 397ec681f3Smrg .alpha_ ## key = value 407ec681f3Smrg 417ec681f3Smrgstatic const struct test blend_tests[] = { 427ec681f3Smrg { 437ec681f3Smrg "Replace", 447ec681f3Smrg { 457ec681f3Smrg .blend_enable = false, 467ec681f3Smrg .color_mask = 0xF, 477ec681f3Smrg }, 487ec681f3Smrg .constant_mask = 0x0, 497ec681f3Smrg .reads_dest = false, 507ec681f3Smrg .opaque = true, 517ec681f3Smrg .fixed_function = true, 527ec681f3Smrg .hardware = 0xF0122122 537ec681f3Smrg }, 547ec681f3Smrg { 557ec681f3Smrg "Alpha", 567ec681f3Smrg { 577ec681f3Smrg .blend_enable = true, 587ec681f3Smrg .color_mask = 0xF, 597ec681f3Smrg 607ec681f3Smrg RGBA(func, BLEND_FUNC_ADD), 617ec681f3Smrg RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA), 627ec681f3Smrg RGBA(dst_factor, BLEND_FACTOR_SRC_ALPHA), 637ec681f3Smrg RGBA(invert_dst_factor, true), 647ec681f3Smrg }, 657ec681f3Smrg .constant_mask = 0x0, 667ec681f3Smrg .reads_dest = true, 677ec681f3Smrg .opaque = false, 687ec681f3Smrg .fixed_function = true, 697ec681f3Smrg .hardware = 0xF0503503 707ec681f3Smrg }, 717ec681f3Smrg { 727ec681f3Smrg "Additive", 737ec681f3Smrg { 747ec681f3Smrg .blend_enable = true, 757ec681f3Smrg .color_mask = 0xF, 767ec681f3Smrg 777ec681f3Smrg RGBA(func, BLEND_FUNC_ADD), 787ec681f3Smrg RGBA(src_factor, BLEND_FACTOR_ZERO), 797ec681f3Smrg RGBA(dst_factor, BLEND_FACTOR_ZERO), 807ec681f3Smrg RGBA(invert_src_factor, true), 817ec681f3Smrg RGBA(invert_dst_factor, true), 827ec681f3Smrg }, 837ec681f3Smrg .constant_mask = 0x0, 847ec681f3Smrg .reads_dest = true, 857ec681f3Smrg .opaque = false, 867ec681f3Smrg .fixed_function = true, 877ec681f3Smrg .hardware = 0xF0932932 /* equivalently 0xF0923923 */ 887ec681f3Smrg }, 897ec681f3Smrg { 907ec681f3Smrg "Additive-Alpha", 917ec681f3Smrg { 927ec681f3Smrg .blend_enable = true, 937ec681f3Smrg .color_mask = 0xF, 947ec681f3Smrg 957ec681f3Smrg RGBA(func, BLEND_FUNC_ADD), 967ec681f3Smrg RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA), 977ec681f3Smrg RGBA(dst_factor, BLEND_FACTOR_ZERO), 987ec681f3Smrg RGBA(invert_dst_factor, true), 997ec681f3Smrg }, 1007ec681f3Smrg .constant_mask = 0x0, 1017ec681f3Smrg .reads_dest = true, 1027ec681f3Smrg .opaque = false, 1037ec681f3Smrg .fixed_function = true, 1047ec681f3Smrg .hardware = 0xF0523523 1057ec681f3Smrg }, 1067ec681f3Smrg { 1077ec681f3Smrg "Subtractive", 1087ec681f3Smrg { 1097ec681f3Smrg .blend_enable = true, 1107ec681f3Smrg .color_mask = 0xF, 1117ec681f3Smrg 1127ec681f3Smrg RGBA(func, BLEND_FUNC_SUBTRACT), 1137ec681f3Smrg RGBA(src_factor, BLEND_FACTOR_ZERO), 1147ec681f3Smrg RGBA(dst_factor, BLEND_FACTOR_ZERO), 1157ec681f3Smrg RGBA(invert_src_factor, true), 1167ec681f3Smrg RGBA(invert_dst_factor, true), 1177ec681f3Smrg }, 1187ec681f3Smrg .constant_mask = 0x0, 1197ec681f3Smrg .reads_dest = true, 1207ec681f3Smrg .opaque = false, 1217ec681f3Smrg .fixed_function = true, 1227ec681f3Smrg .hardware = 0xF09B29B2 /* equivalently 0xF09A39A3 */ 1237ec681f3Smrg }, 1247ec681f3Smrg { 1257ec681f3Smrg "Subtractive-Alpha", 1267ec681f3Smrg { 1277ec681f3Smrg .blend_enable = true, 1287ec681f3Smrg .color_mask = 0xF, 1297ec681f3Smrg 1307ec681f3Smrg RGBA(func, BLEND_FUNC_SUBTRACT), 1317ec681f3Smrg RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA), 1327ec681f3Smrg RGBA(dst_factor, BLEND_FACTOR_ZERO), 1337ec681f3Smrg RGBA(invert_dst_factor, true), 1347ec681f3Smrg }, 1357ec681f3Smrg .constant_mask = 0x0, 1367ec681f3Smrg .reads_dest = true, 1377ec681f3Smrg .opaque = false, 1387ec681f3Smrg .fixed_function = true, 1397ec681f3Smrg .hardware = 0xF052B52b /* equivalently 0xF05A35A3 */ 1407ec681f3Smrg }, 1417ec681f3Smrg { 1427ec681f3Smrg "Modulate", 1437ec681f3Smrg { 1447ec681f3Smrg .blend_enable = true, 1457ec681f3Smrg .color_mask = 0xF, 1467ec681f3Smrg 1477ec681f3Smrg RGBA(func, BLEND_FUNC_ADD), 1487ec681f3Smrg RGBA(src_factor, BLEND_FACTOR_ZERO), 1497ec681f3Smrg RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR), 1507ec681f3Smrg }, 1517ec681f3Smrg .constant_mask = 0x0, 1527ec681f3Smrg .reads_dest = true, 1537ec681f3Smrg .opaque = false, 1547ec681f3Smrg .fixed_function = true, 1557ec681f3Smrg .hardware = 0xF0231231 /* equivalently 0xF0321321 */ 1567ec681f3Smrg }, 1577ec681f3Smrg { 1587ec681f3Smrg "Replace masked", 1597ec681f3Smrg { 1607ec681f3Smrg .blend_enable = false, 1617ec681f3Smrg .color_mask = 0x3, 1627ec681f3Smrg }, 1637ec681f3Smrg .constant_mask = 0x0, 1647ec681f3Smrg .reads_dest = true, 1657ec681f3Smrg .opaque = false, 1667ec681f3Smrg .fixed_function = true, 1677ec681f3Smrg .hardware = 0x30122122 1687ec681f3Smrg }, 1697ec681f3Smrg { 1707ec681f3Smrg "Modulate masked", 1717ec681f3Smrg { 1727ec681f3Smrg .blend_enable = true, 1737ec681f3Smrg .color_mask = 0xA, 1747ec681f3Smrg 1757ec681f3Smrg RGBA(func, BLEND_FUNC_ADD), 1767ec681f3Smrg RGBA(src_factor, BLEND_FACTOR_ZERO), 1777ec681f3Smrg RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR), 1787ec681f3Smrg }, 1797ec681f3Smrg .constant_mask = 0x0, 1807ec681f3Smrg .reads_dest = true, 1817ec681f3Smrg .opaque = false, 1827ec681f3Smrg .fixed_function = true, 1837ec681f3Smrg .hardware = 0xA0231231 /* equivalently 0xA0321321 */ 1847ec681f3Smrg }, 1857ec681f3Smrg { 1867ec681f3Smrg "src*dst + dst*src", 1877ec681f3Smrg { 1887ec681f3Smrg .blend_enable = true, 1897ec681f3Smrg .color_mask = 0xF, 1907ec681f3Smrg 1917ec681f3Smrg RGBA(func, BLEND_FUNC_ADD), 1927ec681f3Smrg RGBA(src_factor, BLEND_FACTOR_DST_COLOR), 1937ec681f3Smrg RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR), 1947ec681f3Smrg }, 1957ec681f3Smrg .constant_mask = 0x0, 1967ec681f3Smrg .reads_dest = true, 1977ec681f3Smrg .opaque = false, 1987ec681f3Smrg .fixed_function = true, 1997ec681f3Smrg .hardware = 0xF0431431 /* 0 + dest * (2*src) */ 2007ec681f3Smrg }, 2017ec681f3Smrg { 2027ec681f3Smrg "Mixed src*dst + dst*src masked I", 2037ec681f3Smrg { 2047ec681f3Smrg .blend_enable = true, 2057ec681f3Smrg .color_mask = 0xC, 2067ec681f3Smrg 2077ec681f3Smrg .rgb_func = BLEND_FUNC_ADD, 2087ec681f3Smrg .rgb_src_factor = BLEND_FACTOR_ZERO, 2097ec681f3Smrg .rgb_invert_src_factor = true, 2107ec681f3Smrg .rgb_dst_factor= BLEND_FACTOR_ZERO, 2117ec681f3Smrg 2127ec681f3Smrg .alpha_func = BLEND_FUNC_ADD, 2137ec681f3Smrg .alpha_src_factor = BLEND_FACTOR_DST_COLOR, 2147ec681f3Smrg .alpha_dst_factor= BLEND_FACTOR_SRC_COLOR, 2157ec681f3Smrg }, 2167ec681f3Smrg .constant_mask = 0x0, 2177ec681f3Smrg .reads_dest = true, 2187ec681f3Smrg .opaque = false, 2197ec681f3Smrg .fixed_function = true, 2207ec681f3Smrg .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */ 2217ec681f3Smrg }, 2227ec681f3Smrg { 2237ec681f3Smrg "Mixed src*dst + dst*src masked II", 2247ec681f3Smrg { 2257ec681f3Smrg .blend_enable = true, 2267ec681f3Smrg .color_mask = 0xC, 2277ec681f3Smrg 2287ec681f3Smrg .rgb_func = BLEND_FUNC_ADD, 2297ec681f3Smrg .rgb_src_factor = BLEND_FACTOR_ZERO, 2307ec681f3Smrg .rgb_invert_src_factor = true, 2317ec681f3Smrg .rgb_dst_factor= BLEND_FACTOR_ZERO, 2327ec681f3Smrg 2337ec681f3Smrg .alpha_func = BLEND_FUNC_ADD, 2347ec681f3Smrg .alpha_src_factor = BLEND_FACTOR_DST_ALPHA, 2357ec681f3Smrg .alpha_dst_factor= BLEND_FACTOR_SRC_COLOR, 2367ec681f3Smrg }, 2377ec681f3Smrg .constant_mask = 0x0, 2387ec681f3Smrg .reads_dest = true, 2397ec681f3Smrg .opaque = false, 2407ec681f3Smrg .fixed_function = true, 2417ec681f3Smrg .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */ 2427ec681f3Smrg }, 2437ec681f3Smrg { 2447ec681f3Smrg "Mixed src*dst + dst*src masked III", 2457ec681f3Smrg { 2467ec681f3Smrg .blend_enable = true, 2477ec681f3Smrg .color_mask = 0xC, 2487ec681f3Smrg 2497ec681f3Smrg .rgb_func = BLEND_FUNC_ADD, 2507ec681f3Smrg .rgb_src_factor = BLEND_FACTOR_ZERO, 2517ec681f3Smrg .rgb_invert_src_factor = true, 2527ec681f3Smrg .rgb_dst_factor= BLEND_FACTOR_ZERO, 2537ec681f3Smrg 2547ec681f3Smrg .alpha_func = BLEND_FUNC_ADD, 2557ec681f3Smrg .alpha_src_factor = BLEND_FACTOR_DST_ALPHA, 2567ec681f3Smrg .alpha_dst_factor= BLEND_FACTOR_SRC_ALPHA, 2577ec681f3Smrg }, 2587ec681f3Smrg .constant_mask = 0x0, 2597ec681f3Smrg .reads_dest = true, 2607ec681f3Smrg .opaque = false, 2617ec681f3Smrg .fixed_function = true, 2627ec681f3Smrg .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */ 2637ec681f3Smrg } 2647ec681f3Smrg}; 2657ec681f3Smrg 2667ec681f3Smrg#define ASSERT_EQ(x, y) do { \ 2677ec681f3Smrg if (x == y) { \ 2687ec681f3Smrg nr_pass++; \ 2697ec681f3Smrg } else { \ 2707ec681f3Smrg nr_fail++; \ 2717ec681f3Smrg fprintf(stderr, "%s: Assertion failed %s (%x) != %s (%x)\n", \ 2727ec681f3Smrg T.label, #x, x, #y, y); \ 2737ec681f3Smrg } \ 2747ec681f3Smrg} while(0) 2757ec681f3Smrg 2767ec681f3Smrgint main(int argc, const char **argv) 2777ec681f3Smrg{ 2787ec681f3Smrg unsigned nr_pass = 0, nr_fail = 0; 2797ec681f3Smrg 2807ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(blend_tests); ++i) { 2817ec681f3Smrg struct test T = blend_tests[i]; 2827ec681f3Smrg ASSERT_EQ(T.constant_mask, pan_blend_constant_mask(T.eq)); 2837ec681f3Smrg ASSERT_EQ(T.reads_dest, pan_blend_reads_dest(T.eq)); 2847ec681f3Smrg ASSERT_EQ(T.opaque, pan_blend_is_opaque(T.eq)); 2857ec681f3Smrg ASSERT_EQ(T.fixed_function, pan_blend_can_fixed_function(T.eq, true)); 2867ec681f3Smrg 2877ec681f3Smrg if (pan_blend_can_fixed_function(T.eq, true)) { 2887ec681f3Smrg ASSERT_EQ(T.hardware, pan_pack_blend(T.eq)); 2897ec681f3Smrg } 2907ec681f3Smrg } 2917ec681f3Smrg 2927ec681f3Smrg printf("Passed %u/%u\n", nr_pass, nr_pass + nr_fail); 2937ec681f3Smrg return nr_fail ? 1 : 0; 2947ec681f3Smrg} 295