u_pack_color.h revision 94abc4b51e134bee1ace2b57400e35c295bda6f8
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_format.h" 41#include "util/u_math.h" 42 43 44 45union util_color { 46 ubyte ub; 47 ushort us; 48 uint ui; 49 float f[4]; 50}; 51 52/** 53 * Pack ubyte R,G,B,A into dest pixel. 54 */ 55static INLINE void 56util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, 57 enum pipe_format format, union util_color *uc) 58{ 59 switch (format) { 60 case PIPE_FORMAT_A8B8G8R8_UNORM: 61 { 62 uc->ui = (r << 24) | (g << 16) | (b << 8) | a; 63 } 64 return; 65 case PIPE_FORMAT_X8B8G8R8_UNORM: 66 { 67 uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; 68 } 69 return; 70 case PIPE_FORMAT_B8G8R8A8_UNORM: 71 { 72 uc->ui = (a << 24) | (r << 16) | (g << 8) | b; 73 } 74 return; 75 case PIPE_FORMAT_B8G8R8X8_UNORM: 76 { 77 uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; 78 } 79 return; 80 case PIPE_FORMAT_A8R8G8B8_UNORM: 81 { 82 uc->ui = (b << 24) | (g << 16) | (r << 8) | a; 83 } 84 return; 85 case PIPE_FORMAT_X8R8G8B8_UNORM: 86 { 87 uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; 88 } 89 return; 90 case PIPE_FORMAT_B5G6R5_UNORM: 91 { 92 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); 93 } 94 return; 95 case PIPE_FORMAT_B5G5R5X1_UNORM: 96 { 97 uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); 98 } 99 return; 100 case PIPE_FORMAT_B5G5R5A1_UNORM: 101 { 102 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); 103 } 104 return; 105 case PIPE_FORMAT_B4G4R4A4_UNORM: 106 { 107 uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); 108 } 109 return; 110 case PIPE_FORMAT_A8_UNORM: 111 { 112 uc->ub = a; 113 } 114 return; 115 case PIPE_FORMAT_L8_UNORM: 116 case PIPE_FORMAT_I8_UNORM: 117 { 118 uc->ub = a; 119 } 120 return; 121 case PIPE_FORMAT_R32G32B32A32_FLOAT: 122 { 123 uc->f[0] = (float)r / 255.0f; 124 uc->f[1] = (float)g / 255.0f; 125 uc->f[2] = (float)b / 255.0f; 126 uc->f[3] = (float)a / 255.0f; 127 } 128 return; 129 case PIPE_FORMAT_R32G32B32_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 } 135 return; 136 137 /* Handle other cases with a generic function. 138 */ 139 default: 140 { 141 ubyte src[4]; 142 143 src[0] = r; 144 src[1] = g; 145 src[2] = b; 146 src[3] = a; 147 util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1); 148 } 149 } 150} 151 152 153/** 154 * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255]. 155 */ 156static INLINE void 157util_unpack_color_ub(enum pipe_format format, union util_color *uc, 158 ubyte *r, ubyte *g, ubyte *b, ubyte *a) 159{ 160 switch (format) { 161 case PIPE_FORMAT_A8B8G8R8_UNORM: 162 { 163 uint p = uc->ui; 164 *r = (ubyte) ((p >> 24) & 0xff); 165 *g = (ubyte) ((p >> 16) & 0xff); 166 *b = (ubyte) ((p >> 8) & 0xff); 167 *a = (ubyte) ((p >> 0) & 0xff); 168 } 169 return; 170 case PIPE_FORMAT_X8B8G8R8_UNORM: 171 { 172 uint p = uc->ui; 173 *r = (ubyte) ((p >> 24) & 0xff); 174 *g = (ubyte) ((p >> 16) & 0xff); 175 *b = (ubyte) ((p >> 8) & 0xff); 176 *a = (ubyte) 0xff; 177 } 178 return; 179 case PIPE_FORMAT_B8G8R8A8_UNORM: 180 { 181 uint p = uc->ui; 182 *r = (ubyte) ((p >> 16) & 0xff); 183 *g = (ubyte) ((p >> 8) & 0xff); 184 *b = (ubyte) ((p >> 0) & 0xff); 185 *a = (ubyte) ((p >> 24) & 0xff); 186 } 187 return; 188 case PIPE_FORMAT_B8G8R8X8_UNORM: 189 { 190 uint p = uc->ui; 191 *r = (ubyte) ((p >> 16) & 0xff); 192 *g = (ubyte) ((p >> 8) & 0xff); 193 *b = (ubyte) ((p >> 0) & 0xff); 194 *a = (ubyte) 0xff; 195 } 196 return; 197 case PIPE_FORMAT_A8R8G8B8_UNORM: 198 { 199 uint p = uc->ui; 200 *r = (ubyte) ((p >> 8) & 0xff); 201 *g = (ubyte) ((p >> 16) & 0xff); 202 *b = (ubyte) ((p >> 24) & 0xff); 203 *a = (ubyte) ((p >> 0) & 0xff); 204 } 205 return; 206 case PIPE_FORMAT_X8R8G8B8_UNORM: 207 { 208 uint p = uc->ui; 209 *r = (ubyte) ((p >> 8) & 0xff); 210 *g = (ubyte) ((p >> 16) & 0xff); 211 *b = (ubyte) ((p >> 24) & 0xff); 212 *a = (ubyte) 0xff; 213 } 214 return; 215 case PIPE_FORMAT_B5G6R5_UNORM: 216 { 217 ushort p = uc->us; 218 *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7)); 219 *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3)); 220 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); 221 *a = (ubyte) 0xff; 222 } 223 return; 224 case PIPE_FORMAT_B5G5R5X1_UNORM: 225 { 226 ushort p = uc->us; 227 *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); 228 *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); 229 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); 230 *a = (ubyte) 0xff; 231 } 232 return; 233 case PIPE_FORMAT_B5G5R5A1_UNORM: 234 { 235 ushort p = uc->us; 236 *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); 237 *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); 238 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); 239 *a = (ubyte) (0xff * (p >> 15)); 240 } 241 return; 242 case PIPE_FORMAT_B4G4R4A4_UNORM: 243 { 244 ushort p = uc->us; 245 *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf)); 246 *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf)); 247 *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf)); 248 *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf)); 249 } 250 return; 251 case PIPE_FORMAT_A8_UNORM: 252 { 253 ubyte p = uc->ub; 254 *r = *g = *b = (ubyte) 0xff; 255 *a = p; 256 } 257 return; 258 case PIPE_FORMAT_L8_UNORM: 259 { 260 ubyte p = uc->ub; 261 *r = *g = *b = p; 262 *a = (ubyte) 0xff; 263 } 264 return; 265 case PIPE_FORMAT_I8_UNORM: 266 { 267 ubyte p = uc->ub; 268 *r = *g = *b = *a = p; 269 } 270 return; 271 case PIPE_FORMAT_R32G32B32A32_FLOAT: 272 { 273 const float *p = &uc->f[0]; 274 *r = float_to_ubyte(p[0]); 275 *g = float_to_ubyte(p[1]); 276 *b = float_to_ubyte(p[2]); 277 *a = float_to_ubyte(p[3]); 278 } 279 return; 280 case PIPE_FORMAT_R32G32B32_FLOAT: 281 { 282 const float *p = &uc->f[0]; 283 *r = float_to_ubyte(p[0]); 284 *g = float_to_ubyte(p[1]); 285 *b = float_to_ubyte(p[2]); 286 *a = (ubyte) 0xff; 287 } 288 return; 289 290 case PIPE_FORMAT_R32G32_FLOAT: 291 { 292 const float *p = &uc->f[0]; 293 *r = float_to_ubyte(p[0]); 294 *g = float_to_ubyte(p[1]); 295 *b = *a = (ubyte) 0xff; 296 } 297 return; 298 299 case PIPE_FORMAT_R32_FLOAT: 300 { 301 const float *p = &uc->f[0]; 302 *r = float_to_ubyte(p[0]); 303 *g = *b = *a = (ubyte) 0xff; 304 } 305 return; 306 307 /* Handle other cases with a generic function. 308 */ 309 default: 310 { 311 ubyte dst[4]; 312 313 util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1); 314 *r = dst[0]; 315 *g = dst[1]; 316 *b = dst[2]; 317 *a = dst[3]; 318 } 319 } 320} 321 322 323/** 324 * Note rgba outside [0,1] will be clamped for int pixel formats. 325 */ 326static INLINE void 327util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc) 328{ 329 ubyte r = 0; 330 ubyte g = 0; 331 ubyte b = 0; 332 ubyte a = 0; 333 334 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) { 335 /* format uses 8-bit components or less */ 336 r = float_to_ubyte(rgba[0]); 337 g = float_to_ubyte(rgba[1]); 338 b = float_to_ubyte(rgba[2]); 339 a = float_to_ubyte(rgba[3]); 340 } 341 342 switch (format) { 343 case PIPE_FORMAT_A8B8G8R8_UNORM: 344 { 345 uc->ui = (r << 24) | (g << 16) | (b << 8) | a; 346 } 347 return; 348 case PIPE_FORMAT_X8B8G8R8_UNORM: 349 { 350 uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; 351 } 352 return; 353 case PIPE_FORMAT_B8G8R8A8_UNORM: 354 { 355 uc->ui = (a << 24) | (r << 16) | (g << 8) | b; 356 } 357 return; 358 case PIPE_FORMAT_B8G8R8X8_UNORM: 359 { 360 uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; 361 } 362 return; 363 case PIPE_FORMAT_A8R8G8B8_UNORM: 364 { 365 uc->ui = (b << 24) | (g << 16) | (r << 8) | a; 366 } 367 return; 368 case PIPE_FORMAT_X8R8G8B8_UNORM: 369 { 370 uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; 371 } 372 return; 373 case PIPE_FORMAT_B5G6R5_UNORM: 374 { 375 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); 376 } 377 return; 378 case PIPE_FORMAT_B5G5R5X1_UNORM: 379 { 380 uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); 381 } 382 return; 383 case PIPE_FORMAT_B5G5R5A1_UNORM: 384 { 385 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); 386 } 387 return; 388 case PIPE_FORMAT_B4G4R4A4_UNORM: 389 { 390 uc->ub = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); 391 } 392 return; 393 case PIPE_FORMAT_A8_UNORM: 394 { 395 uc->ub = a; 396 } 397 return; 398 case PIPE_FORMAT_L8_UNORM: 399 case PIPE_FORMAT_I8_UNORM: 400 { 401 uc->ub = r; 402 } 403 return; 404 case PIPE_FORMAT_R32G32B32A32_FLOAT: 405 { 406 uc->f[0] = rgba[0]; 407 uc->f[1] = rgba[1]; 408 uc->f[2] = rgba[2]; 409 uc->f[3] = rgba[3]; 410 } 411 return; 412 case PIPE_FORMAT_R32G32B32_FLOAT: 413 { 414 uc->f[0] = rgba[0]; 415 uc->f[1] = rgba[1]; 416 uc->f[2] = rgba[2]; 417 } 418 return; 419 420 /* Handle other cases with a generic function. 421 */ 422 default: 423 util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1); 424 } 425} 426 427 428/** 429 * Note: it's assumed that z is in [0,1] 430 */ 431static INLINE uint 432util_pack_z(enum pipe_format format, double z) 433{ 434 if (z == 0.0) 435 return 0; 436 437 switch (format) { 438 case PIPE_FORMAT_Z16_UNORM: 439 if (z == 1.0) 440 return 0xffff; 441 return (uint) (z * 0xffff); 442 case PIPE_FORMAT_Z32_UNORM: 443 /* special-case to avoid overflow */ 444 if (z == 1.0) 445 return 0xffffffff; 446 return (uint) (z * 0xffffffff); 447 case PIPE_FORMAT_Z32_FLOAT: 448 return (uint)z; 449 case PIPE_FORMAT_Z24S8_UNORM: 450 case PIPE_FORMAT_Z24X8_UNORM: 451 if (z == 1.0) 452 return 0xffffff; 453 return (uint) (z * 0xffffff); 454 case PIPE_FORMAT_S8Z24_UNORM: 455 case PIPE_FORMAT_X8Z24_UNORM: 456 if (z == 1.0) 457 return 0xffffff00; 458 return ((uint) (z * 0xffffff)) << 8; 459 case PIPE_FORMAT_S8_UNORM: 460 /* this case can get it via util_pack_z_stencil() */ 461 return 0; 462 default: 463 debug_print_format("gallium: unhandled format in util_pack_z()", format); 464 assert(0); 465 return 0; 466 } 467} 468 469 470/** 471 * Pack Z and/or stencil values into a 32-bit value described by format. 472 * Note: it's assumed that z is in [0,1] and s in [0,255] 473 */ 474static INLINE uint 475util_pack_z_stencil(enum pipe_format format, double z, uint s) 476{ 477 unsigned packed = util_pack_z(format, z); 478 479 switch (format) { 480 case PIPE_FORMAT_Z24S8_UNORM: 481 packed |= s << 24; 482 break; 483 case PIPE_FORMAT_S8Z24_UNORM: 484 packed |= s; 485 break; 486 case PIPE_FORMAT_S8_UNORM: 487 packed |= s; 488 break; 489 default: 490 break; 491 } 492 493 return packed; 494} 495 496 497/** 498 * Pack 4 ubytes into a 4-byte word 499 */ 500static INLINE unsigned 501pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3) 502{ 503 return ((((unsigned int)b0) << 0) | 504 (((unsigned int)b1) << 8) | 505 (((unsigned int)b2) << 16) | 506 (((unsigned int)b3) << 24)); 507} 508 509 510/** 511 * Pack/convert 4 floats into one 4-byte word. 512 */ 513static INLINE unsigned 514pack_ui32_float4(float a, float b, float c, float d) 515{ 516 return pack_ub4( float_to_ubyte(a), 517 float_to_ubyte(b), 518 float_to_ubyte(c), 519 float_to_ubyte(d) ); 520} 521 522 523 524#endif /* U_PACK_COLOR_H */ 525