X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_clear.c;h=bd1dd78b23c8c54fe2ffda174188fd803f1201d7;hb=8983855012301c8ebc023edf42ddf5e423189585;hp=eb9ba0557d3ac5816be7795fbb0fc7f523995fa2;hpb=0203136e69bfa711edd69a4f69c4539cd877b5cb;p=mesa.git diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index eb9ba0557d3..bd1dd78b23c 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -36,17 +36,16 @@ #include "main/glheader.h" #include "main/formats.h" #include "main/macros.h" -#include "shader/prog_instruction.h" +#include "program/prog_instruction.h" #include "st_context.h" #include "st_atom.h" #include "st_cb_accum.h" #include "st_cb_clear.h" #include "st_cb_fbo.h" #include "st_program.h" -#include "st_public.h" -#include "st_inlines.h" #include "pipe/p_context.h" +#include "pipe/p_shader_tokens.h" #include "pipe/p_state.h" #include "pipe/p_defines.h" #include "util/u_format.h" @@ -64,10 +63,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); @@ -110,11 +111,10 @@ st_destroy_clear(struct st_context *st) * Coords are clip coords with y=0=bottom. */ static void -draw_quad(GLcontext *ctx, +draw_quad(struct st_context *st, float x0, float y0, float x1, float y1, GLfloat z, const GLfloat color[4]) { - struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as @@ -165,7 +165,7 @@ draw_quad(GLcontext *ctx, } /* put vertex data into vbuf */ - st_no_flush_pipe_buffer_write_nooverlap(st, st->clear.vbuf, + pipe_buffer_write_nooverlap(st->pipe, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), sizeof(st->clear.vertices), @@ -191,10 +191,10 @@ draw_quad(GLcontext *ctx, * ctx->DrawBuffer->_X/Ymin/max fields. */ static void -clear_with_quad(GLcontext *ctx, +clear_with_quad(struct gl_context *ctx, GLboolean color, GLboolean depth, GLboolean stencil) { - struct st_context *st = ctx->st; + struct st_context *st = st_context(ctx); const struct gl_framebuffer *fb = ctx->DrawBuffer; const GLfloat fb_width = (GLfloat) fb->Width; const GLfloat fb_height = (GLfloat) fb->Height; @@ -296,7 +296,7 @@ clear_with_quad(GLcontext *ctx, cso_set_vertex_shader_handle(st->cso_context, st->clear.vs); /* draw quad matching scissor rect (XXX verify coord round-off) */ - draw_quad(ctx, x0, y0, x1, y1, + draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor); /* Restore pipe state */ @@ -316,7 +316,7 @@ clear_with_quad(GLcontext *ctx, * Determine if we need to clear the depth buffer by drawing a quad. */ static INLINE GLboolean -check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) +check_clear_color_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb) { if (ctx->Scissor.Enabled && (ctx->Scissor.X != 0 || @@ -340,7 +340,7 @@ check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) * drawing a quad. */ static INLINE GLboolean -check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) +check_clear_depth_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb) { const GLuint stencilMax = 0xff; GLboolean maskStencil @@ -368,7 +368,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(struct gl_context *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); @@ -380,7 +381,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; @@ -391,7 +392,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(struct gl_context *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); @@ -418,7 +420,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; @@ -445,11 +447,11 @@ st_flush_clear(struct st_context *st) * Called via ctx->Driver.Clear() */ static void -st_Clear(GLcontext *ctx, GLbitfield mask) +st_Clear(struct gl_context *ctx, GLbitfield mask) { static const GLbitfield BUFFER_BITS_DS = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); - struct st_context *st = ctx->st; + struct st_context *st = st_context(ctx); struct gl_renderbuffer *depthRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; struct gl_renderbuffer *stencilRb @@ -498,24 +500,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; } } } @@ -528,12 +533,23 @@ 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) - ctx->st->pipe->clear(ctx->st->pipe, clear_buffers, ctx->Color.ClearColor, - ctx->Depth.Clear, ctx->Stencil.Clear); - + 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) && + ((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);