u_format.h revision 2a090ae80a597f498f113fe58a772ddf3dca12e0
1/************************************************************************** 2 * 3 * Copyright 2009-2010 Vmware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29#ifndef U_FORMAT_H 30#define U_FORMAT_H 31 32 33#include "pipe/p_format.h" 34#include "util/u_debug.h" 35#include "util/u_format_s3tc.h" 36 37#ifdef __cplusplus 38extern "C" { 39#endif 40 41 42/** 43 * Describe how to pack/unpack pixels into/from the prescribed format. 44 * 45 * XXX: This could be renamed to something like util_format_pack, or broke down 46 * in flags inside util_format_block that said exactly what we want. 47 */ 48enum util_format_layout { 49 /** 50 * Formats with util_format_block::width == util_format_block::height == 1 51 * that can be described as an ordinary data structure. 52 */ 53 UTIL_FORMAT_LAYOUT_PLAIN = 0, 54 55 /** 56 * Formats with sub-sampled channels. 57 * 58 * This is for formats like YV12 where there is less than one sample per 59 * pixel. 60 */ 61 UTIL_FORMAT_LAYOUT_SUBSAMPLED = 3, 62 63 /** 64 * S3 Texture Compression formats. 65 */ 66 UTIL_FORMAT_LAYOUT_S3TC = 4, 67 68 /** 69 * Red-Green Texture Compression formats. 70 */ 71 UTIL_FORMAT_LAYOUT_RGTC = 5, 72 73 /** 74 * Everything else that doesn't fit in any of the above layouts. 75 */ 76 UTIL_FORMAT_LAYOUT_OTHER = 6 77}; 78 79 80struct util_format_block 81{ 82 /** Block width in pixels */ 83 unsigned width; 84 85 /** Block height in pixels */ 86 unsigned height; 87 88 /** Block size in bits */ 89 unsigned bits; 90}; 91 92 93enum util_format_type { 94 UTIL_FORMAT_TYPE_VOID = 0, 95 UTIL_FORMAT_TYPE_UNSIGNED = 1, 96 UTIL_FORMAT_TYPE_SIGNED = 2, 97 UTIL_FORMAT_TYPE_FIXED = 3, 98 UTIL_FORMAT_TYPE_FLOAT = 4 99}; 100 101 102enum util_format_swizzle { 103 UTIL_FORMAT_SWIZZLE_X = 0, 104 UTIL_FORMAT_SWIZZLE_Y = 1, 105 UTIL_FORMAT_SWIZZLE_Z = 2, 106 UTIL_FORMAT_SWIZZLE_W = 3, 107 UTIL_FORMAT_SWIZZLE_0 = 4, 108 UTIL_FORMAT_SWIZZLE_1 = 5, 109 UTIL_FORMAT_SWIZZLE_NONE = 6 110}; 111 112 113enum util_format_colorspace { 114 UTIL_FORMAT_COLORSPACE_RGB = 0, 115 UTIL_FORMAT_COLORSPACE_SRGB = 1, 116 UTIL_FORMAT_COLORSPACE_YUV = 2, 117 UTIL_FORMAT_COLORSPACE_ZS = 3 118}; 119 120 121struct util_format_channel_description 122{ 123 unsigned type:6; 124 unsigned normalized:1; 125 unsigned size:9; 126}; 127 128 129struct util_format_description 130{ 131 enum pipe_format format; 132 133 const char *name; 134 135 /** 136 * Short name, striped of the prefix, lower case. 137 */ 138 const char *short_name; 139 140 /** 141 * Pixel block dimensions. 142 */ 143 struct util_format_block block; 144 145 enum util_format_layout layout; 146 147 /** 148 * The number of channels. 149 */ 150 unsigned nr_channels:3; 151 152 /** 153 * Whether all channels have the same number of (whole) bytes. 154 */ 155 unsigned is_array:1; 156 157 /** 158 * Whether the pixel format can be described as a bitfield structure. 159 * 160 * In particular: 161 * - pixel depth must be 8, 16, or 32 bits; 162 * - all channels must be unsigned, signed, or void 163 */ 164 unsigned is_bitmask:1; 165 166 /** 167 * Whether channels have mixed types (ignoring UTIL_FORMAT_TYPE_VOID). 168 */ 169 unsigned is_mixed:1; 170 171 /** 172 * Whether the pack/unpack functions actually work. 173 * 174 * Call util_format_is_supported instead of using this directly. 175 */ 176 unsigned is_supported:1; 177 178 /** 179 * Input channel description. 180 * 181 * Only valid for UTIL_FORMAT_LAYOUT_PLAIN formats. 182 */ 183 struct util_format_channel_description channel[4]; 184 185 /** 186 * Output channel swizzle. 187 * 188 * The order is either: 189 * - RGBA 190 * - YUV(A) 191 * - ZS 192 * depending on the colorspace. 193 */ 194 unsigned char swizzle[4]; 195 196 /** 197 * Colorspace transformation. 198 */ 199 enum util_format_colorspace colorspace; 200 201 /** 202 * Unpack pixel blocks to R8G8B8A8_UNORM. 203 */ 204 void 205 (*unpack_8unorm)(uint8_t *dst, unsigned dst_stride, 206 const uint8_t *src, unsigned src_stride, 207 unsigned width, unsigned height); 208 209 /** 210 * Pack pixel blocks from R8G8B8A8_UNORM. 211 */ 212 void 213 (*pack_8unorm)(uint8_t *dst, unsigned dst_stride, 214 const uint8_t *src, unsigned src_stride, 215 unsigned width, unsigned height); 216 217 /** 218 * Unpack pixel blocks to R32G32B32A32_FLOAT. 219 */ 220 void 221 (*unpack_float)(float *dst, unsigned dst_stride, 222 const uint8_t *src, unsigned src_stride, 223 unsigned width, unsigned height); 224 225 /** 226 * Pack pixel blocks from R32G32B32A32_FLOAT. 227 */ 228 void 229 (*pack_float)(uint8_t *dst, unsigned dst_stride, 230 const float *src, unsigned src_stride, 231 unsigned width, unsigned height); 232 233 /** 234 * Fetch a single pixel (i, j) from a block. 235 */ 236 void 237 (*fetch_float)(float *dst, 238 const uint8_t *src, 239 unsigned i, unsigned j); 240}; 241 242 243extern const struct util_format_description 244util_format_description_table[]; 245 246 247const struct util_format_description * 248util_format_description(enum pipe_format format); 249 250 251/* 252 * Format query functions. 253 */ 254 255static INLINE const char * 256util_format_name(enum pipe_format format) 257{ 258 const struct util_format_description *desc = util_format_description(format); 259 260 assert(desc); 261 if (!desc) { 262 return "???"; 263 } 264 265 return desc->name; 266} 267 268static INLINE boolean 269util_format_is_s3tc(enum pipe_format format) 270{ 271 const struct util_format_description *desc = util_format_description(format); 272 273 assert(desc); 274 if (!desc) { 275 return FALSE; 276 } 277 278 return desc->layout == UTIL_FORMAT_LAYOUT_S3TC ? TRUE : FALSE; 279} 280 281static INLINE boolean 282util_format_is_depth_or_stencil(enum pipe_format format) 283{ 284 const struct util_format_description *desc = util_format_description(format); 285 286 assert(desc); 287 if (!desc) { 288 return FALSE; 289 } 290 291 return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ? TRUE : FALSE; 292} 293 294static INLINE boolean 295util_format_is_depth_and_stencil(enum pipe_format format) 296{ 297 const struct util_format_description *desc = util_format_description(format); 298 299 assert(desc); 300 if (!desc) { 301 return FALSE; 302 } 303 304 if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) { 305 return FALSE; 306 } 307 308 return (desc->swizzle[0] != UTIL_FORMAT_SWIZZLE_NONE && 309 desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE) ? TRUE : FALSE; 310} 311 312/** 313 * Whether this format is a rgab8 variant. 314 * 315 * That is, any format that matches the 316 * 317 * PIPE_FORMAT_?8?8?8?8_UNORM 318 */ 319static INLINE boolean 320util_format_is_rgba8_variant(const struct util_format_description *desc) 321{ 322 unsigned chan; 323 324 if(desc->block.width != 1 || 325 desc->block.height != 1 || 326 desc->block.bits != 32) 327 return FALSE; 328 329 for(chan = 0; chan < 4; ++chan) { 330 if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED && 331 desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID) 332 return FALSE; 333 if(desc->channel[chan].size != 8) 334 return FALSE; 335 } 336 337 return TRUE; 338} 339 340 341/** 342 * Return total bits needed for the pixel format per block. 343 */ 344static INLINE uint 345util_format_get_blocksizebits(enum pipe_format format) 346{ 347 const struct util_format_description *desc = util_format_description(format); 348 349 assert(desc); 350 if (!desc) { 351 return 0; 352 } 353 354 return desc->block.bits; 355} 356 357/** 358 * Return bytes per block (not pixel) for the given format. 359 */ 360static INLINE uint 361util_format_get_blocksize(enum pipe_format format) 362{ 363 uint bits = util_format_get_blocksizebits(format); 364 365 assert(bits % 8 == 0); 366 367 return bits / 8; 368} 369 370static INLINE uint 371util_format_get_blockwidth(enum pipe_format format) 372{ 373 const struct util_format_description *desc = util_format_description(format); 374 375 assert(desc); 376 if (!desc) { 377 return 1; 378 } 379 380 return desc->block.width; 381} 382 383static INLINE uint 384util_format_get_blockheight(enum pipe_format format) 385{ 386 const struct util_format_description *desc = util_format_description(format); 387 388 assert(desc); 389 if (!desc) { 390 return 1; 391 } 392 393 return desc->block.height; 394} 395 396static INLINE unsigned 397util_format_get_nblocksx(enum pipe_format format, 398 unsigned x) 399{ 400 unsigned blockwidth = util_format_get_blockwidth(format); 401 return (x + blockwidth - 1) / blockwidth; 402} 403 404static INLINE unsigned 405util_format_get_nblocksy(enum pipe_format format, 406 unsigned y) 407{ 408 unsigned blockheight = util_format_get_blockheight(format); 409 return (y + blockheight - 1) / blockheight; 410} 411 412static INLINE unsigned 413util_format_get_nblocks(enum pipe_format format, 414 unsigned width, 415 unsigned height) 416{ 417 return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height); 418} 419 420static INLINE size_t 421util_format_get_stride(enum pipe_format format, 422 unsigned width) 423{ 424 return util_format_get_nblocksx(format, width) * util_format_get_blocksize(format); 425} 426 427static INLINE size_t 428util_format_get_2d_size(enum pipe_format format, 429 size_t stride, 430 unsigned height) 431{ 432 return util_format_get_nblocksy(format, height) * stride; 433} 434 435static INLINE uint 436util_format_get_component_bits(enum pipe_format format, 437 enum util_format_colorspace colorspace, 438 uint component) 439{ 440 const struct util_format_description *desc = util_format_description(format); 441 enum util_format_colorspace desc_colorspace; 442 443 assert(format); 444 if (!format) { 445 return 0; 446 } 447 448 assert(component < 4); 449 450 /* Treat RGB and SRGB as equivalent. */ 451 if (colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { 452 colorspace = UTIL_FORMAT_COLORSPACE_RGB; 453 } 454 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { 455 desc_colorspace = UTIL_FORMAT_COLORSPACE_RGB; 456 } else { 457 desc_colorspace = desc->colorspace; 458 } 459 460 if (desc_colorspace != colorspace) { 461 return 0; 462 } 463 464 switch (desc->swizzle[component]) { 465 case UTIL_FORMAT_SWIZZLE_X: 466 return desc->channel[0].size; 467 case UTIL_FORMAT_SWIZZLE_Y: 468 return desc->channel[1].size; 469 case UTIL_FORMAT_SWIZZLE_Z: 470 return desc->channel[2].size; 471 case UTIL_FORMAT_SWIZZLE_W: 472 return desc->channel[3].size; 473 default: 474 return 0; 475 } 476} 477 478static INLINE boolean 479util_format_has_alpha(enum pipe_format format) 480{ 481 const struct util_format_description *desc = util_format_description(format); 482 483 assert(format); 484 if (!format) { 485 return FALSE; 486 } 487 488 switch (desc->colorspace) { 489 case UTIL_FORMAT_COLORSPACE_RGB: 490 case UTIL_FORMAT_COLORSPACE_SRGB: 491 return desc->swizzle[3] != UTIL_FORMAT_SWIZZLE_1; 492 case UTIL_FORMAT_COLORSPACE_YUV: 493 return FALSE; 494 case UTIL_FORMAT_COLORSPACE_ZS: 495 return FALSE; 496 default: 497 assert(0); 498 return FALSE; 499 } 500} 501 502/** 503 * Return the number of components stored. 504 * Formats with block size != 1x1 will always have 1 component (the block). 505 */ 506static INLINE unsigned 507util_format_get_nr_components(enum pipe_format format) 508{ 509 const struct util_format_description *desc = util_format_description(format); 510 return desc->nr_channels; 511} 512 513/* 514 * Format access functions. 515 */ 516 517static INLINE boolean 518util_format_is_supported(enum pipe_format format) 519{ 520 const struct util_format_description *desc = util_format_description(format); 521 522 if(!desc) 523 return FALSE; 524 525 if(desc->layout == UTIL_FORMAT_LAYOUT_S3TC) 526 util_format_s3tc_init(); 527 528 return desc->is_supported; 529} 530 531void 532util_format_read_4f(enum pipe_format format, 533 float *dst, unsigned dst_stride, 534 const void *src, unsigned src_stride, 535 unsigned x, unsigned y, unsigned w, unsigned h); 536 537void 538util_format_write_4f(enum pipe_format format, 539 const float *src, unsigned src_stride, 540 void *dst, unsigned dst_stride, 541 unsigned x, unsigned y, unsigned w, unsigned h); 542 543void 544util_format_read_4ub(enum pipe_format format, 545 uint8_t *dst, unsigned dst_stride, 546 const void *src, unsigned src_stride, 547 unsigned x, unsigned y, unsigned w, unsigned h); 548 549void 550util_format_write_4ub(enum pipe_format format, 551 const uint8_t *src, unsigned src_stride, 552 void *dst, unsigned dst_stride, 553 unsigned x, unsigned y, unsigned w, unsigned h); 554 555#ifdef __cplusplus 556} // extern "C" { 557#endif 558 559#endif /* ! U_FORMAT_H */ 560