Merge commit 'origin/master' into gallium-0.2
[profile/ivi/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