summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/x11/xm_api.c5
-rw-r--r--src/mesa/drivers/x11/xm_dd.c23
-rw-r--r--src/mesa/drivers/x11/xmesaP.h7
-rw-r--r--src/mesa/pipe/p_context.h6
-rw-r--r--src/mesa/pipe/softpipe/sp_clear.c109
-rw-r--r--src/mesa/pipe/softpipe/sp_clear.h4
-rw-r--r--src/mesa/state_tracker/st_cb_clear.c274
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 92d37085d1a..7fb99df5f4c 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 87f8ede50b3..f64f8780cf6 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 fb1c1f8c3b4..dd95aed4d06 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 0972fd58b55..4f8bdae1409 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 e9b142e780b..d7684d20445 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 d41cc1d070c..e706e731c2d 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 85df549404a..bd58abc4d11 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);
+ }
}
}