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