aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/state_tracker/st_cb_clear.c
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/state_tracker/st_cb_clear.c')
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_clear.c199
1 files changed, 52 insertions, 147 deletions
diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c
index 4aa0bc18f..d01236e28 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_clear.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c
@@ -65,13 +65,10 @@
void
st_init_clear(struct st_context *st)
{
- struct pipe_screen *pscreen = st->pipe->screen;
-
memset(&st->clear, 0, sizeof(st->clear));
st->clear.raster.gl_rasterization_rules = 1;
st->clear.raster.depth_clip = 1;
- st->clear.enable_ds_separate = pscreen->get_param(pscreen, PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE);
}
@@ -99,7 +96,9 @@ static INLINE void
set_fragment_shader(struct st_context *st)
{
if (!st->clear.fs)
- st->clear.fs = util_make_fragment_passthrough_shader(st->pipe);
+ st->clear.fs =
+ util_make_fragment_passthrough_shader(st->pipe, TGSI_SEMANTIC_GENERIC,
+ TGSI_INTERPOLATE_CONSTANT);
cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
}
@@ -117,7 +116,7 @@ set_vertex_shader(struct st_context *st)
if (!st->clear.vs)
{
const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
- TGSI_SEMANTIC_COLOR };
+ TGSI_SEMANTIC_GENERIC };
const uint semantic_indexes[] = { 0, 0 };
st->clear.vs = util_make_vertex_passthrough_shader(st->pipe, 2,
semantic_names,
@@ -233,19 +232,24 @@ clear_with_quad(struct gl_context *ctx,
{
struct pipe_blend_state blend;
memset(&blend, 0, sizeof(blend));
- blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
if (color) {
- if (ctx->Color.ColorMask[0][0])
- blend.rt[0].colormask |= PIPE_MASK_R;
- if (ctx->Color.ColorMask[0][1])
- blend.rt[0].colormask |= PIPE_MASK_G;
- if (ctx->Color.ColorMask[0][2])
- blend.rt[0].colormask |= PIPE_MASK_B;
- if (ctx->Color.ColorMask[0][3])
- blend.rt[0].colormask |= PIPE_MASK_A;
+ int num_buffers = ctx->Extensions.EXT_draw_buffers2 ?
+ ctx->DrawBuffer->_NumColorDrawBuffers : 1;
+ int i;
+
+ blend.independent_blend_enable = num_buffers > 1;
+
+ for (i = 0; i < num_buffers; i++) {
+ if (ctx->Color.ColorMask[i][0])
+ blend.rt[i].colormask |= PIPE_MASK_R;
+ if (ctx->Color.ColorMask[i][1])
+ blend.rt[i].colormask |= PIPE_MASK_G;
+ if (ctx->Color.ColorMask[i][2])
+ blend.rt[i].colormask |= PIPE_MASK_B;
+ if (ctx->Color.ColorMask[i][3])
+ blend.rt[i].colormask |= PIPE_MASK_A;
+ }
+
if (st->ctx->Color.DitherFlag)
blend.dither = 1;
}
@@ -333,113 +337,42 @@ clear_with_quad(struct gl_context *ctx,
/**
- * Determine if we need to clear the depth buffer by drawing a quad.
- */
-static INLINE GLboolean
-check_clear_color_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb)
-{
- if (ctx->Scissor.Enabled &&
- (ctx->Scissor.X != 0 ||
- ctx->Scissor.Y != 0 ||
- ctx->Scissor.Width < rb->Width ||
- ctx->Scissor.Height < rb->Height))
- return GL_TRUE;
-
- if (!ctx->Color.ColorMask[0][0] ||
- !ctx->Color.ColorMask[0][1] ||
- !ctx->Color.ColorMask[0][2] ||
- !ctx->Color.ColorMask[0][3])
- return GL_TRUE;
-
- return GL_FALSE;
-}
-
-
-/**
- * Determine if we need to clear the combiend depth/stencil buffer by
- * drawing a quad.
+ * Return if the scissor must be enabled during the clear.
*/
static INLINE GLboolean
-check_clear_depth_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb)
+is_scissor_enabled(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
- const GLuint stencilMax = 0xff;
- GLboolean maskStencil
- = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
-
- assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);
-
- if (ctx->Scissor.Enabled &&
- (ctx->Scissor.X != 0 ||
- ctx->Scissor.Y != 0 ||
- ctx->Scissor.Width < rb->Width ||
- ctx->Scissor.Height < rb->Height))
- return GL_TRUE;
-
- if (maskStencil)
- return GL_TRUE;
-
- return GL_FALSE;
+ return ctx->Scissor.Enabled &&
+ (ctx->Scissor.X > 0 ||
+ ctx->Scissor.Y > 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height);
}
/**
- * Determine if we need to clear the depth buffer by drawing a quad.
+ * Return if any of the color channels are masked.
*/
static INLINE GLboolean
-check_clear_depth_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
- boolean ds_separate)
+is_color_masked(struct gl_context *ctx, int i)
{
- const struct st_renderbuffer *strb = st_renderbuffer(rb);
- const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
-
- if (ctx->Scissor.Enabled &&
- (ctx->Scissor.X != 0 ||
- ctx->Scissor.Y != 0 ||
- ctx->Scissor.Width < rb->Width ||
- ctx->Scissor.Height < rb->Height))
- return GL_TRUE;
-
- if (!ds_separate && isDS && ctx->DrawBuffer->Visual.stencilBits > 0)
- return GL_TRUE;
-
- return GL_FALSE;
+ return !ctx->Color.ColorMask[i][0] ||
+ !ctx->Color.ColorMask[i][1] ||
+ !ctx->Color.ColorMask[i][2] ||
+ !ctx->Color.ColorMask[i][3];
}
/**
- * Determine if we need to clear the stencil buffer by drawing a quad.
+ * Return if any of the stencil bits are masked.
*/
static INLINE GLboolean
-check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
- boolean ds_separate)
+is_stencil_masked(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
- const struct st_renderbuffer *strb = st_renderbuffer(rb);
- const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
const GLuint stencilMax = 0xff;
- const GLboolean maskStencil
- = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);
-
- if (maskStencil)
- return GL_TRUE;
-
- if (ctx->Scissor.Enabled &&
- (ctx->Scissor.X != 0 ||
- ctx->Scissor.Y != 0 ||
- ctx->Scissor.Width < rb->Width ||
- ctx->Scissor.Height < rb->Height))
- return GL_TRUE;
-
- /* This is correct, but it is necessary to look at the depth clear
- * value held in the surface when it comes time to issue the clear,
- * rather than taking depth and stencil clear values from the
- * current state.
- */
- if (!ds_separate && isDS && ctx->DrawBuffer->Visual.depthBits > 0)
- return GL_TRUE;
-
- return GL_FALSE;
+ return (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
}
@@ -449,8 +382,6 @@ check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb
static void
st_Clear(struct gl_context *ctx, GLbitfield mask)
{
- static const GLbitfield BUFFER_BITS_DS
- = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
struct st_context *st = st_context(ctx);
struct gl_renderbuffer *depthRb
= ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
@@ -471,11 +402,13 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
struct gl_renderbuffer *rb
= ctx->DrawBuffer->Attachment[b].Renderbuffer;
struct st_renderbuffer *strb = st_renderbuffer(rb);
+ int colormask_index = ctx->Extensions.EXT_draw_buffers2 ? i : 0;
if (!strb || !strb->surface)
continue;
- if (check_clear_color_with_quad( ctx, rb ))
+ if (is_scissor_enabled(ctx, rb) ||
+ is_color_masked(ctx, colormask_index))
quad_buffers |= PIPE_CLEAR_COLOR;
else
clear_buffers |= PIPE_CLEAR_COLOR;
@@ -483,41 +416,25 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
}
}
- if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) {
- /* clearing combined depth + stencil */
+ if (mask & BUFFER_BIT_DEPTH) {
struct st_renderbuffer *strb = st_renderbuffer(depthRb);
if (strb->surface) {
- if (check_clear_depth_stencil_with_quad(ctx, depthRb))
- quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ if (is_scissor_enabled(ctx, depthRb))
+ quad_buffers |= PIPE_CLEAR_DEPTH;
else
- clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ clear_buffers |= PIPE_CLEAR_DEPTH;
}
}
- 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,
- st->clear.enable_ds_separate))
- quad_buffers |= PIPE_CLEAR_DEPTH;
- else
- clear_buffers |= PIPE_CLEAR_DEPTH;
- }
- }
- if (mask & BUFFER_BIT_STENCIL) {
- struct st_renderbuffer *strb = st_renderbuffer(stencilRb);
+ if (mask & BUFFER_BIT_STENCIL) {
+ struct st_renderbuffer *strb = st_renderbuffer(stencilRb);
- if (strb->surface) {
- if (check_clear_stencil_with_quad(ctx, stencilRb,
- st->clear.enable_ds_separate))
- quad_buffers |= PIPE_CLEAR_STENCIL;
- else
- clear_buffers |= PIPE_CLEAR_STENCIL;
- }
+ if (strb->surface) {
+ if (is_scissor_enabled(ctx, stencilRb) ||
+ is_stencil_masked(ctx, stencilRb))
+ quad_buffers |= PIPE_CLEAR_STENCIL;
+ else
+ clear_buffers |= PIPE_CLEAR_STENCIL;
}
}
@@ -532,20 +449,8 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
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.
- */
union pipe_color_union clearColor;
- 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;
-
if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
GLboolean is_integer = _mesa_is_enum_format_integer(rb->InternalFormat);