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