1/* 2 * Copyright © 2015 Intel Corporation 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 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24/** 25 * \name mesa_formats.cpp 26 * 27 * Verify that all mesa formats are handled in certain functions and that 28 * the format info table is sane. 29 * 30 */ 31 32#include <gtest/gtest.h> 33 34#include "main/formats.h" 35#include "main/glformats.h" 36#include "main/format_unpack.h" 37#include "main/format_pack.h" 38 39// Test fixture for Format tests. 40class MesaFormatsTest : public ::testing::Test { 41}; 42 43/** 44 * Debug/test: check that all uncompressed formats are handled in the 45 * _mesa_uncompressed_format_to_type_and_comps() function. When new pixel 46 * formats are added to Mesa, that function needs to be updated. 47 */ 48TEST_F(MesaFormatsTest, FormatTypeAndComps) 49{ 50 for (int fi = MESA_FORMAT_NONE + 1; fi < MESA_FORMAT_COUNT; ++fi) { 51 mesa_format f = (mesa_format) fi; 52 SCOPED_TRACE(_mesa_get_format_name(f)); 53 54 if (!_mesa_get_format_name(f)) 55 continue; 56 57 /* This function will emit a problem/warning if the format is 58 * not handled. 59 */ 60 if (!_mesa_is_format_compressed(f)) { 61 GLenum datatype = 0; 62 GLuint comps = 0; 63 64 /* If the datatype is zero, the format was not handled */ 65 _mesa_uncompressed_format_to_type_and_comps(f, &datatype, &comps); 66 EXPECT_NE(datatype, (GLenum)0); 67 } 68 69 } 70} 71 72/** 73 * Do sanity checking of the format info table. 74 */ 75TEST_F(MesaFormatsTest, FormatSanity) 76{ 77 for (int fi = 0; fi < MESA_FORMAT_COUNT; ++fi) { 78 mesa_format f = (mesa_format) fi; 79 SCOPED_TRACE(_mesa_get_format_name(f)); 80 if (!_mesa_get_format_name(f)) 81 continue; 82 83 GLenum datatype = _mesa_get_format_datatype(f); 84 GLint r = _mesa_get_format_bits(f, GL_RED_BITS); 85 GLint g = _mesa_get_format_bits(f, GL_GREEN_BITS); 86 GLint b = _mesa_get_format_bits(f, GL_BLUE_BITS); 87 GLint a = _mesa_get_format_bits(f, GL_ALPHA_BITS); 88 GLint l = _mesa_get_format_bits(f, GL_TEXTURE_LUMINANCE_SIZE); 89 GLint i = _mesa_get_format_bits(f, GL_TEXTURE_INTENSITY_SIZE); 90 91 /* Note: Z32_FLOAT_X24S8 has datatype of GL_NONE */ 92 EXPECT_TRUE(datatype == GL_NONE || 93 datatype == GL_UNSIGNED_NORMALIZED || 94 datatype == GL_SIGNED_NORMALIZED || 95 datatype == GL_UNSIGNED_INT || 96 datatype == GL_INT || 97 datatype == GL_FLOAT); 98 99 if (r > 0 && !_mesa_is_format_compressed(f)) { 100 GLint bytes = _mesa_get_format_bytes(f); 101 EXPECT_LE((r+g+b+a) / 8, bytes); 102 } 103 104 /* Determines if the base format has a channel [rgba] or property [li]. 105 * > indicates existance 106 * == indicates non-existance 107 */ 108 #define HAS_PROP(rop,gop,bop,aop,lop,iop) \ 109 do { \ 110 EXPECT_TRUE(r rop 0); \ 111 EXPECT_TRUE(g gop 0); \ 112 EXPECT_TRUE(b bop 0); \ 113 EXPECT_TRUE(a aop 0); \ 114 EXPECT_TRUE(l lop 0); \ 115 EXPECT_TRUE(i iop 0); \ 116 } while(0) 117 118 switch (_mesa_get_format_base_format(f)) { 119 case GL_RGBA: 120 HAS_PROP(>,>,>,>,==,==); 121 break; 122 case GL_RGB: 123 HAS_PROP(>,>,>,==,==,==); 124 break; 125 case GL_RG: 126 HAS_PROP(>,>,==,==,==,==); 127 break; 128 case GL_RED: 129 HAS_PROP(>,==,==,==,==,==); 130 break; 131 case GL_LUMINANCE: 132 HAS_PROP(==,==,==,==,>,==); 133 break; 134 case GL_INTENSITY: 135 HAS_PROP(==,==,==,==,==,>); 136 break; 137 default: 138 break; 139 } 140 141 #undef HAS_PROP 142 143 } 144} 145 146TEST_F(MesaFormatsTest, IntensityToRed) 147{ 148 EXPECT_EQ(_mesa_get_intensity_format_red(MESA_FORMAT_I_UNORM8), 149 MESA_FORMAT_R_UNORM8); 150 EXPECT_EQ(_mesa_get_intensity_format_red(MESA_FORMAT_I_SINT32), 151 MESA_FORMAT_R_SINT32); 152 EXPECT_EQ(_mesa_get_intensity_format_red(MESA_FORMAT_R8G8B8A8_UNORM), 153 MESA_FORMAT_R8G8B8A8_UNORM); 154} 155 156static mesa_format fffat_wrap(GLenum format, GLenum type) 157{ 158 uint32_t f = _mesa_format_from_format_and_type(format, type); 159 if (_mesa_format_is_mesa_array_format(f)) 160 f = _mesa_format_from_array_format((mesa_array_format)f); 161 return (mesa_format)f; 162} 163 164TEST_F(MesaFormatsTest, FormatFromFormatAndType) 165{ 166 EXPECT_EQ(fffat_wrap(GL_RGBA, GL_SHORT), 167 MESA_FORMAT_RGBA_SNORM16); 168 EXPECT_EQ(fffat_wrap(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT), 169 MESA_FORMAT_Z_UNORM16); 170 EXPECT_EQ(fffat_wrap(GL_STENCIL_INDEX, GL_UNSIGNED_BYTE), 171 MESA_FORMAT_S_UINT8); 172 173 /* Should return an array format, but not a proper MESA_FORMAT. */ 174 EXPECT_TRUE(_mesa_format_is_mesa_array_format(_mesa_format_from_format_and_type(GL_DEPTH_COMPONENT, 175 GL_BYTE))); 176} 177 178TEST_F(MesaFormatsTest, FormatMatchesFormatAndType) 179{ 180 EXPECT_TRUE(_mesa_format_matches_format_and_type(MESA_FORMAT_RGBA_UNORM16, 181 GL_RGBA, 182 GL_UNSIGNED_SHORT, false, 183 NULL)); 184 EXPECT_TRUE(_mesa_format_matches_format_and_type(MESA_FORMAT_S_UINT8, 185 GL_STENCIL_INDEX, 186 GL_UNSIGNED_BYTE, false, 187 NULL)); 188 EXPECT_TRUE(_mesa_format_matches_format_and_type(MESA_FORMAT_Z_UNORM16, 189 GL_DEPTH_COMPONENT, 190 GL_UNSIGNED_SHORT, false, 191 NULL)); 192} 193 194static uint32_t 195test_unpack_r8i(int8_t val) 196{ 197 uint32_t result[4]; 198 _mesa_unpack_uint_rgba_row(MESA_FORMAT_R_SINT8, 1, &val, &result); 199 return result[0]; 200} 201 202static uint32_t 203test_unpack_r32ui(uint32_t val) 204{ 205 uint32_t result[4]; 206 _mesa_unpack_uint_rgba_row(MESA_FORMAT_R_UINT32, 1, &val, &result); 207 return result[0]; 208} 209 210TEST_F(MesaFormatsTest, UnpackRGBAUintRow) 211{ 212 EXPECT_EQ(test_unpack_r8i(0), 0); 213 EXPECT_EQ(test_unpack_r8i(1), 1); 214 EXPECT_EQ(test_unpack_r8i(0xff), 0xffffffff); 215 EXPECT_EQ(test_unpack_r32ui(0), 0); 216 EXPECT_EQ(test_unpack_r32ui(0xffffffff), 0xffffffff); 217} 218 219TEST_F(MesaFormatsTest, UnpackRGBAUbyteRowRGBA32F) 220{ 221 float val[4] = {0, 0.5, -1, 2}; 222 uint8_t result[4]; 223 _mesa_unpack_ubyte_rgba_row(MESA_FORMAT_RGBA_FLOAT32, 1, &val, &result); 224 EXPECT_EQ(result[0], 0); 225 EXPECT_EQ(result[1], 0x80); 226 EXPECT_EQ(result[2], 0); 227 EXPECT_EQ(result[3], 0xff); 228} 229 230TEST_F(MesaFormatsTest, UnpackRGBAUbyteRowRGBA4) 231{ 232 uint16_t val = (1 << 0) | (0x3f << 5) | (0x10 << 11); 233 uint8_t result[4]; 234 _mesa_unpack_ubyte_rgba_row(MESA_FORMAT_R5G6B5_UNORM, 1, &val, &result); 235 EXPECT_EQ(result[0], 0x08); 236 EXPECT_EQ(result[1], 0xff); 237 EXPECT_EQ(result[2], 0x84); 238 EXPECT_EQ(result[3], 0xff); 239} 240 241static float 242test_unpack_floatz_z32f(float val) 243{ 244 float result; 245 _mesa_unpack_float_z_row(MESA_FORMAT_Z_FLOAT32, 1, &val, &result); 246 return result; 247} 248 249TEST_F(MesaFormatsTest, UnpackFloatZRow) 250{ 251 EXPECT_EQ(test_unpack_floatz_z32f(0.5), 0.5); 252 EXPECT_EQ(test_unpack_floatz_z32f(-1.0), -1.0); 253 EXPECT_EQ(test_unpack_floatz_z32f(2.0), 2.0); 254} 255 256static uint32_t 257test_unpack_uintz_z32f(float val) 258{ 259 uint32_t result; 260 _mesa_unpack_uint_z_row(MESA_FORMAT_Z_FLOAT32, 1, &val, &result); 261 return result; 262} 263 264TEST_F(MesaFormatsTest, UnpackUintZRow) 265{ 266 EXPECT_EQ(test_unpack_uintz_z32f(0.5), 0x7fffffff); 267 EXPECT_EQ(test_unpack_uintz_z32f(-1.0), 0); 268 EXPECT_EQ(test_unpack_uintz_z32f(2.0), 0xffffffff); 269} 270 271/* It's easy to have precision issues packing 32-bit floats to unorm. */ 272TEST_F(MesaFormatsTest, PackFloatZ) 273{ 274 float val = 0.571428597f; 275 uint32_t result; 276 _mesa_pack_float_z_row(MESA_FORMAT_Z_UNORM32, 1, &val, &result); 277 EXPECT_EQ(result, 0x924924ff); 278} 279 280TEST_F(MesaFormatsTest, PackUbyteRGBARounding) 281{ 282 for (int i = 0; i <= 255; i++) { 283 uint8_t val[4] = {(uint8_t)i, 0, 0, 0}; 284 uint16_t result; 285 _mesa_pack_ubyte_rgba_row(MESA_FORMAT_R5G6B5_UNORM, 1, val, &result); 286 EXPECT_EQ(result, (i * 31 + 127) / 255); 287 } 288} 289