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_rect.h" 38 #include "u_format.h" 39 #include "u_format_s3tc.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 unsigned 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 == -1) { 57 return FALSE; 58 } 59 60 return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE; 61 } 62 63 64 /** 65 * Return the number of logical channels in the given format by 66 * examining swizzles. 67 * XXX this could be made into a public function if useful elsewhere. 68 */ 69 static unsigned 70 nr_logical_channels(const struct util_format_description *desc) 71 { 72 boolean swizzle_used[UTIL_FORMAT_SWIZZLE_MAX]; 73 74 memset(swizzle_used, 0, sizeof(swizzle_used)); 75 76 swizzle_used[desc->swizzle[0]] = TRUE; 77 swizzle_used[desc->swizzle[1]] = TRUE; 78 swizzle_used[desc->swizzle[2]] = TRUE; 79 swizzle_used[desc->swizzle[3]] = TRUE; 80 81 return (swizzle_used[UTIL_FORMAT_SWIZZLE_X] + 82 swizzle_used[UTIL_FORMAT_SWIZZLE_Y] + 83 swizzle_used[UTIL_FORMAT_SWIZZLE_Z] + 84 swizzle_used[UTIL_FORMAT_SWIZZLE_W]); 85 } 86 87 88 /** Test if the format contains RGB, but not alpha */ 89 boolean 90 util_format_is_rgb_no_alpha(enum pipe_format format) 91 { 92 const struct util_format_description *desc = 93 util_format_description(format); 94 95 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || 96 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && 97 nr_logical_channels(desc) == 3) { 98 return TRUE; 99 } 100 return FALSE; 101 } 102 103 104 boolean 105 util_format_is_luminance(enum pipe_format format) 106 { 107 const struct util_format_description *desc = 108 util_format_description(format); 109 110 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || 111 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && 112 desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X && 113 desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X && 114 desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X && 115 desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1) { 116 return TRUE; 117 } 118 return FALSE; 119 } 120 121 boolean 122 util_format_is_pure_integer(enum pipe_format format) 123 { 124 const struct util_format_description *desc = util_format_description(format); 125 int i; 126 127 /* Find the first non-void channel. */ 128 i = util_format_get_first_non_void_channel(format); 129 if (i == -1) 130 return FALSE; 131 132 return desc->channel[i].pure_integer ? TRUE : FALSE; 133 } 134 135 boolean 136 util_format_is_pure_sint(enum pipe_format format) 137 { 138 const struct util_format_description *desc = util_format_description(format); 139 int i; 140 141 i = util_format_get_first_non_void_channel(format); 142 if (i == -1) 143 return FALSE; 144 145 return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE; 146 } 147 148 boolean 149 util_format_is_pure_uint(enum pipe_format format) 150 { 151 const struct util_format_description *desc = util_format_description(format); 152 int i; 153 154 i = util_format_get_first_non_void_channel(format); 155 if (i == -1) 156 return FALSE; 157 158 return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE; 159 } 160 161 boolean 162 util_format_is_array(const struct util_format_description *desc) 163 { 164 unsigned chan; 165 166 if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN || 167 desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB || 168 desc->block.width != 1 || 169 desc->block.height != 1) { 170 return FALSE; 171 } 172 173 for (chan = 0; chan < desc->nr_channels; ++chan) { 174 if (desc->swizzle[chan] != chan) 175 return FALSE; 176 177 if (desc->channel[chan].type != desc->channel[0].type) 178 return FALSE; 179 180 if (desc->channel[chan].normalized != desc->channel[0].normalized) 181 return FALSE; 182 183 if (desc->channel[chan].pure_integer != desc->channel[0].pure_integer) 184 return FALSE; 185 186 if (desc->channel[chan].size != desc->channel[0].size) 187 return FALSE; 188 } 189 190 return TRUE; 191 } 192 193 boolean 194 util_format_is_luminance_alpha(enum pipe_format format) 195 { 196 const struct util_format_description *desc = 197 util_format_description(format); 198 199 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || 200 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && 201 desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X && 202 desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X && 203 desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X && 204 desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_Y) { 205 return TRUE; 206 } 207 return FALSE; 208 } 209 210 211 boolean 212 util_format_is_intensity(enum pipe_format format) 213 { 214 const struct util_format_description *desc = 215 util_format_description(format); 216 217 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || 218 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) && 219 desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X && 220 desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X && 221 desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X && 222 desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_X) { 223 return TRUE; 224 } 225 return FALSE; 226 } 227 228 229 boolean 230 util_format_is_supported(enum pipe_format format, unsigned bind) 231 { 232 if (util_format_is_s3tc(format) && !util_format_s3tc_enabled) { 233 return FALSE; 234 } 235 236 #ifndef TEXTURE_FLOAT_ENABLED 237 if ((bind & PIPE_BIND_RENDER_TARGET) && 238 format != PIPE_FORMAT_R9G9B9E5_FLOAT && 239 format != PIPE_FORMAT_R11G11B10_FLOAT && 240 util_format_is_float(format)) { 241 return FALSE; 242 } 243 #endif 244 245 return TRUE; 246 } 247 248 249 void 250 util_format_read_4f(enum pipe_format format, 251 float *dst, unsigned dst_stride, 252 const void *src, unsigned src_stride, 253 unsigned x, unsigned y, unsigned w, unsigned h) 254 { 255 const struct util_format_description *format_desc; 256 const uint8_t *src_row; 257 float *dst_row; 258 259 format_desc = util_format_description(format); 260 261 assert(x % format_desc->block.width == 0); 262 assert(y % format_desc->block.height == 0); 263 264 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); 265 dst_row = dst; 266 267 format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h); 268 } 269 270 271 void 272 util_format_write_4f(enum pipe_format format, 273 const float *src, unsigned src_stride, 274 void *dst, unsigned dst_stride, 275 unsigned x, unsigned y, unsigned w, unsigned h) 276 { 277 const struct util_format_description *format_desc; 278 uint8_t *dst_row; 279 const float *src_row; 280 281 format_desc = util_format_description(format); 282 283 assert(x % format_desc->block.width == 0); 284 assert(y % format_desc->block.height == 0); 285 286 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); 287 src_row = src; 288 289 format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h); 290 } 291 292 293 void 294 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) 295 { 296 const struct util_format_description *format_desc; 297 const uint8_t *src_row; 298 uint8_t *dst_row; 299 300 format_desc = util_format_description(format); 301 302 assert(x % format_desc->block.width == 0); 303 assert(y % format_desc->block.height == 0); 304 305 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); 306 dst_row = dst; 307 308 format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h); 309 } 310 311 312 void 313 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) 314 { 315 const struct util_format_description *format_desc; 316 uint8_t *dst_row; 317 const uint8_t *src_row; 318 319 format_desc = util_format_description(format); 320 321 assert(x % format_desc->block.width == 0); 322 assert(y % format_desc->block.height == 0); 323 324 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); 325 src_row = src; 326 327 format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h); 328 } 329 330 void 331 util_format_read_4ui(enum pipe_format format, 332 unsigned *dst, unsigned dst_stride, 333 const void *src, unsigned src_stride, 334 unsigned x, unsigned y, unsigned w, unsigned h) 335 { 336 const struct util_format_description *format_desc; 337 const uint8_t *src_row; 338 unsigned *dst_row; 339 340 format_desc = util_format_description(format); 341 342 assert(x % format_desc->block.width == 0); 343 assert(y % format_desc->block.height == 0); 344 345 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); 346 dst_row = dst; 347 348 format_desc->unpack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h); 349 } 350 351 void 352 util_format_write_4ui(enum pipe_format format, 353 const unsigned int *src, unsigned src_stride, 354 void *dst, unsigned dst_stride, 355 unsigned x, unsigned y, unsigned w, unsigned h) 356 { 357 const struct util_format_description *format_desc; 358 uint8_t *dst_row; 359 const unsigned *src_row; 360 361 format_desc = util_format_description(format); 362 363 assert(x % format_desc->block.width == 0); 364 assert(y % format_desc->block.height == 0); 365 366 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); 367 src_row = src; 368 369 format_desc->pack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h); 370 } 371 372 void 373 util_format_read_4i(enum pipe_format format, 374 int *dst, unsigned dst_stride, 375 const void *src, unsigned src_stride, 376 unsigned x, unsigned y, unsigned w, unsigned h) 377 { 378 const struct util_format_description *format_desc; 379 const uint8_t *src_row; 380 int *dst_row; 381 382 format_desc = util_format_description(format); 383 384 assert(x % format_desc->block.width == 0); 385 assert(y % format_desc->block.height == 0); 386 387 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); 388 dst_row = dst; 389 390 format_desc->unpack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h); 391 } 392 393 void 394 util_format_write_4i(enum pipe_format format, 395 const int *src, unsigned src_stride, 396 void *dst, unsigned dst_stride, 397 unsigned x, unsigned y, unsigned w, unsigned h) 398 { 399 const struct util_format_description *format_desc; 400 uint8_t *dst_row; 401 const int *src_row; 402 403 format_desc = util_format_description(format); 404 405 assert(x % format_desc->block.width == 0); 406 assert(y % format_desc->block.height == 0); 407 408 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); 409 src_row = src; 410 411 format_desc->pack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h); 412 } 413 414 boolean 415 util_is_format_compatible(const struct util_format_description *src_desc, 416 const struct util_format_description *dst_desc) 417 { 418 unsigned chan; 419 420 if (src_desc->format == dst_desc->format) { 421 return TRUE; 422 } 423 424 if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN || 425 dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) { 426 return FALSE; 427 } 428 429 if (src_desc->block.bits != dst_desc->block.bits || 430 src_desc->nr_channels != dst_desc->nr_channels || 431 src_desc->colorspace != dst_desc->colorspace) { 432 return FALSE; 433 } 434 435 for (chan = 0; chan < 4; ++chan) { 436 if (src_desc->channel[chan].size != 437 dst_desc->channel[chan].size) { 438 return FALSE; 439 } 440 } 441 442 for (chan = 0; chan < 4; ++chan) { 443 enum util_format_swizzle swizzle = dst_desc->swizzle[chan]; 444 445 if (swizzle < 4) { 446 if (src_desc->swizzle[chan] != swizzle) { 447 return FALSE; 448 } 449 if ((src_desc->channel[swizzle].type != 450 dst_desc->channel[swizzle].type) || 451 (src_desc->channel[swizzle].normalized != 452 dst_desc->channel[swizzle].normalized)) { 453 return FALSE; 454 } 455 } 456 } 457 458 return TRUE; 459 } 460 461 462 boolean 463 util_format_fits_8unorm(const struct util_format_description *format_desc) 464 { 465 unsigned chan; 466 467 /* 468 * After linearized sRGB values require more than 8bits. 469 */ 470 471 if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { 472 return FALSE; 473 } 474 475 switch (format_desc->layout) { 476 477 case UTIL_FORMAT_LAYOUT_S3TC: 478 /* 479 * These are straight forward. 480 */ 481 return TRUE; 482 case UTIL_FORMAT_LAYOUT_RGTC: 483 if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM || 484 format_desc->format == PIPE_FORMAT_RGTC2_SNORM || 485 format_desc->format == PIPE_FORMAT_LATC1_SNORM || 486 format_desc->format == PIPE_FORMAT_LATC2_SNORM) 487 return FALSE; 488 return TRUE; 489 490 case UTIL_FORMAT_LAYOUT_PLAIN: 491 /* 492 * For these we can find a generic rule. 493 */ 494 495 for (chan = 0; chan < format_desc->nr_channels; ++chan) { 496 switch (format_desc->channel[chan].type) { 497 case UTIL_FORMAT_TYPE_VOID: 498 break; 499 case UTIL_FORMAT_TYPE_UNSIGNED: 500 if (!format_desc->channel[chan].normalized || 501 format_desc->channel[chan].size > 8) { 502 return FALSE; 503 } 504 break; 505 default: 506 return FALSE; 507 } 508 } 509 return TRUE; 510 511 default: 512 /* 513 * Handle all others on a case by case basis. 514 */ 515 516 switch (format_desc->format) { 517 case PIPE_FORMAT_R1_UNORM: 518 case PIPE_FORMAT_UYVY: 519 case PIPE_FORMAT_YUYV: 520 case PIPE_FORMAT_R8G8_B8G8_UNORM: 521 case PIPE_FORMAT_G8R8_G8B8_UNORM: 522 return TRUE; 523 524 default: 525 return FALSE; 526 } 527 } 528 } 529 530 531 void 532 util_format_translate(enum pipe_format dst_format, 533 void *dst, unsigned dst_stride, 534 unsigned dst_x, unsigned dst_y, 535 enum pipe_format src_format, 536 const void *src, unsigned src_stride, 537 unsigned src_x, unsigned src_y, 538 unsigned width, unsigned height) 539 { 540 const struct util_format_description *dst_format_desc; 541 const struct util_format_description *src_format_desc; 542 uint8_t *dst_row; 543 const uint8_t *src_row; 544 unsigned x_step, y_step; 545 unsigned dst_step; 546 unsigned src_step; 547 548 dst_format_desc = util_format_description(dst_format); 549 src_format_desc = util_format_description(src_format); 550 551 if (util_is_format_compatible(src_format_desc, dst_format_desc)) { 552 /* 553 * Trivial case. 554 */ 555 556 util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y, 557 width, height, src, (int)src_stride, 558 src_x, src_y); 559 return; 560 } 561 562 assert(dst_x % dst_format_desc->block.width == 0); 563 assert(dst_y % dst_format_desc->block.height == 0); 564 assert(src_x % src_format_desc->block.width == 0); 565 assert(src_y % src_format_desc->block.height == 0); 566 567 dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8); 568 src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8); 569 570 /* 571 * This works because all pixel formats have pixel blocks with power of two 572 * sizes. 573 */ 574 575 y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height); 576 x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width); 577 assert(y_step % dst_format_desc->block.height == 0); 578 assert(y_step % src_format_desc->block.height == 0); 579 580 dst_step = y_step / dst_format_desc->block.height * dst_stride; 581 src_step = y_step / src_format_desc->block.height * src_stride; 582 583 /* 584 * TODO: double formats will loose precision 585 * TODO: Add a special case for formats that are mere swizzles of each other 586 */ 587 588 if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS || 589 dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { 590 float *tmp_z = NULL; 591 uint8_t *tmp_s = NULL; 592 593 assert(x_step == 1); 594 assert(y_step == 1); 595 596 if (src_format_desc->unpack_z_float && 597 dst_format_desc->pack_z_float) { 598 tmp_z = MALLOC(width * sizeof *tmp_z); 599 } 600 601 if (src_format_desc->unpack_s_8uint && 602 dst_format_desc->pack_s_8uint) { 603 tmp_s = MALLOC(width * sizeof *tmp_s); 604 } 605 606 while (height--) { 607 if (tmp_z) { 608 src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1); 609 dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1); 610 } 611 612 if (tmp_s) { 613 src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1); 614 dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1); 615 } 616 617 dst_row += dst_step; 618 src_row += src_step; 619 } 620 621 if (tmp_s) { 622 FREE(tmp_s); 623 } 624 625 if (tmp_z) { 626 FREE(tmp_z); 627 } 628 629 return; 630 } 631 632 if (util_format_fits_8unorm(src_format_desc) || 633 util_format_fits_8unorm(dst_format_desc)) { 634 unsigned tmp_stride; 635 uint8_t *tmp_row; 636 637 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; 638 tmp_row = MALLOC(y_step * tmp_stride); 639 if (!tmp_row) 640 return; 641 642 while (height >= y_step) { 643 src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step); 644 dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); 645 646 dst_row += dst_step; 647 src_row += src_step; 648 height -= y_step; 649 } 650 651 if (height) { 652 src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height); 653 dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height); 654 } 655 656 FREE(tmp_row); 657 } 658 else { 659 unsigned tmp_stride; 660 float *tmp_row; 661 662 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; 663 tmp_row = MALLOC(y_step * tmp_stride); 664 if (!tmp_row) 665 return; 666 667 while (height >= y_step) { 668 src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step); 669 dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); 670 671 dst_row += dst_step; 672 src_row += src_step; 673 height -= y_step; 674 } 675 676 if (height) { 677 src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height); 678 dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height); 679 } 680 681 FREE(tmp_row); 682 } 683 } 684 685 void util_format_compose_swizzles(const unsigned char swz1[4], 686 const unsigned char swz2[4], 687 unsigned char dst[4]) 688 { 689 unsigned i; 690 691 for (i = 0; i < 4; i++) { 692 dst[i] = swz2[i] <= UTIL_FORMAT_SWIZZLE_W ? 693 swz1[swz2[i]] : swz2[i]; 694 } 695 } 696 697 void util_format_swizzle_4f(float *dst, const float *src, 698 const unsigned char swz[4]) 699 { 700 unsigned i; 701 702 for (i = 0; i < 4; i++) { 703 if (swz[i] <= UTIL_FORMAT_SWIZZLE_W) 704 dst[i] = src[swz[i]]; 705 else if (swz[i] == UTIL_FORMAT_SWIZZLE_0) 706 dst[i] = 0; 707 else if (swz[i] == UTIL_FORMAT_SWIZZLE_1) 708 dst[i] = 1; 709 } 710 } 711 712 void util_format_unswizzle_4f(float *dst, const float *src, 713 const unsigned char swz[4]) 714 { 715 unsigned i; 716 717 for (i = 0; i < 4; i++) { 718 switch (swz[i]) { 719 case UTIL_FORMAT_SWIZZLE_X: 720 dst[0] = src[i]; 721 break; 722 case UTIL_FORMAT_SWIZZLE_Y: 723 dst[1] = src[i]; 724 break; 725 case UTIL_FORMAT_SWIZZLE_Z: 726 dst[2] = src[i]; 727 break; 728 case UTIL_FORMAT_SWIZZLE_W: 729 dst[3] = src[i]; 730 break; 731 } 732 } 733 } 734