u_tile.c revision 77388559886dd84c69aaffc9a385ad87c410afa9
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 */
48void
49pipe_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 */
76void
77pipe_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
112static void
113a8r8g8b8_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
134static void
135a8r8g8b8_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
159static void
160x8r8g8b8_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
181static void
182x8r8g8b8_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
205static void
206b8g8r8a8_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
227static void
228b8g8r8a8_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
252static void
253a1r5g5b5_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
274static void
275a1r5g5b5_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
303static void
304a4r4g4b4_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
325static void
326a4r4g4b4_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
354static void
355r5g6b5_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
376static void
377r5g6b5_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 */
403static void
404z16_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
429static void
430l8_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
450static void
451l8_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++ = r;
464      }
465      p += src_stride;
466   }
467}
468
469
470
471/*** PIPE_FORMAT_A8_UNORM ***/
472
473static void
474a8_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
494static void
495a8_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++ = a;
508      }
509      p += src_stride;
510   }
511}
512
513
514
515/*** PIPE_FORMAT_R16_SNORM ***/
516
517static void
518r16_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
538static void
539r16_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
558static void
559r16g16b16a16_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
579static void
580r16g16b16a16_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
603static void
604i8_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
624static void
625i8_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++ = r;
638      }
639      p += src_stride;
640   }
641}
642
643
644/*** PIPE_FORMAT_A8L8_UNORM ***/
645
646static void
647a8l8_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
668static void
669a8l8_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 */
696static void
697z32_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 */
723static void
724s8z24_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 */
750static void
751z24s8_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.
776 */
777static void
778z32f_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 */
803static void
804ycbcr_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
886static void
887fake_get_tile_rgba(const ushort *src,
888                   unsigned w, unsigned h,
889                   float *p,
890                   unsigned dst_stride)
891{
892   unsigned i, j;
893
894   for (i = 0; i < h; i++) {
895      float *pRow = p;
896      for (j = 0; j < w; j++, pRow += 4) {
897         pRow[0] =
898         pRow[1] =
899         pRow[2] =
900         pRow[3] = (i ^ j) & 1 ? 1.0f : 0.0f;
901      }
902      p += dst_stride;
903   }
904}
905
906
907void
908pipe_tile_raw_to_rgba(enum pipe_format format,
909                      void *src,
910                      uint w, uint h,
911                      float *dst, unsigned dst_stride)
912{
913   switch (format) {
914   case PIPE_FORMAT_A8R8G8B8_UNORM:
915      a8r8g8b8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
916      break;
917   case PIPE_FORMAT_X8R8G8B8_UNORM:
918      x8r8g8b8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
919      break;
920   case PIPE_FORMAT_B8G8R8A8_UNORM:
921      b8g8r8a8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
922      break;
923   case PIPE_FORMAT_A1R5G5B5_UNORM:
924      a1r5g5b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
925      break;
926   case PIPE_FORMAT_A4R4G4B4_UNORM:
927      a4r4g4b4_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
928      break;
929   case PIPE_FORMAT_R5G6B5_UNORM:
930      r5g6b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
931      break;
932   case PIPE_FORMAT_L8_UNORM:
933      l8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
934      break;
935   case PIPE_FORMAT_A8_UNORM:
936      a8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
937      break;
938   case PIPE_FORMAT_I8_UNORM:
939      i8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
940      break;
941   case PIPE_FORMAT_A8L8_UNORM:
942      a8l8_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
943      break;
944   case PIPE_FORMAT_R16_SNORM:
945      r16_get_tile_rgba((short *) src, w, h, dst, dst_stride);
946      break;
947   case PIPE_FORMAT_R16G16B16A16_SNORM:
948      r16g16b16a16_get_tile_rgba((short *) src, w, h, dst, dst_stride);
949      break;
950   case PIPE_FORMAT_Z16_UNORM:
951      z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
952      break;
953   case PIPE_FORMAT_Z32_UNORM:
954      z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
955      break;
956   case PIPE_FORMAT_S8Z24_UNORM:
957   case PIPE_FORMAT_X8Z24_UNORM:
958      s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
959      break;
960   case PIPE_FORMAT_Z24S8_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
979void
980pipe_get_tile_rgba(struct pipe_surface *ps,
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, ps))
988      return;
989
990   packed = MALLOC(pf_get_nblocks(&ps->block, w, h) * ps->block.size);
991
992   if (!packed)
993      return;
994
995   if(ps->format == PIPE_FORMAT_YCBCR || ps->format == PIPE_FORMAT_YCBCR_REV)
996      assert((x & 1) == 0);
997
998   pipe_get_tile_raw(ps, x, y, w, h, packed, 0);
999
1000   pipe_tile_raw_to_rgba(ps->format, packed, w, h, p, dst_stride);
1001
1002   FREE(packed);
1003}
1004
1005
1006void
1007pipe_put_tile_rgba(struct pipe_surface *ps,
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, ps))
1015      return;
1016
1017   packed = MALLOC(pf_get_nblocks(&ps->block, w, h) * ps->block.size);
1018
1019   if (!packed)
1020      return;
1021
1022   switch (ps->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      /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
1074      break;
1075   default:
1076      debug_printf("%s: unsupported format %s\n", __FUNCTION__, pf_name(ps->format));
1077   }
1078
1079   pipe_put_tile_raw(ps, x, y, w, h, packed, 0);
1080
1081   FREE(packed);
1082}
1083
1084
1085/**
1086 * Get a block of Z values, converted to 32-bit range.
1087 */
1088void
1089pipe_get_tile_z(struct pipe_surface *ps,
1090                uint x, uint y, uint w, uint h,
1091                uint *z)
1092{
1093   const uint dstStride = w;
1094   ubyte *map;
1095   uint *pDest = z;
1096   uint i, j;
1097
1098   if (pipe_clip_tile(x, y, &w, &h, ps))
1099      return;
1100
1101   map = (ubyte *)pipe_surface_map(ps, PIPE_BUFFER_USAGE_CPU_READ);
1102   if (!map) {
1103      assert(0);
1104      return;
1105   }
1106
1107   switch (ps->format) {
1108   case PIPE_FORMAT_Z32_UNORM:
1109      {
1110         const uint *pSrc
1111            = (const uint *)(map  + y * ps->stride + x*4);
1112         for (i = 0; i < h; i++) {
1113            memcpy(pDest, pSrc, 4 * w);
1114            pDest += dstStride;
1115            pSrc += ps->stride/4;
1116         }
1117      }
1118      break;
1119   case PIPE_FORMAT_S8Z24_UNORM:
1120   case PIPE_FORMAT_X8Z24_UNORM:
1121      {
1122         const uint *pSrc
1123            = (const uint *)(map + y * ps->stride + x*4);
1124         for (i = 0; i < h; i++) {
1125            for (j = 0; j < w; j++) {
1126               /* convert 24-bit Z to 32-bit Z */
1127               pDest[j] = (pSrc[j] << 8) | (pSrc[j] & 0xff);
1128            }
1129            pDest += dstStride;
1130            pSrc += ps->stride/4;
1131         }
1132      }
1133      break;
1134   case PIPE_FORMAT_Z16_UNORM:
1135      {
1136         const ushort *pSrc
1137            = (const ushort *)(map + y * ps->stride + x*2);
1138         for (i = 0; i < h; i++) {
1139            for (j = 0; j < w; j++) {
1140               /* convert 16-bit Z to 32-bit Z */
1141               pDest[j] = (pSrc[j] << 16) | pSrc[j];
1142            }
1143            pDest += dstStride;
1144            pSrc += ps->stride/2;
1145         }
1146      }
1147      break;
1148   default:
1149      assert(0);
1150   }
1151
1152   pipe_surface_unmap(ps);
1153}
1154
1155
1156void
1157pipe_put_tile_z(struct pipe_surface *ps,
1158                uint x, uint y, uint w, uint h,
1159                const uint *zSrc)
1160{
1161   const uint srcStride = w;
1162   const uint *pSrc = zSrc;
1163   ubyte *map;
1164   uint i, j;
1165
1166   if (pipe_clip_tile(x, y, &w, &h, ps))
1167      return;
1168
1169   map = (ubyte *)pipe_surface_map(ps, PIPE_BUFFER_USAGE_CPU_WRITE);
1170   if (!map) {
1171      assert(0);
1172      return;
1173   }
1174
1175   switch (ps->format) {
1176   case PIPE_FORMAT_Z32_UNORM:
1177      {
1178         uint *pDest = (uint *) (map + y * ps->stride + x*4);
1179         for (i = 0; i < h; i++) {
1180            memcpy(pDest, pSrc, 4 * w);
1181            pDest += ps->stride/4;
1182            pSrc += srcStride;
1183         }
1184      }
1185      break;
1186   case PIPE_FORMAT_S8Z24_UNORM:
1187   case PIPE_FORMAT_X8Z24_UNORM:
1188      {
1189         uint *pDest = (uint *) (map + y * ps->stride + x*4);
1190         for (i = 0; i < h; i++) {
1191            for (j = 0; j < w; j++) {
1192               /* convert 32-bit Z to 24-bit Z (0 stencil) */
1193               pDest[j] = pSrc[j] >> 8;
1194            }
1195            pDest += ps->stride/4;
1196            pSrc += srcStride;
1197         }
1198      }
1199      break;
1200   case PIPE_FORMAT_Z16_UNORM:
1201      {
1202         ushort *pDest = (ushort *) (map + y * ps->stride + x*2);
1203         for (i = 0; i < h; i++) {
1204            for (j = 0; j < w; j++) {
1205               /* convert 32-bit Z to 16-bit Z */
1206               pDest[j] = pSrc[j] >> 16;
1207            }
1208            pDest += ps->stride/2;
1209            pSrc += srcStride;
1210         }
1211      }
1212      break;
1213   default:
1214      assert(0);
1215   }
1216
1217   pipe_surface_unmap(ps);
1218}
1219
1220
1221