include surface.offset in address calculations
[mesa.git] / src / mesa / pipe / softpipe / sp_surface.c
1 /**************************************************************************
2 *
3 * Copyright 2003 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 #include "sp_context.h"
29 #include "sp_state.h"
30 #include "sp_surface.h"
31 #include "pipe/p_defines.h"
32 #include "main/imports.h"
33 #include "main/macros.h"
34
35
36 /**
37 * Softpipe surface functions.
38 * Basically, create surface of a particular type, then plug in default
39 * read/write_quad and get/put_tile() functions.
40 * Note that these quad funcs assume the buffer/region is in a linear
41 * layout with Y=0=top.
42 * If we had swizzled/AOS buffers the read/write quad functions could be
43 * simplified a lot....
44 */
45
46
47
48 /*** PIPE_FORMAT_U_A8_R8_G8_B8 ***/
49
50 static void
51 a8r8g8b8_read_quad_f_swz(struct softpipe_surface *sps, GLint x, GLint y,
52 GLfloat (*rrrr)[QUAD_SIZE])
53 {
54 const GLuint *src
55 = ((const GLuint *) (sps->surface.region->map + sps->surface.offset))
56 + y * sps->surface.region->pitch + x;
57 GLuint i, j;
58
59 assert(sps->surface.format == PIPE_FORMAT_U_A8_R8_G8_B8);
60 assert(x < sps->surface.width - 1);
61 assert(y < sps->surface.height - 1);
62
63 for (i = 0; i < 2; i++) { /* loop over pixel row */
64 for (j = 0; j < 2; j++) { /* loop over pixel column */
65 const GLuint p = src[j];
66 rrrr[0][i * 2 + j] = UBYTE_TO_FLOAT((p >> 16) & 0xff); /*R*/
67 rrrr[1][i * 2 + j] = UBYTE_TO_FLOAT((p >> 8) & 0xff); /*G*/
68 rrrr[2][i * 2 + j] = UBYTE_TO_FLOAT((p ) & 0xff); /*B*/
69 rrrr[3][i * 2 + j] = UBYTE_TO_FLOAT((p >> 24) & 0xff); /*A*/
70 }
71 src += sps->surface.region->pitch;
72 }
73 }
74
75 static void
76 a8r8g8b8_write_quad_f_swz(struct softpipe_surface *sps, GLint x, GLint y,
77 GLfloat (*rrrr)[QUAD_SIZE])
78 {
79 GLuint *dst
80 = ((GLuint *) (sps->surface.region->map + sps->surface.offset))
81 + y * sps->surface.region->pitch + x;
82 GLuint i, j;
83
84 assert(sps->surface.format == PIPE_FORMAT_U_A8_R8_G8_B8);
85
86 for (i = 0; i < 2; i++) { /* loop over pixel row */
87 for (j = 0; j < 2; j++) { /* loop over pixel column */
88 GLubyte r, g, b, a;
89 UNCLAMPED_FLOAT_TO_UBYTE(r, rrrr[0][i * 2 + j]); /*R*/
90 UNCLAMPED_FLOAT_TO_UBYTE(g, rrrr[1][i * 2 + j]); /*G*/
91 UNCLAMPED_FLOAT_TO_UBYTE(b, rrrr[2][i * 2 + j]); /*B*/
92 UNCLAMPED_FLOAT_TO_UBYTE(a, rrrr[3][i * 2 + j]); /*A*/
93 dst[j] = (a << 24) | (r << 16) | (g << 8) | b;
94 }
95 dst += sps->surface.region->pitch;
96 }
97 }
98
99 static void
100 a8r8g8b8_get_tile(struct pipe_surface *ps,
101 GLuint x, GLuint y, GLuint w, GLuint h, GLfloat *p)
102 {
103 const GLuint *src
104 = ((const GLuint *) (ps->region->map + ps->offset))
105 + y * ps->region->pitch + x;
106 GLuint i, j;
107
108 assert(ps->format == PIPE_FORMAT_U_A8_R8_G8_B8);
109
110 #if 0
111 assert(x + w <= ps->width);
112 assert(y + h <= ps->height);
113 #else
114 /* temp hack */
115 if (x + w > ps->width)
116 w = ps->width - x;
117 if (y + h > ps->height)
118 h = ps->height -y;
119 #endif
120 for (i = 0; i < h; i++) {
121 for (j = 0; j < w; j++) {
122 const GLuint pixel = src[j];
123 p[0] = UBYTE_TO_FLOAT((pixel >> 16) & 0xff);
124 p[1] = UBYTE_TO_FLOAT((pixel >> 8) & 0xff);
125 p[2] = UBYTE_TO_FLOAT((pixel >> 0) & 0xff);
126 p[3] = UBYTE_TO_FLOAT((pixel >> 24) & 0xff);
127 p += 4;
128 }
129 src += ps->region->pitch;
130 }
131 }
132
133
134 /*** PIPE_FORMAT_U_A1_R5_G5_B5 ***/
135
136 static void
137 a1r5g5b5_get_tile(struct pipe_surface *ps,
138 GLuint x, GLuint y, GLuint w, GLuint h, GLfloat *p)
139 {
140 const GLushort *src
141 = ((const GLushort *) (ps->region->map + ps->offset))
142 + y * ps->region->pitch + x;
143 GLuint i, j;
144
145 assert(ps->format == PIPE_FORMAT_U_A1_R5_G5_B5);
146
147 for (i = 0; i < h; i++) {
148 for (j = 0; j < w; j++) {
149 const GLushort pixel = src[j];
150 p[0] = ((pixel >> 10) & 0x1f) * (1.0 / 31);
151 p[1] = ((pixel >> 5) & 0x1f) * (1.0 / 31);
152 p[2] = ((pixel ) & 0x1f) * (1.0 / 31);
153 p[3] = ((pixel >> 15) );
154 p += 4;
155 }
156 src += ps->region->pitch;
157 }
158 }
159
160
161
162 /*** PIPE_FORMAT_U_Z16 ***/
163
164 static void
165 z16_read_quad_z(struct softpipe_surface *sps,
166 GLint x, GLint y, GLuint zzzz[QUAD_SIZE])
167 {
168 const GLushort *src
169 = ((const GLushort *) (sps->surface.region->map + sps->surface.offset))
170 + y * sps->surface.region->pitch + x;
171
172 assert(sps->surface.format == PIPE_FORMAT_U_Z16);
173
174 /* converting GLushort to GLuint: */
175 zzzz[0] = src[0];
176 zzzz[1] = src[1];
177 src += sps->surface.region->pitch;
178 zzzz[2] = src[0];
179 zzzz[3] = src[1];
180 }
181
182 static void
183 z16_write_quad_z(struct softpipe_surface *sps,
184 GLint x, GLint y, const GLuint zzzz[QUAD_SIZE])
185 {
186 GLushort *dst
187 = ((GLushort *) (sps->surface.region->map + sps->surface.offset))
188 + y * sps->surface.region->pitch + x;
189
190 assert(sps->surface.format == PIPE_FORMAT_U_Z16);
191
192 /* converting GLuint to GLushort: */
193 dst[0] = zzzz[0];
194 dst[1] = zzzz[1];
195 dst += sps->surface.region->pitch;
196 dst[0] = zzzz[2];
197 dst[1] = zzzz[3];
198 }
199
200
201 /*** PIPE_FORMAT_U_Z32 ***/
202
203 static void
204 z32_read_quad_z(struct softpipe_surface *sps,
205 GLint x, GLint y, GLuint zzzz[QUAD_SIZE])
206 {
207 const GLuint *src
208 = ((GLuint *) (sps->surface.region->map + sps->surface.offset))
209 + y * sps->surface.region->pitch + x;
210
211 assert(sps->surface.format == PIPE_FORMAT_U_Z32);
212
213 zzzz[0] = src[0];
214 zzzz[1] = src[1];
215 src += sps->surface.region->pitch;
216 zzzz[2] = src[0];
217 zzzz[3] = src[1];
218 }
219
220 static void
221 z32_write_quad_z(struct softpipe_surface *sps,
222 GLint x, GLint y, const GLuint zzzz[QUAD_SIZE])
223 {
224 GLuint *dst
225 = ((GLuint *) (sps->surface.region->map + sps->surface.offset))
226 + y * sps->surface.region->pitch + x;
227
228 assert(sps->surface.format == PIPE_FORMAT_U_Z32);
229
230 dst[0] = zzzz[0];
231 dst[1] = zzzz[1];
232 dst += sps->surface.region->pitch;
233 dst[0] = zzzz[2];
234 dst[1] = zzzz[3];
235 }
236
237
238 /*** PIPE_FORMAT_S8_Z24 ***/
239
240 static void
241 s8z24_read_quad_z(struct softpipe_surface *sps,
242 GLint x, GLint y, GLuint zzzz[QUAD_SIZE])
243 {
244 static const GLuint mask = 0x00ffffff;
245 const GLuint *src
246 = ((GLuint *) (sps->surface.region->map + sps->surface.offset))
247 + y * sps->surface.region->pitch + x;
248
249 assert(sps->surface.format == PIPE_FORMAT_S8_Z24);
250
251 /* extract lower three bytes */
252 zzzz[0] = src[0] & mask;
253 zzzz[1] = src[1] & mask;
254 src += sps->surface.region->pitch;
255 zzzz[2] = src[0] & mask;
256 zzzz[3] = src[1] & mask;
257 }
258
259 static void
260 s8z24_write_quad_z(struct softpipe_surface *sps,
261 GLint x, GLint y, const GLuint zzzz[QUAD_SIZE])
262 {
263 static const GLuint mask = 0xff000000;
264 GLuint *dst
265 = ((GLuint *) (sps->surface.region->map + sps->surface.offset))
266 + y * sps->surface.region->pitch + x;
267
268 assert(sps->surface.format == PIPE_FORMAT_S8_Z24);
269 assert(zzzz[0] <= 0xffffff);
270
271 dst[0] = (dst[0] & mask) | zzzz[0];
272 dst[1] = (dst[1] & mask) | zzzz[1];
273 dst += sps->surface.region->pitch;
274 dst[0] = (dst[0] & mask) | zzzz[2];
275 dst[1] = (dst[1] & mask) | zzzz[3];
276 }
277
278 static void
279 s8z24_read_quad_stencil(struct softpipe_surface *sps,
280 GLint x, GLint y, GLubyte ssss[QUAD_SIZE])
281 {
282 const GLuint *src
283 = ((GLuint *) (sps->surface.region->map + sps->surface.offset))
284 + y * sps->surface.region->pitch + x;
285
286 assert(sps->surface.format == PIPE_FORMAT_S8_Z24);
287
288 ssss[0] = src[0] >> 24;
289 ssss[1] = src[1] >> 24;
290 src += sps->surface.region->pitch;
291 ssss[2] = src[0] >> 24;
292 ssss[3] = src[1] >> 24;
293 }
294
295 static void
296 s8z24_write_quad_stencil(struct softpipe_surface *sps,
297 GLint x, GLint y, const GLubyte ssss[QUAD_SIZE])
298 {
299 static const GLuint mask = 0x00ffffff;
300 GLuint *dst
301 = ((GLuint *) (sps->surface.region->map + sps->surface.offset))
302 + y * sps->surface.region->pitch + x;
303
304 assert(sps->surface.format == PIPE_FORMAT_S8_Z24);
305
306 dst[0] = (dst[0] & mask) | (ssss[0] << 24);
307 dst[1] = (dst[1] & mask) | (ssss[1] << 24);
308 dst += sps->surface.region->pitch;
309 dst[0] = (dst[0] & mask) | (ssss[2] << 24);
310 dst[1] = (dst[1] & mask) | (ssss[3] << 24);
311 }
312
313
314 /*** PIPE_FORMAT_U_S8 ***/
315
316 static void
317 s8_read_quad_stencil(struct softpipe_surface *sps,
318 GLint x, GLint y, GLubyte ssss[QUAD_SIZE])
319 {
320 const GLubyte *src
321 = sps->surface.region->map + sps->surface.offset
322 + y * sps->surface.region->pitch + x;
323
324 assert(sps->surface.format == PIPE_FORMAT_U_S8);
325
326 ssss[0] = src[0];
327 ssss[1] = src[1];
328 src += sps->surface.region->pitch;
329 ssss[2] = src[0];
330 ssss[3] = src[1];
331 }
332
333 static void
334 s8_write_quad_stencil(struct softpipe_surface *sps,
335 GLint x, GLint y, const GLubyte ssss[QUAD_SIZE])
336 {
337 GLubyte *dst
338 = sps->surface.region->map + sps->surface.offset
339 + y * sps->surface.region->pitch + x;
340
341 assert(sps->surface.format == PIPE_FORMAT_U_S8);
342
343 dst[0] = ssss[0];
344 dst[1] = ssss[1];
345 dst += sps->surface.region->pitch;
346 dst[0] = ssss[2];
347 dst[1] = ssss[3];
348 }
349
350
351 void
352 softpipe_init_surface_funcs(struct softpipe_surface *sps)
353 {
354 switch (sps->surface.format) {
355 case PIPE_FORMAT_U_A8_R8_G8_B8:
356 sps->read_quad_f_swz = a8r8g8b8_read_quad_f_swz;
357 sps->write_quad_f_swz = a8r8g8b8_write_quad_f_swz;
358 sps->surface.get_tile = a8r8g8b8_get_tile;
359 case PIPE_FORMAT_U_A1_R5_G5_B5:
360 sps->surface.get_tile = a1r5g5b5_get_tile;
361 break;
362 case PIPE_FORMAT_U_Z16:
363 sps->read_quad_z = z16_read_quad_z;
364 sps->write_quad_z = z16_write_quad_z;
365 break;
366 case PIPE_FORMAT_U_Z32:
367 sps->read_quad_z = z32_read_quad_z;
368 sps->write_quad_z = z32_write_quad_z;
369 break;
370 case PIPE_FORMAT_S8_Z24:
371 sps->read_quad_z = s8z24_read_quad_z;
372 sps->write_quad_z = s8z24_write_quad_z;
373 sps->read_quad_stencil = s8z24_read_quad_stencil;
374 sps->write_quad_stencil = s8z24_write_quad_stencil;
375 break;
376 case PIPE_FORMAT_U_S8:
377 sps->read_quad_stencil = s8_read_quad_stencil;
378 sps->write_quad_stencil = s8_write_quad_stencil;
379 break;
380 default:
381 assert(0);
382 }
383 }
384
385
386 static struct pipe_surface *
387 softpipe_surface_alloc(struct pipe_context *pipe, GLuint pipeFormat)
388 {
389 struct softpipe_surface *sps = CALLOC_STRUCT(softpipe_surface);
390 if (!sps)
391 return NULL;
392
393 assert(pipeFormat < PIPE_FORMAT_COUNT);
394
395 sps->surface.format = pipeFormat;
396 sps->surface.refcount = 1;
397 softpipe_init_surface_funcs(sps);
398
399 return &sps->surface;
400 }
401
402
403
404
405
406 /**
407 * Called via pipe->get_tex_surface()
408 * XXX is this in the right place?
409 */
410 struct pipe_surface *
411 softpipe_get_tex_surface(struct pipe_context *pipe,
412 struct pipe_mipmap_tree *mt,
413 GLuint face, GLuint level, GLuint zslice)
414 {
415 struct pipe_surface *ps;
416 GLuint offset; /* in bytes */
417
418 offset = mt->level[level].level_offset;
419
420 if (mt->target == GL_TEXTURE_CUBE_MAP_ARB) {
421 offset += mt->level[level].image_offset[face] * mt->cpp;
422 }
423 else if (mt->target == GL_TEXTURE_3D) {
424 offset += mt->level[level].image_offset[zslice] * mt->cpp;
425 }
426 else {
427 assert(face == 0);
428 assert(zslice == 0);
429 }
430
431 ps = pipe->surface_alloc(pipe, mt->format);
432 if (ps) {
433 assert(ps->format);
434 assert(ps->refcount);
435 ps->region = mt->region;
436 ps->width = mt->level[level].width;
437 ps->height = mt->level[level].height;
438 ps->offset = offset;
439 }
440 return ps;
441 }
442
443
444 void
445 sp_init_surface_functions(struct softpipe_context *sp)
446 {
447 sp->pipe.surface_alloc = softpipe_surface_alloc;
448 }