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