1 /**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
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 VMWARE 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 gallium frontends.
31 */
32
33
34 #include "pipe/p_defines.h"
35 #include "util/u_inlines.h"
36
37 #include "util/format/u_format.h"
38 #include "util/format/u_format_bptc.h"
39 #include "util/u_math.h"
40 #include "util/u_memory.h"
41 #include "util/u_surface.h"
42 #include "util/u_tile.h"
43
44
45 /**
46 * Move raw block of pixels from transfer object to user memory.
47 */
48 void
pipe_get_tile_raw(struct pipe_transfer * pt,const void * src,unsigned x,unsigned y,unsigned w,unsigned h,void * dst,int dst_stride)49 pipe_get_tile_raw(struct pipe_transfer *pt,
50 const void *src,
51 unsigned x, unsigned y,
52 unsigned w, unsigned h,
53 void *dst, int dst_stride)
54 {
55 if (dst_stride == 0)
56 dst_stride = util_format_get_stride(pt->resource->format, w);
57
58 if (u_clip_tile(x, y, &w, &h, &pt->box))
59 return;
60
61 util_copy_rect(dst, pt->resource->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y);
62 }
63
64
65 /**
66 * Move raw block of pixels from user memory to transfer object.
67 */
68 void
pipe_put_tile_raw(struct pipe_transfer * pt,void * dst,unsigned x,unsigned y,unsigned w,unsigned h,const void * src,int src_stride)69 pipe_put_tile_raw(struct pipe_transfer *pt,
70 void *dst,
71 unsigned x, unsigned y,
72 unsigned w, unsigned h,
73 const void *src, int src_stride)
74 {
75 enum pipe_format format = pt->resource->format;
76
77 if (src_stride == 0)
78 src_stride = util_format_get_stride(format, w);
79
80 if (u_clip_tile(x, y, &w, &h, &pt->box))
81 return;
82
83 util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0);
84 }
85
86
87
88
89 /** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */
90 #define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
91
92 #define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
93 us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
94
95
96
97 /*** PIPE_FORMAT_Z16_UNORM ***/
98
99 /**
100 * Return each Z value as four floats in [0,1].
101 */
102 static void
z16_get_tile_rgba(const uint16_t * src,unsigned w,unsigned h,float * p,unsigned dst_stride)103 z16_get_tile_rgba(const uint16_t *src,
104 unsigned w, unsigned h,
105 float *p,
106 unsigned dst_stride)
107 {
108 const float scale = 1.0f / 65535.0f;
109 unsigned i, j;
110
111 for (i = 0; i < h; i++) {
112 float *pRow = p;
113 for (j = 0; j < w; j++, pRow += 4) {
114 pRow[0] =
115 pRow[1] =
116 pRow[2] =
117 pRow[3] = *src++ * scale;
118 }
119 p += dst_stride;
120 }
121 }
122
123
124
125
126 /*** PIPE_FORMAT_Z32_UNORM ***/
127
128 /**
129 * Return each Z value as four floats in [0,1].
130 */
131 static void
z32_get_tile_rgba(const uint32_t * src,unsigned w,unsigned h,float * p,unsigned dst_stride)132 z32_get_tile_rgba(const uint32_t *src,
133 unsigned w, unsigned h,
134 float *p,
135 unsigned dst_stride)
136 {
137 const double scale = 1.0 / (double) 0xffffffff;
138 unsigned i, j;
139
140 for (i = 0; i < h; i++) {
141 float *pRow = p;
142 for (j = 0; j < w; j++, pRow += 4) {
143 pRow[0] =
144 pRow[1] =
145 pRow[2] =
146 pRow[3] = (float) (*src++ * scale);
147 }
148 p += dst_stride;
149 }
150 }
151
152
153 /*** PIPE_FORMAT_Z24_UNORM_S8_UINT ***/
154
155 /**
156 * Return Z component as four float in [0,1]. Stencil part ignored.
157 */
158 static void
s8z24_get_tile_rgba(const uint32_t * src,unsigned w,unsigned h,float * p,unsigned dst_stride)159 s8z24_get_tile_rgba(const uint32_t *src,
160 unsigned w, unsigned h,
161 float *p,
162 unsigned dst_stride)
163 {
164 const double scale = 1.0 / ((1 << 24) - 1);
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 pRow[0] =
171 pRow[1] =
172 pRow[2] =
173 pRow[3] = (float) (scale * (*src++ & 0xffffff));
174 }
175 p += dst_stride;
176 }
177 }
178
179
180 /*** PIPE_FORMAT_S8_UINT_Z24_UNORM ***/
181
182 /**
183 * Return Z component as four float in [0,1]. Stencil part ignored.
184 */
185 static void
z24s8_get_tile_rgba(const uint32_t * src,unsigned w,unsigned h,float * p,unsigned dst_stride)186 z24s8_get_tile_rgba(const uint32_t *src,
187 unsigned w, unsigned h,
188 float *p,
189 unsigned dst_stride)
190 {
191 const double scale = 1.0 / ((1 << 24) - 1);
192 unsigned i, j;
193
194 for (i = 0; i < h; i++) {
195 float *pRow = p;
196 for (j = 0; j < w; j++, pRow += 4) {
197 pRow[0] =
198 pRow[1] =
199 pRow[2] =
200 pRow[3] = (float) (scale * (*src++ >> 8));
201 }
202 p += dst_stride;
203 }
204 }
205
206 /*** PIPE_FORMAT_S8X24_UINT ***/
207
208 /**
209 * Return S component as four uint32_t in [0..255]. Z part ignored.
210 */
211 static void
s8x24_get_tile_rgba(const uint32_t * src,unsigned w,unsigned h,float * p,unsigned dst_stride)212 s8x24_get_tile_rgba(const uint32_t *src,
213 unsigned w, unsigned h,
214 float *p,
215 unsigned dst_stride)
216 {
217 unsigned i, j;
218
219 for (i = 0; i < h; i++) {
220 uint32_t *pRow = (uint32_t *)p;
221
222 for (j = 0; j < w; j++, pRow += 4) {
223 pRow[0] =
224 pRow[1] =
225 pRow[2] =
226 pRow[3] = ((*src++ >> 24) & 0xff);
227 }
228
229 p += dst_stride;
230 }
231 }
232
233 /*** PIPE_FORMAT_X24S8_UINT ***/
234
235 /**
236 * Return S component as four uint32_t in [0..255]. Z part ignored.
237 */
238 static void
x24s8_get_tile_rgba(const uint32_t * src,unsigned w,unsigned h,float * p,unsigned dst_stride)239 x24s8_get_tile_rgba(const uint32_t *src,
240 unsigned w, unsigned h,
241 float *p,
242 unsigned dst_stride)
243 {
244 unsigned i, j;
245
246 for (i = 0; i < h; i++) {
247 uint32_t *pRow = (uint32_t *)p;
248 for (j = 0; j < w; j++, pRow += 4) {
249 pRow[0] =
250 pRow[1] =
251 pRow[2] =
252 pRow[3] = (*src++ & 0xff);
253 }
254 p += dst_stride;
255 }
256 }
257
258
259 /**
260 * Return S component as four uint32_t in [0..255]. Z part ignored.
261 */
262 static void
s8_get_tile_rgba(const unsigned char * src,unsigned w,unsigned h,float * p,unsigned dst_stride)263 s8_get_tile_rgba(const unsigned char *src,
264 unsigned w, unsigned h,
265 float *p,
266 unsigned dst_stride)
267 {
268 unsigned i, j;
269
270 for (i = 0; i < h; i++) {
271 uint32_t *pRow = (uint32_t *)p;
272 for (j = 0; j < w; j++, pRow += 4) {
273 pRow[0] =
274 pRow[1] =
275 pRow[2] =
276 pRow[3] = (*src++ & 0xff);
277 }
278 p += dst_stride;
279 }
280 }
281
282 /*** PIPE_FORMAT_Z32_FLOAT ***/
283
284 /**
285 * Return each Z value as four floats in [0,1].
286 */
287 static void
z32f_get_tile_rgba(const float * src,unsigned w,unsigned h,float * p,unsigned dst_stride)288 z32f_get_tile_rgba(const float *src,
289 unsigned w, unsigned h,
290 float *p,
291 unsigned dst_stride)
292 {
293 unsigned i, j;
294
295 for (i = 0; i < h; i++) {
296 float *pRow = p;
297 for (j = 0; j < w; j++, pRow += 4) {
298 pRow[0] =
299 pRow[1] =
300 pRow[2] =
301 pRow[3] = *src++;
302 }
303 p += dst_stride;
304 }
305 }
306
307 /*** PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ***/
308
309 /**
310 * Return each Z value as four floats in [0,1].
311 */
312 static void
z32f_x24s8_get_tile_rgba(const float * src,unsigned w,unsigned h,float * p,unsigned dst_stride)313 z32f_x24s8_get_tile_rgba(const float *src,
314 unsigned w, unsigned h,
315 float *p,
316 unsigned dst_stride)
317 {
318 unsigned i, j;
319
320 for (i = 0; i < h; i++) {
321 float *pRow = p;
322 for (j = 0; j < w; j++, pRow += 4) {
323 pRow[0] =
324 pRow[1] =
325 pRow[2] =
326 pRow[3] = *src;
327 src += 2;
328 }
329 p += dst_stride;
330 }
331 }
332
333 /*** PIPE_FORMAT_X32_S8X24_UINT ***/
334
335 /**
336 * Return S component as four uint32_t in [0..255]. Z part ignored.
337 */
338 static void
x32_s8_get_tile_rgba(const uint32_t * src,unsigned w,unsigned h,float * p,unsigned dst_stride)339 x32_s8_get_tile_rgba(const uint32_t *src,
340 unsigned w, unsigned h,
341 float *p,
342 unsigned dst_stride)
343 {
344 unsigned i, j;
345
346 for (i = 0; i < h; i++) {
347 uint32_t *pRow = (uint32_t *)p;
348 for (j = 0; j < w; j++, pRow += 4) {
349 src++;
350 pRow[0] =
351 pRow[1] =
352 pRow[2] =
353 pRow[3] = (*src++ & 0xff);
354 }
355 p += dst_stride;
356 }
357 }
358
359 void
pipe_put_tile_rgba(struct pipe_transfer * pt,void * dst,unsigned x,unsigned y,unsigned w,unsigned h,enum pipe_format format,const void * p)360 pipe_put_tile_rgba(struct pipe_transfer *pt,
361 void *dst,
362 unsigned x, unsigned y, unsigned w, unsigned h,
363 enum pipe_format format, const void *p)
364 {
365 unsigned src_stride = w * 4;
366
367 if (u_clip_tile(x, y, &w, &h, &pt->box))
368 return;
369
370 /* While we do generate RGBA tiles for z/s for softpipe's texture fetch
371 * path, we never have to store from "RGBA" to Z/S.
372 */
373 if (util_format_is_depth_or_stencil(format))
374 return;
375
376 util_format_write_4(format,
377 p, src_stride * sizeof(float),
378 dst, pt->stride,
379 x, y, w, h);
380 }
381
382 void
pipe_get_tile_rgba(struct pipe_transfer * pt,const void * src,unsigned x,unsigned y,unsigned w,unsigned h,enum pipe_format format,void * dst)383 pipe_get_tile_rgba(struct pipe_transfer *pt,
384 const void *src,
385 unsigned x, unsigned y, unsigned w, unsigned h,
386 enum pipe_format format,
387 void *dst)
388 {
389 unsigned dst_stride = w * 4;
390 void *packed;
391
392 if (u_clip_tile(x, y, &w, &h, &pt->box)) {
393 return;
394 }
395
396 packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
397 if (!packed) {
398 return;
399 }
400
401 if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) {
402 assert((x & 1) == 0);
403 }
404
405 pipe_get_tile_raw(pt, src, x, y, w, h, packed, 0);
406
407 switch (format) {
408 case PIPE_FORMAT_Z16_UNORM:
409 z16_get_tile_rgba((uint16_t *) packed, w, h, dst, dst_stride);
410 break;
411 case PIPE_FORMAT_Z32_UNORM:
412 z32_get_tile_rgba((uint32_t *) packed, w, h, dst, dst_stride);
413 break;
414 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
415 case PIPE_FORMAT_Z24X8_UNORM:
416 s8z24_get_tile_rgba((uint32_t *) packed, w, h, dst, dst_stride);
417 break;
418 case PIPE_FORMAT_S8_UINT:
419 s8_get_tile_rgba((uint8_t *) packed, w, h, dst, dst_stride);
420 break;
421 case PIPE_FORMAT_X24S8_UINT:
422 s8x24_get_tile_rgba((uint32_t *) packed, w, h, dst, dst_stride);
423 break;
424 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
425 case PIPE_FORMAT_X8Z24_UNORM:
426 z24s8_get_tile_rgba((uint32_t *) packed, w, h, dst, dst_stride);
427 break;
428 case PIPE_FORMAT_S8X24_UINT:
429 x24s8_get_tile_rgba((uint32_t *) packed, w, h, dst, dst_stride);
430 break;
431 case PIPE_FORMAT_Z32_FLOAT:
432 z32f_get_tile_rgba((float *) packed, w, h, dst, dst_stride);
433 break;
434 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
435 z32f_x24s8_get_tile_rgba((float *) packed, w, h, dst, dst_stride);
436 break;
437 case PIPE_FORMAT_X32_S8X24_UINT:
438 x32_s8_get_tile_rgba((uint32_t *) packed, w, h, dst, dst_stride);
439 break;
440 default:
441 util_format_read_4(format,
442 dst, dst_stride * sizeof(float),
443 packed, util_format_get_stride(format, w),
444 0, 0, w, h);
445 }
446
447 FREE(packed);
448 }
449