diff --git a/src/panfrost/lib/meson.build b/src/panfrost/lib/meson.build index 934440d3276..f01cb6c19b2 100644 --- a/src/panfrost/lib/meson.build +++ b/src/panfrost/lib/meson.build @@ -100,3 +100,18 @@ libpanfrost_dep = declare_dependency( include_directories: [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_panfrost_hw, inc_panfrost], dependencies: [dep_libdrm, idep_nir, idep_midgard_pack], ) + +if with_tests + test( + 'panfrost_blend', + executable( + 'panfrost_blend_test', + files('tests/test-blend.c'), + c_args : [c_msvc_compat_args, no_override_init_args], + gnu_symbol_visibility : 'hidden', + include_directories : [inc_include, inc_src, inc_mesa], + dependencies: [libpanfrost_dep], + ), + suite : ['panfrost'], + ) +endif diff --git a/src/panfrost/lib/tests/test-blend.c b/src/panfrost/lib/tests/test-blend.c new file mode 100644 index 00000000000..b088415f364 --- /dev/null +++ b/src/panfrost/lib/tests/test-blend.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2021 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "pan_blend.h" + +/* A test consists of a given blend mode and its translated form */ +struct test { + const char *label; + struct pan_blend_equation eq; + unsigned constant_mask; + bool reads_dest; + bool opaque; + bool fixed_function; + uint32_t hardware; +}; + +#define RGBA(key, value) \ + .rgb_ ## key = value, \ + .alpha_ ## key = value + +static const struct test blend_tests[] = { + { + "Replace", + { + .blend_enable = false, + .color_mask = 0xF, + }, + .constant_mask = 0x0, + .reads_dest = false, + .opaque = true, + .fixed_function = true, + .hardware = 0xF0122122 + }, + { + "Alpha", + { + .blend_enable = true, + .color_mask = 0xF, + + RGBA(func, BLEND_FUNC_ADD), + RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA), + RGBA(dst_factor, BLEND_FACTOR_SRC_ALPHA), + RGBA(invert_dst_factor, true), + }, + .constant_mask = 0x0, + .reads_dest = true, + .opaque = false, + .fixed_function = true, + .hardware = 0xF0503503 + }, + { + "Additive", + { + .blend_enable = true, + .color_mask = 0xF, + + RGBA(func, BLEND_FUNC_ADD), + RGBA(src_factor, BLEND_FACTOR_ZERO), + RGBA(dst_factor, BLEND_FACTOR_ZERO), + RGBA(invert_src_factor, true), + RGBA(invert_dst_factor, true), + }, + .constant_mask = 0x0, + .reads_dest = true, + .opaque = false, + .fixed_function = true, + .hardware = 0xF0932932 /* equivalently 0xF0923923 */ + }, + { + "Additive-Alpha", + { + .blend_enable = true, + .color_mask = 0xF, + + RGBA(func, BLEND_FUNC_ADD), + RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA), + RGBA(dst_factor, BLEND_FACTOR_ZERO), + RGBA(invert_dst_factor, true), + }, + .constant_mask = 0x0, + .reads_dest = true, + .opaque = false, + .fixed_function = true, + .hardware = 0xF0523523 + }, + { + "Subtractive", + { + .blend_enable = true, + .color_mask = 0xF, + + RGBA(func, BLEND_FUNC_SUBTRACT), + RGBA(src_factor, BLEND_FACTOR_ZERO), + RGBA(dst_factor, BLEND_FACTOR_ZERO), + RGBA(invert_src_factor, true), + RGBA(invert_dst_factor, true), + }, + .constant_mask = 0x0, + .reads_dest = true, + .opaque = false, + .fixed_function = true, + .hardware = 0xF09B29B2 /* equivalently 0xF09A39A3 */ + }, + { + "Subtractive-Alpha", + { + .blend_enable = true, + .color_mask = 0xF, + + RGBA(func, BLEND_FUNC_SUBTRACT), + RGBA(src_factor, BLEND_FACTOR_SRC_ALPHA), + RGBA(dst_factor, BLEND_FACTOR_ZERO), + RGBA(invert_dst_factor, true), + }, + .constant_mask = 0x0, + .reads_dest = true, + .opaque = false, + .fixed_function = true, + .hardware = 0xF052B52b /* equivalently 0xF05A35A3 */ + }, + { + "Modulate", + { + .blend_enable = true, + .color_mask = 0xF, + + RGBA(func, BLEND_FUNC_ADD), + RGBA(src_factor, BLEND_FACTOR_ZERO), + RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR), + }, + .constant_mask = 0x0, + .reads_dest = true, + .opaque = false, + .fixed_function = true, + .hardware = 0xF0231231 /* equivalently 0xF0321321 */ + }, + { + "Replace masked", + { + .blend_enable = false, + .color_mask = 0x3, + }, + .constant_mask = 0x0, + .reads_dest = true, + .opaque = false, + .fixed_function = true, + .hardware = 0x30122122 + }, + { + "Modulate masked", + { + .blend_enable = true, + .color_mask = 0xA, + + RGBA(func, BLEND_FUNC_ADD), + RGBA(src_factor, BLEND_FACTOR_ZERO), + RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR), + }, + .constant_mask = 0x0, + .reads_dest = true, + .opaque = false, + .fixed_function = true, + .hardware = 0xA0231231 /* equivalently 0xA0321321 */ + }, + +}; + +#define ASSERT_EQ(x, y) do { \ + if (x == y) { \ + nr_pass++; \ + } else { \ + nr_fail++; \ + fprintf(stderr, "%s: Assertion failed %s (%x) != %s (%x)\n", \ + T.label, #x, x, #y, y); \ + } \ +} while(0) + +int main(int argc, const char **argv) +{ + unsigned nr_pass = 0, nr_fail = 0; + + for (unsigned i = 0; i < ARRAY_SIZE(blend_tests); ++i) { + struct test T = blend_tests[i]; + ASSERT_EQ(T.constant_mask, pan_blend_constant_mask(T.eq)); + ASSERT_EQ(T.reads_dest, pan_blend_reads_dest(T.eq)); + ASSERT_EQ(T.opaque, pan_blend_is_opaque(T.eq)); + ASSERT_EQ(T.fixed_function, pan_blend_can_fixed_function(T.eq)); + + if (pan_blend_can_fixed_function(T.eq)) { + ASSERT_EQ(T.hardware, pan_pack_blend(T.eq)); + } + } + + printf("Passed %u/%u\n", nr_pass, nr_pass + nr_fail); + return nr_fail ? 1 : 0; +}