From: Roland Scheidegger Date: Fri, 28 May 2010 23:31:01 +0000 (+0200) Subject: llvmpipe: adapt to clear interface changes X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1e17178fc40b6a1a54cb3e93c098bdd0d490b88a;p=mesa.git llvmpipe: adapt to clear interface changes with some newfangled code, should support separate depth/stencil clears. Needs some testing. --- diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 6bb868bf1a9..2280c71c361 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -177,7 +177,7 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task, if (zsbuf) { struct llvmpipe_resource *lpt = llvmpipe_resource(zsbuf->texture); - if (scene->has_depth_clear) + if (scene->has_depthstencil_clear) usage = LP_TEX_USAGE_WRITE_ALL; else usage = LP_TEX_USAGE_READ_WRITE; @@ -269,6 +269,9 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { struct lp_rasterizer *rast = task->rast; + const struct lp_rast_clearzs *clearzs = arg.clear_zstencil; + unsigned clear_value = clearzs->clearzs_value; + unsigned clear_mask = clearzs->clearzs_mask; const unsigned height = TILE_SIZE / TILE_VECTOR_HEIGHT; const unsigned width = TILE_SIZE * TILE_VECTOR_HEIGHT; const unsigned block_size = rast->zsbuf.blocksize; @@ -276,7 +279,7 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task, uint8_t *dst; unsigned i, j; - LP_DBG(DEBUG_RAST, "%s 0x%x\n", __FUNCTION__, arg.clear_zstencil); + LP_DBG(DEBUG_RAST, "%s 0x%x%x\n", __FUNCTION__, clear_value, clear_mask); /* * Clear the aera of the swizzled depth/depth buffer matching this tile, in @@ -292,22 +295,34 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task, switch (block_size) { case 1: - memset(dst, (uint8_t) arg.clear_zstencil, height * width); + memset(dst, (uint8_t) clear_value, height * width); break; case 2: for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst; for (j = 0; j < width; j++) - *row++ = (uint16_t) arg.clear_zstencil; + *row++ = (uint16_t) clear_value; dst += dst_stride; } break; case 4: - for (i = 0; i < height; i++) { - uint32_t *row = (uint32_t *)dst; - for (j = 0; j < width; j++) - *row++ = arg.clear_zstencil; - dst += dst_stride; + if (clear_mask == 0xffffffff) { + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst; + for (j = 0; j < width; j++) + *row++ = clear_value; + dst += dst_stride; + } + } + else { + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst; + for (j = 0; j < width; j++) { + uint32_t tmp = ~clear_mask & *row; + *row++ = (clear_value & clear_mask) | tmp; + } + dst += dst_stride; + } } break; default: diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index 881f475189e..757009d13f7 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -92,6 +92,11 @@ struct lp_rast_shader_inputs { PIPE_ALIGN_VAR(16) int step[3][16]; }; +struct lp_rast_clearzs { + unsigned clearzs_value; + unsigned clearzs_mask; +}; + /** * Rasterization information for a triangle known to be in this bin, @@ -155,7 +160,7 @@ union lp_rast_cmd_arg { const struct lp_rast_triangle *triangle; const struct lp_rast_state *set_state; uint8_t clear_color[4]; - unsigned clear_zstencil; + const struct lp_rast_clearzs *clear_zstencil; struct lp_fence *fence; struct llvmpipe_query *query_obj; }; @@ -196,6 +201,14 @@ lp_rast_arg_fence( struct lp_fence *fence ) } +static INLINE union lp_rast_cmd_arg +lp_rast_arg_clearzs( const struct lp_rast_clearzs *clearzs ) +{ + union lp_rast_cmd_arg arg; + arg.clear_zstencil = clearzs; + return arg; +} + static INLINE union lp_rast_cmd_arg lp_rast_arg_null( void ) { @@ -205,7 +218,6 @@ lp_rast_arg_null( void ) } - /** * Binnable Commands. * These get put into bins by the setup code and are called when diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 59e4c18ad05..845c175cf2e 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -201,7 +201,7 @@ lp_scene_reset(struct lp_scene *scene ) scene->scene_size = 0; scene->has_color_clear = FALSE; - scene->has_depth_clear = FALSE; + scene->has_depthstencil_clear = FALSE; } diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h index 22d619fdbc3..4e55d431746 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.h +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -125,7 +125,7 @@ struct lp_scene { unsigned scene_size; boolean has_color_clear; - boolean has_depth_clear; + boolean has_depthstencil_clear; /** * Number of active tiles in each dimension. diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index cedc08e9292..e24b86d938a 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -162,6 +162,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_MAX_VS_PREDS: case PIPE_CAP_MAX_FS_PREDS: return LP_MAX_TGSI_PREDS; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + return 1; default: assert(0); return 0; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 656e6cc38a6..1970173af4c 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -143,6 +143,7 @@ static void reset_context( struct lp_setup_context *setup ) /* Reset some state: */ setup->clear.flags = 0; + setup->clear.clearzs.clearzs_mask = 0; /* Have an explicit "start-binning" call and get rid of this * pointer twiddling? @@ -172,10 +173,15 @@ static void begin_binning( struct lp_setup_context *setup ) { struct lp_scene *scene = lp_setup_get_current_scene(setup); + boolean need_zsload = FALSE; + if (setup->fb.zsbuf && + ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) + need_zsload = TRUE; LP_DBG(DEBUG_SETUP, "%s color: %s depth: %s\n", __FUNCTION__, (setup->clear.flags & PIPE_CLEAR_COLOR) ? "clear": "load", - (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) ? "clear": "load"); + need_zsload ? "clear": "load"); if (setup->fb.nr_cbufs) { if (setup->clear.flags & PIPE_CLEAR_COLOR) { @@ -188,10 +194,11 @@ begin_binning( struct lp_setup_context *setup ) if (setup->fb.zsbuf) { if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { - lp_scene_bin_everywhere( scene, - lp_rast_clear_zstencil, - setup->clear.zstencil ); - scene->has_depth_clear = TRUE; + if (!need_zsload) + scene->has_depthstencil_clear = TRUE; + lp_scene_bin_everywhere( scene, + lp_rast_clear_zstencil, + lp_rast_arg_clearzs(&setup->clear.clearzs) ); } } @@ -306,6 +313,8 @@ lp_setup_clear( struct lp_setup_context *setup, { struct lp_scene *scene = lp_setup_get_current_scene(setup); unsigned i; + boolean full_zs_clear = TRUE; + uint32_t mask = 0; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); @@ -316,10 +325,53 @@ lp_setup_clear( struct lp_setup_context *setup, } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { - setup->clear.zstencil.clear_zstencil = - util_pack_z_stencil(setup->fb.zsbuf->format, - depth, - stencil); + if (setup->fb.zsbuf && + ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) + full_zs_clear = FALSE; + + if (full_zs_clear) { + setup->clear.clearzs.clearzs_value = + util_pack_z_stencil(setup->fb.zsbuf->format, + depth, + stencil); + setup->clear.clearzs.clearzs_mask = 0xffffffff; + } + else { + /* hmm */ + uint32_t tmpval; + if (flags & PIPE_CLEAR_DEPTH) { + tmpval = util_pack_z(setup->fb.zsbuf->format, + depth); + switch (setup->fb.zsbuf->format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + mask = 0xffffff; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + mask = 0xffffff00; + break; + default: + assert(0); + } + } + else { + switch (setup->fb.zsbuf->format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + mask = 0xff000000; + tmpval = stencil << 24; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + mask = 0xff; + tmpval = stencil; + break; + default: + assert(0); + } + } + setup->clear.clearzs.clearzs_mask |= mask; + setup->clear.clearzs.clearzs_value = + (setup->clear.clearzs.clearzs_value & ~mask) | (tmpval & mask); + } } if (setup->state == SETUP_ACTIVE) { @@ -336,11 +388,16 @@ lp_setup_clear( struct lp_setup_context *setup, scene->has_color_clear = TRUE; } - if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { - lp_scene_bin_everywhere( scene, + if (flags & PIPE_CLEAR_DEPTHSTENCIL) { + if (full_zs_clear) + scene->has_depthstencil_clear = TRUE; + else + setup->clear.clearzs.clearzs_mask = mask; + lp_scene_bin_everywhere( scene, lp_rast_clear_zstencil, - setup->clear.zstencil ); - scene->has_depth_clear = TRUE; + lp_rast_arg_clearzs(&setup->clear.clearzs) ); + + } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index 584764ce8ac..c8b8a2480b0 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -97,7 +97,7 @@ struct lp_setup_context struct { unsigned flags; union lp_rast_cmd_arg color; /**< lp_rast_clear_color() cmd */ - union lp_rast_cmd_arg zstencil; /**< lp_rast_clear_zstencil() cmd */ + struct lp_rast_clearzs clearzs; /**< lp_rast_clear_zstencil() cmd */ } clear; enum setup_state { diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c index 85687ada1c4..4f409f9b638 100644 --- a/src/gallium/drivers/llvmpipe/lp_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_surface.c @@ -153,5 +153,4 @@ void llvmpipe_init_surface_functions(struct llvmpipe_context *lp) { lp->pipe.resource_copy_region = lp_resource_copy; - lp->pipe.resource_fill_region = util_resource_fill_region; }