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