summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Girlin <[email protected]>2012-08-21 15:39:25 +0400
committerVadim Girlin <[email protected]>2012-08-22 12:12:22 +0400
commit8d1a9a984f33d8e45f932a9f47cdd57da617a919 (patch)
tree7388bf485857208049374e4d0e6e5dcb42ba1fe1
parentc4610e9f927caa679f34f0d3135d7b1b8cb8bd29 (diff)
r600g: fix lockups with dual_src_blend v2
Disable blending when dual_src_blend is enabled and number of color exports in the current fragment shader is less than 2. Fixes lockups with ext_framebuffer_multisample- alpha-to-coverage-dual-src-blend piglit test. Signed-off-by: Vadim Girlin <[email protected]>
-rw-r--r--src/gallium/drivers/r600/r600_pipe.c7
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h8
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c39
3 files changed, 45 insertions, 9 deletions
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index cf2983315b2..7936c475bb6 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -156,6 +156,9 @@ static void r600_destroy_context(struct pipe_context *context)
{
struct r600_context *rctx = (struct r600_context *)context;
+ if (rctx->no_blend) {
+ rctx->context.delete_blend_state(&rctx->context, rctx->no_blend);
+ }
if (rctx->dummy_pixel_shader) {
rctx->context.delete_fs_state(&rctx->context, rctx->dummy_pixel_shader);
}
@@ -195,6 +198,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
{
struct r600_context *rctx = CALLOC_STRUCT(r600_context);
struct r600_screen* rscreen = (struct r600_screen *)screen;
+ struct pipe_blend_state no_blend = {};
if (rctx == NULL)
return NULL;
@@ -296,6 +300,9 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
TGSI_INTERPOLATE_CONSTANT);
rctx->context.bind_fs_state(&rctx->context, rctx->dummy_pixel_shader);
+ no_blend.rt[0].colormask = 0xF;
+ rctx->no_blend = rctx->context.create_blend_state(&rctx->context, &no_blend);
+
return &rctx->context;
fail:
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 7046573ab0b..3686521862e 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -389,6 +389,14 @@ struct r600_context {
struct r600_cs_shader_state cs_shader_state;
struct r600_sample_mask sample_mask;
+ /* current external blend state (from state tracker) */
+ struct r600_pipe_blend *blend;
+ /* state with disabled blending - used internally with blend_override */
+ struct r600_pipe_blend *no_blend;
+
+ /* 1 - override current blend state with no_blend, 0 - use external state */
+ unsigned blend_override;
+
struct radeon_winsys_cs *cs;
struct r600_range *range;
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index ba5e26c6411..0870cc7e958 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -165,19 +165,15 @@ static bool r600_conv_pipe_prim(unsigned pprim, unsigned *prim)
}
/* common state between evergreen and r600 */
-void r600_bind_blend_state(struct pipe_context *ctx, void *state)
+
+static void r600_bind_blend_state_internal(struct r600_context *rctx,
+ struct r600_pipe_blend *blend)
{
- struct r600_context *rctx = (struct r600_context *)ctx;
- struct r600_pipe_blend *blend = (struct r600_pipe_blend *)state;
struct r600_pipe_state *rstate;
bool update_cb = false;
- if (state == NULL)
- return;
rstate = &blend->rstate;
rctx->states[rstate->id] = rstate;
- rctx->dual_src_blend = blend->dual_src_blend;
- rctx->alpha_to_one = blend->alpha_to_one;
r600_context_pipe_state_set(rctx, rstate);
if (rctx->cb_misc_state.blend_colormask != blend->cb_target_mask) {
@@ -198,6 +194,22 @@ void r600_bind_blend_state(struct pipe_context *ctx, void *state)
}
}
+void r600_bind_blend_state(struct pipe_context *ctx, void *state)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ struct r600_pipe_blend *blend = (struct r600_pipe_blend *)state;
+
+ if (blend == NULL)
+ return;
+
+ rctx->blend = blend;
+ rctx->alpha_to_one = blend->alpha_to_one;
+ rctx->dual_src_blend = blend->dual_src_blend;
+
+ if (!rctx->blend_override)
+ r600_bind_blend_state_internal(rctx, blend);
+}
+
void r600_set_blend_color(struct pipe_context *ctx,
const struct pipe_blend_color *state)
{
@@ -1024,7 +1036,7 @@ void r600_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
static void r600_update_derived_state(struct r600_context *rctx)
{
struct pipe_context * ctx = (struct pipe_context*)rctx;
- unsigned ps_dirty = 0;
+ unsigned ps_dirty = 0, blend_override;
if (!rctx->blitter->running) {
/* Flush depth textures which need to be flushed. */
@@ -1052,7 +1064,16 @@ static void r600_update_derived_state(struct r600_context *rctx)
if (ps_dirty)
r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate);
-
+
+ blend_override = (rctx->dual_src_blend &&
+ rctx->ps_shader->current->nr_ps_color_outputs < 2);
+
+ if (blend_override != rctx->blend_override) {
+ rctx->blend_override = blend_override;
+ r600_bind_blend_state_internal(rctx,
+ blend_override ? rctx->no_blend : rctx->blend);
+ }
+
if (rctx->chip_class >= EVERGREEN) {
evergreen_update_dual_export_state(rctx);
} else {