/** * Called via ctx->Driver.Clear() * XXX: doesn't pick up the differences between front/back/left/right * clears. Need to sort that out... */ static void st_clear(GLcontext *ctx, GLbitfield mask) { static const GLbitfield BUFFER_BITS_DS = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); struct st_context *st = ctx->st; struct gl_renderbuffer *depthRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; struct gl_renderbuffer *stencilRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; GLbitfield quad_buffers = 0; GLbitfield clear_buffers = 0; GLuint i; /* This makes sure the pipe has the latest scissor, etc values */ st_validate_state( st ); if (mask & BUFFER_BITS_COLOR) { for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { GLuint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; if (mask & (1 << b)) { struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[b].Renderbuffer; struct st_renderbuffer *strb; assert(rb); strb = st_renderbuffer(rb); if (!strb->surface) continue; if (check_clear_color_with_quad( ctx, rb )) quad_buffers |= PIPE_CLEAR_COLOR; else clear_buffers |= PIPE_CLEAR_COLOR; } } } if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) { /* clearing combined depth + stencil */ struct st_renderbuffer *strb = st_renderbuffer(depthRb); if (strb->surface) { if (check_clear_depth_stencil_with_quad(ctx, depthRb)) quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; else clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; } } else { /* separate depth/stencil clears */ 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; else clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; } } 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; else clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; } } } /* * If we're going to use clear_with_quad() for any reason, use it for * everything possible. */ if (quad_buffers) { 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); if (mask & BUFFER_BIT_ACCUM) st_clear_accum_buffer(ctx, ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); }
/** * Called via ctx->Driver.Clear() */ 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; struct gl_renderbuffer *stencilRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; GLbitfield quad_buffers = 0x0; GLbitfield clear_buffers = 0x0; GLuint i; /* This makes sure the pipe has the latest scissor, etc values */ st_validate_state( st ); if (mask & BUFFER_BITS_COLOR) { for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { GLuint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; if (mask & (1 << b)) { struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[b].Renderbuffer; struct st_renderbuffer *strb = st_renderbuffer(rb); if (!strb || !strb->surface) continue; if (check_clear_color_with_quad( ctx, rb )) quad_buffers |= PIPE_CLEAR_COLOR; else clear_buffers |= PIPE_CLEAR_COLOR; } } } if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) { /* clearing combined depth + stencil */ struct st_renderbuffer *strb = st_renderbuffer(depthRb); if (strb->surface) { if (check_clear_depth_stencil_with_quad(ctx, depthRb)) quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; else clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; } } 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 (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 we're going to use clear_with_quad() for any reason, use it for * everything possible. */ if (quad_buffers) { quad_buffers |= clear_buffers; clear_with_quad(ctx, quad_buffers & PIPE_CLEAR_COLOR, 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. */ float clearColor[4]; 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]) { st_translate_color(ctx->Color.ClearColor, ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, clearColor); } st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColorUnclamped, ctx->Depth.Clear, ctx->Stencil.Clear); } if (mask & BUFFER_BIT_ACCUM) st_clear_accum_buffer(ctx, ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); }