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