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_util.h" 25 26/* A test consists of a render target format, clear colour, dither state, and 27 * translated form. Dither state matters when the tilebuffer format is more 28 * precise than the final format. */ 29struct test { 30 enum pipe_format format; 31 bool dithered; 32 union pipe_color_union colour; 33 uint32_t packed[4]; 34}; 35 36#define RRRR(r) { r, r, r, r } 37#define RGRG(r, g) { r, g, r, g } 38#define F(r, g, b, a) { .f = { r, g, b, a } } 39#define UI(r, g, b, a) { .ui = { r, g, b, a } } 40#define D (true) 41#define _ (false) 42 43static const struct test clear_tests[] = { 44 /* Basic tests */ 45 { PIPE_FORMAT_R8G8B8A8_UNORM, D, F(0.0, 0.0, 0.0, 0.0), RRRR(0x00000000) }, 46 { PIPE_FORMAT_R8G8B8A8_UNORM, _, F(0.0, 0.0, 0.0, 0.0), RRRR(0x00000000) }, 47 { PIPE_FORMAT_R8G8B8A8_UNORM, D, F(1.0, 0.0, 0.0, 1.0), RRRR(0xFF0000FF) }, 48 { PIPE_FORMAT_R8G8B8A8_UNORM, _, F(1.0, 0.0, 0.0, 1.0), RRRR(0xFF0000FF) }, 49 { PIPE_FORMAT_B8G8R8A8_UNORM, D, F(1.0, 0.0, 0.0, 1.0), RRRR(0xFF0000FF) }, 50 { PIPE_FORMAT_B8G8R8A8_UNORM, _, F(1.0, 0.0, 0.0, 1.0), RRRR(0xFF0000FF) }, 51 { PIPE_FORMAT_R8G8B8A8_UNORM, D, F(0.664, 0.0, 0.0, 0.0), RRRR(0x000000A9) }, 52 { PIPE_FORMAT_R8G8B8A8_UNORM, _, F(0.664, 0.0, 0.0, 0.0), RRRR(0x000000A9) }, 53 { PIPE_FORMAT_R4G4B4A4_UNORM, D, F(0.664, 0.0, 0.0, 0.0), RRRR(0x0000009F) }, 54 { PIPE_FORMAT_R4G4B4A4_UNORM, _, F(0.664, 0.0, 0.0, 0.0), RRRR(0x000000A0) }, 55 56 /* Test rounding to nearest even. The values are cherrypicked to multiply 57 * out to a fractional part of 0.5. The first test should round down and 58 * second test should round up. */ 59 60 { PIPE_FORMAT_R4G4B4A4_UNORM, D, F(0.41875, 0.0, 0.0, 1.0), RRRR(0xF0000064) }, 61 { PIPE_FORMAT_R4G4B4A4_UNORM, D, F(0.40625, 0.0, 0.0, 1.0), RRRR(0xF0000062) }, 62 63 /* Testing rounding direction when dithering is disabled. The packed value 64 * is what gets rounded. This behaves as round-to-even with the cutoff point 65 * at 2^-m + 2^-n for an m:n representation. */ 66 67 { PIPE_FORMAT_R4G4B4A4_UNORM, _, F(0.03125, 0.0, 0.0, 1.0), RRRR(0xF0000000) }, 68 { PIPE_FORMAT_R4G4B4A4_UNORM, _, F(0.03125, 0.0, 0.0, 1.0), RRRR(0xF0000000) }, 69 { PIPE_FORMAT_R4G4B4A4_UNORM, _, F(0.03333, 0.0, 0.0, 1.0), RRRR(0xF0000000) }, 70 { PIPE_FORMAT_R4G4B4A4_UNORM, _, F(0.03334, 0.0, 0.0, 1.0), RRRR(0xF0000010) }, 71 { PIPE_FORMAT_R4G4B4A4_UNORM, _, F(0.09375, 0.0, 0.0, 1.0), RRRR(0xF0000010) }, 72 73 /* Check all the special formats with different edge cases */ 74 75 { PIPE_FORMAT_R4G4B4A4_UNORM, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x7800F01E) }, 76 { PIPE_FORMAT_R5G5B5A1_UNORM, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x400F807E) }, 77 { PIPE_FORMAT_R5G6B5_UNORM, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x000FC07E) }, 78 { PIPE_FORMAT_R10G10B10A2_UNORM, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x800FFC82) }, 79 { PIPE_FORMAT_R8G8B8A8_SRGB, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x8000FF64) }, 80 81 { PIPE_FORMAT_R4G4B4A4_UNORM, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0xF0F02BAC) }, 82 { PIPE_FORMAT_R5G6B5_UNORM, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0x3E02D6C8) }, 83 { PIPE_FORMAT_R5G5B5A1_UNORM, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0xBE02CEC8) }, 84 { PIPE_FORMAT_R10G10B10A2_UNORM, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0xFFF2E2DF) }, 85 { PIPE_FORMAT_R8G8B8A8_SRGB, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0xFFFF76DC) }, 86 87 /* Check that values are padded when dithering is disabled */ 88 89 { PIPE_FORMAT_R4G4B4A4_UNORM, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0xF0F030B0) }, 90 { PIPE_FORMAT_R5G6B5_UNORM, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0x3E02C2C0) }, 91 { PIPE_FORMAT_R5G5B5A1_UNORM, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0xBE0302C0) }, 92 { PIPE_FORMAT_R10G10B10A2_UNORM, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0xFFF2E2DF) }, 93 { PIPE_FORMAT_R8G8B8A8_SRGB, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0xFFFF76DC) }, 94 95 /* Check that blendable tilebuffer values are invariant under swizzling */ 96 97 { PIPE_FORMAT_B4G4R4A4_UNORM, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x7800F01E) }, 98 { PIPE_FORMAT_B5G5R5A1_UNORM, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x400F807E) }, 99 { PIPE_FORMAT_B5G6R5_UNORM, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x000FC07E) }, 100 { PIPE_FORMAT_B10G10R10A2_UNORM, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x800FFC82) }, 101 { PIPE_FORMAT_B8G8R8A8_SRGB, D, F(0.127, 2.4, -1.0, 0.5), RRRR(0x8000FF64) }, 102 103 { PIPE_FORMAT_B4G4R4A4_UNORM, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0xF0F02BAC) }, 104 { PIPE_FORMAT_B5G6R5_UNORM, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0x3E02D6C8) }, 105 { PIPE_FORMAT_B5G5R5A1_UNORM, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0xBE02CEC8) }, 106 { PIPE_FORMAT_B10G10R10A2_UNORM, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0xFFF2E2DF) }, 107 { PIPE_FORMAT_B8G8R8A8_SRGB, D, F(0.718, 0.18, 1.0, 2.0), RRRR(0xFFFF76DC) }, 108 109 { PIPE_FORMAT_B4G4R4A4_UNORM, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0xF0F030B0) }, 110 { PIPE_FORMAT_B5G6R5_UNORM, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0x3E02C2C0) }, 111 { PIPE_FORMAT_B5G5R5A1_UNORM, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0xBE0302C0) }, 112 { PIPE_FORMAT_B10G10R10A2_UNORM, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0xFFF2E2DF) }, 113 { PIPE_FORMAT_B8G8R8A8_SRGB, _, F(0.718, 0.18, 1.0, 2.0), RRRR(0xFFFF76DC) }, 114 115 /* Check raw formats, which are not invariant under swizzling. Raw formats 116 * cannot be dithered. */ 117 118 { PIPE_FORMAT_R8G8B8A8_UINT, D, UI(0xCA, 0xFE, 0xBA, 0xBE), RRRR(0xBEBAFECA) }, 119 { PIPE_FORMAT_R8G8B8A8_UINT, _, UI(0xCA, 0xFE, 0xBA, 0xBE), RRRR(0xBEBAFECA) }, 120 121 { PIPE_FORMAT_B8G8R8A8_UINT, D, UI(0xCA, 0xFE, 0xBA, 0xBE), RRRR(0xBECAFEBA) }, 122 { PIPE_FORMAT_B8G8R8A8_UINT, _, UI(0xCA, 0xFE, 0xBA, 0xBE), RRRR(0xBECAFEBA) }, 123 124 /* Check that larger raw formats are replicated correctly */ 125 126 { PIPE_FORMAT_R16G16B16A16_UINT, D, UI(0xCAFE, 0xBABE, 0xABAD, 0x1DEA), 127 RGRG(0xBABECAFE, 0x1DEAABAD) }, 128 129 { PIPE_FORMAT_R16G16B16A16_UINT, _, UI(0xCAFE, 0xBABE, 0xABAD, 0x1DEA), 130 RGRG(0xBABECAFE, 0x1DEAABAD) }, 131 132 { PIPE_FORMAT_R32G32B32A32_UINT, D, 133 UI(0xCAFEBABE, 0xABAD1DEA, 0xDEADBEEF, 0xABCDEF01), 134 { 0xCAFEBABE, 0xABAD1DEA, 0xDEADBEEF, 0xABCDEF01 } }, 135 136 { PIPE_FORMAT_R32G32B32A32_UINT, _, 137 UI(0xCAFEBABE, 0xABAD1DEA, 0xDEADBEEF, 0xABCDEF01), 138 { 0xCAFEBABE, 0xABAD1DEA, 0xDEADBEEF, 0xABCDEF01 } }, 139}; 140 141#define ASSERT_EQ(x, y) do { \ 142 if ((x[0] == y[0]) && (x[1] == y[1]) && (x[2] == y[2]) && (x[3] == y[3])) { \ 143 nr_pass++; \ 144 } else { \ 145 nr_fail++; \ 146 fprintf(stderr, "%s%s: Assertion failed %s (%08X %08X %08X %08X) != %s (%08X %08X %08X %08X)\n", \ 147 util_format_short_name(T.format), T.dithered ? " dithered" : "", #x, x[0], x[1], x[2], x[3], #y, y[0], y[1], y[2], y[3]); \ 148 } \ 149} while(0) 150 151int main(int argc, const char **argv) 152{ 153 unsigned nr_pass = 0, nr_fail = 0; 154 155 for (unsigned i = 0; i < ARRAY_SIZE(clear_tests); ++i) { 156 struct test T = clear_tests[i]; 157 uint32_t packed[4]; 158 pan_pack_color(&packed[0], &T.colour, T.format, T.dithered); 159 160 ASSERT_EQ(T.packed, packed); 161 } 162 163 printf("Passed %u/%u\n", nr_pass, nr_pass + nr_fail); 164 return nr_fail ? 1 : 0; 165} 166