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