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