Merge branch 'mesa_7_5_branch'
[mesa.git] / src / gallium / auxiliary / util / u_tile.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 * RGBA/float tile get/put functions.
30 * Usable both by drivers and state trackers.
31 */
32
33
34 #include "pipe/p_defines.h"
35 #include "pipe/p_inlines.h"
36
37 #include "util/u_math.h"
38 #include "util/u_memory.h"
39 #include "util/u_rect.h"
40 #include "util/u_tile.h"
41
42
43 /**
44 * Move raw block of pixels from transfer object to user memory.
45 */
46 void
47 pipe_get_tile_raw(struct pipe_transfer *pt,
48 uint x, uint y, uint w, uint h,
49 void *dst, int dst_stride)
50 {
51 struct pipe_screen *screen = pt->texture->screen;
52 const void *src;
53
54 if (dst_stride == 0)
55 dst_stride = pf_get_nblocksx(&pt->block, w) * pt->block.size;
56
57 if (pipe_clip_tile(x, y, &w, &h, pt))
58 return;
59
60 src = screen->transfer_map(screen, pt);
61 assert(src);
62 if(!src)
63 return;
64
65 util_copy_rect(dst, &pt->block, dst_stride, 0, 0, w, h, src, pt->stride, x, y);
66
67 screen->transfer_unmap(screen, pt);
68 }
69
70
71 /**
72 * Move raw block of pixels from user memory to transfer object.
73 */
74 void
75 pipe_put_tile_raw(struct pipe_transfer *pt,
76 uint x, uint y, uint w, uint h,
77 const void *src, int src_stride)
78 {
79 struct pipe_screen *screen = pt->texture->screen;
80 void *dst;
81
82 if (src_stride == 0)
83 src_stride = pf_get_nblocksx(&pt->block, w) * pt->block.size;
84
85 if (pipe_clip_tile(x, y, &w, &h, pt))
86 return;
87
88 dst = screen->transfer_map(screen, pt);
89 assert(dst);
90 if(!dst)
91 return;
92
93 util_copy_rect(dst, &pt->block, pt->stride, x, y, w, h, src, src_stride, 0, 0);
94
95 screen->transfer_unmap(screen, pt);
96 }
97
98
99
100
101 /** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */
102 #define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
103
104 #define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
105 us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
106
107
108
109 /*** PIPE_FORMAT_A8R8G8B8_UNORM ***/
110
111 static void
112 a8r8g8b8_get_tile_rgba(const unsigned *src,
113 unsigned w, unsigned h,
114 float *p,
115 unsigned dst_stride)
116 {
117 unsigned i, j;
118
119 for (i = 0; i < h; i++) {
120 float *pRow = p;
121 for (j = 0; j < w; j++, pRow += 4) {
122 const unsigned pixel = *src++;
123 pRow[0] = ubyte_to_float((pixel >> 16) & 0xff);
124 pRow[1] = ubyte_to_float((pixel >> 8) & 0xff);
125 pRow[2] = ubyte_to_float((pixel >> 0) & 0xff);
126 pRow[3] = ubyte_to_float((pixel >> 24) & 0xff);
127 }
128 p += dst_stride;
129 }
130 }
131
132
133 static void
134 a8r8g8b8_put_tile_rgba(unsigned *dst,
135 unsigned w, unsigned h,
136 const float *p,
137 unsigned src_stride)
138 {
139 unsigned i, j;
140
141 for (i = 0; i < h; i++) {
142 const float *pRow = p;
143 for (j = 0; j < w; j++, pRow += 4) {
144 unsigned r, g, b, a;
145 r = float_to_ubyte(pRow[0]);
146 g = float_to_ubyte(pRow[1]);
147 b = float_to_ubyte(pRow[2]);
148 a = float_to_ubyte(pRow[3]);
149 *dst++ = (a << 24) | (r << 16) | (g << 8) | b;
150 }
151 p += src_stride;
152 }
153 }
154
155
156 /*** PIPE_FORMAT_X8R8G8B8_UNORM ***/
157
158 static void
159 x8r8g8b8_get_tile_rgba(const unsigned *src,
160 unsigned w, unsigned h,
161 float *p,
162 unsigned dst_stride)
163 {
164 unsigned i, j;
165
166 for (i = 0; i < h; i++) {
167 float *pRow = p;
168 for (j = 0; j < w; j++, pRow += 4) {
169 const unsigned pixel = *src++;
170 pRow[0] = ubyte_to_float((pixel >> 16) & 0xff);
171 pRow[1] = ubyte_to_float((pixel >> 8) & 0xff);
172 pRow[2] = ubyte_to_float((pixel >> 0) & 0xff);
173 pRow[3] = ubyte_to_float(0xff);
174 }
175 p += dst_stride;
176 }
177 }
178
179
180 static void
181 x8r8g8b8_put_tile_rgba(unsigned *dst,
182 unsigned w, unsigned h,
183 const float *p,
184 unsigned src_stride)
185 {
186 unsigned i, j;
187
188 for (i = 0; i < h; i++) {
189 const float *pRow = p;
190 for (j = 0; j < w; j++, pRow += 4) {
191 unsigned r, g, b;
192 r = float_to_ubyte(pRow[0]);
193 g = float_to_ubyte(pRow[1]);
194 b = float_to_ubyte(pRow[2]);
195 *dst++ = (0xff << 24) | (r << 16) | (g << 8) | b;
196 }
197 p += src_stride;
198 }
199 }
200
201
202 /*** PIPE_FORMAT_B8G8R8A8_UNORM ***/
203
204 static void
205 b8g8r8a8_get_tile_rgba(const unsigned *src,
206 unsigned w, unsigned h,
207 float *p,
208 unsigned dst_stride)
209 {
210 unsigned i, j;
211
212 for (i = 0; i < h; i++) {
213 float *pRow = p;
214 for (j = 0; j < w; j++, pRow += 4) {
215 const unsigned pixel = *src++;
216 pRow[0] = ubyte_to_float((pixel >> 8) & 0xff);
217 pRow[1] = ubyte_to_float((pixel >> 16) & 0xff);
218 pRow[2] = ubyte_to_float((pixel >> 24) & 0xff);
219 pRow[3] = ubyte_to_float((pixel >> 0) & 0xff);
220 }
221 p += dst_stride;
222 }
223 }
224
225
226 static void
227 b8g8r8a8_put_tile_rgba(unsigned *dst,
228 unsigned w, unsigned h,
229 const float *p,
230 unsigned src_stride)
231 {
232 unsigned i, j;
233
234 for (i = 0; i < h; i++) {
235 const float *pRow = p;
236 for (j = 0; j < w; j++, pRow += 4) {
237 unsigned r, g, b, a;
238 r = float_to_ubyte(pRow[0]);
239 g = float_to_ubyte(pRow[1]);
240 b = float_to_ubyte(pRow[2]);
241 a = float_to_ubyte(pRow[3]);
242 *dst++ = (b << 24) | (g << 16) | (r << 8) | a;
243 }
244 p += src_stride;
245 }
246 }
247
248
249 /*** PIPE_FORMAT_A1R5G5B5_UNORM ***/
250
251 static void
252 a1r5g5b5_get_tile_rgba(const ushort *src,
253 unsigned w, unsigned h,
254 float *p,
255 unsigned dst_stride)
256 {
257 unsigned i, j;
258
259 for (i = 0; i < h; i++) {
260 float *pRow = p;
261 for (j = 0; j < w; j++, pRow += 4) {
262 const ushort pixel = *src++;
263 pRow[0] = ((pixel >> 10) & 0x1f) * (1.0f / 31.0f);
264 pRow[1] = ((pixel >> 5) & 0x1f) * (1.0f / 31.0f);
265 pRow[2] = ((pixel ) & 0x1f) * (1.0f / 31.0f);
266 pRow[3] = ((pixel >> 15) ) * 1.0f;
267 }
268 p += dst_stride;
269 }
270 }
271
272
273 static void
274 a1r5g5b5_put_tile_rgba(ushort *dst,
275 unsigned w, unsigned h,
276 const float *p,
277 unsigned src_stride)
278 {
279 unsigned i, j;
280
281 for (i = 0; i < h; i++) {
282 const float *pRow = p;
283 for (j = 0; j < w; j++, pRow += 4) {
284 unsigned r, g, b, a;
285 r = float_to_ubyte(pRow[0]);
286 g = float_to_ubyte(pRow[1]);
287 b = float_to_ubyte(pRow[2]);
288 a = float_to_ubyte(pRow[3]);
289 r = r >> 3; /* 5 bits */
290 g = g >> 3; /* 5 bits */
291 b = b >> 3; /* 5 bits */
292 a = a >> 7; /* 1 bit */
293 *dst++ = (a << 15) | (r << 10) | (g << 5) | b;
294 }
295 p += src_stride;
296 }
297 }
298
299
300 /*** PIPE_FORMAT_A4R4G4B4_UNORM ***/
301
302 static void
303 a4r4g4b4_get_tile_rgba(const ushort *src,
304 unsigned w, unsigned h,
305 float *p,
306 unsigned dst_stride)
307 {
308 unsigned i, j;
309
310 for (i = 0; i < h; i++) {
311 float *pRow = p;
312 for (j = 0; j < w; j++, pRow += 4) {
313 const ushort pixel = *src++;
314 pRow[0] = ((pixel >> 8) & 0xf) * (1.0f / 15.0f);
315 pRow[1] = ((pixel >> 4) & 0xf) * (1.0f / 15.0f);
316 pRow[2] = ((pixel ) & 0xf) * (1.0f / 15.0f);
317 pRow[3] = ((pixel >> 12) ) * (1.0f / 15.0f);
318 }
319 p += dst_stride;
320 }
321 }
322
323
324 static void
325 a4r4g4b4_put_tile_rgba(ushort *dst,
326 unsigned w, unsigned h,
327 const float *p,
328 unsigned src_stride)
329 {
330 unsigned i, j;
331
332 for (i = 0; i < h; i++) {
333 const float *pRow = p;
334 for (j = 0; j < w; j++, pRow += 4) {
335 unsigned r, g, b, a;
336 r = float_to_ubyte(pRow[0]);
337 g = float_to_ubyte(pRow[1]);
338 b = float_to_ubyte(pRow[2]);
339 a = float_to_ubyte(pRow[3]);
340 r >>= 4;
341 g >>= 4;
342 b >>= 4;
343 a >>= 4;
344 *dst++ = (a << 12) | (r << 16) | (g << 4) | b;
345 }
346 p += src_stride;
347 }
348 }
349
350
351 /*** PIPE_FORMAT_R5G6B5_UNORM ***/
352
353 static void
354 r5g6b5_get_tile_rgba(const ushort *src,
355 unsigned w, unsigned h,
356 float *p,
357 unsigned dst_stride)
358 {
359 unsigned i, j;
360
361 for (i = 0; i < h; i++) {
362 float *pRow = p;
363 for (j = 0; j < w; j++, pRow += 4) {
364 const ushort pixel = *src++;
365 pRow[0] = ((pixel >> 11) & 0x1f) * (1.0f / 31.0f);
366 pRow[1] = ((pixel >> 5) & 0x3f) * (1.0f / 63.0f);
367 pRow[2] = ((pixel ) & 0x1f) * (1.0f / 31.0f);
368 pRow[3] = 1.0f;
369 }
370 p += dst_stride;
371 }
372 }
373
374
375 static void
376 r5g6b5_put_tile_rgba(ushort *dst,
377 unsigned w, unsigned h,
378 const float *p,
379 unsigned src_stride)
380 {
381 unsigned i, j;
382
383 for (i = 0; i < h; i++) {
384 const float *pRow = p;
385 for (j = 0; j < w; j++, pRow += 4) {
386 uint r = (uint) (CLAMP(pRow[0], 0.0, 1.0) * 31.0);
387 uint g = (uint) (CLAMP(pRow[1], 0.0, 1.0) * 63.0);
388 uint b = (uint) (CLAMP(pRow[2], 0.0, 1.0) * 31.0);
389 *dst++ = (r << 11) | (g << 5) | (b);
390 }
391 p += src_stride;
392 }
393 }
394
395
396
397 /*** PIPE_FORMAT_Z16_UNORM ***/
398
399 /**
400 * Return each Z value as four floats in [0,1].
401 */
402 static void
403 z16_get_tile_rgba(const ushort *src,
404 unsigned w, unsigned h,
405 float *p,
406 unsigned dst_stride)
407 {
408 const float scale = 1.0f / 65535.0f;
409 unsigned i, j;
410
411 for (i = 0; i < h; i++) {
412 float *pRow = p;
413 for (j = 0; j < w; j++, pRow += 4) {
414 pRow[0] =
415 pRow[1] =
416 pRow[2] =
417 pRow[3] = *src++ * scale;
418 }
419 p += dst_stride;
420 }
421 }
422
423
424
425
426 /*** PIPE_FORMAT_L8_UNORM ***/
427
428 static void
429 l8_get_tile_rgba(const ubyte *src,
430 unsigned w, unsigned h,
431 float *p,
432 unsigned dst_stride)
433 {
434 unsigned i, j;
435
436 for (i = 0; i < h; i++) {
437 float *pRow = p;
438 for (j = 0; j < w; j++, src++, pRow += 4) {
439 pRow[0] =
440 pRow[1] =
441 pRow[2] = ubyte_to_float(*src);
442 pRow[3] = 1.0;
443 }
444 p += dst_stride;
445 }
446 }
447
448
449 static void
450 l8_put_tile_rgba(ubyte *dst,
451 unsigned w, unsigned h,
452 const float *p,
453 unsigned src_stride)
454 {
455 unsigned i, j;
456
457 for (i = 0; i < h; i++) {
458 const float *pRow = p;
459 for (j = 0; j < w; j++, pRow += 4) {
460 unsigned r;
461 r = float_to_ubyte(pRow[0]);
462 *dst++ = (ubyte) r;
463 }
464 p += src_stride;
465 }
466 }
467
468
469
470 /*** PIPE_FORMAT_A8_UNORM ***/
471
472 static void
473 a8_get_tile_rgba(const ubyte *src,
474 unsigned w, unsigned h,
475 float *p,
476 unsigned dst_stride)
477 {
478 unsigned i, j;
479
480 for (i = 0; i < h; i++) {
481 float *pRow = p;
482 for (j = 0; j < w; j++, src++, pRow += 4) {
483 pRow[0] =
484 pRow[1] =
485 pRow[2] = 0.0;
486 pRow[3] = ubyte_to_float(*src);
487 }
488 p += dst_stride;
489 }
490 }
491
492
493 static void
494 a8_put_tile_rgba(ubyte *dst,
495 unsigned w, unsigned h,
496 const float *p,
497 unsigned src_stride)
498 {
499 unsigned i, j;
500
501 for (i = 0; i < h; i++) {
502 const float *pRow = p;
503 for (j = 0; j < w; j++, pRow += 4) {
504 unsigned a;
505 a = float_to_ubyte(pRow[3]);
506 *dst++ = (ubyte) a;
507 }
508 p += src_stride;
509 }
510 }
511
512
513
514 /*** PIPE_FORMAT_R16_SNORM ***/
515
516 static void
517 r16_get_tile_rgba(const short *src,
518 unsigned w, unsigned h,
519 float *p,
520 unsigned dst_stride)
521 {
522 unsigned i, j;
523
524 for (i = 0; i < h; i++) {
525 float *pRow = p;
526 for (j = 0; j < w; j++, src++, pRow += 4) {
527 pRow[0] = SHORT_TO_FLOAT(src[0]);
528 pRow[1] =
529 pRow[2] = 0.0;
530 pRow[3] = 1.0;
531 }
532 p += dst_stride;
533 }
534 }
535
536
537 static void
538 r16_put_tile_rgba(short *dst,
539 unsigned w, unsigned h,
540 const float *p,
541 unsigned src_stride)
542 {
543 unsigned i, j;
544
545 for (i = 0; i < h; i++) {
546 const float *pRow = p;
547 for (j = 0; j < w; j++, dst++, pRow += 4) {
548 UNCLAMPED_FLOAT_TO_SHORT(dst[0], pRow[0]);
549 }
550 p += src_stride;
551 }
552 }
553
554
555 /*** PIPE_FORMAT_R16G16B16A16_SNORM ***/
556
557 static void
558 r16g16b16a16_get_tile_rgba(const short *src,
559 unsigned w, unsigned h,
560 float *p,
561 unsigned dst_stride)
562 {
563 unsigned i, j;
564
565 for (i = 0; i < h; i++) {
566 float *pRow = p;
567 for (j = 0; j < w; j++, src += 4, pRow += 4) {
568 pRow[0] = SHORT_TO_FLOAT(src[0]);
569 pRow[1] = SHORT_TO_FLOAT(src[1]);
570 pRow[2] = SHORT_TO_FLOAT(src[2]);
571 pRow[3] = SHORT_TO_FLOAT(src[3]);
572 }
573 p += dst_stride;
574 }
575 }
576
577
578 static void
579 r16g16b16a16_put_tile_rgba(short *dst,
580 unsigned w, unsigned h,
581 const float *p,
582 unsigned src_stride)
583 {
584 unsigned i, j;
585
586 for (i = 0; i < h; i++) {
587 const float *pRow = p;
588 for (j = 0; j < w; j++, dst += 4, pRow += 4) {
589 UNCLAMPED_FLOAT_TO_SHORT(dst[0], pRow[0]);
590 UNCLAMPED_FLOAT_TO_SHORT(dst[1], pRow[1]);
591 UNCLAMPED_FLOAT_TO_SHORT(dst[2], pRow[2]);
592 UNCLAMPED_FLOAT_TO_SHORT(dst[3], pRow[3]);
593 }
594 p += src_stride;
595 }
596 }
597
598
599
600 /*** PIPE_FORMAT_I8_UNORM ***/
601
602 static void
603 i8_get_tile_rgba(const ubyte *src,
604 unsigned w, unsigned h,
605 float *p,
606 unsigned dst_stride)
607 {
608 unsigned i, j;
609
610 for (i = 0; i < h; i++) {
611 float *pRow = p;
612 for (j = 0; j < w; j++, src++, pRow += 4) {
613 pRow[0] =
614 pRow[1] =
615 pRow[2] =
616 pRow[3] = ubyte_to_float(*src);
617 }
618 p += dst_stride;
619 }
620 }
621
622
623 static void
624 i8_put_tile_rgba(ubyte *dst,
625 unsigned w, unsigned h,
626 const float *p,
627 unsigned src_stride)
628 {
629 unsigned i, j;
630
631 for (i = 0; i < h; i++) {
632 const float *pRow = p;
633 for (j = 0; j < w; j++, pRow += 4) {
634 unsigned r;
635 r = float_to_ubyte(pRow[0]);
636 *dst++ = (ubyte) r;
637 }
638 p += src_stride;
639 }
640 }
641
642
643 /*** PIPE_FORMAT_A8L8_UNORM ***/
644
645 static void
646 a8l8_get_tile_rgba(const ushort *src,
647 unsigned w, unsigned h,
648 float *p,
649 unsigned dst_stride)
650 {
651 unsigned i, j;
652
653 for (i = 0; i < h; i++) {
654 float *pRow = p;
655 for (j = 0; j < w; j++, pRow += 4) {
656 ushort p = *src++;
657 pRow[0] =
658 pRow[1] =
659 pRow[2] = ubyte_to_float(p & 0xff);
660 pRow[3] = ubyte_to_float(p >> 8);
661 }
662 p += dst_stride;
663 }
664 }
665
666
667 static void
668 a8l8_put_tile_rgba(ushort *dst,
669 unsigned w, unsigned h,
670 const float *p,
671 unsigned src_stride)
672 {
673 unsigned i, j;
674
675 for (i = 0; i < h; i++) {
676 const float *pRow = p;
677 for (j = 0; j < w; j++, pRow += 4) {
678 unsigned r, a;
679 r = float_to_ubyte(pRow[0]);
680 a = float_to_ubyte(pRow[3]);
681 *dst++ = (a << 8) | r;
682 }
683 p += src_stride;
684 }
685 }
686
687
688
689
690 /*** PIPE_FORMAT_Z32_UNORM ***/
691
692 /**
693 * Return each Z value as four floats in [0,1].
694 */
695 static void
696 z32_get_tile_rgba(const unsigned *src,
697 unsigned w, unsigned h,
698 float *p,
699 unsigned dst_stride)
700 {
701 const double scale = 1.0 / (double) 0xffffffff;
702 unsigned i, j;
703
704 for (i = 0; i < h; i++) {
705 float *pRow = p;
706 for (j = 0; j < w; j++, pRow += 4) {
707 pRow[0] =
708 pRow[1] =
709 pRow[2] =
710 pRow[3] = (float) (*src++ * scale);
711 }
712 p += dst_stride;
713 }
714 }
715
716
717 /*** PIPE_FORMAT_S8Z24_UNORM ***/
718
719 /**
720 * Return Z component as four float in [0,1]. Stencil part ignored.
721 */
722 static void
723 s8z24_get_tile_rgba(const unsigned *src,
724 unsigned w, unsigned h,
725 float *p,
726 unsigned dst_stride)
727 {
728 const double scale = 1.0 / ((1 << 24) - 1);
729 unsigned i, j;
730
731 for (i = 0; i < h; i++) {
732 float *pRow = p;
733 for (j = 0; j < w; j++, pRow += 4) {
734 pRow[0] =
735 pRow[1] =
736 pRow[2] =
737 pRow[3] = (float) (scale * (*src++ & 0xffffff));
738 }
739 p += dst_stride;
740 }
741 }
742
743
744 /*** PIPE_FORMAT_Z24S8_UNORM ***/
745
746 /**
747 * Return Z component as four float in [0,1]. Stencil part ignored.
748 */
749 static void
750 z24s8_get_tile_rgba(const unsigned *src,
751 unsigned w, unsigned h,
752 float *p,
753 unsigned dst_stride)
754 {
755 const double scale = 1.0 / ((1 << 24) - 1);
756 unsigned i, j;
757
758 for (i = 0; i < h; i++) {
759 float *pRow = p;
760 for (j = 0; j < w; j++, pRow += 4) {
761 pRow[0] =
762 pRow[1] =
763 pRow[2] =
764 pRow[3] = (float) (scale * (*src++ >> 8));
765 }
766 p += dst_stride;
767 }
768 }
769
770
771 /*** PIPE_FORMAT_Z32_FLOAT ***/
772
773 /**
774 * Return each Z value as four floats in [0,1].
775 */
776 static void
777 z32f_get_tile_rgba(const float *src,
778 unsigned w, unsigned h,
779 float *p,
780 unsigned dst_stride)
781 {
782 unsigned i, j;
783
784 for (i = 0; i < h; i++) {
785 float *pRow = p;
786 for (j = 0; j < w; j++, pRow += 4) {
787 pRow[0] =
788 pRow[1] =
789 pRow[2] =
790 pRow[3] = *src++;
791 }
792 p += dst_stride;
793 }
794 }
795
796
797 /*** PIPE_FORMAT_YCBCR / PIPE_FORMAT_YCBCR_REV ***/
798
799 /**
800 * Convert YCbCr (or YCrCb) to RGBA.
801 */
802 static void
803 ycbcr_get_tile_rgba(const ushort *src,
804 unsigned w, unsigned h,
805 float *p,
806 unsigned dst_stride,
807 boolean rev)
808 {
809 const float scale = 1.0f / 255.0f;
810 unsigned i, j;
811
812 for (i = 0; i < h; i++) {
813 float *pRow = p;
814 /* do two texels at a time */
815 for (j = 0; j < (w & ~1); j += 2, src += 2) {
816 const ushort t0 = src[0];
817 const ushort t1 = src[1];
818 const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */
819 const ubyte y1 = (t1 >> 8) & 0xff; /* luminance */
820 ubyte cb, cr;
821 float r, g, b;
822
823 if (rev) {
824 cb = t1 & 0xff; /* chroma U */
825 cr = t0 & 0xff; /* chroma V */
826 }
827 else {
828 cb = t0 & 0xff; /* chroma U */
829 cr = t1 & 0xff; /* chroma V */
830 }
831
832 /* even pixel: y0,cr,cb */
833 r = 1.164f * (y0-16) + 1.596f * (cr-128);
834 g = 1.164f * (y0-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
835 b = 1.164f * (y0-16) + 2.018f * (cb-128);
836 pRow[0] = r * scale;
837 pRow[1] = g * scale;
838 pRow[2] = b * scale;
839 pRow[3] = 1.0f;
840 pRow += 4;
841
842 /* odd pixel: use y1,cr,cb */
843 r = 1.164f * (y1-16) + 1.596f * (cr-128);
844 g = 1.164f * (y1-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
845 b = 1.164f * (y1-16) + 2.018f * (cb-128);
846 pRow[0] = r * scale;
847 pRow[1] = g * scale;
848 pRow[2] = b * scale;
849 pRow[3] = 1.0f;
850 pRow += 4;
851
852 }
853 /* do the last texel */
854 if (w & 1) {
855 const ushort t0 = src[0];
856 const ushort t1 = src[1];
857 const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */
858 ubyte cb, cr;
859 float r, g, b;
860
861 if (rev) {
862 cb = t1 & 0xff; /* chroma U */
863 cr = t0 & 0xff; /* chroma V */
864 }
865 else {
866 cb = t0 & 0xff; /* chroma U */
867 cr = t1 & 0xff; /* chroma V */
868 }
869
870 /* even pixel: y0,cr,cb */
871 r = 1.164f * (y0-16) + 1.596f * (cr-128);
872 g = 1.164f * (y0-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
873 b = 1.164f * (y0-16) + 2.018f * (cb-128);
874 pRow[0] = r * scale;
875 pRow[1] = g * scale;
876 pRow[2] = b * scale;
877 pRow[3] = 1.0f;
878 pRow += 4;
879 }
880 p += dst_stride;
881 }
882 }
883
884
885 static void
886 fake_get_tile_rgba(const ushort *src,
887 unsigned w, unsigned h,
888 float *p,
889 unsigned dst_stride)
890 {
891 unsigned i, j;
892
893 for (i = 0; i < h; i++) {
894 float *pRow = p;
895 for (j = 0; j < w; j++, pRow += 4) {
896 pRow[0] =
897 pRow[1] =
898 pRow[2] =
899 pRow[3] = (i ^ j) & 1 ? 1.0f : 0.0f;
900 }
901 p += dst_stride;
902 }
903 }
904
905
906 void
907 pipe_tile_raw_to_rgba(enum pipe_format format,
908 void *src,
909 uint w, uint h,
910 float *dst, unsigned dst_stride)
911 {
912 switch (format) {
913 case PIPE_FORMAT_A8R8G8B8_UNORM:
914 a8r8g8b8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
915 break;
916 case PIPE_FORMAT_X8R8G8B8_UNORM:
917 x8r8g8b8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
918 break;
919 case PIPE_FORMAT_B8G8R8A8_UNORM:
920 b8g8r8a8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
921 break;
922 case PIPE_FORMAT_A1R5G5B5_UNORM:
923 a1r5g5b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
924 break;
925 case PIPE_FORMAT_A4R4G4B4_UNORM:
926 a4r4g4b4_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
927 break;
928 case PIPE_FORMAT_R5G6B5_UNORM:
929 r5g6b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
930 break;
931 case PIPE_FORMAT_L8_UNORM:
932 l8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
933 break;
934 case PIPE_FORMAT_A8_UNORM:
935 a8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
936 break;
937 case PIPE_FORMAT_I8_UNORM:
938 i8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
939 break;
940 case PIPE_FORMAT_A8L8_UNORM:
941 a8l8_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
942 break;
943 case PIPE_FORMAT_R16_SNORM:
944 r16_get_tile_rgba((short *) src, w, h, dst, dst_stride);
945 break;
946 case PIPE_FORMAT_R16G16B16A16_SNORM:
947 r16g16b16a16_get_tile_rgba((short *) src, w, h, dst, dst_stride);
948 break;
949 case PIPE_FORMAT_Z16_UNORM:
950 z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
951 break;
952 case PIPE_FORMAT_Z32_UNORM:
953 z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
954 break;
955 case PIPE_FORMAT_S8Z24_UNORM:
956 case PIPE_FORMAT_X8Z24_UNORM:
957 s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
958 break;
959 case PIPE_FORMAT_Z24S8_UNORM:
960 case PIPE_FORMAT_Z24X8_UNORM:
961 z24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
962 break;
963 case PIPE_FORMAT_Z32_FLOAT:
964 z32f_get_tile_rgba((float *) src, w, h, dst, dst_stride);
965 break;
966 case PIPE_FORMAT_YCBCR:
967 ycbcr_get_tile_rgba((ushort *) src, w, h, dst, dst_stride, FALSE);
968 break;
969 case PIPE_FORMAT_YCBCR_REV:
970 ycbcr_get_tile_rgba((ushort *) src, w, h, dst, dst_stride, TRUE);
971 break;
972 default:
973 debug_printf("%s: unsupported format %s\n", __FUNCTION__, pf_name(format));
974 fake_get_tile_rgba(src, w, h, dst, dst_stride);
975 }
976 }
977
978
979 void
980 pipe_get_tile_rgba(struct pipe_transfer *pt,
981 uint x, uint y, uint w, uint h,
982 float *p)
983 {
984 unsigned dst_stride = w * 4;
985 void *packed;
986
987 if (pipe_clip_tile(x, y, &w, &h, pt))
988 return;
989
990 packed = MALLOC(pf_get_nblocks(&pt->block, w, h) * pt->block.size);
991
992 if (!packed)
993 return;
994
995 if(pt->format == PIPE_FORMAT_YCBCR || pt->format == PIPE_FORMAT_YCBCR_REV)
996 assert((x & 1) == 0);
997
998 pipe_get_tile_raw(pt, x, y, w, h, packed, 0);
999
1000 pipe_tile_raw_to_rgba(pt->format, packed, w, h, p, dst_stride);
1001
1002 FREE(packed);
1003 }
1004
1005
1006 void
1007 pipe_put_tile_rgba(struct pipe_transfer *pt,
1008 uint x, uint y, uint w, uint h,
1009 const float *p)
1010 {
1011 unsigned src_stride = w * 4;
1012 void *packed;
1013
1014 if (pipe_clip_tile(x, y, &w, &h, pt))
1015 return;
1016
1017 packed = MALLOC(pf_get_nblocks(&pt->block, w, h) * pt->block.size);
1018
1019 if (!packed)
1020 return;
1021
1022 switch (pt->format) {
1023 case PIPE_FORMAT_A8R8G8B8_UNORM:
1024 a8r8g8b8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);
1025 break;
1026 case PIPE_FORMAT_X8R8G8B8_UNORM:
1027 x8r8g8b8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);
1028 break;
1029 case PIPE_FORMAT_B8G8R8A8_UNORM:
1030 b8g8r8a8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);
1031 break;
1032 case PIPE_FORMAT_A1R5G5B5_UNORM:
1033 a1r5g5b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
1034 break;
1035 case PIPE_FORMAT_R5G6B5_UNORM:
1036 r5g6b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
1037 break;
1038 case PIPE_FORMAT_R8G8B8A8_UNORM:
1039 assert(0);
1040 break;
1041 case PIPE_FORMAT_A4R4G4B4_UNORM:
1042 a4r4g4b4_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
1043 break;
1044 case PIPE_FORMAT_L8_UNORM:
1045 l8_put_tile_rgba((ubyte *) packed, w, h, p, src_stride);
1046 break;
1047 case PIPE_FORMAT_A8_UNORM:
1048 a8_put_tile_rgba((ubyte *) packed, w, h, p, src_stride);
1049 break;
1050 case PIPE_FORMAT_I8_UNORM:
1051 i8_put_tile_rgba((ubyte *) packed, w, h, p, src_stride);
1052 break;
1053 case PIPE_FORMAT_A8L8_UNORM:
1054 a8l8_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
1055 break;
1056 case PIPE_FORMAT_R16_SNORM:
1057 r16_put_tile_rgba((short *) packed, w, h, p, src_stride);
1058 break;
1059 case PIPE_FORMAT_R16G16B16A16_SNORM:
1060 r16g16b16a16_put_tile_rgba((short *) packed, w, h, p, src_stride);
1061 break;
1062 case PIPE_FORMAT_Z16_UNORM:
1063 /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/
1064 break;
1065 case PIPE_FORMAT_Z32_UNORM:
1066 /*z32_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
1067 break;
1068 case PIPE_FORMAT_S8Z24_UNORM:
1069 case PIPE_FORMAT_X8Z24_UNORM:
1070 /*s8z24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
1071 break;
1072 case PIPE_FORMAT_Z24S8_UNORM:
1073 case PIPE_FORMAT_Z24X8_UNORM:
1074 /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
1075 break;
1076 default:
1077 debug_printf("%s: unsupported format %s\n", __FUNCTION__, pf_name(pt->format));
1078 }
1079
1080 pipe_put_tile_raw(pt, x, y, w, h, packed, 0);
1081
1082 FREE(packed);
1083 }
1084
1085
1086 /**
1087 * Get a block of Z values, converted to 32-bit range.
1088 */
1089 void
1090 pipe_get_tile_z(struct pipe_transfer *pt,
1091 uint x, uint y, uint w, uint h,
1092 uint *z)
1093 {
1094 struct pipe_screen *screen = pt->texture->screen;
1095 const uint dstStride = w;
1096 ubyte *map;
1097 uint *pDest = z;
1098 uint i, j;
1099
1100 if (pipe_clip_tile(x, y, &w, &h, pt))
1101 return;
1102
1103 map = (ubyte *)screen->transfer_map(screen, pt);
1104 if (!map) {
1105 assert(0);
1106 return;
1107 }
1108
1109 switch (pt->format) {
1110 case PIPE_FORMAT_Z32_UNORM:
1111 {
1112 const uint *ptrc
1113 = (const uint *)(map + y * pt->stride + x*4);
1114 for (i = 0; i < h; i++) {
1115 memcpy(pDest, ptrc, 4 * w);
1116 pDest += dstStride;
1117 ptrc += pt->stride/4;
1118 }
1119 }
1120 break;
1121 case PIPE_FORMAT_S8Z24_UNORM:
1122 case PIPE_FORMAT_X8Z24_UNORM:
1123 {
1124 const uint *ptrc
1125 = (const uint *)(map + y * pt->stride + x*4);
1126 for (i = 0; i < h; i++) {
1127 for (j = 0; j < w; j++) {
1128 /* convert 24-bit Z to 32-bit Z */
1129 pDest[j] = (ptrc[j] << 8) | ((ptrc[j] >> 16) & 0xff);
1130 }
1131 pDest += dstStride;
1132 ptrc += pt->stride/4;
1133 }
1134 }
1135 break;
1136 case PIPE_FORMAT_Z24S8_UNORM:
1137 case PIPE_FORMAT_Z24X8_UNORM:
1138 {
1139 const uint *ptrc
1140 = (const uint *)(map + y * pt->stride + x*4);
1141 for (i = 0; i < h; i++) {
1142 for (j = 0; j < w; j++) {
1143 /* convert 24-bit Z to 32-bit Z */
1144 pDest[j] = (ptrc[j] & 0xffffff00) | ((ptrc[j] >> 24) & 0xff);
1145 }
1146 pDest += dstStride;
1147 ptrc += pt->stride/4;
1148 }
1149 }
1150 break;
1151 case PIPE_FORMAT_Z16_UNORM:
1152 {
1153 const ushort *ptrc
1154 = (const ushort *)(map + y * pt->stride + x*2);
1155 for (i = 0; i < h; i++) {
1156 for (j = 0; j < w; j++) {
1157 /* convert 16-bit Z to 32-bit Z */
1158 pDest[j] = (ptrc[j] << 16) | ptrc[j];
1159 }
1160 pDest += dstStride;
1161 ptrc += pt->stride/2;
1162 }
1163 }
1164 break;
1165 default:
1166 assert(0);
1167 }
1168
1169 screen->transfer_unmap(screen, pt);
1170 }
1171
1172
1173 void
1174 pipe_put_tile_z(struct pipe_transfer *pt,
1175 uint x, uint y, uint w, uint h,
1176 const uint *zSrc)
1177 {
1178 struct pipe_screen *screen = pt->texture->screen;
1179 const uint srcStride = w;
1180 const uint *ptrc = zSrc;
1181 ubyte *map;
1182 uint i, j;
1183
1184 if (pipe_clip_tile(x, y, &w, &h, pt))
1185 return;
1186
1187 map = (ubyte *)screen->transfer_map(screen, pt);
1188 if (!map) {
1189 assert(0);
1190 return;
1191 }
1192
1193 switch (pt->format) {
1194 case PIPE_FORMAT_Z32_UNORM:
1195 {
1196 uint *pDest = (uint *) (map + y * pt->stride + x*4);
1197 for (i = 0; i < h; i++) {
1198 memcpy(pDest, ptrc, 4 * w);
1199 pDest += pt->stride/4;
1200 ptrc += srcStride;
1201 }
1202 }
1203 break;
1204 case PIPE_FORMAT_S8Z24_UNORM:
1205 {
1206 uint *pDest = (uint *) (map + y * pt->stride + x*4);
1207 assert(pt->usage == PIPE_TRANSFER_READ_WRITE);
1208 for (i = 0; i < h; i++) {
1209 for (j = 0; j < w; j++) {
1210 /* convert 32-bit Z to 24-bit Z, preserve stencil */
1211 pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8;
1212 }
1213 pDest += pt->stride/4;
1214 ptrc += srcStride;
1215 }
1216 }
1217 break;
1218 case PIPE_FORMAT_X8Z24_UNORM:
1219 {
1220 uint *pDest = (uint *) (map + y * pt->stride + x*4);
1221 for (i = 0; i < h; i++) {
1222 for (j = 0; j < w; j++) {
1223 /* convert 32-bit Z to 24-bit Z (0 stencil) */
1224 pDest[j] = ptrc[j] >> 8;
1225 }
1226 pDest += pt->stride/4;
1227 ptrc += srcStride;
1228 }
1229 }
1230 break;
1231 case PIPE_FORMAT_Z24S8_UNORM:
1232 {
1233 uint *pDest = (uint *) (map + y * pt->stride + x*4);
1234 assert(pt->usage == PIPE_TRANSFER_READ_WRITE);
1235 for (i = 0; i < h; i++) {
1236 for (j = 0; j < w; j++) {
1237 /* convert 32-bit Z to 24-bit Z, preserve stencil */
1238 pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00);
1239 }
1240 pDest += pt->stride/4;
1241 ptrc += srcStride;
1242 }
1243 }
1244 break;
1245 case PIPE_FORMAT_Z24X8_UNORM:
1246 {
1247 uint *pDest = (uint *) (map + y * pt->stride + x*4);
1248 for (i = 0; i < h; i++) {
1249 for (j = 0; j < w; j++) {
1250 /* convert 32-bit Z to 24-bit Z (0 stencil) */
1251 pDest[j] = ptrc[j] & 0xffffff00;
1252 }
1253 pDest += pt->stride/4;
1254 ptrc += srcStride;
1255 }
1256 }
1257 break;
1258 case PIPE_FORMAT_Z16_UNORM:
1259 {
1260 ushort *pDest = (ushort *) (map + y * pt->stride + x*2);
1261 for (i = 0; i < h; i++) {
1262 for (j = 0; j < w; j++) {
1263 /* convert 32-bit Z to 16-bit Z */
1264 pDest[j] = ptrc[j] >> 16;
1265 }
1266 pDest += pt->stride/2;
1267 ptrc += srcStride;
1268 }
1269 }
1270 break;
1271 default:
1272 assert(0);
1273 }
1274
1275 screen->transfer_unmap(screen, pt);
1276 }
1277
1278