From 7e8396399824108d62dc3e02b2af0422e98aab8e Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 20 Oct 2007 15:18:02 -0600 Subject: [PATCH] Convert Z/stencil ops to use cached tiles like colors. Also, quite a bit of re-org of the tile caches and surface mapping/unmapping. Leave surfaces mapped between primitives now. --- src/mesa/pipe/softpipe/sp_clear.c | 2 + src/mesa/pipe/softpipe/sp_context.c | 82 +++++++++---- src/mesa/pipe/softpipe/sp_context.h | 8 ++ src/mesa/pipe/softpipe/sp_draw_arrays.c | 5 +- src/mesa/pipe/softpipe/sp_flush.c | 14 ++- src/mesa/pipe/softpipe/sp_quad_blend.c | 6 +- src/mesa/pipe/softpipe/sp_quad_colormask.c | 3 +- src/mesa/pipe/softpipe/sp_quad_depth_test.c | 125 ++++++++++++++------ src/mesa/pipe/softpipe/sp_quad_output.c | 3 +- src/mesa/pipe/softpipe/sp_quad_stencil.c | 52 +++++++- src/mesa/pipe/softpipe/sp_state.h | 6 + src/mesa/pipe/softpipe/sp_state_surface.c | 88 +++++++++++++- src/mesa/pipe/softpipe/sp_surface.c | 9 +- src/mesa/pipe/softpipe/sp_surface.h | 2 - src/mesa/pipe/softpipe/sp_tile_cache.c | 97 ++++++++++----- src/mesa/pipe/softpipe/sp_tile_cache.h | 17 ++- 16 files changed, 394 insertions(+), 125 deletions(-) diff --git a/src/mesa/pipe/softpipe/sp_clear.c b/src/mesa/pipe/softpipe/sp_clear.c index 46370b4ed9a..4f04f8243fa 100644 --- a/src/mesa/pipe/softpipe/sp_clear.c +++ b/src/mesa/pipe/softpipe/sp_clear.c @@ -69,5 +69,7 @@ softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, /* XXX skip this fill if we're using tile cache */ pipe->region_fill(pipe, ps->region, 0, x, y, w, h, clearValue); +#if 0 sp_clear_tile_cache(sps, clearValue); +#endif } diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c index 44cc6851053..87eaf6fb544 100644 --- a/src/mesa/pipe/softpipe/sp_context.c +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -39,6 +39,7 @@ #include "sp_region.h" #include "sp_state.h" #include "sp_surface.h" +#include "sp_tile_cache.h" #include "sp_tex_layout.h" #include "sp_winsys.h" @@ -113,6 +114,9 @@ softpipe_max_texture_size(struct pipe_context *pipe, unsigned textureType, } +/** + * Map any drawing surfaces which aren't already mapped + */ void softpipe_map_surfaces(struct softpipe_context *sp) { @@ -120,68 +124,88 @@ softpipe_map_surfaces(struct softpipe_context *sp) unsigned i; for (i = 0; i < sp->framebuffer.num_cbufs; i++) { - struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.cbufs[i]); - if (sps->surface.region) - pipe->region_map(pipe, sps->surface.region); + struct pipe_surface *ps = sp->framebuffer.cbufs[i]; + if (ps->region && !ps->region->map) { + pipe->region_map(pipe, ps->region); + } } if (sp->framebuffer.zbuf) { - struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.zbuf); - if (sps->surface.region) - pipe->region_map(pipe, sps->surface.region); + struct pipe_surface *ps = sp->framebuffer.zbuf; + if (ps->region && !ps->region->map) { + pipe->region_map(pipe, ps->region); + } } if (sp->framebuffer.sbuf) { - struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.sbuf); - if (sps->surface.region) - pipe->region_map(pipe, sps->surface.region); + struct pipe_surface *ps = sp->framebuffer.sbuf; + if (ps->region && !ps->region->map) { + pipe->region_map(pipe, ps->region); + } } +} + + +void +softpipe_map_texture_surfaces(struct softpipe_context *sp) +{ + struct pipe_context *pipe = &sp->pipe; + uint i; - /* textures */ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { struct pipe_mipmap_tree *mt = sp->texture[i]; if (mt) { pipe->region_map(pipe, mt->region); } } - - /* XXX depth & stencil bufs */ } +/** + * Unmap any mapped drawing surfaces + */ void softpipe_unmap_surfaces(struct softpipe_context *sp) { struct pipe_context *pipe = &sp->pipe; - unsigned i; + uint i; + + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) + sp_flush_tile_cache(sp->cbuf_cache[i]); + sp_flush_tile_cache(sp->zbuf_cache); + sp_flush_tile_cache(sp->sbuf_cache); for (i = 0; i < sp->framebuffer.num_cbufs; i++) { - struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.cbufs[i]); - if (sps->surface.region) - pipe->region_unmap(pipe, sps->surface.region); + struct pipe_surface *ps = sp->framebuffer.cbufs[i]; + if (ps->region) + pipe->region_unmap(pipe, ps->region); } if (sp->framebuffer.zbuf) { - struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.zbuf); - if (sps->surface.region) - pipe->region_unmap(pipe, sps->surface.region); + struct pipe_surface *ps = sp->framebuffer.zbuf; + if (ps->region) + pipe->region_unmap(pipe, ps->region); } - if (sp->framebuffer.sbuf) { - struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.sbuf); - if (sps->surface.region) - pipe->region_unmap(pipe, sps->surface.region); + if (sp->framebuffer.sbuf && sp->framebuffer.sbuf != sp->framebuffer.zbuf) { + struct pipe_surface *ps = sp->framebuffer.sbuf; + if (ps->region) + pipe->region_unmap(pipe, ps->region); } +} - /* textures */ + +void +softpipe_unmap_texture_surfaces(struct softpipe_context *sp) +{ + struct pipe_context *pipe = &sp->pipe; + uint i; for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { struct pipe_mipmap_tree *mt = sp->texture[i]; if (mt) { pipe->region_unmap(pipe, mt->region); } } - - /* XXX depth & stencil bufs */ } @@ -248,6 +272,7 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys, struct softpipe_winsys *softpipe_winsys ) { struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context); + uint i; #if defined(__i386__) || defined(__386__) softpipe->use_sse = getenv("GALLIUM_SSE") != NULL; @@ -355,5 +380,10 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys, sp_init_region_functions(softpipe); sp_init_surface_functions(softpipe); + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) + softpipe->cbuf_cache[i] = sp_create_tile_cache(); + softpipe->zbuf_cache = sp_create_tile_cache(); + softpipe->sbuf_cache_sep = sp_create_tile_cache(); + return &softpipe->pipe; } diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h index 4f429e81397..ea05f80d59a 100644 --- a/src/mesa/pipe/softpipe/sp_context.h +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -44,6 +44,7 @@ struct softpipe_surface; struct softpipe_winsys; struct draw_context; struct draw_stage; +struct softpipe_tile_cache; #define SP_NEW_VIEWPORT 0x1 @@ -155,6 +156,13 @@ struct softpipe_context { struct pipe_surface *cbuf; /**< current color buffer (one of cbufs) */ + struct softpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS]; + struct softpipe_tile_cache *zbuf_cache; + /** Stencil buffer cache, for stencil separate from Z */ + struct softpipe_tile_cache *sbuf_cache_sep; + /** This either points to zbuf_cache or sbuf_cache_sep */ + struct softpipe_tile_cache *sbuf_cache; + int use_sse : 1; }; diff --git a/src/mesa/pipe/softpipe/sp_draw_arrays.c b/src/mesa/pipe/softpipe/sp_draw_arrays.c index 405659fb464..64a4fbe333e 100644 --- a/src/mesa/pipe/softpipe/sp_draw_arrays.c +++ b/src/mesa/pipe/softpipe/sp_draw_arrays.c @@ -113,7 +113,7 @@ softpipe_draw_elements(struct pipe_context *pipe, softpipe_update_derived( sp ); softpipe_map_surfaces(sp); - + softpipe_map_texture_surfaces(sp); softpipe_map_constant_buffers(sp); /* @@ -184,7 +184,8 @@ softpipe_draw_elements(struct pipe_context *pipe, } - softpipe_unmap_surfaces(sp); + /* Note: leave drawing surfaces mapped */ + softpipe_unmap_texture_surfaces(sp); softpipe_unmap_constant_buffers(sp); return TRUE; diff --git a/src/mesa/pipe/softpipe/sp_flush.c b/src/mesa/pipe/softpipe/sp_flush.c index d4eada82287..f2186dbb653 100644 --- a/src/mesa/pipe/softpipe/sp_flush.c +++ b/src/mesa/pipe/softpipe/sp_flush.c @@ -54,10 +54,14 @@ softpipe_flush( struct pipe_context *pipe, * - flush the render cache */ - for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) { - struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.cbufs[i]); - if (sps) - sp_flush_tile_cache(sps); - } + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) + if (softpipe->cbuf_cache[i]) + sp_flush_tile_cache(softpipe->cbuf_cache[i]); + + if (softpipe->zbuf_cache) + sp_flush_tile_cache(softpipe->zbuf_cache); + + if (softpipe->sbuf_cache) + sp_flush_tile_cache(softpipe->sbuf_cache); } diff --git a/src/mesa/pipe/softpipe/sp_quad_blend.c b/src/mesa/pipe/softpipe/sp_quad_blend.c index 43294e4cd4d..5787b89588d 100644 --- a/src/mesa/pipe/softpipe/sp_quad_blend.c +++ b/src/mesa/pipe/softpipe/sp_quad_blend.c @@ -101,14 +101,13 @@ static void logicop_quad(struct quad_stage *qs, struct quad_header *quad) { struct softpipe_context *softpipe = qs->softpipe; - struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf); float dest[4][QUAD_SIZE]; ubyte src[4][4], dst[4][4], res[4][4]; uint *src4 = (uint *) src; uint *dst4 = (uint *) dst; uint *res4 = (uint *) res; struct softpipe_cached_tile * - tile = sp_get_cached_tile(sps, quad->x0, quad->y0); + tile = sp_get_cached_tile(softpipe->cbuf_cache[0], quad->x0, quad->y0); uint i, j; /* get/swizzle dest colors */ @@ -220,12 +219,11 @@ static void blend_quad(struct quad_stage *qs, struct quad_header *quad) { struct softpipe_context *softpipe = qs->softpipe; - struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf); static const float zero[4] = { 0, 0, 0, 0 }; static const float one[4] = { 1, 1, 1, 1 }; float source[4][QUAD_SIZE], dest[4][QUAD_SIZE]; struct softpipe_cached_tile * - tile = sp_get_cached_tile(sps, quad->x0, quad->y0); + tile = sp_get_cached_tile(softpipe->cbuf_cache[0], quad->x0, quad->y0); uint i, j; if (softpipe->blend->logicop_enable) { diff --git a/src/mesa/pipe/softpipe/sp_quad_colormask.c b/src/mesa/pipe/softpipe/sp_quad_colormask.c index aa69f53580e..3c0196dd5dc 100644 --- a/src/mesa/pipe/softpipe/sp_quad_colormask.c +++ b/src/mesa/pipe/softpipe/sp_quad_colormask.c @@ -47,10 +47,9 @@ static void colormask_quad(struct quad_stage *qs, struct quad_header *quad) { struct softpipe_context *softpipe = qs->softpipe; - struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf); float dest[4][QUAD_SIZE]; struct softpipe_cached_tile * - tile = sp_get_cached_tile(sps, quad->x0, quad->y0); + tile = sp_get_cached_tile(softpipe->cbuf_cache[0], quad->x0, quad->y0); uint i, j; /* get/swizzle dest colors */ diff --git a/src/mesa/pipe/softpipe/sp_quad_depth_test.c b/src/mesa/pipe/softpipe/sp_quad_depth_test.c index efd08b981cf..29231322b83 100644 --- a/src/mesa/pipe/softpipe/sp_quad_depth_test.c +++ b/src/mesa/pipe/softpipe/sp_quad_depth_test.c @@ -39,55 +39,86 @@ * Do depth testing for a quad. * Not static since it's used by the stencil code. */ + +/* + * To increase efficiency, we should probably have multiple versions + * of this function that are specifically for Z16, Z32 and FP Z buffers. + * Try to effectively do that with codegen... + */ + void sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad) { struct softpipe_context *softpipe = qs->softpipe; struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.zbuf); + const uint format = sps->surface.format; unsigned bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */ unsigned qzzzz[QUAD_SIZE]; /**< Z values from the quad */ unsigned zmask = 0; unsigned j; - float scale; -#if 0 - struct cached_tile *tile = sp_get_cached_tile(softpipe, quad->x0, quad->y0); -#endif + struct softpipe_cached_tile *tile + = sp_get_cached_tile(softpipe->zbuf_cache, quad->x0, quad->y0); assert(sps); /* shouldn't get here if there's no zbuffer */ /* - * To increase efficiency, we should probably have multiple versions - * of this function that are specifically for Z16, Z32 and FP Z buffers. - * Try to effectively do that with codegen... - */ - if (sps->surface.format == PIPE_FORMAT_U_Z16) - scale = 65535.0; - else if (sps->surface.format == PIPE_FORMAT_S8_Z24) - scale = (float) ((1 << 24) - 1); - else - assert(0); /* XXX fix this someday */ - - /* - * Convert quad's float depth values to int depth values. + * Convert quad's float depth values to int depth values (qzzzz). * If the Z buffer stores integer values, we _have_ to do the depth * compares with integers (not floats). Otherwise, the float->int->float * conversion of Z values (which isn't an identity function) will cause * Z-fighting errors. + * + * Also, get the zbuffer values (bzzzz) from the cached tile. */ - for (j = 0; j < QUAD_SIZE; j++) { - qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale); - } + switch (format) { + case PIPE_FORMAT_U_Z16: + { + float scale = 65535.0; -#if 0 - for (j = 0; j < 4; j++) { - int x = quad->x0 % TILE_SIZE + (j & 1); - int y = quad->y0 % TILE_SIZE + (j >> 1); - bzzzz[j] = tile->depth[y][x]; + for (j = 0; j < QUAD_SIZE; j++) { + qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale); + } + + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + bzzzz[j] = tile->data.depth16[y][x]; + } + } + break; + case PIPE_FORMAT_U_Z32: + { + double scale = (double) (uint) ~0UL; + + for (j = 0; j < QUAD_SIZE; j++) { + qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale); + } + + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + bzzzz[j] = tile->data.depth32[y][x]; + } + } + break; + case PIPE_FORMAT_S8_Z24: + { + float scale = (float) ((1 << 24) - 1); + + for (j = 0; j < QUAD_SIZE; j++) { + qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale); + } + + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + bzzzz[j] = tile->data.depth32[y][x] & 0xffffff; + } + } + break; + default: + assert(0); } -#else - /* get zquad from zbuffer */ - sps->read_quad_z(sps, quad->x0, quad->y0, bzzzz); -#endif switch (softpipe->depth_stencil->depth.func) { case PIPE_FUNC_NEVER: @@ -151,16 +182,34 @@ sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad) } } -#if 1 - /* write updated zquad to zbuffer */ - sps->write_quad_z(sps, quad->x0, quad->y0, bzzzz); -#else - for (j = 0; j < 4; j++) { - int x = quad->x0 % TILE_SIZE + (j & 1); - int y = quad->y0 % TILE_SIZE + (j >> 1); - tile->depth[y][x] = bzzzz[j]; + /* put updated Z values back into cached tile */ + switch (format) { + case PIPE_FORMAT_U_Z16: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + tile->data.depth16[y][x] = bzzzz[j]; + } + break; + case PIPE_FORMAT_U_Z32: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + tile->data.depth32[y][x] = bzzzz[j]; + } + break; + case PIPE_FORMAT_S8_Z24: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + uint s8z24 = tile->data.depth32[y][x]; + s8z24 = (s8z24 & 0xff000000) | bzzzz[j]; + tile->data.depth32[y][x] = s8z24; + } + break; + default: + assert(0); } -#endif } } diff --git a/src/mesa/pipe/softpipe/sp_quad_output.c b/src/mesa/pipe/softpipe/sp_quad_output.c index 01ee06a69c1..e86f42be461 100644 --- a/src/mesa/pipe/softpipe/sp_quad_output.c +++ b/src/mesa/pipe/softpipe/sp_quad_output.c @@ -42,9 +42,8 @@ static void output_quad(struct quad_stage *qs, struct quad_header *quad) { struct softpipe_context *softpipe = qs->softpipe; - struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf); struct softpipe_cached_tile *tile - = sp_get_cached_tile(sps, quad->x0, quad->y0); + = sp_get_cached_tile(softpipe->cbuf_cache[0], quad->x0, quad->y0); /* in-tile pos: */ const int itx = quad->x0 % TILE_SIZE; const int ity = quad->y0 % TILE_SIZE; diff --git a/src/mesa/pipe/softpipe/sp_quad_stencil.c b/src/mesa/pipe/softpipe/sp_quad_stencil.c index bf72bb23cd0..4a3823d6468 100644 --- a/src/mesa/pipe/softpipe/sp_quad_stencil.c +++ b/src/mesa/pipe/softpipe/sp_quad_stencil.c @@ -7,6 +7,7 @@ #include "sp_context.h" #include "sp_headers.h" #include "sp_surface.h" +#include "sp_tile_cache.h" #include "sp_quad.h" #include "pipe/p_defines.h" #include "pipe/p_util.h" @@ -200,10 +201,13 @@ static void stencil_test_quad(struct quad_stage *qs, struct quad_header *quad) { struct softpipe_context *softpipe = qs->softpipe; - struct softpipe_surface *s_surf = softpipe_surface(softpipe->framebuffer.sbuf); + struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.sbuf); unsigned func, zFailOp, zPassOp, failOp; ubyte ref, wrtMask, valMask; ubyte stencilVals[QUAD_SIZE]; + struct softpipe_cached_tile *tile + = sp_get_cached_tile(softpipe->sbuf_cache, quad->x0, quad->y0); + uint j; /* choose front or back face function, operator, etc */ /* XXX we could do these initializations once per primitive */ @@ -226,8 +230,27 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad) valMask = softpipe->depth_stencil->stencil.value_mask[0]; } - assert(s_surf); /* shouldn't get here if there's no stencil buffer */ - s_surf->read_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals); + assert(sps); /* shouldn't get here if there's no stencil buffer */ + + /* get stencil values from cached tile */ + switch (sps->surface.format) { + case PIPE_FORMAT_S8_Z24: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + stencilVals[j] = tile->data.depth32[y][x] >> 24; + } + break; + case PIPE_FORMAT_U_S8: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + stencilVals[j] = tile->data.stencil8[y][x]; + } + break; + default: + assert(0); + } /* do the stencil test first */ { @@ -242,7 +265,6 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad) } if (quad->mask) { - /* now the pixels that passed the stencil test are depth tested */ if (softpipe->depth_stencil->depth.enabled) { const unsigned origMask = quad->mask; @@ -267,7 +289,27 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad) } - s_surf->write_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals); + /* put new stencil values into cached tile */ + switch (sps->surface.format) { + case PIPE_FORMAT_S8_Z24: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + uint s8z24 = tile->data.depth32[y][x]; + s8z24 = (stencilVals[j] << 24) | (s8z24 & 0xffffff); + tile->data.depth32[y][x] = s8z24; + } + break; + case PIPE_FORMAT_U_S8: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->x0 % TILE_SIZE + (j & 1); + int y = quad->y0 % TILE_SIZE + (j >> 1); + tile->data.stencil8[y][x] = stencilVals[j]; + } + break; + default: + assert(0); + } if (quad->mask) qs->next->run(qs->next, quad); diff --git a/src/mesa/pipe/softpipe/sp_state.h b/src/mesa/pipe/softpipe/sp_state.h index f9061e86e53..c194f0ea0db 100644 --- a/src/mesa/pipe/softpipe/sp_state.h +++ b/src/mesa/pipe/softpipe/sp_state.h @@ -141,4 +141,10 @@ softpipe_map_surfaces(struct softpipe_context *sp); void softpipe_unmap_surfaces(struct softpipe_context *sp); +void +softpipe_map_texture_surfaces(struct softpipe_context *sp); + +void +softpipe_unmap_texture_surfaces(struct softpipe_context *sp); + #endif diff --git a/src/mesa/pipe/softpipe/sp_state_surface.c b/src/mesa/pipe/softpipe/sp_state_surface.c index a534ffb2c2e..cd1e75c563a 100644 --- a/src/mesa/pipe/softpipe/sp_state_surface.c +++ b/src/mesa/pipe/softpipe/sp_state_surface.c @@ -30,20 +30,100 @@ #include "sp_context.h" #include "sp_state.h" #include "sp_surface.h" +#include "sp_tile_cache.h" -/* +/** * XXX this might get moved someday + * Set the framebuffer surface info: color buffers, zbuffer, stencil buffer. + * Here, we map the surfaces and update the tile cache to point to the new + * surfaces. */ void softpipe_set_framebuffer_state(struct pipe_context *pipe, const struct pipe_framebuffer_state *fb) { - struct softpipe_context *softpipe = softpipe_context(pipe); + struct softpipe_context *sp = softpipe_context(pipe); + struct softpipe_surface *sps; + uint i; - softpipe->framebuffer = *fb; /* struct copy */ + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { + /* check if changing cbuf */ + if (sp->framebuffer.cbufs[i] != fb->cbufs[i]) { + /* flush old */ + sp_flush_tile_cache(sp->cbuf_cache[i]); + /* unmap old */ + sps = softpipe_surface(sp->framebuffer.cbufs[i]); + if (sps && sps->surface.region) + pipe->region_unmap(pipe, sps->surface.region); + /* map new */ + sps = softpipe_surface(fb->cbufs[i]); + if (sps) + pipe->region_map(pipe, sps->surface.region); + /* assign new */ + sp->framebuffer.cbufs[i] = fb->cbufs[i]; - softpipe->dirty |= SP_NEW_FRAMEBUFFER; + /* update cache */ + sp_tile_cache_set_surface(sp->cbuf_cache[i], sps); + } + } + + sp->framebuffer.num_cbufs = fb->num_cbufs; + + /* zbuf changing? */ + if (sp->framebuffer.zbuf != fb->zbuf) { + /* flush old */ + sp_flush_tile_cache(sp->zbuf_cache); + /* unmap old */ + sps = softpipe_surface(sp->framebuffer.zbuf); + if (sps && sps->surface.region) + pipe->region_unmap(pipe, sps->surface.region); + if (sp->framebuffer.sbuf == sp->framebuffer.zbuf) { + /* combined z/stencil */ + sp->framebuffer.sbuf = NULL; + } + /* map new */ + sps = softpipe_surface(fb->zbuf); + if (sps) + pipe->region_map(pipe, sps->surface.region); + /* assign new */ + sp->framebuffer.zbuf = fb->zbuf; + + /* update cache */ + sp_tile_cache_set_surface(sp->zbuf_cache, sps); + } + + /* XXX combined depth/stencil here */ + + /* sbuf changing? */ + if (sp->framebuffer.sbuf != fb->sbuf) { + /* flush old */ + sp_flush_tile_cache(sp->sbuf_cache_sep); + /* unmap old */ + sps = softpipe_surface(sp->framebuffer.sbuf); + if (sps && sps->surface.region) + pipe->region_unmap(pipe, sps->surface.region); + /* map new */ + sps = softpipe_surface(fb->sbuf); + if (sps && fb->sbuf != fb->zbuf) + pipe->region_map(pipe, sps->surface.region); + /* assign new */ + sp->framebuffer.sbuf = fb->sbuf; + + /* update cache */ + if (fb->sbuf != fb->zbuf) { + /* separate stencil buf */ + sp->sbuf_cache = sp->sbuf_cache_sep; + sp_tile_cache_set_surface(sp->sbuf_cache, sps); + } + else { + /* combined depth/stencil */ + sp->sbuf_cache = sp->zbuf_cache; + sp_tile_cache_set_surface(sp->sbuf_cache, sps); + } + } + + sp->dirty |= SP_NEW_FRAMEBUFFER; } diff --git a/src/mesa/pipe/softpipe/sp_surface.c b/src/mesa/pipe/softpipe/sp_surface.c index 8aad5f6c13e..fb8c8d08265 100644 --- a/src/mesa/pipe/softpipe/sp_surface.c +++ b/src/mesa/pipe/softpipe/sp_surface.c @@ -61,6 +61,10 @@ #else #define CLIP_TILE \ do { \ + if (x >= ps->width) \ + return; \ + if (y >= ps->height) \ + return; \ if (x + w > ps->width) \ w = ps->width - x; \ if (y + h > ps->height) \ @@ -907,13 +911,16 @@ put_tile_raw32(struct pipe_surface *ps, unsigned i; unsigned w0 = w; + assert(w < 1000); assert(ps->region->map); assert(ps->format == PIPE_FORMAT_S8_Z24 || ps->format == PIPE_FORMAT_U_Z32); + assert(w < 1000); CLIP_TILE; for (i = 0; i < h; i++) { + assert(w < 1000); memcpy(dst, pSrc, w * sizeof(uint)); dst += ps->region->pitch; pSrc += w0; @@ -980,8 +987,6 @@ put_tile_raw16(struct pipe_surface *ps, void softpipe_init_surface_funcs(struct softpipe_surface *sps) { - sps->tc = sp_create_tile_cache(); - assert(sps->surface.format); switch (sps->surface.format) { diff --git a/src/mesa/pipe/softpipe/sp_surface.h b/src/mesa/pipe/softpipe/sp_surface.h index 431303553fb..522f7612ab9 100644 --- a/src/mesa/pipe/softpipe/sp_surface.h +++ b/src/mesa/pipe/softpipe/sp_surface.h @@ -46,8 +46,6 @@ struct softpipe_tile_cache; struct softpipe_surface { struct pipe_surface surface; - struct softpipe_tile_cache *tc; - /** * Functions for read/writing surface data */ diff --git a/src/mesa/pipe/softpipe/sp_tile_cache.c b/src/mesa/pipe/softpipe/sp_tile_cache.c index 2ecdfc89e42..74bd4a3d11c 100644 --- a/src/mesa/pipe/softpipe/sp_tile_cache.c +++ b/src/mesa/pipe/softpipe/sp_tile_cache.c @@ -48,6 +48,7 @@ struct softpipe_tile_cache { + struct softpipe_surface *surface; /**< the surface we're caching */ struct softpipe_cached_tile entries[NUM_ENTRIES]; uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32]; }; @@ -115,45 +116,64 @@ sp_destroy_tile_cache(struct softpipe_tile_cache *tc) } +void +sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, + struct softpipe_surface *sps) +{ + tc->surface = sps; +} + + + void -sp_flush_tile_cache(struct softpipe_surface *sps) +sp_flush_tile_cache(struct softpipe_tile_cache *tc) { - struct softpipe_tile_cache *tc = sps->tc; - /* - struct softpipe_surface *zsurf = softpipe_surface(softpipe->zbuf); - */ + struct pipe_surface *ps = &tc->surface->surface; + boolean is_depth_stencil; int inuse = 0, pos; + if (!ps || !ps->region || !ps->region->map) + return; + + is_depth_stencil = (ps->format == PIPE_FORMAT_S8_Z24 || + ps->format == PIPE_FORMAT_U_Z16 || + ps->format == PIPE_FORMAT_U_Z32 || + ps->format == PIPE_FORMAT_U_S8); + for (pos = 0; pos < NUM_ENTRIES; pos++) { struct softpipe_cached_tile *tile = tc->entries + pos; if (tile->x >= 0) { - sps->surface.put_tile(&sps->surface, - tile->x, - tile->y, - TILE_SIZE, TILE_SIZE, - (float *) tile->data.color); - /* - sps->surface.put_tile(&zsurf->surface, - tile->x, - tile->y, - TILE_SIZE, TILE_SIZE, - (float *) tile->depth); - */ + if (is_depth_stencil) { + ps->put_tile_raw(ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + tile->data.depth32); + } + else { + ps->put_tile(ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + (float *) tile->data.color); + } tile->x = tile->y = -1; /* mark as empty */ inuse++; } } - - /*printf("flushed tiles in use: %d\n", inuse);*/ + /* + printf("flushed tiles in use: %d\n", inuse); + */ } struct softpipe_cached_tile * -sp_get_cached_tile(struct softpipe_surface *sps, int x, int y) +sp_get_cached_tile(struct softpipe_tile_cache *tc, int x, int y) { - struct softpipe_tile_cache *tc = sps->tc; + struct pipe_surface *ps = &tc->surface->surface; + boolean is_depth_stencil + = (ps->format == PIPE_FORMAT_S8_Z24 || + ps->format == PIPE_FORMAT_U_Z16 || + ps->format == PIPE_FORMAT_U_Z32 || + ps->format == PIPE_FORMAT_U_S8); /* tile pos in framebuffer: */ const int tile_x = x & ~(TILE_SIZE - 1); @@ -176,13 +196,22 @@ sp_get_cached_tile(struct softpipe_surface *sps, int x, int y) if (tile->x != -1) { /* put dirty tile back in framebuffer */ - sps->surface.put_tile(&sps->surface, tile->x, tile->y, - TILE_SIZE, TILE_SIZE, (float *) tile->data.color); + if (is_depth_stencil) { + ps->put_tile_raw(ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + tile->data.depth32); + } + else { + ps->put_tile(ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + (float *) tile->data.color); + } } - if (is_clear_flag_set(tc->clear_flags, x, y)) { - printf("clear tile\n"); + if (0/*is_clear_flag_set(tc->clear_flags, x, y)*/) { + /* don't get tile from framebuffer, just clear it */ #if 0 + printf("clear tile\n"); uint i, j; for (i = 0; i < TILE_SIZE; i++) { for (j = 0; j < TILE_SIZE; j++) { @@ -192,14 +221,24 @@ sp_get_cached_tile(struct softpipe_surface *sps, int x, int y) tile->data.color[i][j][3] = 0.5; } } +#else + (void) is_clear_flag_set; #endif memset(tile->data.color, 0, sizeof(tile->data.color)); clear_clear_flag(tc->clear_flags, x, y); } else { /* get new tile from framebuffer */ - sps->surface.get_tile(&sps->surface, tile_x, tile_y, - TILE_SIZE, TILE_SIZE, (float *) tile->data.color); + if (is_depth_stencil) { + ps->get_tile_raw(ps, + tile_x, tile_y, TILE_SIZE, TILE_SIZE, + tile->data.depth32); + } + else { + ps->get_tile(ps, + tile_x, tile_y, TILE_SIZE, TILE_SIZE, + (float *) tile->data.color); + } } tile->x = tile_x; @@ -211,8 +250,8 @@ sp_get_cached_tile(struct softpipe_surface *sps, int x, int y) void -sp_clear_tile_cache(struct softpipe_surface *sps, unsigned clearval) +sp_clear_tile_cache(struct softpipe_tile_cache *tc, unsigned clearval) { (void) clearval; /* XXX use this */ - memset(sps->tc->clear_flags, 255, sizeof(sps->tc->clear_flags)); + memset(tc->clear_flags, 255, sizeof(tc->clear_flags)); } diff --git a/src/mesa/pipe/softpipe/sp_tile_cache.h b/src/mesa/pipe/softpipe/sp_tile_cache.h index 4248361f99d..80bcac6904d 100644 --- a/src/mesa/pipe/softpipe/sp_tile_cache.h +++ b/src/mesa/pipe/softpipe/sp_tile_cache.h @@ -36,6 +36,9 @@ struct softpipe_context; struct softpipe_tile_cache; +/** + * Cache tile size (width and height). This needs to be a power of two. + */ #define TILE_SIZE 64 @@ -45,7 +48,9 @@ struct softpipe_cached_tile int x, y; /** pos of tile in window coords */ union { float color[TILE_SIZE][TILE_SIZE][4]; - uint depth[TILE_SIZE][TILE_SIZE]; + uint depth32[TILE_SIZE][TILE_SIZE]; + ushort depth16[TILE_SIZE][TILE_SIZE]; + ubyte stencil8[TILE_SIZE][TILE_SIZE]; } data; }; @@ -57,13 +62,17 @@ extern void sp_destroy_tile_cache(struct softpipe_tile_cache *tc); extern void -sp_flush_tile_cache(struct softpipe_surface *sps); +sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, + struct softpipe_surface *sps); extern void -sp_clear_tile_cache(struct softpipe_surface *sps, unsigned clearval); +sp_flush_tile_cache(struct softpipe_tile_cache *tc); + +extern void +sp_clear_tile_cache(struct softpipe_tile_cache *tc, unsigned clearval); extern struct softpipe_cached_tile * -sp_get_cached_tile(struct softpipe_surface *sps, int x, int y); +sp_get_cached_tile(struct softpipe_tile_cache *tc, int x, int y); #endif /* SP_TILE_CACHE_H */