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