diff options
author | Marek Olšák <[email protected]> | 2010-04-05 06:26:11 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2010-04-05 07:09:46 +0200 |
commit | a955f86b31304a1a0f35faa0e0861e920354e23b (patch) | |
tree | ac1fc496b191fc20da8983bfe95d029e819ebe48 /src/gallium/drivers/r300/r300_state.c | |
parent | b71bfc4400e1d7c15a2bebbbd3b26a8770fbf546 (diff) |
r300g: add fallback for back stencil reference value and masks for r3xx-r4xx
This splits rendering into two passes when front and back stencil
reference value, value mask, or write mask don't match.
The advantages of doing it in the driver instead of in st are:
* SWTCL is executed just once and the resulting vertex buffer is reused
in the second pass.
* Lower driver overhead due to the fallback being very close to
the actual draw emission with minimum state change.
Diffstat (limited to 'src/gallium/drivers/r300/r300_state.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 2adb3e7221b..2309f353268 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -444,6 +444,8 @@ static void* (state->stencil[0].writemask << R300_STENCILWRITEMASK_SHIFT); if (state->stencil[1].enabled) { + dsa->two_sided = TRUE; + dsa->z_buffer_control |= R300_STENCIL_FRONT_BACK; dsa->z_stencil_control |= (r300_translate_depth_stencil_function(state->stencil[1].func) << @@ -455,14 +457,16 @@ static void* (r300_translate_stencil_op(state->stencil[1].zfail_op) << R300_S_BACK_ZFAIL_OP_SHIFT); - if (caps->is_r500) - { + dsa->stencil_ref_bf = + (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) | + (state->stencil[1].writemask << R300_STENCILWRITEMASK_SHIFT); + + if (caps->is_r500) { dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK; - dsa->stencil_ref_bf = - (state->stencil[1].valuemask << - R300_STENCILMASK_SHIFT) | - (state->stencil[1].writemask << - R300_STENCILWRITEMASK_SHIFT); + } else { + dsa->stencil_ref_bf_fallback = + (state->stencil[0].valuemask != state->stencil[1].valuemask || + state->stencil[0].writemask != state->stencil[1].writemask); } } } @@ -483,13 +487,33 @@ static void* return (void*)dsa; } +static void r300_update_stencil_ref_fallback_status(struct r300_context *r300) +{ + struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; + + if (r300->screen->caps.is_r500) { + return; + } + + r300->stencil_ref_bf_fallback = + dsa->stencil_ref_bf_fallback || + (dsa->two_sided && + r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]); +} + /* Bind DSA state. */ static void r300_bind_dsa_state(struct pipe_context* pipe, void* state) { struct r300_context* r300 = r300_context(pipe); + if (!state) { + return; + } + UPDATE_STATE(state, r300->dsa_state); + + r300_update_stencil_ref_fallback_status(r300); } /* Free DSA state. */ @@ -503,8 +527,11 @@ static void r300_set_stencil_ref(struct pipe_context* pipe, const struct pipe_stencil_ref* sr) { struct r300_context* r300 = r300_context(pipe); + r300->stencil_ref = *sr; r300->dsa_state.dirty = TRUE; + + r300_update_stencil_ref_fallback_status(r300); } /* This switcheroo is needed just because of goddamned MACRO_SWITCH. */ |