u_format.h revision 329814c6ee8a87d67a55ecf197af9d6e6fb7ade0
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 a span of pixel blocks to R8G8B8A8_UNORM. 195 */ 196 void 197 (*unpack_8unorm)(uint8_t *dst, const uint8_t *src, unsigned nr_blocks); 198 199 /** 200 * Pack a span of pixel blocks from R8G8B8A8_UNORM. 201 */ 202 void 203 (*pack_8unorm)(uint8_t *dst, const uint8_t *src, unsigned nr_blocks); 204 205 /** 206 * Unpack a span of pixel blocks to R32G32B32A32_FLOAT. 207 */ 208 void 209 (*unpack_float)(float *dst, const uint8_t *src, unsigned nr_blocks); 210 211 /** 212 * Pack a span of pixel blocks from R32G32B32A32_FLOAT. 213 */ 214 void 215 (*pack_float)(uint8_t *dst, const float *src, unsigned nr_blocks); 216 217 /** 218 * Fetch a single pixel (i, j) from a block. 219 */ 220 void 221 (*fetch_float)(float *dst, const uint8_t *src, unsigned i, unsigned j); 222}; 223 224 225extern const struct util_format_description 226util_format_description_table[]; 227 228 229const struct util_format_description * 230util_format_description(enum pipe_format format); 231 232 233/* 234 * Format query functions. 235 */ 236 237static INLINE const char * 238util_format_name(enum pipe_format format) 239{ 240 const struct util_format_description *desc = util_format_description(format); 241 242 assert(desc); 243 if (!desc) { 244 return "???"; 245 } 246 247 return desc->name; 248} 249 250static INLINE boolean 251util_format_is_s3tc(enum pipe_format format) 252{ 253 const struct util_format_description *desc = util_format_description(format); 254 255 assert(desc); 256 if (!desc) { 257 return FALSE; 258 } 259 260 return desc->layout == UTIL_FORMAT_LAYOUT_S3TC ? TRUE : FALSE; 261} 262 263static INLINE boolean 264util_format_is_depth_or_stencil(enum pipe_format format) 265{ 266 const struct util_format_description *desc = util_format_description(format); 267 268 assert(desc); 269 if (!desc) { 270 return FALSE; 271 } 272 273 return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ? TRUE : FALSE; 274} 275 276static INLINE boolean 277util_format_is_depth_and_stencil(enum pipe_format format) 278{ 279 const struct util_format_description *desc = util_format_description(format); 280 281 assert(desc); 282 if (!desc) { 283 return FALSE; 284 } 285 286 if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) { 287 return FALSE; 288 } 289 290 return (desc->swizzle[0] != UTIL_FORMAT_SWIZZLE_NONE && 291 desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE) ? TRUE : FALSE; 292} 293 294/** 295 * Whether this format is a rgab8 variant. 296 * 297 * That is, any format that matches the 298 * 299 * PIPE_FORMAT_?8?8?8?8_UNORM 300 */ 301static INLINE boolean 302util_format_is_rgba8_variant(const struct util_format_description *desc) 303{ 304 unsigned chan; 305 306 if(desc->block.width != 1 || 307 desc->block.height != 1 || 308 desc->block.bits != 32) 309 return FALSE; 310 311 for(chan = 0; chan < 4; ++chan) { 312 if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED && 313 desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID) 314 return FALSE; 315 if(desc->channel[chan].size != 8) 316 return FALSE; 317 } 318 319 return TRUE; 320} 321 322 323/** 324 * Return total bits needed for the pixel format per block. 325 */ 326static INLINE uint 327util_format_get_blocksizebits(enum pipe_format format) 328{ 329 const struct util_format_description *desc = util_format_description(format); 330 331 assert(desc); 332 if (!desc) { 333 return 0; 334 } 335 336 return desc->block.bits; 337} 338 339/** 340 * Return bytes per block (not pixel) for the given format. 341 */ 342static INLINE uint 343util_format_get_blocksize(enum pipe_format format) 344{ 345 uint bits = util_format_get_blocksizebits(format); 346 347 assert(bits % 8 == 0); 348 349 return bits / 8; 350} 351 352static INLINE uint 353util_format_get_blockwidth(enum pipe_format format) 354{ 355 const struct util_format_description *desc = util_format_description(format); 356 357 assert(desc); 358 if (!desc) { 359 return 1; 360 } 361 362 return desc->block.width; 363} 364 365static INLINE uint 366util_format_get_blockheight(enum pipe_format format) 367{ 368 const struct util_format_description *desc = util_format_description(format); 369 370 assert(desc); 371 if (!desc) { 372 return 1; 373 } 374 375 return desc->block.height; 376} 377 378static INLINE unsigned 379util_format_get_nblocksx(enum pipe_format format, 380 unsigned x) 381{ 382 unsigned blockwidth = util_format_get_blockwidth(format); 383 return (x + blockwidth - 1) / blockwidth; 384} 385 386static INLINE unsigned 387util_format_get_nblocksy(enum pipe_format format, 388 unsigned y) 389{ 390 unsigned blockheight = util_format_get_blockheight(format); 391 return (y + blockheight - 1) / blockheight; 392} 393 394static INLINE unsigned 395util_format_get_nblocks(enum pipe_format format, 396 unsigned width, 397 unsigned height) 398{ 399 return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height); 400} 401 402static INLINE size_t 403util_format_get_stride(enum pipe_format format, 404 unsigned width) 405{ 406 return util_format_get_nblocksx(format, width) * util_format_get_blocksize(format); 407} 408 409static INLINE size_t 410util_format_get_2d_size(enum pipe_format format, 411 size_t stride, 412 unsigned height) 413{ 414 return util_format_get_nblocksy(format, height) * stride; 415} 416 417static INLINE uint 418util_format_get_component_bits(enum pipe_format format, 419 enum util_format_colorspace colorspace, 420 uint component) 421{ 422 const struct util_format_description *desc = util_format_description(format); 423 enum util_format_colorspace desc_colorspace; 424 425 assert(format); 426 if (!format) { 427 return 0; 428 } 429 430 assert(component < 4); 431 432 /* Treat RGB and SRGB as equivalent. */ 433 if (colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { 434 colorspace = UTIL_FORMAT_COLORSPACE_RGB; 435 } 436 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { 437 desc_colorspace = UTIL_FORMAT_COLORSPACE_RGB; 438 } else { 439 desc_colorspace = desc->colorspace; 440 } 441 442 if (desc_colorspace != colorspace) { 443 return 0; 444 } 445 446 switch (desc->swizzle[component]) { 447 case UTIL_FORMAT_SWIZZLE_X: 448 return desc->channel[0].size; 449 case UTIL_FORMAT_SWIZZLE_Y: 450 return desc->channel[1].size; 451 case UTIL_FORMAT_SWIZZLE_Z: 452 return desc->channel[2].size; 453 case UTIL_FORMAT_SWIZZLE_W: 454 return desc->channel[3].size; 455 default: 456 return 0; 457 } 458} 459 460static INLINE boolean 461util_format_has_alpha(enum pipe_format format) 462{ 463 const struct util_format_description *desc = util_format_description(format); 464 465 assert(format); 466 if (!format) { 467 return FALSE; 468 } 469 470 switch (desc->colorspace) { 471 case UTIL_FORMAT_COLORSPACE_RGB: 472 case UTIL_FORMAT_COLORSPACE_SRGB: 473 return desc->swizzle[3] != UTIL_FORMAT_SWIZZLE_1; 474 case UTIL_FORMAT_COLORSPACE_YUV: 475 return FALSE; 476 case UTIL_FORMAT_COLORSPACE_ZS: 477 return FALSE; 478 default: 479 assert(0); 480 return FALSE; 481 } 482} 483 484/** 485 * Return the number of components stored. 486 * Formats with block size != 1x1 will always have 1 component (the block). 487 */ 488static INLINE unsigned 489util_format_get_nr_components(enum pipe_format format) 490{ 491 const struct util_format_description *desc = util_format_description(format); 492 return desc->nr_channels; 493} 494 495/* 496 * Format access functions. 497 */ 498 499void 500util_format_read_4f(enum pipe_format format, 501 float *dst, unsigned dst_stride, 502 const void *src, unsigned src_stride, 503 unsigned x, unsigned y, unsigned w, unsigned h); 504 505void 506util_format_write_4f(enum pipe_format format, 507 const float *src, unsigned src_stride, 508 void *dst, unsigned dst_stride, 509 unsigned x, unsigned y, unsigned w, unsigned h); 510 511void 512util_format_read_4ub(enum pipe_format format, 513 uint8_t *dst, unsigned dst_stride, 514 const void *src, unsigned src_stride, 515 unsigned x, unsigned y, unsigned w, unsigned h); 516 517void 518util_format_write_4ub(enum pipe_format format, 519 const uint8_t *src, unsigned src_stride, 520 void *dst, unsigned dst_stride, 521 unsigned x, unsigned y, unsigned w, unsigned h); 522 523#ifdef __cplusplus 524} // extern "C" { 525#endif 526 527#endif /* ! U_FORMAT_H */ 528