gallium/{r600, radeonsi}: Fix segfault with color format (v2)
[mesa.git] / src / gallium / auxiliary / util / u_format.c
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@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 (format >= PIPE_FORMAT_COUNT) {
242 return FALSE;
243 }
244
245 if (util_format_is_s3tc(format) && !util_format_s3tc_enabled) {
246 return FALSE;
247 }
248
249 #ifndef TEXTURE_FLOAT_ENABLED
250 if ((bind & PIPE_BIND_RENDER_TARGET) &&
251 format != PIPE_FORMAT_R9G9B9E5_FLOAT &&
252 format != PIPE_FORMAT_R11G11B10_FLOAT &&
253 util_format_is_float(format)) {
254 return FALSE;
255 }
256 #endif
257
258 return TRUE;
259 }
260
261
262 /**
263 * Calculates the MRD for the depth format. MRD is used in depth bias
264 * for UNORM and unbound depth buffers. When the depth buffer is floating
265 * point, the depth bias calculation does not use the MRD. However, the
266 * default MRD will be 1.0 / ((1 << 24) - 1).
267 */
268 double
269 util_get_depth_format_mrd(const struct util_format_description *desc)
270 {
271 /*
272 * Depth buffer formats without a depth component OR scenarios
273 * without a bound depth buffer default to D24.
274 */
275 double mrd = 1.0 / ((1 << 24) - 1);
276 unsigned depth_channel;
277
278 assert(desc);
279
280 /*
281 * Some depth formats do not store the depth component in the first
282 * channel, detect the format and adjust the depth channel. Get the
283 * swizzled depth component channel.
284 */
285 depth_channel = desc->swizzle[0];
286
287 if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
288 desc->channel[depth_channel].normalized) {
289 int depth_bits;
290
291 depth_bits = desc->channel[depth_channel].size;
292 mrd = 1.0 / ((1ULL << depth_bits) - 1);
293 }
294
295 return mrd;
296 }
297
298
299 void
300 util_format_read_4f(enum pipe_format format,
301 float *dst, unsigned dst_stride,
302 const void *src, unsigned src_stride,
303 unsigned x, unsigned y, unsigned w, unsigned h)
304 {
305 const struct util_format_description *format_desc;
306 const uint8_t *src_row;
307 float *dst_row;
308
309 format_desc = util_format_description(format);
310
311 assert(x % format_desc->block.width == 0);
312 assert(y % format_desc->block.height == 0);
313
314 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
315 dst_row = dst;
316
317 format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
318 }
319
320
321 void
322 util_format_write_4f(enum pipe_format format,
323 const float *src, unsigned src_stride,
324 void *dst, unsigned dst_stride,
325 unsigned x, unsigned y, unsigned w, unsigned h)
326 {
327 const struct util_format_description *format_desc;
328 uint8_t *dst_row;
329 const float *src_row;
330
331 format_desc = util_format_description(format);
332
333 assert(x % format_desc->block.width == 0);
334 assert(y % format_desc->block.height == 0);
335
336 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
337 src_row = src;
338
339 format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
340 }
341
342
343 void
344 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)
345 {
346 const struct util_format_description *format_desc;
347 const uint8_t *src_row;
348 uint8_t *dst_row;
349
350 format_desc = util_format_description(format);
351
352 assert(x % format_desc->block.width == 0);
353 assert(y % format_desc->block.height == 0);
354
355 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
356 dst_row = dst;
357
358 format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
359 }
360
361
362 void
363 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)
364 {
365 const struct util_format_description *format_desc;
366 uint8_t *dst_row;
367 const uint8_t *src_row;
368
369 format_desc = util_format_description(format);
370
371 assert(x % format_desc->block.width == 0);
372 assert(y % format_desc->block.height == 0);
373
374 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
375 src_row = src;
376
377 format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
378 }
379
380 void
381 util_format_read_4ui(enum pipe_format format,
382 unsigned *dst, unsigned dst_stride,
383 const void *src, unsigned src_stride,
384 unsigned x, unsigned y, unsigned w, unsigned h)
385 {
386 const struct util_format_description *format_desc;
387 const uint8_t *src_row;
388 uint32_t *dst_row;
389
390 format_desc = util_format_description(format);
391
392 assert(x % format_desc->block.width == 0);
393 assert(y % format_desc->block.height == 0);
394
395 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
396 dst_row = dst;
397
398 format_desc->unpack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
399 }
400
401 void
402 util_format_write_4ui(enum pipe_format format,
403 const unsigned int *src, unsigned src_stride,
404 void *dst, unsigned dst_stride,
405 unsigned x, unsigned y, unsigned w, unsigned h)
406 {
407 const struct util_format_description *format_desc;
408 uint8_t *dst_row;
409 const uint32_t *src_row;
410
411 format_desc = util_format_description(format);
412
413 assert(x % format_desc->block.width == 0);
414 assert(y % format_desc->block.height == 0);
415
416 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
417 src_row = src;
418
419 format_desc->pack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
420 }
421
422 void
423 util_format_read_4i(enum pipe_format format,
424 int *dst, unsigned dst_stride,
425 const void *src, unsigned src_stride,
426 unsigned x, unsigned y, unsigned w, unsigned h)
427 {
428 const struct util_format_description *format_desc;
429 const uint8_t *src_row;
430 int32_t *dst_row;
431
432 format_desc = util_format_description(format);
433
434 assert(x % format_desc->block.width == 0);
435 assert(y % format_desc->block.height == 0);
436
437 src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
438 dst_row = dst;
439
440 format_desc->unpack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
441 }
442
443 void
444 util_format_write_4i(enum pipe_format format,
445 const int *src, unsigned src_stride,
446 void *dst, unsigned dst_stride,
447 unsigned x, unsigned y, unsigned w, unsigned h)
448 {
449 const struct util_format_description *format_desc;
450 uint8_t *dst_row;
451 const int32_t *src_row;
452
453 format_desc = util_format_description(format);
454
455 assert(x % format_desc->block.width == 0);
456 assert(y % format_desc->block.height == 0);
457
458 dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
459 src_row = src;
460
461 format_desc->pack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
462 }
463
464 /**
465 * Check if we can safely memcopy from the source format to the dest format.
466 * This basically covers the cases of a "used" channel copied to a typeless
467 * channel, plus some 1-channel cases.
468 * Examples of compatible copy formats include:
469 * b8g8r8a8_unorm -> b8g8r8x8_unorm
470 * a8r8g8b8_unorm -> x8r8g8b8_unorm
471 * b5g5r5a1_unorm -> b5g5r5x1_unorm
472 * b4g4r4a4_unorm -> b4g4r4x4_unorm
473 * l8_unorm -> r8_unorm
474 * i8_unorm -> l8_unorm
475 * i8_unorm -> a8_unorm
476 * i8_unorm -> r8_unorm
477 * l16_unorm -> r16_unorm
478 * z24_unorm_s8_uint -> z24x8_unorm
479 * s8_uint_z24_unorm -> x8z24_unorm
480 * r8g8b8a8_unorm -> r8g8b8x8_unorm
481 * a8b8g8r8_srgb -> x8b8g8r8_srgb
482 * b8g8r8a8_srgb -> b8g8r8x8_srgb
483 * a8r8g8b8_srgb -> x8r8g8b8_srgb
484 * a8b8g8r8_unorm -> x8b8g8r8_unorm
485 * r10g10b10a2_uscaled -> r10g10b10x2_uscaled
486 * r10sg10sb10sa2u_norm -> r10g10b10x2_snorm
487 */
488 boolean
489 util_is_format_compatible(const struct util_format_description *src_desc,
490 const struct util_format_description *dst_desc)
491 {
492 unsigned chan;
493
494 if (src_desc->format == dst_desc->format) {
495 return TRUE;
496 }
497
498 if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
499 dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
500 return FALSE;
501 }
502
503 if (src_desc->block.bits != dst_desc->block.bits ||
504 src_desc->nr_channels != dst_desc->nr_channels ||
505 src_desc->colorspace != dst_desc->colorspace) {
506 return FALSE;
507 }
508
509 for (chan = 0; chan < 4; ++chan) {
510 if (src_desc->channel[chan].size !=
511 dst_desc->channel[chan].size) {
512 return FALSE;
513 }
514 }
515
516 for (chan = 0; chan < 4; ++chan) {
517 enum pipe_swizzle swizzle = dst_desc->swizzle[chan];
518
519 if (swizzle < 4) {
520 if (src_desc->swizzle[chan] != swizzle) {
521 return FALSE;
522 }
523 if ((src_desc->channel[swizzle].type !=
524 dst_desc->channel[swizzle].type) ||
525 (src_desc->channel[swizzle].normalized !=
526 dst_desc->channel[swizzle].normalized)) {
527 return FALSE;
528 }
529 }
530 }
531
532 return TRUE;
533 }
534
535
536 boolean
537 util_format_fits_8unorm(const struct util_format_description *format_desc)
538 {
539 unsigned chan;
540
541 /*
542 * After linearized sRGB values require more than 8bits.
543 */
544
545 if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
546 return FALSE;
547 }
548
549 switch (format_desc->layout) {
550
551 case UTIL_FORMAT_LAYOUT_S3TC:
552 /*
553 * These are straight forward.
554 */
555 return TRUE;
556 case UTIL_FORMAT_LAYOUT_RGTC:
557 if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
558 format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
559 format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
560 format_desc->format == PIPE_FORMAT_LATC2_SNORM)
561 return FALSE;
562 return TRUE;
563 case UTIL_FORMAT_LAYOUT_BPTC:
564 if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM)
565 return TRUE;
566 return FALSE;
567
568 case UTIL_FORMAT_LAYOUT_ETC:
569 if (format_desc->format == PIPE_FORMAT_ETC1_RGB8)
570 return TRUE;
571 return FALSE;
572
573 case UTIL_FORMAT_LAYOUT_PLAIN:
574 /*
575 * For these we can find a generic rule.
576 */
577
578 for (chan = 0; chan < format_desc->nr_channels; ++chan) {
579 switch (format_desc->channel[chan].type) {
580 case UTIL_FORMAT_TYPE_VOID:
581 break;
582 case UTIL_FORMAT_TYPE_UNSIGNED:
583 if (!format_desc->channel[chan].normalized ||
584 format_desc->channel[chan].size > 8) {
585 return FALSE;
586 }
587 break;
588 default:
589 return FALSE;
590 }
591 }
592 return TRUE;
593
594 default:
595 /*
596 * Handle all others on a case by case basis.
597 */
598
599 switch (format_desc->format) {
600 case PIPE_FORMAT_R1_UNORM:
601 case PIPE_FORMAT_UYVY:
602 case PIPE_FORMAT_YUYV:
603 case PIPE_FORMAT_R8G8_B8G8_UNORM:
604 case PIPE_FORMAT_G8R8_G8B8_UNORM:
605 return TRUE;
606
607 default:
608 return FALSE;
609 }
610 }
611 }
612
613
614 boolean
615 util_format_translate(enum pipe_format dst_format,
616 void *dst, unsigned dst_stride,
617 unsigned dst_x, unsigned dst_y,
618 enum pipe_format src_format,
619 const void *src, unsigned src_stride,
620 unsigned src_x, unsigned src_y,
621 unsigned width, unsigned height)
622 {
623 const struct util_format_description *dst_format_desc;
624 const struct util_format_description *src_format_desc;
625 uint8_t *dst_row;
626 const uint8_t *src_row;
627 unsigned x_step, y_step;
628 unsigned dst_step;
629 unsigned src_step;
630
631 dst_format_desc = util_format_description(dst_format);
632 src_format_desc = util_format_description(src_format);
633
634 if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
635 /*
636 * Trivial case.
637 */
638
639 util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y,
640 width, height, src, (int)src_stride,
641 src_x, src_y);
642 return TRUE;
643 }
644
645 assert(dst_x % dst_format_desc->block.width == 0);
646 assert(dst_y % dst_format_desc->block.height == 0);
647 assert(src_x % src_format_desc->block.width == 0);
648 assert(src_y % src_format_desc->block.height == 0);
649
650 dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
651 src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8);
652
653 /*
654 * This works because all pixel formats have pixel blocks with power of two
655 * sizes.
656 */
657
658 y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
659 x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
660 assert(y_step % dst_format_desc->block.height == 0);
661 assert(y_step % src_format_desc->block.height == 0);
662
663 dst_step = y_step / dst_format_desc->block.height * dst_stride;
664 src_step = y_step / src_format_desc->block.height * src_stride;
665
666 /*
667 * TODO: double formats will loose precision
668 * TODO: Add a special case for formats that are mere swizzles of each other
669 */
670
671 if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
672 dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
673 float *tmp_z = NULL;
674 uint8_t *tmp_s = NULL;
675
676 assert(x_step == 1);
677 assert(y_step == 1);
678
679 if (src_format_desc->unpack_z_float &&
680 dst_format_desc->pack_z_float) {
681 tmp_z = MALLOC(width * sizeof *tmp_z);
682 }
683
684 if (src_format_desc->unpack_s_8uint &&
685 dst_format_desc->pack_s_8uint) {
686 tmp_s = MALLOC(width * sizeof *tmp_s);
687 }
688
689 while (height--) {
690 if (tmp_z) {
691 src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1);
692 dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1);
693 }
694
695 if (tmp_s) {
696 src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1);
697 dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1);
698 }
699
700 dst_row += dst_step;
701 src_row += src_step;
702 }
703
704 FREE(tmp_s);
705
706 FREE(tmp_z);
707
708 return TRUE;
709 }
710
711 if (util_format_fits_8unorm(src_format_desc) ||
712 util_format_fits_8unorm(dst_format_desc)) {
713 unsigned tmp_stride;
714 uint8_t *tmp_row;
715
716 if (!src_format_desc->unpack_rgba_8unorm ||
717 !dst_format_desc->pack_rgba_8unorm) {
718 return FALSE;
719 }
720
721 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
722 tmp_row = MALLOC(y_step * tmp_stride);
723 if (!tmp_row)
724 return FALSE;
725
726 while (height >= y_step) {
727 src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
728 dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
729
730 dst_row += dst_step;
731 src_row += src_step;
732 height -= y_step;
733 }
734
735 if (height) {
736 src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height);
737 dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
738 }
739
740 FREE(tmp_row);
741 }
742 else {
743 unsigned tmp_stride;
744 float *tmp_row;
745
746 if (!src_format_desc->unpack_rgba_float ||
747 !dst_format_desc->pack_rgba_float) {
748 return FALSE;
749 }
750
751 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
752 tmp_row = MALLOC(y_step * tmp_stride);
753 if (!tmp_row)
754 return FALSE;
755
756 while (height >= y_step) {
757 src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
758 dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
759
760 dst_row += dst_step;
761 src_row += src_step;
762 height -= y_step;
763 }
764
765 if (height) {
766 src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height);
767 dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
768 }
769
770 FREE(tmp_row);
771 }
772 return TRUE;
773 }
774
775 boolean
776 util_format_translate_3d(enum pipe_format dst_format,
777 void *dst, unsigned dst_stride,
778 unsigned dst_slice_stride,
779 unsigned dst_x, unsigned dst_y,
780 unsigned dst_z,
781 enum pipe_format src_format,
782 const void *src, unsigned src_stride,
783 unsigned src_slice_stride,
784 unsigned src_x, unsigned src_y,
785 unsigned src_z, unsigned width,
786 unsigned height, unsigned depth)
787 {
788 uint8_t *dst_layer;
789 const uint8_t *src_layer;
790 unsigned z;
791 dst_layer = dst;
792 src_layer = src;
793 dst_layer += dst_z * dst_slice_stride;
794 src_layer += src_z * src_slice_stride;
795 for (z = 0; z < depth; ++z) {
796 if (!util_format_translate(dst_format, dst_layer, dst_stride,
797 dst_x, dst_y,
798 src_format, src_layer, src_stride,
799 src_x, src_y,
800 width, height))
801 return FALSE;
802
803 dst_layer += dst_slice_stride;
804 src_layer += src_slice_stride;
805 }
806 return TRUE;
807 }
808
809 void util_format_compose_swizzles(const unsigned char swz1[4],
810 const unsigned char swz2[4],
811 unsigned char dst[4])
812 {
813 unsigned i;
814
815 for (i = 0; i < 4; i++) {
816 dst[i] = swz2[i] <= PIPE_SWIZZLE_W ?
817 swz1[swz2[i]] : swz2[i];
818 }
819 }
820
821 void util_format_apply_color_swizzle(union pipe_color_union *dst,
822 const union pipe_color_union *src,
823 const unsigned char swz[4],
824 const boolean is_integer)
825 {
826 unsigned c;
827
828 if (is_integer) {
829 for (c = 0; c < 4; ++c) {
830 switch (swz[c]) {
831 case PIPE_SWIZZLE_X: dst->ui[c] = src->ui[0]; break;
832 case PIPE_SWIZZLE_Y: dst->ui[c] = src->ui[1]; break;
833 case PIPE_SWIZZLE_Z: dst->ui[c] = src->ui[2]; break;
834 case PIPE_SWIZZLE_W: dst->ui[c] = src->ui[3]; break;
835 default:
836 dst->ui[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1 : 0;
837 break;
838 }
839 }
840 } else {
841 for (c = 0; c < 4; ++c) {
842 switch (swz[c]) {
843 case PIPE_SWIZZLE_X: dst->f[c] = src->f[0]; break;
844 case PIPE_SWIZZLE_Y: dst->f[c] = src->f[1]; break;
845 case PIPE_SWIZZLE_Z: dst->f[c] = src->f[2]; break;
846 case PIPE_SWIZZLE_W: dst->f[c] = src->f[3]; break;
847 default:
848 dst->f[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1.0f : 0.0f;
849 break;
850 }
851 }
852 }
853 }
854
855 void pipe_swizzle_4f(float *dst, const float *src,
856 const unsigned char swz[4])
857 {
858 unsigned i;
859
860 for (i = 0; i < 4; i++) {
861 if (swz[i] <= PIPE_SWIZZLE_W)
862 dst[i] = src[swz[i]];
863 else if (swz[i] == PIPE_SWIZZLE_0)
864 dst[i] = 0;
865 else if (swz[i] == PIPE_SWIZZLE_1)
866 dst[i] = 1;
867 }
868 }
869
870 void util_format_unswizzle_4f(float *dst, const float *src,
871 const unsigned char swz[4])
872 {
873 unsigned i;
874
875 for (i = 0; i < 4; i++) {
876 switch (swz[i]) {
877 case PIPE_SWIZZLE_X:
878 dst[0] = src[i];
879 break;
880 case PIPE_SWIZZLE_Y:
881 dst[1] = src[i];
882 break;
883 case PIPE_SWIZZLE_Z:
884 dst[2] = src[i];
885 break;
886 case PIPE_SWIZZLE_W:
887 dst[3] = src[i];
888 break;
889 }
890 }
891 }