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