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