diff options
author | Roland Scheidegger <[email protected]> | 2010-05-29 00:04:14 +0200 |
---|---|---|
committer | Roland Scheidegger <[email protected]> | 2010-05-29 00:04:14 +0200 |
commit | 783083c3b81c51bae541e0a86801f0492ca352cd (patch) | |
tree | 49ace6d31ed5d28f05518dcb3027c992bcf2e3e4 | |
parent | a1d5131d2eaa5f5ccc8b38f9379f9c6bc989bc1a (diff) |
st/mesa: use new ability to clear only depth or stencil
-rw-r--r-- | src/mesa/state_tracker/st_cb_clear.c | 45 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_context.h | 1 |
2 files changed, 32 insertions, 14 deletions
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 7e3b87351f1..a819d305303 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -62,10 +62,12 @@ void st_init_clear(struct st_context *st) { struct pipe_context *pipe = st->pipe; + struct pipe_screen *pscreen = st->pipe->screen; memset(&st->clear, 0, sizeof(st->clear)); st->clear.raster.gl_rasterization_rules = 1; + st->clear.enable_ds_separate = pscreen->get_param(pscreen, PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE); /* fragment shader state: color pass-through program */ st->clear.fs = util_make_fragment_passthrough_shader(pipe); @@ -365,7 +367,8 @@ check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) * Determine if we need to clear the depth buffer by drawing a quad. */ static INLINE GLboolean -check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) +check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb, + boolean ds_separate) { const struct st_renderbuffer *strb = st_renderbuffer(rb); const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format); @@ -377,7 +380,7 @@ check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) ctx->Scissor.Height < rb->Height)) return GL_TRUE; - if (isDS && ctx->DrawBuffer->Visual.stencilBits > 0) + if (!ds_separate && isDS && ctx->DrawBuffer->Visual.stencilBits > 0) return GL_TRUE; return GL_FALSE; @@ -388,7 +391,8 @@ check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) * Determine if we need to clear the stencil buffer by drawing a quad. */ static INLINE GLboolean -check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) +check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb, + boolean ds_separate) { const struct st_renderbuffer *strb = st_renderbuffer(rb); const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format); @@ -415,7 +419,7 @@ check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) * rather than taking depth and stencil clear values from the * current state. */ - if (isDS && ctx->DrawBuffer->Visual.depthBits > 0) + if (!ds_separate && isDS && ctx->DrawBuffer->Visual.depthBits > 0) return GL_TRUE; return GL_FALSE; @@ -495,24 +499,27 @@ st_Clear(GLcontext *ctx, GLbitfield mask) } else { /* separate depth/stencil clears */ + /* I don't think truly separate buffers are actually possible in gallium or hw? */ if (mask & BUFFER_BIT_DEPTH) { struct st_renderbuffer *strb = st_renderbuffer(depthRb); if (strb->surface) { - if (check_clear_depth_with_quad(ctx, depthRb)) - quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + if (check_clear_depth_with_quad(ctx, depthRb, + st->clear.enable_ds_separate)) + quad_buffers |= PIPE_CLEAR_DEPTH; else - clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + clear_buffers |= PIPE_CLEAR_DEPTH; } } if (mask & BUFFER_BIT_STENCIL) { struct st_renderbuffer *strb = st_renderbuffer(stencilRb); if (strb->surface) { - if (check_clear_stencil_with_quad(ctx, stencilRb)) - quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + if (check_clear_stencil_with_quad(ctx, stencilRb, + st->clear.enable_ds_separate)) + quad_buffers |= PIPE_CLEAR_STENCIL; else - clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + clear_buffers |= PIPE_CLEAR_STENCIL; } } } @@ -525,12 +532,22 @@ st_Clear(GLcontext *ctx, GLbitfield mask) quad_buffers |= clear_buffers; clear_with_quad(ctx, quad_buffers & PIPE_CLEAR_COLOR, - mask & BUFFER_BIT_DEPTH, - mask & BUFFER_BIT_STENCIL); - } else if (clear_buffers) + quad_buffers & PIPE_CLEAR_DEPTH, + quad_buffers & PIPE_CLEAR_STENCIL); + } else if (clear_buffers) { + /* driver cannot know it can clear everything if the buffer + * is a combined depth/stencil buffer but this wasn't actually + * required from the visual. Hence fix this up to avoid potential + * read-modify-write in the driver. + */ + if (((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + (depthRb == stencilRb) && + (ctx->DrawBuffer->Visual.depthBits == 0 || + ctx->DrawBuffer->Visual.stencilBits == 0)) + clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor, ctx->Depth.Clear, ctx->Stencil.Clear); - + } if (mask & BUFFER_BIT_ACCUM) st_clear_accum_buffer(ctx, ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index a578143abc8..efff55a9057 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -175,6 +175,7 @@ struct st_context float vertices[4][2][4]; /**< vertex pos + color */ struct pipe_resource *vbuf; unsigned vbuf_slot; + boolean enable_ds_separate; } clear; /** used for anything using util_draw_vertex_buffer */ |