util: Respect destination stride in pipe_get_tile_swizzle().
[mesa.git] / src / gallium / auxiliary / util / u_tile.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * RGBA/float tile get/put functions.
30 * Usable both by drivers and state trackers.
31 */
32
33
34 #include "pipe/p_defines.h"
35 #include "util/u_inlines.h"
36
37 #include "util/u_format.h"
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 transfer object to user memory.
46 */
47 void
48 pipe_get_tile_raw(struct pipe_context *pipe,
49 struct pipe_transfer *pt,
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 = util_format_get_stride(pt->texture->format, w);
57
58 if (pipe_clip_tile(x, y, &w, &h, pt))
59 return;
60
61 src = pipe->transfer_map(pipe, pt);
62 assert(src);
63 if(!src)
64 return;
65
66 util_copy_rect(dst, pt->texture->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y);
67
68 pipe->transfer_unmap(pipe, pt);
69 }
70
71
72 /**
73 * Move raw block of pixels from user memory to transfer object.
74 */
75 void
76 pipe_put_tile_raw(struct pipe_context *pipe,
77 struct pipe_transfer *pt,
78 uint x, uint y, uint w, uint h,
79 const void *src, int src_stride)
80 {
81 void *dst;
82 enum pipe_format format = pt->texture->format;
83
84 if (src_stride == 0)
85 src_stride = util_format_get_stride(format, w);
86
87 if (pipe_clip_tile(x, y, &w, &h, pt))
88 return;
89
90 dst = pipe->transfer_map(pipe, pt);
91 assert(dst);
92 if(!dst)
93 return;
94
95 util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0);
96
97 pipe->transfer_unmap(pipe, pt);
98 }
99
100
101
102
103 /** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */
104 #define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
105
106 #define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
107 us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
108
109
110
111 /*** PIPE_FORMAT_Z16_UNORM ***/
112
113 /**
114 * Return each Z value as four floats in [0,1].
115 */
116 static void
117 z16_get_tile_rgba(const ushort *src,
118 unsigned w, unsigned h,
119 float *p,
120 unsigned dst_stride)
121 {
122 const float scale = 1.0f / 65535.0f;
123 unsigned i, j;
124
125 for (i = 0; i < h; i++) {
126 float *pRow = p;
127 for (j = 0; j < w; j++, pRow += 4) {
128 pRow[0] =
129 pRow[1] =
130 pRow[2] =
131 pRow[3] = *src++ * scale;
132 }
133 p += dst_stride;
134 }
135 }
136
137
138
139
140 /*** PIPE_FORMAT_Z32_UNORM ***/
141
142 /**
143 * Return each Z value as four floats in [0,1].
144 */
145 static void
146 z32_get_tile_rgba(const unsigned *src,
147 unsigned w, unsigned h,
148 float *p,
149 unsigned dst_stride)
150 {
151 const double scale = 1.0 / (double) 0xffffffff;
152 unsigned i, j;
153
154 for (i = 0; i < h; i++) {
155 float *pRow = p;
156 for (j = 0; j < w; j++, pRow += 4) {
157 pRow[0] =
158 pRow[1] =
159 pRow[2] =
160 pRow[3] = (float) (*src++ * scale);
161 }
162 p += dst_stride;
163 }
164 }
165
166
167 /*** PIPE_FORMAT_Z24_UNORM_S8_USCALED ***/
168
169 /**
170 * Return Z component as four float in [0,1]. Stencil part ignored.
171 */
172 static void
173 s8z24_get_tile_rgba(const unsigned *src,
174 unsigned w, unsigned h,
175 float *p,
176 unsigned dst_stride)
177 {
178 const double scale = 1.0 / ((1 << 24) - 1);
179 unsigned i, j;
180
181 for (i = 0; i < h; i++) {
182 float *pRow = p;
183 for (j = 0; j < w; j++, pRow += 4) {
184 pRow[0] =
185 pRow[1] =
186 pRow[2] =
187 pRow[3] = (float) (scale * (*src++ & 0xffffff));
188 }
189 p += dst_stride;
190 }
191 }
192
193
194 /*** PIPE_FORMAT_S8_USCALED_Z24_UNORM ***/
195
196 /**
197 * Return Z component as four float in [0,1]. Stencil part ignored.
198 */
199 static void
200 z24s8_get_tile_rgba(const unsigned *src,
201 unsigned w, unsigned h,
202 float *p,
203 unsigned dst_stride)
204 {
205 const double scale = 1.0 / ((1 << 24) - 1);
206 unsigned i, j;
207
208 for (i = 0; i < h; i++) {
209 float *pRow = p;
210 for (j = 0; j < w; j++, pRow += 4) {
211 pRow[0] =
212 pRow[1] =
213 pRow[2] =
214 pRow[3] = (float) (scale * (*src++ >> 8));
215 }
216 p += dst_stride;
217 }
218 }
219
220
221 /*** PIPE_FORMAT_Z32_FLOAT ***/
222
223 /**
224 * Return each Z value as four floats in [0,1].
225 */
226 static void
227 z32f_get_tile_rgba(const float *src,
228 unsigned w, unsigned h,
229 float *p,
230 unsigned dst_stride)
231 {
232 unsigned i, j;
233
234 for (i = 0; i < h; i++) {
235 float *pRow = p;
236 for (j = 0; j < w; j++, pRow += 4) {
237 pRow[0] =
238 pRow[1] =
239 pRow[2] =
240 pRow[3] = *src++;
241 }
242 p += dst_stride;
243 }
244 }
245
246
247 /*** PIPE_FORMAT_UYVY / PIPE_FORMAT_YUYV ***/
248
249 /**
250 * Convert YCbCr (or YCrCb) to RGBA.
251 */
252 static void
253 ycbcr_get_tile_rgba(const ushort *src,
254 unsigned w, unsigned h,
255 float *p,
256 unsigned dst_stride,
257 boolean rev)
258 {
259 const float scale = 1.0f / 255.0f;
260 unsigned i, j;
261
262 for (i = 0; i < h; i++) {
263 float *pRow = p;
264 /* do two texels at a time */
265 for (j = 0; j < (w & ~1); j += 2, src += 2) {
266 const ushort t0 = src[0];
267 const ushort t1 = src[1];
268 const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */
269 const ubyte y1 = (t1 >> 8) & 0xff; /* luminance */
270 ubyte cb, cr;
271 float r, g, b;
272
273 if (rev) {
274 cb = t1 & 0xff; /* chroma U */
275 cr = t0 & 0xff; /* chroma V */
276 }
277 else {
278 cb = t0 & 0xff; /* chroma U */
279 cr = t1 & 0xff; /* chroma V */
280 }
281
282 /* even pixel: y0,cr,cb */
283 r = 1.164f * (y0-16) + 1.596f * (cr-128);
284 g = 1.164f * (y0-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
285 b = 1.164f * (y0-16) + 2.018f * (cb-128);
286 pRow[0] = r * scale;
287 pRow[1] = g * scale;
288 pRow[2] = b * scale;
289 pRow[3] = 1.0f;
290 pRow += 4;
291
292 /* odd pixel: use y1,cr,cb */
293 r = 1.164f * (y1-16) + 1.596f * (cr-128);
294 g = 1.164f * (y1-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
295 b = 1.164f * (y1-16) + 2.018f * (cb-128);
296 pRow[0] = r * scale;
297 pRow[1] = g * scale;
298 pRow[2] = b * scale;
299 pRow[3] = 1.0f;
300 pRow += 4;
301
302 }
303 /* do the last texel */
304 if (w & 1) {
305 const ushort t0 = src[0];
306 const ushort t1 = src[1];
307 const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */
308 ubyte cb, cr;
309 float r, g, b;
310
311 if (rev) {
312 cb = t1 & 0xff; /* chroma U */
313 cr = t0 & 0xff; /* chroma V */
314 }
315 else {
316 cb = t0 & 0xff; /* chroma U */
317 cr = t1 & 0xff; /* chroma V */
318 }
319
320 /* even pixel: y0,cr,cb */
321 r = 1.164f * (y0-16) + 1.596f * (cr-128);
322 g = 1.164f * (y0-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
323 b = 1.164f * (y0-16) + 2.018f * (cb-128);
324 pRow[0] = r * scale;
325 pRow[1] = g * scale;
326 pRow[2] = b * scale;
327 pRow[3] = 1.0f;
328 pRow += 4;
329 }
330 p += dst_stride;
331 }
332 }
333
334
335 void
336 pipe_tile_raw_to_rgba(enum pipe_format format,
337 void *src,
338 uint w, uint h,
339 float *dst, unsigned dst_stride)
340 {
341 switch (format) {
342 case PIPE_FORMAT_Z16_UNORM:
343 z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
344 break;
345 case PIPE_FORMAT_Z32_UNORM:
346 z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
347 break;
348 case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
349 case PIPE_FORMAT_Z24X8_UNORM:
350 s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
351 break;
352 case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
353 case PIPE_FORMAT_X8Z24_UNORM:
354 z24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
355 break;
356 case PIPE_FORMAT_Z32_FLOAT:
357 z32f_get_tile_rgba((float *) src, w, h, dst, dst_stride);
358 break;
359 case PIPE_FORMAT_UYVY:
360 ycbcr_get_tile_rgba((ushort *) src, w, h, dst, dst_stride, FALSE);
361 break;
362 case PIPE_FORMAT_YUYV:
363 ycbcr_get_tile_rgba((ushort *) src, w, h, dst, dst_stride, TRUE);
364 break;
365 default:
366 util_format_read_4f(format,
367 dst, dst_stride * sizeof(float),
368 src, util_format_get_stride(format, w),
369 0, 0, w, h);
370 }
371 }
372
373
374 void
375 pipe_get_tile_rgba(struct pipe_context *pipe,
376 struct pipe_transfer *pt,
377 uint x, uint y, uint w, uint h,
378 float *p)
379 {
380 unsigned dst_stride = w * 4;
381 void *packed;
382 enum pipe_format format = pt->texture->format;
383
384 if (pipe_clip_tile(x, y, &w, &h, pt))
385 return;
386
387 packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
388
389 if (!packed)
390 return;
391
392 if(format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV)
393 assert((x & 1) == 0);
394
395 pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0);
396
397 pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride);
398
399 FREE(packed);
400 }
401
402
403 void
404 pipe_get_tile_swizzle(struct pipe_context *pipe,
405 struct pipe_transfer *pt,
406 uint x,
407 uint y,
408 uint w,
409 uint h,
410 uint swizzle_r,
411 uint swizzle_g,
412 uint swizzle_b,
413 uint swizzle_a,
414 enum pipe_format format,
415 float *p)
416 {
417 unsigned dst_stride = w * 4;
418 void *packed;
419 uint iy;
420 float rgba01[6];
421
422 if (pipe_clip_tile(x, y, &w, &h, pt)) {
423 return;
424 }
425
426 packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
427 if (!packed) {
428 return;
429 }
430
431 if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) {
432 assert((x & 1) == 0);
433 }
434
435 pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0);
436
437 pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride);
438
439 FREE(packed);
440
441 if (swizzle_r == PIPE_SWIZZLE_RED &&
442 swizzle_g == PIPE_SWIZZLE_GREEN &&
443 swizzle_b == PIPE_SWIZZLE_BLUE &&
444 swizzle_a == PIPE_SWIZZLE_ALPHA) {
445 /* no-op, skip */
446 return;
447 }
448
449 rgba01[PIPE_SWIZZLE_ZERO] = 0.0f;
450 rgba01[PIPE_SWIZZLE_ONE] = 1.0f;
451
452 for (iy = 0; iy < h; iy++) {
453 float *row = p;
454 uint ix;
455
456 for (ix = 0; ix < w; ix++) {
457 rgba01[PIPE_SWIZZLE_RED] = row[0];
458 rgba01[PIPE_SWIZZLE_GREEN] = row[1];
459 rgba01[PIPE_SWIZZLE_BLUE] = row[2];
460 rgba01[PIPE_SWIZZLE_ALPHA] = row[3];
461
462 *row++ = rgba01[swizzle_r];
463 *row++ = rgba01[swizzle_g];
464 *row++ = rgba01[swizzle_b];
465 *row++ = rgba01[swizzle_a];
466 }
467 p += dst_stride;
468 }
469 }
470
471
472 void
473 pipe_put_tile_rgba(struct pipe_context *pipe,
474 struct pipe_transfer *pt,
475 uint x, uint y, uint w, uint h,
476 const float *p)
477 {
478 unsigned src_stride = w * 4;
479 void *packed;
480 enum pipe_format format = pt->texture->format;
481
482 if (pipe_clip_tile(x, y, &w, &h, pt))
483 return;
484
485 packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
486
487 if (!packed)
488 return;
489
490 switch (format) {
491 case PIPE_FORMAT_Z16_UNORM:
492 /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/
493 break;
494 case PIPE_FORMAT_Z32_UNORM:
495 /*z32_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
496 break;
497 case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
498 case PIPE_FORMAT_Z24X8_UNORM:
499 /*s8z24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
500 break;
501 case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
502 case PIPE_FORMAT_X8Z24_UNORM:
503 /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
504 break;
505 default:
506 util_format_write_4f(format,
507 p, src_stride * sizeof(float),
508 packed, util_format_get_stride(format, w),
509 0, 0, w, h);
510 }
511
512 pipe_put_tile_raw(pipe, pt, x, y, w, h, packed, 0);
513
514 FREE(packed);
515 }
516
517
518 /**
519 * Get a block of Z values, converted to 32-bit range.
520 */
521 void
522 pipe_get_tile_z(struct pipe_context *pipe,
523 struct pipe_transfer *pt,
524 uint x, uint y, uint w, uint h,
525 uint *z)
526 {
527 const uint dstStride = w;
528 ubyte *map;
529 uint *pDest = z;
530 uint i, j;
531 enum pipe_format format = pt->texture->format;
532
533 if (pipe_clip_tile(x, y, &w, &h, pt))
534 return;
535
536 map = (ubyte *)pipe->transfer_map(pipe, pt);
537 if (!map) {
538 assert(0);
539 return;
540 }
541
542 switch (format) {
543 case PIPE_FORMAT_Z32_UNORM:
544 {
545 const uint *ptrc
546 = (const uint *)(map + y * pt->stride + x*4);
547 for (i = 0; i < h; i++) {
548 memcpy(pDest, ptrc, 4 * w);
549 pDest += dstStride;
550 ptrc += pt->stride/4;
551 }
552 }
553 break;
554 case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
555 case PIPE_FORMAT_Z24X8_UNORM:
556 {
557 const uint *ptrc
558 = (const uint *)(map + y * pt->stride + x*4);
559 for (i = 0; i < h; i++) {
560 for (j = 0; j < w; j++) {
561 /* convert 24-bit Z to 32-bit Z */
562 pDest[j] = (ptrc[j] << 8) | ((ptrc[j] >> 16) & 0xff);
563 }
564 pDest += dstStride;
565 ptrc += pt->stride/4;
566 }
567 }
568 break;
569 case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
570 case PIPE_FORMAT_X8Z24_UNORM:
571 {
572 const uint *ptrc
573 = (const uint *)(map + y * pt->stride + x*4);
574 for (i = 0; i < h; i++) {
575 for (j = 0; j < w; j++) {
576 /* convert 24-bit Z to 32-bit Z */
577 pDest[j] = (ptrc[j] & 0xffffff00) | ((ptrc[j] >> 24) & 0xff);
578 }
579 pDest += dstStride;
580 ptrc += pt->stride/4;
581 }
582 }
583 break;
584 case PIPE_FORMAT_Z16_UNORM:
585 {
586 const ushort *ptrc
587 = (const ushort *)(map + y * pt->stride + x*2);
588 for (i = 0; i < h; i++) {
589 for (j = 0; j < w; j++) {
590 /* convert 16-bit Z to 32-bit Z */
591 pDest[j] = (ptrc[j] << 16) | ptrc[j];
592 }
593 pDest += dstStride;
594 ptrc += pt->stride/2;
595 }
596 }
597 break;
598 default:
599 assert(0);
600 }
601
602 pipe->transfer_unmap(pipe, pt);
603 }
604
605
606 void
607 pipe_put_tile_z(struct pipe_context *pipe,
608 struct pipe_transfer *pt,
609 uint x, uint y, uint w, uint h,
610 const uint *zSrc)
611 {
612 const uint srcStride = w;
613 const uint *ptrc = zSrc;
614 ubyte *map;
615 uint i, j;
616 enum pipe_format format = pt->texture->format;
617
618 if (pipe_clip_tile(x, y, &w, &h, pt))
619 return;
620
621 map = (ubyte *)pipe->transfer_map(pipe, pt);
622 if (!map) {
623 assert(0);
624 return;
625 }
626
627 switch (format) {
628 case PIPE_FORMAT_Z32_UNORM:
629 {
630 uint *pDest = (uint *) (map + y * pt->stride + x*4);
631 for (i = 0; i < h; i++) {
632 memcpy(pDest, ptrc, 4 * w);
633 pDest += pt->stride/4;
634 ptrc += srcStride;
635 }
636 }
637 break;
638 case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
639 {
640 uint *pDest = (uint *) (map + y * pt->stride + x*4);
641 assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);
642 for (i = 0; i < h; i++) {
643 for (j = 0; j < w; j++) {
644 /* convert 32-bit Z to 24-bit Z, preserve stencil */
645 pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8;
646 }
647 pDest += pt->stride/4;
648 ptrc += srcStride;
649 }
650 }
651 break;
652 case PIPE_FORMAT_Z24X8_UNORM:
653 {
654 uint *pDest = (uint *) (map + y * pt->stride + x*4);
655 for (i = 0; i < h; i++) {
656 for (j = 0; j < w; j++) {
657 /* convert 32-bit Z to 24-bit Z (0 stencil) */
658 pDest[j] = ptrc[j] >> 8;
659 }
660 pDest += pt->stride/4;
661 ptrc += srcStride;
662 }
663 }
664 break;
665 case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
666 {
667 uint *pDest = (uint *) (map + y * pt->stride + x*4);
668 assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);
669 for (i = 0; i < h; i++) {
670 for (j = 0; j < w; j++) {
671 /* convert 32-bit Z to 24-bit Z, preserve stencil */
672 pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00);
673 }
674 pDest += pt->stride/4;
675 ptrc += srcStride;
676 }
677 }
678 break;
679 case PIPE_FORMAT_X8Z24_UNORM:
680 {
681 uint *pDest = (uint *) (map + y * pt->stride + x*4);
682 for (i = 0; i < h; i++) {
683 for (j = 0; j < w; j++) {
684 /* convert 32-bit Z to 24-bit Z (0 stencil) */
685 pDest[j] = ptrc[j] & 0xffffff00;
686 }
687 pDest += pt->stride/4;
688 ptrc += srcStride;
689 }
690 }
691 break;
692 case PIPE_FORMAT_Z16_UNORM:
693 {
694 ushort *pDest = (ushort *) (map + y * pt->stride + x*2);
695 for (i = 0; i < h; i++) {
696 for (j = 0; j < w; j++) {
697 /* convert 32-bit Z to 16-bit Z */
698 pDest[j] = ptrc[j] >> 16;
699 }
700 pDest += pt->stride/2;
701 ptrc += srcStride;
702 }
703 }
704 break;
705 default:
706 assert(0);
707 }
708
709 pipe->transfer_unmap(pipe, pt);
710 }
711
712