summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/llvmpipe
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/llvmpipe')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c33
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h16
-rw-r--r--src/gallium/drivers/llvmpipe/lp_scene.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_scene.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_screen.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c83
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_context.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_surface.c1
8 files changed, 113 insertions, 28 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 386387b3a5..50e44dcb2b 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -172,7 +172,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;
@@ -264,6 +264,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;
@@ -271,7 +274,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
@@ -287,22 +290,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 ff0e3cfc73..80ca68f5a2 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -88,6 +88,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,
@@ -151,7 +156,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;
};
@@ -193,6 +198,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 )
{
union lp_rast_cmd_arg arg;
@@ -201,7 +214,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 59e4c18ad0..845c175cf2 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 22d619fdbc..4e55d43174 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 98ac11d76a..2fc5d6ecff 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 bdb40a2d4b..8556dc87b4 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 584764ce8a..c8b8a2480b 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 85687ada1c..4f409f9b63 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;
}