1 /************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 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 TUNGSTEN GRAPHICS 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 * @file 30 * Functions to produce packed colors/Z from floats. 31 */ 32 33 34 #ifndef U_PACK_COLOR_H 35 #define U_PACK_COLOR_H 36 37 38 #include "pipe/p_compiler.h" 39 #include "pipe/p_format.h" 40 #include "util/u_debug.h" 41 #include "util/u_format.h" 42 #include "util/u_math.h" 43 44 45 /** 46 * Helper union for packing pixel values. 47 * Will often contain values in formats which are too complex to be described 48 * in simple terms, hence might just effectively contain a number of bytes. 49 * Must be big enough to hold data for all formats (currently 256 bits). 50 */ 51 union util_color { 52 ubyte ub; 53 ushort us; 54 uint ui; 55 float f[4]; 56 double d[4]; 57 }; 58 59 /** 60 * Pack ubyte R,G,B,A into dest pixel. 61 */ 62 static INLINE void 63 util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, 64 enum pipe_format format, union util_color *uc) 65 { 66 switch (format) { 67 case PIPE_FORMAT_A8B8G8R8_UNORM: 68 { 69 uc->ui = (r << 24) | (g << 16) | (b << 8) | a; 70 } 71 return; 72 case PIPE_FORMAT_X8B8G8R8_UNORM: 73 { 74 uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; 75 } 76 return; 77 case PIPE_FORMAT_B8G8R8A8_UNORM: 78 { 79 uc->ui = (a << 24) | (r << 16) | (g << 8) | b; 80 } 81 return; 82 case PIPE_FORMAT_B8G8R8X8_UNORM: 83 { 84 uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; 85 } 86 return; 87 case PIPE_FORMAT_A8R8G8B8_UNORM: 88 { 89 uc->ui = (b << 24) | (g << 16) | (r << 8) | a; 90 } 91 return; 92 case PIPE_FORMAT_X8R8G8B8_UNORM: 93 { 94 uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; 95 } 96 return; 97 case PIPE_FORMAT_B5G6R5_UNORM: 98 { 99 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); 100 } 101 return; 102 case PIPE_FORMAT_B5G5R5X1_UNORM: 103 { 104 uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); 105 } 106 return; 107 case PIPE_FORMAT_B5G5R5A1_UNORM: 108 { 109 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); 110 } 111 return; 112 case PIPE_FORMAT_B4G4R4A4_UNORM: 113 { 114 uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); 115 } 116 return; 117 case PIPE_FORMAT_A8_UNORM: 118 { 119 uc->ub = a; 120 } 121 return; 122 case PIPE_FORMAT_L8_UNORM: 123 case PIPE_FORMAT_I8_UNORM: 124 { 125 uc->ub = r; 126 } 127 return; 128 case PIPE_FORMAT_R32G32B32A32_FLOAT: 129 { 130 uc->f[0] = (float)r / 255.0f; 131 uc->f[1] = (float)g / 255.0f; 132 uc->f[2] = (float)b / 255.0f; 133 uc->f[3] = (float)a / 255.0f; 134 } 135 return; 136 case PIPE_FORMAT_R32G32B32_FLOAT: 137 { 138 uc->f[0] = (float)r / 255.0f; 139 uc->f[1] = (float)g / 255.0f; 140 uc->f[2] = (float)b / 255.0f; 141 } 142 return; 143 144 /* Handle other cases with a generic function. 145 */ 146 default: 147 { 148 ubyte src[4]; 149 150 src[0] = r; 151 src[1] = g; 152 src[2] = b; 153 src[3] = a; 154 util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1); 155 } 156 } 157 } 158 159 160 /** 161 * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255]. 162 */ 163 static INLINE void 164 util_unpack_color_ub(enum pipe_format format, union util_color *uc, 165 ubyte *r, ubyte *g, ubyte *b, ubyte *a) 166 { 167 switch (format) { 168 case PIPE_FORMAT_A8B8G8R8_UNORM: 169 { 170 uint p = uc->ui; 171 *r = (ubyte) ((p >> 24) & 0xff); 172 *g = (ubyte) ((p >> 16) & 0xff); 173 *b = (ubyte) ((p >> 8) & 0xff); 174 *a = (ubyte) ((p >> 0) & 0xff); 175 } 176 return; 177 case PIPE_FORMAT_X8B8G8R8_UNORM: 178 { 179 uint p = uc->ui; 180 *r = (ubyte) ((p >> 24) & 0xff); 181 *g = (ubyte) ((p >> 16) & 0xff); 182 *b = (ubyte) ((p >> 8) & 0xff); 183 *a = (ubyte) 0xff; 184 } 185 return; 186 case PIPE_FORMAT_B8G8R8A8_UNORM: 187 { 188 uint p = uc->ui; 189 *r = (ubyte) ((p >> 16) & 0xff); 190 *g = (ubyte) ((p >> 8) & 0xff); 191 *b = (ubyte) ((p >> 0) & 0xff); 192 *a = (ubyte) ((p >> 24) & 0xff); 193 } 194 return; 195 case PIPE_FORMAT_B8G8R8X8_UNORM: 196 { 197 uint p = uc->ui; 198 *r = (ubyte) ((p >> 16) & 0xff); 199 *g = (ubyte) ((p >> 8) & 0xff); 200 *b = (ubyte) ((p >> 0) & 0xff); 201 *a = (ubyte) 0xff; 202 } 203 return; 204 case PIPE_FORMAT_A8R8G8B8_UNORM: 205 { 206 uint p = uc->ui; 207 *r = (ubyte) ((p >> 8) & 0xff); 208 *g = (ubyte) ((p >> 16) & 0xff); 209 *b = (ubyte) ((p >> 24) & 0xff); 210 *a = (ubyte) ((p >> 0) & 0xff); 211 } 212 return; 213 case PIPE_FORMAT_X8R8G8B8_UNORM: 214 { 215 uint p = uc->ui; 216 *r = (ubyte) ((p >> 8) & 0xff); 217 *g = (ubyte) ((p >> 16) & 0xff); 218 *b = (ubyte) ((p >> 24) & 0xff); 219 *a = (ubyte) 0xff; 220 } 221 return; 222 case PIPE_FORMAT_B5G6R5_UNORM: 223 { 224 ushort p = uc->us; 225 *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7)); 226 *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3)); 227 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); 228 *a = (ubyte) 0xff; 229 } 230 return; 231 case PIPE_FORMAT_B5G5R5X1_UNORM: 232 { 233 ushort p = uc->us; 234 *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); 235 *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); 236 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); 237 *a = (ubyte) 0xff; 238 } 239 return; 240 case PIPE_FORMAT_B5G5R5A1_UNORM: 241 { 242 ushort p = uc->us; 243 *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); 244 *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); 245 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); 246 *a = (ubyte) (0xff * (p >> 15)); 247 } 248 return; 249 case PIPE_FORMAT_B4G4R4A4_UNORM: 250 { 251 ushort p = uc->us; 252 *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf)); 253 *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf)); 254 *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf)); 255 *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf)); 256 } 257 return; 258 case PIPE_FORMAT_A8_UNORM: 259 { 260 ubyte p = uc->ub; 261 *r = *g = *b = (ubyte) 0xff; 262 *a = p; 263 } 264 return; 265 case PIPE_FORMAT_L8_UNORM: 266 { 267 ubyte p = uc->ub; 268 *r = *g = *b = p; 269 *a = (ubyte) 0xff; 270 } 271 return; 272 case PIPE_FORMAT_I8_UNORM: 273 { 274 ubyte p = uc->ub; 275 *r = *g = *b = *a = p; 276 } 277 return; 278 case PIPE_FORMAT_R32G32B32A32_FLOAT: 279 { 280 const float *p = &uc->f[0]; 281 *r = float_to_ubyte(p[0]); 282 *g = float_to_ubyte(p[1]); 283 *b = float_to_ubyte(p[2]); 284 *a = float_to_ubyte(p[3]); 285 } 286 return; 287 case PIPE_FORMAT_R32G32B32_FLOAT: 288 { 289 const float *p = &uc->f[0]; 290 *r = float_to_ubyte(p[0]); 291 *g = float_to_ubyte(p[1]); 292 *b = float_to_ubyte(p[2]); 293 *a = (ubyte) 0xff; 294 } 295 return; 296 297 case PIPE_FORMAT_R32G32_FLOAT: 298 { 299 const float *p = &uc->f[0]; 300 *r = float_to_ubyte(p[0]); 301 *g = float_to_ubyte(p[1]); 302 *b = *a = (ubyte) 0xff; 303 } 304 return; 305 306 case PIPE_FORMAT_R32_FLOAT: 307 { 308 const float *p = &uc->f[0]; 309 *r = float_to_ubyte(p[0]); 310 *g = *b = *a = (ubyte) 0xff; 311 } 312 return; 313 314 /* Handle other cases with a generic function. 315 */ 316 default: 317 { 318 ubyte dst[4]; 319 320 util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1); 321 *r = dst[0]; 322 *g = dst[1]; 323 *b = dst[2]; 324 *a = dst[3]; 325 } 326 } 327 } 328 329 330 /** 331 * Note rgba outside [0,1] will be clamped for int pixel formats. 332 */ 333 static INLINE void 334 util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc) 335 { 336 ubyte r = 0; 337 ubyte g = 0; 338 ubyte b = 0; 339 ubyte a = 0; 340 341 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) { 342 /* format uses 8-bit components or less */ 343 r = float_to_ubyte(rgba[0]); 344 g = float_to_ubyte(rgba[1]); 345 b = float_to_ubyte(rgba[2]); 346 a = float_to_ubyte(rgba[3]); 347 } 348 349 switch (format) { 350 case PIPE_FORMAT_A8B8G8R8_UNORM: 351 { 352 uc->ui = (r << 24) | (g << 16) | (b << 8) | a; 353 } 354 return; 355 case PIPE_FORMAT_X8B8G8R8_UNORM: 356 { 357 uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; 358 } 359 return; 360 case PIPE_FORMAT_B8G8R8A8_UNORM: 361 { 362 uc->ui = (a << 24) | (r << 16) | (g << 8) | b; 363 } 364 return; 365 case PIPE_FORMAT_B8G8R8X8_UNORM: 366 { 367 uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; 368 } 369 return; 370 case PIPE_FORMAT_A8R8G8B8_UNORM: 371 { 372 uc->ui = (b << 24) | (g << 16) | (r << 8) | a; 373 } 374 return; 375 case PIPE_FORMAT_X8R8G8B8_UNORM: 376 { 377 uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; 378 } 379 return; 380 case PIPE_FORMAT_B5G6R5_UNORM: 381 { 382 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); 383 } 384 return; 385 case PIPE_FORMAT_B5G5R5X1_UNORM: 386 { 387 uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); 388 } 389 return; 390 case PIPE_FORMAT_B5G5R5A1_UNORM: 391 { 392 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); 393 } 394 return; 395 case PIPE_FORMAT_B4G4R4A4_UNORM: 396 { 397 uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); 398 } 399 return; 400 case PIPE_FORMAT_A8_UNORM: 401 { 402 uc->ub = a; 403 } 404 return; 405 case PIPE_FORMAT_L8_UNORM: 406 case PIPE_FORMAT_I8_UNORM: 407 { 408 uc->ub = r; 409 } 410 return; 411 case PIPE_FORMAT_R32G32B32A32_FLOAT: 412 { 413 uc->f[0] = rgba[0]; 414 uc->f[1] = rgba[1]; 415 uc->f[2] = rgba[2]; 416 uc->f[3] = rgba[3]; 417 } 418 return; 419 case PIPE_FORMAT_R32G32B32_FLOAT: 420 { 421 uc->f[0] = rgba[0]; 422 uc->f[1] = rgba[1]; 423 uc->f[2] = rgba[2]; 424 } 425 return; 426 427 /* Handle other cases with a generic function. 428 */ 429 default: 430 util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1); 431 } 432 } 433 434 /* Integer versions of util_pack_z and util_pack_z_stencil - useful for 435 * constructing clear masks. 436 */ 437 static INLINE uint32_t 438 util_pack_mask_z(enum pipe_format format, uint32_t z) 439 { 440 switch (format) { 441 case PIPE_FORMAT_Z16_UNORM: 442 return z & 0xffff; 443 case PIPE_FORMAT_Z32_UNORM: 444 case PIPE_FORMAT_Z32_FLOAT: 445 return z; 446 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 447 case PIPE_FORMAT_Z24X8_UNORM: 448 return z & 0xffffff; 449 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 450 case PIPE_FORMAT_X8Z24_UNORM: 451 return (z & 0xffffff) << 8; 452 case PIPE_FORMAT_S8_UINT: 453 return 0; 454 default: 455 debug_print_format("gallium: unhandled format in util_pack_mask_z()", format); 456 assert(0); 457 return 0; 458 } 459 } 460 461 462 static INLINE uint64_t 463 util_pack64_mask_z(enum pipe_format format, uint32_t z) 464 { 465 switch (format) { 466 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 467 return z; 468 default: 469 return util_pack_mask_z(format, z); 470 } 471 } 472 473 474 static INLINE uint32_t 475 util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) 476 { 477 uint32_t packed = util_pack_mask_z(format, z); 478 479 switch (format) { 480 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 481 packed |= (uint32_t)s << 24; 482 break; 483 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 484 packed |= s; 485 break; 486 case PIPE_FORMAT_S8_UINT: 487 packed |= s; 488 break; 489 default: 490 break; 491 } 492 493 return packed; 494 } 495 496 497 static INLINE uint64_t 498 util_pack64_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) 499 { 500 uint64_t packed; 501 502 switch (format) { 503 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 504 packed = util_pack64_mask_z(format, z); 505 packed |= (uint64_t)s << 32ull; 506 return packed; 507 default: 508 return util_pack_mask_z_stencil(format, z, s); 509 } 510 } 511 512 513 /** 514 * Note: it's assumed that z is in [0,1] 515 */ 516 static INLINE uint32_t 517 util_pack_z(enum pipe_format format, double z) 518 { 519 union fi fui; 520 521 if (z == 0.0) 522 return 0; 523 524 switch (format) { 525 case PIPE_FORMAT_Z16_UNORM: 526 if (z == 1.0) 527 return 0xffff; 528 return (uint32_t) (z * 0xffff); 529 case PIPE_FORMAT_Z32_UNORM: 530 /* special-case to avoid overflow */ 531 if (z == 1.0) 532 return 0xffffffff; 533 return (uint32_t) (z * 0xffffffff); 534 case PIPE_FORMAT_Z32_FLOAT: 535 fui.f = (float)z; 536 return fui.ui; 537 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 538 case PIPE_FORMAT_Z24X8_UNORM: 539 if (z == 1.0) 540 return 0xffffff; 541 return (uint32_t) (z * 0xffffff); 542 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 543 case PIPE_FORMAT_X8Z24_UNORM: 544 if (z == 1.0) 545 return 0xffffff00; 546 return ((uint32_t) (z * 0xffffff)) << 8; 547 case PIPE_FORMAT_S8_UINT: 548 /* this case can get it via util_pack_z_stencil() */ 549 return 0; 550 default: 551 debug_print_format("gallium: unhandled format in util_pack_z()", format); 552 assert(0); 553 return 0; 554 } 555 } 556 557 558 static INLINE uint64_t 559 util_pack64_z(enum pipe_format format, double z) 560 { 561 union fi fui; 562 563 if (z == 0) 564 return 0; 565 566 switch (format) { 567 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 568 fui.f = (float)z; 569 return fui.ui; 570 default: 571 return util_pack_z(format, z); 572 } 573 } 574 575 576 /** 577 * Pack Z and/or stencil values into a 32-bit value described by format. 578 * Note: it's assumed that z is in [0,1] and s in [0,255] 579 */ 580 static INLINE uint32_t 581 util_pack_z_stencil(enum pipe_format format, double z, uint8_t s) 582 { 583 uint32_t packed = util_pack_z(format, z); 584 585 switch (format) { 586 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 587 packed |= (uint32_t)s << 24; 588 break; 589 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 590 packed |= s; 591 break; 592 case PIPE_FORMAT_S8_UINT: 593 packed |= s; 594 break; 595 default: 596 break; 597 } 598 599 return packed; 600 } 601 602 603 static INLINE uint64_t 604 util_pack64_z_stencil(enum pipe_format format, double z, uint8_t s) 605 { 606 uint64_t packed; 607 608 switch (format) { 609 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 610 packed = util_pack64_z(format, z); 611 packed |= (uint64_t)s << 32ull; 612 break; 613 default: 614 return util_pack_z_stencil(format, z, s); 615 } 616 617 return packed; 618 } 619 620 621 /** 622 * Pack 4 ubytes into a 4-byte word 623 */ 624 static INLINE unsigned 625 pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3) 626 { 627 return ((((unsigned int)b0) << 0) | 628 (((unsigned int)b1) << 8) | 629 (((unsigned int)b2) << 16) | 630 (((unsigned int)b3) << 24)); 631 } 632 633 634 /** 635 * Pack/convert 4 floats into one 4-byte word. 636 */ 637 static INLINE unsigned 638 pack_ui32_float4(float a, float b, float c, float d) 639 { 640 return pack_ub4( float_to_ubyte(a), 641 float_to_ubyte(b), 642 float_to_ubyte(c), 643 float_to_ubyte(d) ); 644 } 645 646 647 648 #endif /* U_PACK_COLOR_H */ 649