/* * 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 */ }, { "src*dst + dst*src", { .blend_enable = true, .color_mask = 0xF, RGBA(func, BLEND_FUNC_ADD), RGBA(src_factor, BLEND_FACTOR_DST_COLOR), RGBA(dst_factor, BLEND_FACTOR_SRC_COLOR), }, .constant_mask = 0x0, .reads_dest = true, .opaque = false, .fixed_function = true, .hardware = 0xF0431431 /* 0 + dest * (2*src) */ }, { "Mixed src*dst + dst*src masked I", { .blend_enable = true, .color_mask = 0xC, .rgb_func = BLEND_FUNC_ADD, .rgb_src_factor = BLEND_FACTOR_ZERO, .rgb_invert_src_factor = true, .rgb_dst_factor= BLEND_FACTOR_ZERO, .alpha_func = BLEND_FUNC_ADD, .alpha_src_factor = BLEND_FACTOR_DST_COLOR, .alpha_dst_factor= BLEND_FACTOR_SRC_COLOR, }, .constant_mask = 0x0, .reads_dest = true, .opaque = false, .fixed_function = true, .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */ }, { "Mixed src*dst + dst*src masked II", { .blend_enable = true, .color_mask = 0xC, .rgb_func = BLEND_FUNC_ADD, .rgb_src_factor = BLEND_FACTOR_ZERO, .rgb_invert_src_factor = true, .rgb_dst_factor= BLEND_FACTOR_ZERO, .alpha_func = BLEND_FUNC_ADD, .alpha_src_factor = BLEND_FACTOR_DST_ALPHA, .alpha_dst_factor= BLEND_FACTOR_SRC_COLOR, }, .constant_mask = 0x0, .reads_dest = true, .opaque = false, .fixed_function = true, .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */ }, { "Mixed src*dst + dst*src masked III", { .blend_enable = true, .color_mask = 0xC, .rgb_func = BLEND_FUNC_ADD, .rgb_src_factor = BLEND_FACTOR_ZERO, .rgb_invert_src_factor = true, .rgb_dst_factor= BLEND_FACTOR_ZERO, .alpha_func = BLEND_FUNC_ADD, .alpha_src_factor = BLEND_FACTOR_DST_ALPHA, .alpha_dst_factor= BLEND_FACTOR_SRC_ALPHA, }, .constant_mask = 0x0, .reads_dest = true, .opaque = false, .fixed_function = true, .hardware = 0xC0431132 /* 0 + dest * (2*src); equivalent 0xC0431122 */ } }; #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, true)); if (pan_blend_can_fixed_function(T.eq, true)) { 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; }