1 /************************************************************************** 2 * 3 * Copyright 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 * @file 30 * Pixel format accessor functions. 31 * 32 * @author Jose Fonseca <jfonseca (at) vmware.com> 33 */ 34 35 #include "u_math.h" 36 #include "u_memory.h" 37 #include "u_format.h" 38 #include "u_format_s3tc.h" 39 #include "u_surface.h" 40 41 #include "pipe/p_defines.h" 42 43 44 boolean 45 util_format_is_float(enum pipe_format format) 46 { 47 const struct util_format_description *desc = util_format_description(format); 48 int i; 49 50 assert(desc); 51 if (!desc) { 52 return FALSE; 53 } 54 55 i = util_format_get_first_non_void_channel(format); 56 if (i < 0) { 57 return FALSE; 58 } 59 60 return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE; 61 } 62 63 64 /** Test if the format contains RGB, but not alpha */ 65 boolean 66 util_format_has_alpha(enum pipe_format format) 67 { 68 const struct util_format_description *desc = 69 util_format_description(format); 70 71 return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || 72 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && 73 desc->swizzle[3] != PIPE_SWIZZLE_1; 74 } 75 76 77 boolean 78 util_format_is_luminance(enum pipe_format format) 79 { 80 const struct util_format_description *desc = 81 util_format_description(format); 82 83 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || 84 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && 85 desc->swizzle[0] == PIPE_SWIZZLE_X && 86 desc->swizzle[1] == PIPE_SWIZZLE_X && 87 desc->swizzle[2] == PIPE_SWIZZLE_X && 88 desc->swizzle[3] == PIPE_SWIZZLE_1) { 89 return TRUE; 90 } 91 return FALSE; 92 } 93 94 boolean 95 util_format_is_alpha(enum pipe_format format) 96 { 97 const struct util_format_description *desc = 98 util_format_description(format); 99 100 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || 101 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && 102 desc->swizzle[0] == PIPE_SWIZZLE_0 && 103 desc->swizzle[1] == PIPE_SWIZZLE_0 && 104 desc->swizzle[2] == PIPE_SWIZZLE_0 && 105 desc->swizzle[3] == PIPE_SWIZZLE_X) { 106 return TRUE; 107 } 108 return FALSE; 109 } 110 111 boolean 112 util_format_is_pure_integer(enum pipe_format format) 113 { 114 const struct util_format_description *desc = util_format_description(format); 115 int i; 116 117 /* Find the first non-void channel. */ 118 i = util_format_get_first_non_void_channel(format); 119 if (i == -1) 120 return FALSE; 121 122 return desc->channel[i].pure_integer ? TRUE : FALSE; 123 } 124 125 boolean 126 util_format_is_pure_sint(enum pipe_format format) 127 { 128 const struct util_format_description *desc = util_format_description(format); 129 int i; 130 131 i = util_format_get_first_non_void_channel(format); 132 if (i == -1) 133 return FALSE; 134 135 return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE; 136 } 137 138 boolean 139 util_format_is_pure_uint(enum pipe_format format) 140 { 141 const struct util_format_description *desc = util_format_description(format); 142 int i; 143 144 i = util_format_get_first_non_void_channel(format); 145 if (i == -1) 146 return FALSE; 147 148 return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE; 149 } 150 151 /** 152 * Returns true if all non-void channels are normalized signed. 153 */ 154 boolean 155 util_format_is_snorm(enum pipe_format format) 156 { 157 const struct util_format_description *desc = util_format_description(format); 158 int i; 159 160 if (desc->is_mixed) 161 return FALSE; 162 163 i = util_format_get_first_non_void_channel(format); 164 if (i == -1) 165 return FALSE; 166 167 return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && 168 !desc->channel[i].pure_integer && 169 desc->channel[i].normalized; 170 } 171 172 boolean 173 util_format_is_snorm8(enum pipe_format format) 174 { 175 const struct util_format_description *desc = util_format_description(format); 176 int i; 177 178 if (desc->is_mixed) 179 return FALSE; 180 181 i = util_format_get_first_non_void_channel(format); 182 if (i == -1) 183 return FALSE; 184 185 return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && 186 !desc->channel[i].pure_integer && 187 desc->channel[i].normalized && 188 desc->channel[i].size == 8; 189 } 190 191 boolean 192 util_format_is_luminance_alpha(enum pipe_format format) 193 { 194 const struct util_format_description *desc = 195 util_format_description(format); 196 197 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || 198 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && 199 desc->swizzle[0] == PIPE_SWIZZLE_X && 200 desc->swizzle[1] == PIPE_SWIZZLE_X && 201 desc->swizzle[2] == PIPE_SWIZZLE_X && 202 desc->swizzle[3] == PIPE_SWIZZLE_Y) { 203 return TRUE; 204 } 205 return FALSE; 206 } 207 208 209 boolean 210 util_format_is_intensity(enum pipe_format format) 211 { 212 const struct util_format_description *desc = 213 util_format_description(format); 214 215 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || 216 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && 217 desc->swizzle[0] == PIPE_SWIZZLE_X && 218 desc->swizzle[1] == PIPE_SWIZZLE_X && 219 desc->swizzle[2] == PIPE_SWIZZLE_X && 220 desc->swizzle[3] == PIPE_SWIZZLE_X) { 221 return TRUE; 222 } 223 return FALSE; 224 } 225 226 boolean 227 util_format_is_subsampled_422(enum pipe_format format) 228 { 229 const struct util_format_description *desc = 230 util_format_description(format); 231 232 return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED && 233 desc->block.width == 2 && 234 desc->block.height == 1 && 235 desc->block.bits == 32; 236 } 237 238 boolean 239 util_format_is_supported(enum pipe_format format, unsigned bind) 240 { 241 if (util_format_is_s3tc(format) && !util_format_s3tc_enabled) { 242 return FALSE; 243 } 244 245 #ifndef TEXTURE_FLOAT_ENABLED 246 if ((bind & PIPE_BIND_RENDER_TARGET) && 247 format != PIPE_FORMAT_R9G9B9E5_FLOAT && 248 format != PIPE_FORMAT_R11G11B10_FLOAT && 249 util_format_is_float(format)) { 250 return FALSE; 251 } 252 #endif 253 254 return TRUE; 255 } 256 257 258 /** 259 * Calculates the MRD for the depth format. MRD is used in depth bias 260 * for UNORM and unbound depth buffers. When the depth buffer is floating 261 * point, the depth bias calculation does not use the MRD. However, the 262 * default MRD will be 1.0 / ((1 << 24) - 1). 263 */ 264 double 265 util_get_depth_format_mrd(const struct util_format_description *desc) 266 { 267 /* 268 * Depth buffer formats without a depth component OR scenarios 269 * without a bound depth buffer default to D24. 270 */ 271 double mrd = 1.0 / ((1 << 24) - 1); 272 unsigned depth_channel; 273 274 assert(desc); 275 276 /* 277 * Some depth formats do not store the depth component in the first 278 * channel, detect the format and adjust the depth channel. Get the 279 * swizzled depth component channel. 280 */ 281 depth_channel = desc->swizzle[0]; 282 283 if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED && 284 desc->channel[depth_channel].normalized) { 285 int depth_bits; 286 287 depth_bits = desc->channel[depth_channel].size; 288 mrd = 1.0 / ((1ULL << depth_bits) - 1); 289 } 290 291 return mrd; 292 } 293 294 295 void 296 util_format_read_4f(enum pipe_format format, 297 float *dst, unsigned dst_stride, 298 const void *src, unsigned src_stride, 299 unsigned x, unsigned y, unsigned w, unsigned h) 300 { 301 const struct util_format_description *format_desc; 302 const uint8_t *src_row; 303 float *dst_row; 304 305 format_desc = util_format_description(format); 306 307 assert(x % format_desc->block.width == 0); 308 assert(y % format_desc->block.height == 0); 309 310 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); 311 dst_row = dst; 312 313 format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h); 314 } 315 316 317 void 318 util_format_write_4f(enum pipe_format format, 319 const float *src, unsigned src_stride, 320 void *dst, unsigned dst_stride, 321 unsigned x, unsigned y, unsigned w, unsigned h) 322 { 323 const struct util_format_description *format_desc; 324 uint8_t *dst_row; 325 const float *src_row; 326 327 format_desc = util_format_description(format); 328 329 assert(x % format_desc->block.width == 0); 330 assert(y % format_desc->block.height == 0); 331 332 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); 333 src_row = src; 334 335 format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h); 336 } 337 338 339 void 340 util_format_read_4ub(enum pipe_format format, uint8_t *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h) 341 { 342 const struct util_format_description *format_desc; 343 const uint8_t *src_row; 344 uint8_t *dst_row; 345 346 format_desc = util_format_description(format); 347 348 assert(x % format_desc->block.width == 0); 349 assert(y % format_desc->block.height == 0); 350 351 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); 352 dst_row = dst; 353 354 format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h); 355 } 356 357 358 void 359 util_format_write_4ub(enum pipe_format format, const uint8_t *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h) 360 { 361 const struct util_format_description *format_desc; 362 uint8_t *dst_row; 363 const uint8_t *src_row; 364 365 format_desc = util_format_description(format); 366 367 assert(x % format_desc->block.width == 0); 368 assert(y % format_desc->block.height == 0); 369 370 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); 371 src_row = src; 372 373 format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h); 374 } 375 376 void 377 util_format_read_4ui(enum pipe_format format, 378 unsigned *dst, unsigned dst_stride, 379 const void *src, unsigned src_stride, 380 unsigned x, unsigned y, unsigned w, unsigned h) 381 { 382 const struct util_format_description *format_desc; 383 const uint8_t *src_row; 384 uint32_t *dst_row; 385 386 format_desc = util_format_description(format); 387 388 assert(x % format_desc->block.width == 0); 389 assert(y % format_desc->block.height == 0); 390 391 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); 392 dst_row = dst; 393 394 format_desc->unpack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h); 395 } 396 397 void 398 util_format_write_4ui(enum pipe_format format, 399 const unsigned int *src, unsigned src_stride, 400 void *dst, unsigned dst_stride, 401 unsigned x, unsigned y, unsigned w, unsigned h) 402 { 403 const struct util_format_description *format_desc; 404 uint8_t *dst_row; 405 const uint32_t *src_row; 406 407 format_desc = util_format_description(format); 408 409 assert(x % format_desc->block.width == 0); 410 assert(y % format_desc->block.height == 0); 411 412 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); 413 src_row = src; 414 415 format_desc->pack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h); 416 } 417 418 void 419 util_format_read_4i(enum pipe_format format, 420 int *dst, unsigned dst_stride, 421 const void *src, unsigned src_stride, 422 unsigned x, unsigned y, unsigned w, unsigned h) 423 { 424 const struct util_format_description *format_desc; 425 const uint8_t *src_row; 426 int32_t *dst_row; 427 428 format_desc = util_format_description(format); 429 430 assert(x % format_desc->block.width == 0); 431 assert(y % format_desc->block.height == 0); 432 433 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); 434 dst_row = dst; 435 436 format_desc->unpack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h); 437 } 438 439 void 440 util_format_write_4i(enum pipe_format format, 441 const int *src, unsigned src_stride, 442 void *dst, unsigned dst_stride, 443 unsigned x, unsigned y, unsigned w, unsigned h) 444 { 445 const struct util_format_description *format_desc; 446 uint8_t *dst_row; 447 const int32_t *src_row; 448 449 format_desc = util_format_description(format); 450 451 assert(x % format_desc->block.width == 0); 452 assert(y % format_desc->block.height == 0); 453 454 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); 455 src_row = src; 456 457 format_desc->pack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h); 458 } 459 460 /** 461 * Check if we can safely memcopy from the source format to the dest format. 462 * This basically covers the cases of a "used" channel copied to a typeless 463 * channel, plus some 1-channel cases. 464 * Examples of compatible copy formats include: 465 * b8g8r8a8_unorm -> b8g8r8x8_unorm 466 * a8r8g8b8_unorm -> x8r8g8b8_unorm 467 * b5g5r5a1_unorm -> b5g5r5x1_unorm 468 * b4g4r4a4_unorm -> b4g4r4x4_unorm 469 * l8_unorm -> r8_unorm 470 * i8_unorm -> l8_unorm 471 * i8_unorm -> a8_unorm 472 * i8_unorm -> r8_unorm 473 * l16_unorm -> r16_unorm 474 * z24_unorm_s8_uint -> z24x8_unorm 475 * s8_uint_z24_unorm -> x8z24_unorm 476 * r8g8b8a8_unorm -> r8g8b8x8_unorm 477 * a8b8g8r8_srgb -> x8b8g8r8_srgb 478 * b8g8r8a8_srgb -> b8g8r8x8_srgb 479 * a8r8g8b8_srgb -> x8r8g8b8_srgb 480 * a8b8g8r8_unorm -> x8b8g8r8_unorm 481 * r10g10b10a2_uscaled -> r10g10b10x2_uscaled 482 * r10sg10sb10sa2u_norm -> r10g10b10x2_snorm 483 */ 484 boolean 485 util_is_format_compatible(const struct util_format_description *src_desc, 486 const struct util_format_description *dst_desc) 487 { 488 unsigned chan; 489 490 if (src_desc->format == dst_desc->format) { 491 return TRUE; 492 } 493 494 if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN || 495 dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) { 496 return FALSE; 497 } 498 499 if (src_desc->block.bits != dst_desc->block.bits || 500 src_desc->nr_channels != dst_desc->nr_channels || 501 src_desc->colorspace != dst_desc->colorspace) { 502 return FALSE; 503 } 504 505 for (chan = 0; chan < 4; ++chan) { 506 if (src_desc->channel[chan].size != 507 dst_desc->channel[chan].size) { 508 return FALSE; 509 } 510 } 511 512 for (chan = 0; chan < 4; ++chan) { 513 enum pipe_swizzle swizzle = dst_desc->swizzle[chan]; 514 515 if (swizzle < 4) { 516 if (src_desc->swizzle[chan] != swizzle) { 517 return FALSE; 518 } 519 if ((src_desc->channel[swizzle].type != 520 dst_desc->channel[swizzle].type) || 521 (src_desc->channel[swizzle].normalized != 522 dst_desc->channel[swizzle].normalized)) { 523 return FALSE; 524 } 525 } 526 } 527 528 return TRUE; 529 } 530 531 532 boolean 533 util_format_fits_8unorm(const struct util_format_description *format_desc) 534 { 535 unsigned chan; 536 537 /* 538 * After linearized sRGB values require more than 8bits. 539 */ 540 541 if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { 542 return FALSE; 543 } 544 545 switch (format_desc->layout) { 546 547 case UTIL_FORMAT_LAYOUT_S3TC: 548 /* 549 * These are straight forward. 550 */ 551 return TRUE; 552 case UTIL_FORMAT_LAYOUT_RGTC: 553 if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM || 554 format_desc->format == PIPE_FORMAT_RGTC2_SNORM || 555 format_desc->format == PIPE_FORMAT_LATC1_SNORM || 556 format_desc->format == PIPE_FORMAT_LATC2_SNORM) 557 return FALSE; 558 return TRUE; 559 case UTIL_FORMAT_LAYOUT_BPTC: 560 if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM) 561 return TRUE; 562 return FALSE; 563 564 case UTIL_FORMAT_LAYOUT_ETC: 565 if (format_desc->format == PIPE_FORMAT_ETC1_RGB8) 566 return TRUE; 567 return FALSE; 568 569 case UTIL_FORMAT_LAYOUT_PLAIN: 570 /* 571 * For these we can find a generic rule. 572 */ 573 574 for (chan = 0; chan < format_desc->nr_channels; ++chan) { 575 switch (format_desc->channel[chan].type) { 576 case UTIL_FORMAT_TYPE_VOID: 577 break; 578 case UTIL_FORMAT_TYPE_UNSIGNED: 579 if (!format_desc->channel[chan].normalized || 580 format_desc->channel[chan].size > 8) { 581 return FALSE; 582 } 583 break; 584 default: 585 return FALSE; 586 } 587 } 588 return TRUE; 589 590 default: 591 /* 592 * Handle all others on a case by case basis. 593 */ 594 595 switch (format_desc->format) { 596 case PIPE_FORMAT_R1_UNORM: 597 case PIPE_FORMAT_UYVY: 598 case PIPE_FORMAT_YUYV: 599 case PIPE_FORMAT_R8G8_B8G8_UNORM: 600 case PIPE_FORMAT_G8R8_G8B8_UNORM: 601 return TRUE; 602 603 default: 604 return FALSE; 605 } 606 } 607 } 608 609 610 boolean 611 util_format_translate(enum pipe_format dst_format, 612 void *dst, unsigned dst_stride, 613 unsigned dst_x, unsigned dst_y, 614 enum pipe_format src_format, 615 const void *src, unsigned src_stride, 616 unsigned src_x, unsigned src_y, 617 unsigned width, unsigned height) 618 { 619 const struct util_format_description *dst_format_desc; 620 const struct util_format_description *src_format_desc; 621 uint8_t *dst_row; 622 const uint8_t *src_row; 623 unsigned x_step, y_step; 624 unsigned dst_step; 625 unsigned src_step; 626 627 dst_format_desc = util_format_description(dst_format); 628 src_format_desc = util_format_description(src_format); 629 630 if (util_is_format_compatible(src_format_desc, dst_format_desc)) { 631 /* 632 * Trivial case. 633 */ 634 635 util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y, 636 width, height, src, (int)src_stride, 637 src_x, src_y); 638 return TRUE; 639 } 640 641 assert(dst_x % dst_format_desc->block.width == 0); 642 assert(dst_y % dst_format_desc->block.height == 0); 643 assert(src_x % src_format_desc->block.width == 0); 644 assert(src_y % src_format_desc->block.height == 0); 645 646 dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8); 647 src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8); 648 649 /* 650 * This works because all pixel formats have pixel blocks with power of two 651 * sizes. 652 */ 653 654 y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height); 655 x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width); 656 assert(y_step % dst_format_desc->block.height == 0); 657 assert(y_step % src_format_desc->block.height == 0); 658 659 dst_step = y_step / dst_format_desc->block.height * dst_stride; 660 src_step = y_step / src_format_desc->block.height * src_stride; 661 662 /* 663 * TODO: double formats will loose precision 664 * TODO: Add a special case for formats that are mere swizzles of each other 665 */ 666 667 if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS || 668 dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { 669 float *tmp_z = NULL; 670 uint8_t *tmp_s = NULL; 671 672 assert(x_step == 1); 673 assert(y_step == 1); 674 675 if (src_format_desc->unpack_z_float && 676 dst_format_desc->pack_z_float) { 677 tmp_z = MALLOC(width * sizeof *tmp_z); 678 } 679 680 if (src_format_desc->unpack_s_8uint && 681 dst_format_desc->pack_s_8uint) { 682 tmp_s = MALLOC(width * sizeof *tmp_s); 683 } 684 685 while (height--) { 686 if (tmp_z) { 687 src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1); 688 dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1); 689 } 690 691 if (tmp_s) { 692 src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1); 693 dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1); 694 } 695 696 dst_row += dst_step; 697 src_row += src_step; 698 } 699 700 FREE(tmp_s); 701 702 FREE(tmp_z); 703 704 return TRUE; 705 } 706 707 if (util_format_fits_8unorm(src_format_desc) || 708 util_format_fits_8unorm(dst_format_desc)) { 709 unsigned tmp_stride; 710 uint8_t *tmp_row; 711 712 if (!src_format_desc->unpack_rgba_8unorm || 713 !dst_format_desc->pack_rgba_8unorm) { 714 return FALSE; 715 } 716 717 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; 718 tmp_row = MALLOC(y_step * tmp_stride); 719 if (!tmp_row) 720 return FALSE; 721 722 while (height >= y_step) { 723 src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step); 724 dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); 725 726 dst_row += dst_step; 727 src_row += src_step; 728 height -= y_step; 729 } 730 731 if (height) { 732 src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height); 733 dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height); 734 } 735 736 FREE(tmp_row); 737 } 738 else { 739 unsigned tmp_stride; 740 float *tmp_row; 741 742 if (!src_format_desc->unpack_rgba_float || 743 !dst_format_desc->pack_rgba_float) { 744 return FALSE; 745 } 746 747 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; 748 tmp_row = MALLOC(y_step * tmp_stride); 749 if (!tmp_row) 750 return FALSE; 751 752 while (height >= y_step) { 753 src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step); 754 dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); 755 756 dst_row += dst_step; 757 src_row += src_step; 758 height -= y_step; 759 } 760 761 if (height) { 762 src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height); 763 dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height); 764 } 765 766 FREE(tmp_row); 767 } 768 return TRUE; 769 } 770 771 boolean 772 util_format_translate_3d(enum pipe_format dst_format, 773 void *dst, unsigned dst_stride, 774 unsigned dst_slice_stride, 775 unsigned dst_x, unsigned dst_y, 776 unsigned dst_z, 777 enum pipe_format src_format, 778 const void *src, unsigned src_stride, 779 unsigned src_slice_stride, 780 unsigned src_x, unsigned src_y, 781 unsigned src_z, unsigned width, 782 unsigned height, unsigned depth) 783 { 784 uint8_t *dst_layer; 785 const uint8_t *src_layer; 786 unsigned z; 787 dst_layer = dst; 788 src_layer = src; 789 dst_layer += dst_z * dst_slice_stride; 790 src_layer += src_z * src_slice_stride; 791 for (z = 0; z < depth; ++z) { 792 if (!util_format_translate(dst_format, dst_layer, dst_stride, 793 dst_x, dst_y, 794 src_format, src_layer, src_stride, 795 src_x, src_y, 796 width, height)) 797 return FALSE; 798 799 dst_layer += dst_slice_stride; 800 src_layer += src_slice_stride; 801 } 802 return TRUE; 803 } 804 805 void util_format_compose_swizzles(const unsigned char swz1[4], 806 const unsigned char swz2[4], 807 unsigned char dst[4]) 808 { 809 unsigned i; 810 811 for (i = 0; i < 4; i++) { 812 dst[i] = swz2[i] <= PIPE_SWIZZLE_W ? 813 swz1[swz2[i]] : swz2[i]; 814 } 815 } 816 817 void util_format_apply_color_swizzle(union pipe_color_union *dst, 818 const union pipe_color_union *src, 819 const unsigned char swz[4], 820 const boolean is_integer) 821 { 822 unsigned c; 823 824 if (is_integer) { 825 for (c = 0; c < 4; ++c) { 826 switch (swz[c]) { 827 case PIPE_SWIZZLE_X: dst->ui[c] = src->ui[0]; break; 828 case PIPE_SWIZZLE_Y: dst->ui[c] = src->ui[1]; break; 829 case PIPE_SWIZZLE_Z: dst->ui[c] = src->ui[2]; break; 830 case PIPE_SWIZZLE_W: dst->ui[c] = src->ui[3]; break; 831 default: 832 dst->ui[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1 : 0; 833 break; 834 } 835 } 836 } else { 837 for (c = 0; c < 4; ++c) { 838 switch (swz[c]) { 839 case PIPE_SWIZZLE_X: dst->f[c] = src->f[0]; break; 840 case PIPE_SWIZZLE_Y: dst->f[c] = src->f[1]; break; 841 case PIPE_SWIZZLE_Z: dst->f[c] = src->f[2]; break; 842 case PIPE_SWIZZLE_W: dst->f[c] = src->f[3]; break; 843 default: 844 dst->f[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1.0f : 0.0f; 845 break; 846 } 847 } 848 } 849 } 850 851 void pipe_swizzle_4f(float *dst, const float *src, 852 const unsigned char swz[4]) 853 { 854 unsigned i; 855 856 for (i = 0; i < 4; i++) { 857 if (swz[i] <= PIPE_SWIZZLE_W) 858 dst[i] = src[swz[i]]; 859 else if (swz[i] == PIPE_SWIZZLE_0) 860 dst[i] = 0; 861 else if (swz[i] == PIPE_SWIZZLE_1) 862 dst[i] = 1; 863 } 864 } 865 866 void util_format_unswizzle_4f(float *dst, const float *src, 867 const unsigned char swz[4]) 868 { 869 unsigned i; 870 871 for (i = 0; i < 4; i++) { 872 switch (swz[i]) { 873 case PIPE_SWIZZLE_X: 874 dst[0] = src[i]; 875 break; 876 case PIPE_SWIZZLE_Y: 877 dst[1] = src[i]; 878 break; 879 case PIPE_SWIZZLE_Z: 880 dst[2] = src[i]; 881 break; 882 case PIPE_SWIZZLE_W: 883 dst[3] = src[i]; 884 break; 885 } 886 } 887 } 888