llvmpipe: quick & dirty implementation of lp_rast_store_zstencil()
[mesa.git] / src / gallium / drivers / llvmpipe / lp_rast.c
1 /**************************************************************************
2 *
3 * Copyright 2009 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 #include "util/u_memory.h"
29
30 #include "lp_state.h"
31 #include "lp_rast.h"
32 #include "lp_rast_priv.h"
33 #include "lp_tile_soa.h"
34 #include "lp_bld_debug.h"
35
36 #define RAST_DEBUG debug_printf
37
38 struct lp_rasterizer *lp_rast_create( struct pipe_screen *screen )
39 {
40 struct lp_rasterizer *rast;
41
42 rast = CALLOC_STRUCT(lp_rasterizer);
43 if(!rast)
44 return NULL;
45
46 rast->screen = screen;
47 rast->tile.color = align_malloc( TILE_SIZE*TILE_SIZE*4, 16 );
48 rast->tile.depth = align_malloc( TILE_SIZE*TILE_SIZE*4, 16 );
49
50 return rast;
51 }
52
53
54 /**
55 * Begin the rasterization phase.
56 * Map the framebuffer surfaces. Initialize the 'rast' state.
57 */
58 boolean lp_rast_begin( struct lp_rasterizer *rast,
59 struct pipe_surface *cbuf,
60 struct pipe_surface *zsbuf,
61 boolean write_color,
62 boolean write_zstencil,
63 unsigned width,
64 unsigned height )
65 {
66 struct pipe_screen *screen = rast->screen;
67
68 RAST_DEBUG("%s %dx%d\n", __FUNCTION__, width, height);
69
70 pipe_surface_reference(&rast->state.cbuf, cbuf);
71 pipe_surface_reference(&rast->state.zsbuf, zsbuf);
72
73 rast->width = width;
74 rast->height = height;
75 rast->state.write_zstencil = write_zstencil;
76 rast->state.write_color = write_color;
77
78 rast->check_for_clipped_tiles = (width % TILE_SIZE != 0 ||
79 height % TILE_SIZE != 0);
80
81 if (cbuf) {
82 rast->cbuf_transfer = screen->get_tex_transfer(rast->screen,
83 cbuf->texture,
84 cbuf->face,
85 cbuf->level,
86 cbuf->zslice,
87 PIPE_TRANSFER_READ_WRITE,
88 0, 0, width, height);
89 if (!rast->cbuf_transfer)
90 return FALSE;
91
92 rast->cbuf_map = screen->transfer_map(rast->screen,
93 rast->cbuf_transfer);
94 if (!rast->cbuf_map)
95 return FALSE;
96 }
97
98 if (zsbuf) {
99 rast->zsbuf_transfer = screen->get_tex_transfer(rast->screen,
100 zsbuf->texture,
101 zsbuf->face,
102 zsbuf->level,
103 zsbuf->zslice,
104 PIPE_TRANSFER_READ_WRITE,
105 0, 0, width, height);
106 if (!rast->zsbuf_transfer)
107 return FALSE;
108
109 rast->zsbuf_map = screen->transfer_map(rast->screen,
110 rast->zsbuf_transfer);
111 if (!rast->zsbuf_map)
112 return FALSE;
113 }
114
115 return TRUE;
116 }
117
118
119 /**
120 * Finish the rasterization phase.
121 * Unmap framebuffer surfaces.
122 */
123 void lp_rast_end( struct lp_rasterizer *rast )
124 {
125 struct pipe_screen *screen = rast->screen;
126
127 if (rast->cbuf_map)
128 screen->transfer_unmap(screen, rast->cbuf_transfer);
129
130 if (rast->zsbuf_map)
131 screen->transfer_unmap(screen, rast->zsbuf_transfer);
132
133 if (rast->cbuf_transfer)
134 screen->tex_transfer_destroy(rast->cbuf_transfer);
135
136 if (rast->zsbuf_transfer)
137 screen->tex_transfer_destroy(rast->zsbuf_transfer);
138
139 rast->cbuf_transfer = NULL;
140 rast->zsbuf_transfer = NULL;
141 rast->cbuf_map = NULL;
142 rast->zsbuf_map = NULL;
143 }
144
145
146 /**
147 * Begining rasterization of a tile.
148 * \param x window X position of the tile, in pixels
149 * \param y window Y position of the tile, in pixels
150 */
151 void lp_rast_start_tile( struct lp_rasterizer *rast,
152 unsigned x,
153 unsigned y )
154 {
155 RAST_DEBUG("%s %d,%d\n", __FUNCTION__, x, y);
156
157 rast->x = x;
158 rast->y = y;
159 }
160
161
162 /**
163 * Clear the rasterizer's current color tile.
164 */
165 void lp_rast_clear_color( struct lp_rasterizer *rast,
166 const union lp_rast_cmd_arg arg )
167 {
168 const uint8_t *clear_color = arg.clear_color;
169
170 RAST_DEBUG("%s 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__,
171 clear_color[0],
172 clear_color[1],
173 clear_color[2],
174 clear_color[3]);
175
176 if (clear_color[0] == clear_color[1] &&
177 clear_color[1] == clear_color[2] &&
178 clear_color[2] == clear_color[3]) {
179 memset(rast->tile.color, clear_color[0], TILE_SIZE * TILE_SIZE * 4);
180 }
181 else {
182 unsigned x, y, chan;
183 for (y = 0; y < TILE_SIZE; y++)
184 for (x = 0; x < TILE_SIZE; x++)
185 for (chan = 0; chan < 4; ++chan)
186 TILE_PIXEL(rast->tile.color, x, y, chan) = clear_color[chan];
187 }
188 }
189
190
191 /**
192 * Clear the rasterizer's current z/stencil tile.
193 */
194 void lp_rast_clear_zstencil( struct lp_rasterizer *rast,
195 const union lp_rast_cmd_arg arg)
196 {
197 unsigned i, j;
198
199 RAST_DEBUG("%s 0x%x\n", __FUNCTION__, arg.clear_zstencil);
200
201 for (i = 0; i < TILE_SIZE; i++)
202 for (j = 0; j < TILE_SIZE; j++)
203 rast->tile.depth[i*TILE_SIZE + j] = arg.clear_zstencil;
204 }
205
206
207 void lp_rast_load_color( struct lp_rasterizer *rast,
208 const union lp_rast_cmd_arg arg)
209 {
210 RAST_DEBUG("%s\n", __FUNCTION__);
211
212 /* call u_tile func to load colors from surface */
213 }
214
215 void lp_rast_load_zstencil( struct lp_rasterizer *rast,
216 const union lp_rast_cmd_arg arg )
217 {
218 RAST_DEBUG("%s\n", __FUNCTION__);
219
220 /* call u_tile func to load depth (and stencil?) from surface */
221 }
222
223 /* Within a tile:
224 */
225
226 void lp_rast_shade_tile( struct lp_rasterizer *rast,
227 const union lp_rast_cmd_arg arg )
228 {
229 const struct lp_rast_shader_inputs *inputs = arg.shade_tile;
230 const unsigned mask = ~0;
231 unsigned x, y;
232
233 RAST_DEBUG("%s\n", __FUNCTION__);
234
235 /* Use the existing preference for 4x4 (four quads) shading:
236 */
237 for (y = 0; y < TILE_SIZE; y += 4)
238 for (x = 0; x < TILE_SIZE; x += 4)
239 lp_rast_shade_quads( rast, inputs, rast->x + x, rast->y + y, mask);
240 }
241
242
243 /**
244 * Compute shading for a 4x4 block of pixels.
245 */
246 void lp_rast_shade_quads( struct lp_rasterizer *rast,
247 const struct lp_rast_shader_inputs *inputs,
248 unsigned x, unsigned y,
249 unsigned mask)
250 {
251 #if 1
252 const struct lp_rast_state *state = inputs->state;
253 struct lp_rast_tile *tile = &rast->tile;
254 void *color;
255 void *depth;
256 uint32_t ALIGN16_ATTRIB masks[2][2][2][2];
257 unsigned ix, iy;
258 int block_offset;
259
260 /* Sanity checks */
261 assert(x % TILE_VECTOR_WIDTH == 0);
262 assert(y % TILE_VECTOR_HEIGHT == 0);
263
264 /* mask: the rasterizer wants to treat pixels in 4x4 blocks, but
265 * the pixel shader wants to swizzle them into 4 2x2 quads.
266 *
267 * Additionally, the pixel shader wants masks as full dword ~0,
268 * while the rasterizer wants to pack per-pixel bits tightly.
269 */
270 #if 0
271 unsigned qx, qy;
272 for (qy = 0; qy < 2; ++qy)
273 for (qx = 0; qx < 2; ++qx)
274 for (iy = 0; iy < 2; ++iy)
275 for (ix = 0; ix < 2; ++ix)
276 masks[qy][qx][iy][ix] = mask & (1 << (qy*8+iy*4+qx*2+ix)) ? ~0 : 0;
277 #else
278 masks[0][0][0][0] = mask & (1 << (0*8+0*4+0*2+0)) ? ~0 : 0;
279 masks[0][0][0][1] = mask & (1 << (0*8+0*4+0*2+1)) ? ~0 : 0;
280 masks[0][0][1][0] = mask & (1 << (0*8+1*4+0*2+0)) ? ~0 : 0;
281 masks[0][0][1][1] = mask & (1 << (0*8+1*4+0*2+1)) ? ~0 : 0;
282 masks[0][1][0][0] = mask & (1 << (0*8+0*4+1*2+0)) ? ~0 : 0;
283 masks[0][1][0][1] = mask & (1 << (0*8+0*4+1*2+1)) ? ~0 : 0;
284 masks[0][1][1][0] = mask & (1 << (0*8+1*4+1*2+0)) ? ~0 : 0;
285 masks[0][1][1][1] = mask & (1 << (0*8+1*4+1*2+1)) ? ~0 : 0;
286
287 masks[1][0][0][0] = mask & (1 << (1*8+0*4+0*2+0)) ? ~0 : 0;
288 masks[1][0][0][1] = mask & (1 << (1*8+0*4+0*2+1)) ? ~0 : 0;
289 masks[1][0][1][0] = mask & (1 << (1*8+1*4+0*2+0)) ? ~0 : 0;
290 masks[1][0][1][1] = mask & (1 << (1*8+1*4+0*2+1)) ? ~0 : 0;
291 masks[1][1][0][0] = mask & (1 << (1*8+0*4+1*2+0)) ? ~0 : 0;
292 masks[1][1][0][1] = mask & (1 << (1*8+0*4+1*2+1)) ? ~0 : 0;
293 masks[1][1][1][0] = mask & (1 << (1*8+1*4+1*2+0)) ? ~0 : 0;
294 masks[1][1][1][1] = mask & (1 << (1*8+1*4+1*2+1)) ? ~0 : 0;
295 #endif
296
297 assert((x % 2) == 0);
298 assert((y % 2) == 0);
299
300 ix = x % TILE_SIZE;
301 iy = y % TILE_SIZE;
302
303 /* offset of the 16x16 pixel block within the tile */
304 block_offset = ((iy/4)*(16*16) + (ix/4)*16);
305
306 /* color buffer */
307 color = tile->color + 4 * block_offset;
308
309 /* depth buffer */
310 depth = tile->depth + block_offset;
311
312 /* XXX: This will most likely fail on 32bit x86 without -mstackrealign */
313 assert(lp_check_alignment(masks, 16));
314
315 assert(lp_check_alignment(depth, 16));
316 assert(lp_check_alignment(color, 16));
317 assert(lp_check_alignment(state->jit_context.blend_color, 16));
318
319 /* run shader */
320 state->jit_function( &state->jit_context,
321 x, y,
322 inputs->a0,
323 inputs->dadx,
324 inputs->dady,
325 &masks[0][0][0][0],
326 color,
327 depth);
328 #else
329 struct lp_rast_tile *tile = &rast->tile;
330 unsigned chan_index;
331 unsigned q, ix, iy;
332
333 x %= TILE_SIZE;
334 y %= TILE_SIZE;
335
336 /* mask */
337 for (q = 0; q < 4; ++q)
338 for(iy = 0; iy < 2; ++iy)
339 for(ix = 0; ix < 2; ++ix)
340 if(masks[q] & (1 << (iy*2 + ix)))
341 for (chan_index = 0; chan_index < NUM_CHANNELS; ++chan_index)
342 TILE_PIXEL(tile->color, x + q*2 + ix, y + iy, chan_index) = 0xff;
343
344 #endif
345 }
346
347
348 /* End of tile:
349 */
350
351
352 /**
353 * Write the rasterizer's color tile to the framebuffer.
354 */
355 static void lp_rast_store_color( struct lp_rasterizer *rast )
356 {
357 const unsigned x = rast->x;
358 const unsigned y = rast->y;
359 unsigned w = TILE_SIZE;
360 unsigned h = TILE_SIZE;
361
362 if (x + w > rast->width)
363 w -= x + w - rast->width;
364
365 if (y + h > rast->height)
366 h -= y + h - rast->height;
367
368 RAST_DEBUG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h);
369
370 lp_tile_write_4ub(rast->cbuf_transfer->format,
371 rast->tile.color,
372 rast->cbuf_map,
373 rast->cbuf_transfer->stride,
374 x, y,
375 w, h);
376 }
377
378
379 static void
380 lp_tile_write_z32(const uint32_t *src, uint8_t *dst, unsigned dst_stride,
381 unsigned x0, unsigned y0, unsigned w, unsigned h)
382 {
383 unsigned x, y;
384 uint8_t *dst_row = dst + y0*dst_stride;
385 for (y = 0; y < h; ++y) {
386 uint32_t *dst_pixel = (uint32_t *)(dst_row + x0*4);
387 for (x = 0; x < w; ++x) {
388 *dst_pixel++ = *src++;
389 }
390 dst_row += dst_stride;
391 }
392 }
393
394 /**
395 * Write the rasterizer's z/stencil tile to the framebuffer.
396 */
397 static void lp_rast_store_zstencil( struct lp_rasterizer *rast )
398 {
399 const unsigned x = rast->x;
400 const unsigned y = rast->y;
401 unsigned w = TILE_SIZE;
402 unsigned h = TILE_SIZE;
403
404 if (x + w > rast->width)
405 w -= x + w - rast->width;
406
407 if (y + h > rast->height)
408 h -= y + h - rast->height;
409
410 RAST_DEBUG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h);
411
412 assert(rast->zsbuf_transfer->format == PIPE_FORMAT_Z32_UNORM);
413 lp_tile_write_z32(rast->tile.depth,
414 rast->zsbuf_map,
415 rast->zsbuf_transfer->stride,
416 x, y, w, h);
417 }
418
419
420 /**
421 * Write the rasterizer's tiles to the framebuffer.
422 */
423 void lp_rast_end_tile( struct lp_rasterizer *rast )
424 {
425 RAST_DEBUG("%s\n", __FUNCTION__);
426
427 if (rast->state.write_color)
428 lp_rast_store_color(rast);
429
430 if (rast->state.write_zstencil)
431 lp_rast_store_zstencil(rast);
432 }
433
434
435 /* Shutdown:
436 */
437 void lp_rast_destroy( struct lp_rasterizer *rast )
438 {
439 pipe_surface_reference(&rast->state.cbuf, NULL);
440 pipe_surface_reference(&rast->state.zsbuf, NULL);
441 align_free(rast->tile.depth);
442 align_free(rast->tile.color);
443 FREE(rast);
444 }
445