From 47fdaf0ed9ef2f89cdaa97d0d48b1f1194d710c6 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 2 Aug 2007 16:08:18 -0600 Subject: pipe->clear() now takes a surface, rather than color/depth/stencil flags. pipe->clear() only used to clear whole buffers (no scissor) w/out masking. Draw a colored quadrilateral in all other cases. --- src/mesa/drivers/x11/xm_api.c | 5 +- src/mesa/drivers/x11/xm_dd.c | 23 ++- src/mesa/drivers/x11/xmesaP.h | 7 +- src/mesa/pipe/p_context.h | 6 +- src/mesa/pipe/softpipe/sp_clear.c | 109 +------------- src/mesa/pipe/softpipe/sp_clear.h | 4 +- src/mesa/state_tracker/st_cb_clear.c | 274 ++++++++++++++++++++++++++++++----- 7 files changed, 270 insertions(+), 158 deletions(-) diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c index 92d37085d1..7fb99df5f4 100644 --- a/src/mesa/drivers/x11/xm_api.c +++ b/src/mesa/drivers/x11/xm_api.c @@ -1573,8 +1573,11 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) st_create_context( mesaCtx, softpipe_create() ); + mesaCtx->Driver.Clear = xmesa_clear_buffers; + /* mesaCtx->st->pipe->clear = xmesa_clear; - + */ + return c; } diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c index 87f8ede50b..f64f8780cf 100644 --- a/src/mesa/drivers/x11/xm_dd.c +++ b/src/mesa/drivers/x11/xm_dd.c @@ -381,8 +381,8 @@ clear_nbit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb, -static void -clear_buffers(GLcontext *ctx, GLbitfield buffers) +void +xmesa_clear_buffers(GLcontext *ctx, GLbitfield buffers) { if (ctx->DrawBuffer->Name == 0) { /* this is a window system framebuffer */ @@ -395,7 +395,6 @@ clear_buffers(GLcontext *ctx, GLbitfield buffers) /* we can't handle color or index masking */ if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) { -#if 0 if (buffers & BUFFER_BIT_FRONT_LEFT) { /* clear front color buffer */ struct gl_renderbuffer *frontRb @@ -419,14 +418,6 @@ clear_buffers(GLcontext *ctx, GLbitfield buffers) buffers &= ~BUFFER_BIT_BACK_LEFT; } } -#else - /* Clear with state-tracker/pipe interface */ - struct st_context *st = st_context(ctx); - GLboolean color = (buffers & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) ? 1: 0; - GLboolean depth = (buffers & BUFFER_BIT_DEPTH) ? 1 : 0; - GLboolean stencil = (buffers & BUFFER_BIT_STENCIL) ? 1 : 0; - st_clear(st, color, depth, stencil); -#endif } } if (buffers) @@ -434,6 +425,7 @@ clear_buffers(GLcontext *ctx, GLbitfield buffers) } +#if 0 void xmesa_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth, GLboolean stencil, GLboolean accum) @@ -458,9 +450,14 @@ xmesa_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth, xrb->clearFunc(ctx, xrb, x, y, w, h); } } - } +#endif + +void +xmesa_clear(struct pipe_context *pipe, struct pipe_surface *ps, GLuint value) +{ +} #ifndef XFree86Server @@ -1113,7 +1110,7 @@ xmesa_init_driver_functions( XMesaVisual xmvisual, driver->IndexMask = index_mask; driver->ColorMask = color_mask; driver->Enable = enable; - driver->Clear = clear_buffers; + driver->Clear = xmesa_clear_buffers; driver->Viewport = xmesa_viewport; #ifndef XFree86Server driver->CopyPixels = xmesa_CopyPixels; diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h index fb1c1f8c3b..dd95aed4d0 100644 --- a/src/mesa/drivers/x11/xmesaP.h +++ b/src/mesa/drivers/x11/xmesaP.h @@ -593,7 +593,10 @@ extern struct pipe_surface * xmesa_new_surface(GLcontext *ctx, struct xmesa_renderbuffer *xrb); extern void -xmesa_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth, - GLboolean stencil, GLboolean accum); +xmesa_clear(struct pipe_context *pipe, struct pipe_surface *ps, GLuint value); + +extern void +xmesa_clear_buffers(GLcontext *ctx, GLbitfield buffers); + #endif diff --git a/src/mesa/pipe/p_context.h b/src/mesa/pipe/p_context.h index 0972fd58b5..4f8bdae140 100644 --- a/src/mesa/pipe/p_context.h +++ b/src/mesa/pipe/p_context.h @@ -60,9 +60,9 @@ struct pipe_context { GLuint numVertex, const GLfloat *verts, GLuint numAttribs, const GLuint attribs[]); - /** Clear framebuffer */ - void (*clear)(struct pipe_context *pipe, GLboolean color, GLboolean depth, - GLboolean stencil); + /** Clear a surface to given value (no scissor; clear whole surface) */ + void (*clear)(struct pipe_context *pipe, struct pipe_surface *ps, + GLuint clearValue); /** occlusion counting (XXX this may be temporary - we should probably * have generic query objects with begin/end methods) diff --git a/src/mesa/pipe/softpipe/sp_clear.c b/src/mesa/pipe/softpipe/sp_clear.c index e9b142e780..d7684d2044 100644 --- a/src/mesa/pipe/softpipe/sp_clear.c +++ b/src/mesa/pipe/softpipe/sp_clear.c @@ -38,32 +38,13 @@ #include "colormac.h" -static GLuint -color_value(GLuint format, const GLfloat color[4]) -{ - GLubyte r, g, b, a; - - UNCLAMPED_FLOAT_TO_UBYTE(r, color[0]); - UNCLAMPED_FLOAT_TO_UBYTE(g, color[1]); - UNCLAMPED_FLOAT_TO_UBYTE(b, color[2]); - UNCLAMPED_FLOAT_TO_UBYTE(a, color[3]); - - switch (format) { - case PIPE_FORMAT_U_R8_G8_B8_A8: - return (r << 24) | (g << 16) | (b << 8) | a; - case PIPE_FORMAT_U_A8_R8_G8_B8: - return (a << 24) | (r << 16) | (g << 8) | b; - case PIPE_FORMAT_U_R5_G6_B5: - return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); - default: - return 0; - } -} - - +/** + * Clear the given surface to the specified value. + * No masking, no scissor (clear entire buffer). + */ void -softpipe_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth, - GLboolean stencil) +softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, + GLuint clearValue) { struct softpipe_context *softpipe = softpipe_context(pipe); GLint x, y, w, h; @@ -75,81 +56,5 @@ softpipe_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth, w = softpipe->framebuffer.cbufs[0]->width; h = softpipe->framebuffer.cbufs[0]->height; - if (color) { - GLuint i; - for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) { - struct pipe_surface *ps = softpipe->framebuffer.cbufs[i]; - GLuint clearVal = color_value(ps->format, - softpipe->clear_color.color); - pipe->region_fill(pipe, ps->region, 0, x, y, w, h, clearVal, ~0); - } - } - - if (depth && stencil && - softpipe->framebuffer.zbuf == softpipe->framebuffer.sbuf) { - /* clear Z and stencil together */ - struct pipe_surface *ps = softpipe->framebuffer.zbuf; - if (ps->format == PIPE_FORMAT_S8_Z24) { - GLuint mask = (softpipe->stencil.write_mask[0] << 8) | 0xffffff; - GLuint clearVal = (GLuint) (softpipe->depth_test.clear * 0xffffff); - - assert (mask == ~0); - - clearVal |= (softpipe->stencil.clear_value << 24); - pipe->region_fill(pipe, ps->region, 0, x, y, w, h, clearVal, ~0); - } - else { - /* XXX Z24_S8 format? */ - assert(0); - } - } - else { - /* separate Z and stencil */ - if (depth) { - struct pipe_surface *ps = softpipe->framebuffer.zbuf; - GLuint clearVal; - - switch (ps->format) { - case PIPE_FORMAT_U_Z16: - clearVal = (GLuint) (softpipe->depth_test.clear * 65535.0); - break; - case PIPE_FORMAT_U_Z32: - clearVal = (GLuint) (softpipe->depth_test.clear * 0xffffffff); - break; - case PIPE_FORMAT_S8_Z24: - clearVal = (GLuint) (softpipe->depth_test.clear * 0xffffff); - break; - default: - assert(0); - } - - pipe->region_fill(pipe, ps->region, 0, x, y, w, h, clearVal, ~0); - } - - if (stencil) { - struct pipe_surface *ps = softpipe->framebuffer.sbuf; - GLuint clearVal = softpipe->stencil.clear_value; - - /* If this is not ~0, we shouldn't get here - clear should be - * done with geometry instead. - */ - GLuint mask = softpipe->stencil.write_mask[0]; - - assert((mask & 0xff) == 0xff); - - switch (ps->format) { - case PIPE_FORMAT_S8_Z24: - clearVal = clearVal << 24; - mask = mask << 24; - break; - case PIPE_FORMAT_U_S8: - /* nothing */ - break; - default: - assert(0); - } - - pipe->region_fill(pipe, ps->region, 0, x, y, w, h, clearVal, mask); - } - } + pipe->region_fill(pipe, ps->region, 0, x, y, w, h, clearValue, ~0); } diff --git a/src/mesa/pipe/softpipe/sp_clear.h b/src/mesa/pipe/softpipe/sp_clear.h index d41cc1d070..e706e731c2 100644 --- a/src/mesa/pipe/softpipe/sp_clear.h +++ b/src/mesa/pipe/softpipe/sp_clear.h @@ -36,8 +36,8 @@ struct pipe_context; extern void -softpipe_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth, - GLboolean stencil); +softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, + GLuint clearValue); #endif /* SP_CLEAR_H */ diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 85df549404..bd58abc4d1 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -43,6 +43,65 @@ #include "vf/vf.h" + +static GLuint +color_value(GLuint pipeFormat, const GLfloat color[4]) +{ + GLubyte r, g, b, a; + + UNCLAMPED_FLOAT_TO_UBYTE(r, color[0]); + UNCLAMPED_FLOAT_TO_UBYTE(g, color[1]); + UNCLAMPED_FLOAT_TO_UBYTE(b, color[2]); + UNCLAMPED_FLOAT_TO_UBYTE(a, color[3]); + + switch (pipeFormat) { + case PIPE_FORMAT_U_R8_G8_B8_A8: + return (r << 24) | (g << 16) | (b << 8) | a; + case PIPE_FORMAT_U_A8_R8_G8_B8: + return (a << 24) | (r << 16) | (g << 8) | b; + case PIPE_FORMAT_U_R5_G6_B5: + return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); + default: + return 0; + } +} + + +static GLuint +depth_value(GLuint pipeFormat, GLfloat value) +{ + GLuint val; + switch (pipeFormat) { + case PIPE_FORMAT_U_Z16: + val = (GLuint) (value * 0xffffff); + break; + case PIPE_FORMAT_U_Z32: + val = (GLuint) (value * 0xffffffff); + break; + case PIPE_FORMAT_S8_Z24: + /*case PIPE_FORMAT_Z24_S8:*/ + val = (GLuint) (value * 0xffffff); + break; + default: + assert(0); + } + return val; +} + + +static GLboolean +is_depth_stencil_format(GLuint pipeFormat) +{ + switch (pipeFormat) { + case PIPE_FORMAT_S8_Z24: + /*case PIPE_FORMAT_Z24_S8:*/ + return GL_TRUE; + default: + return GL_FALSE; + } +} + + /** * Draw a screen-aligned quadrilateral. * Coords are window coords. @@ -92,7 +151,8 @@ draw_quad(GLcontext *ctx, * Do glClear by drawing a quadrilateral. */ static void -clear_with_quad(GLcontext *ctx, +clear_with_quad(GLcontext *ctx, GLuint x0, GLuint y0, + GLuint x1, GLuint y1, GLboolean color, GLboolean depth, GLboolean stencil) { struct st_context *st = ctx->st; @@ -133,6 +193,8 @@ clear_with_quad(GLcontext *ctx, /* setup state: nothing */ memset(&setup, 0, sizeof(setup)); + if (ctx->Scissor.Enabled) + setup.scissor = 1; st->pipe->set_setup_state(st->pipe, &setup); /* stencil state: always set to ref value */ @@ -145,18 +207,14 @@ clear_with_quad(GLcontext *ctx, stencil_test.front_zfail_op = PIPE_STENCIL_OP_REPLACE; stencil_test.ref_value[0] = ctx->Stencil.Clear; stencil_test.value_mask[0] = 0xff; - stencil_test.write_mask[0] = ctx->Stencil.WriteMask[0]; + stencil_test.write_mask[0] = ctx->Stencil.WriteMask[0] & 0xff; } st->pipe->set_stencil_state(st->pipe, &stencil_test); /* draw quad matching scissor rect (XXX verify coord round-off) */ - draw_quad(ctx, - ctx->Scissor.X, ctx->Scissor.Y, - ctx->Scissor.X + ctx->Scissor.Width, - ctx->Scissor.Y + ctx->Scissor.Height, - ctx->Depth.Clear, ctx->Color.ClearColor); + draw_quad(ctx, x0, y0, x1, y1, ctx->Depth.Clear, ctx->Color.ClearColor); - /* Restore GL state */ + /* Restore pipe state */ st->pipe->set_alpha_test_state(st->pipe, &st->state.alpha_test); st->pipe->set_blend_state(st->pipe, &st->state.blend); st->pipe->set_depth_state(st->pipe, &st->state.depth); @@ -168,6 +226,141 @@ clear_with_quad(GLcontext *ctx, } +static void +clear_color_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) +{ + if (ctx->Color.ColorMask[0] && + ctx->Color.ColorMask[1] && + ctx->Color.ColorMask[2] && + ctx->Color.ColorMask[3] && + !ctx->Scissor.Enabled) + { + /* clear whole buffer w/out masking */ + GLuint clearValue + = color_value(rb->surface->format, ctx->Color.ClearColor); + ctx->st->pipe->clear(ctx->st->pipe, rb->surface, clearValue); + } + else { + /* masking or scissoring */ + clear_with_quad(ctx, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmax, + ctx->DrawBuffer->_Ymax, + GL_TRUE, GL_FALSE, GL_FALSE); + } +} + + +static void +clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) +{ + if (!ctx->Scissor.Enabled) { + /* clear whole buffer w/out masking */ + GLuint clearValue + = color_value(rb->surface->format, ctx->Accum.ClearColor); + /* Note that clearValue is 32 bits but the accum buffer will + * typically be 64bpp... + */ + ctx->st->pipe->clear(ctx->st->pipe, rb->surface, clearValue); + } + else { + /* scissoring */ + /* XXX point framebuffer.cbufs[0] at the accum buffer */ + clear_with_quad(ctx, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmax, + ctx->DrawBuffer->_Ymax, + GL_TRUE, GL_FALSE, GL_FALSE); + } +} + + +static void +clear_depth_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) +{ + if (!ctx->Scissor.Enabled && + !is_depth_stencil_format(rb->surface->format)) { + /* clear whole depth buffer w/out masking */ + GLuint clearValue = depth_value(rb->surface->format, ctx->Depth.Clear); + ctx->st->pipe->clear(ctx->st->pipe, rb->surface, clearValue); + } + else { + /* masking or scissoring or combined z/stencil buffer */ + clear_with_quad(ctx, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmax, + ctx->DrawBuffer->_Ymax, + GL_FALSE, GL_TRUE, GL_FALSE); + } +} + + +static void +clear_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) +{ + const GLuint stencilMax = (1 << rb->StencilBits) - 1; + GLboolean maskStencil = ctx->Stencil.WriteMask[0] != stencilMax; + + if (!maskStencil && !ctx->Scissor.Enabled && + !is_depth_stencil_format(rb->surface->format)) { + /* clear whole stencil buffer w/out masking */ + GLuint clearValue = ctx->Stencil.Clear; + ctx->st->pipe->clear(ctx->st->pipe, rb->surface, clearValue); + } + else { + /* masking or scissoring */ + clear_with_quad(ctx, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmax, + ctx->DrawBuffer->_Ymax, + GL_FALSE, GL_FALSE, GL_TRUE); + } +} + + +static void +clear_depth_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) +{ + const GLuint stencilMax = 1 << rb->StencilBits; + GLboolean maskStencil = ctx->Stencil.WriteMask[0] != stencilMax; + + assert(is_depth_stencil_format(rb->surface->format)); + + if (!maskStencil && !ctx->Scissor.Enabled) { + /* clear whole buffer w/out masking */ + GLuint clearValue = depth_value(rb->surface->format, ctx->Depth.Clear); + + switch (rb->surface->format) { + case PIPE_FORMAT_S8_Z24: + clearValue |= ctx->Stencil.Clear << 24; + break; +#if 0 + case PIPE_FORMAT_Z24_S8: + clearValue = (clearValue << 8) | clearVal; + break; +#endif + default: + assert(0); + } + + ctx->st->pipe->clear(ctx->st->pipe, rb->surface, clearValue); + } + else { + /* masking or scissoring */ + clear_with_quad(ctx, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmin, + ctx->DrawBuffer->_Xmax, + ctx->DrawBuffer->_Ymax, + GL_FALSE, GL_TRUE, GL_TRUE); + } +} + + /** * Called via ctx->Driver.Clear() @@ -176,41 +369,52 @@ clear_with_quad(GLcontext *ctx, */ 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; - GLboolean color = (mask & BUFFER_BITS_COLOR) ? GL_TRUE : GL_FALSE; - GLboolean depth = (mask & BUFFER_BIT_DEPTH) ? GL_TRUE : GL_FALSE; - GLboolean stencil = (mask & BUFFER_BIT_STENCIL) ? GL_TRUE : GL_FALSE; - GLboolean accum = (mask & BUFFER_BIT_ACCUM) ? GL_TRUE : GL_FALSE; - - GLboolean maskColor, maskStencil; - GLboolean fullscreen = !ctx->Scissor.Enabled; - GLuint stencilMax = stencil ? (1 << ctx->DrawBuffer->_StencilBuffer->StencilBits) : 0; + struct gl_renderbuffer *depthRb + = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + struct gl_renderbuffer *stencilRb + = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; /* This makes sure the softpipe has the latest scissor, etc values */ st_validate_state( st ); - maskColor = color && st->state.blend.colormask != PIPE_MASK_RGBA; - maskStencil = stencil && ctx->Stencil.WriteMask[0] != stencilMax; - - if (fullscreen && !maskColor && !maskStencil) { - /* pipe->clear() should clear a particular surface, so that we - * can iterate over render buffers at this level and clear the - * ones GL is asking for. - * - * Will probably need something like pipe->clear_z_stencil() to - * cope with the special case of paired and unpaired z/stencil - * buffers, though could perhaps deal with them explicitly at - * this level. - */ - st->pipe->clear(st->pipe, color, depth, stencil); + /* + * XXX TO-DO: + * If we're going to use clear_with_quad() for any reason, use it to + * clear as many other buffers as possible. + * As it is now, we sometimes call clear_with_quad() three times to clear + * color/depth/stencil individually... + */ + + if (mask & BUFFER_BITS_COLOR) { + GLuint b; + for (b = 0; b < BUFFER_COUNT; b++) { + if (BUFFER_BITS_COLOR & mask & (1 << b)) { + clear_color_buffer(ctx, + ctx->DrawBuffer->Attachment[b].Renderbuffer); + } + } + } - /* And here we would do a clear on whatever surface we are using - * to implement accum buffers: - */ - assert(!accum); + if (mask & BUFFER_BIT_ACCUM) { + clear_accum_buffer(ctx, + ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); + } + + if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) { + /* clearing combined depth + stencil */ + clear_depth_stencil_buffer(ctx, depthRb); } else { - clear_with_quad(ctx, color, depth, stencil); + /* separate depth/stencil clears */ + if (mask & BUFFER_BIT_DEPTH) { + clear_depth_buffer(ctx, depthRb); + } + if (mask & BUFFER_BIT_STENCIL) { + clear_stencil_buffer(ctx, stencilRb); + } } } -- cgit v1.2.3