pipe->clear() now takes a surface, rather than color/depth/stencil flags.
authorBrian <brian@i915.localnet.net>
Thu, 2 Aug 2007 22:08:18 +0000 (16:08 -0600)
committerBrian <brian@i915.localnet.net>
Thu, 2 Aug 2007 22:08:18 +0000 (16:08 -0600)
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
src/mesa/drivers/x11/xm_dd.c
src/mesa/drivers/x11/xmesaP.h
src/mesa/pipe/p_context.h
src/mesa/pipe/softpipe/sp_clear.c
src/mesa/pipe/softpipe/sp_clear.h
src/mesa/state_tracker/st_cb_clear.c

index 92d37085d1a4fe01e5a6362e8a38f81d6a6cf47b..7fb99df5f4c93f28405bc4a0b06c0ba4336ad320 100644 (file)
@@ -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;
 }
 
index 87f8ede50b305b113f0ef142d8ac5755615e5030..f64f8780cf606da167973b3ec6a18068e5c79dd5 100644 (file)
@@ -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;
index fb1c1f8c3b4f604277defeec02a876fcf8faf4f0..dd95aed4d06c8655b5083bbb574ef4a3451b3a80 100644 (file)
@@ -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
index 0972fd58b5500cb2b7759e5f1e81751129d650b0..4f8bdae1409e561934240230089ffda318007bc7 100644 (file)
@@ -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)
index e9b142e780b194a4a7316b938542c52eb1d5e7f5..d7684d204453d9bff4496e8319d3c2734e876808 100644 (file)
 #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);
 }
index d41cc1d070cda17d643a80eaeca4ddd3b9a942f6..e706e731c2de0973dc3d4baccef48f0b49ea5b75 100644 (file)
@@ -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 */
index 85df549404acb8daef074ea5e8b6a5c443d71ad0..bd58abc4d11b8c8d0659ce6148ea693af367fd41 100644 (file)
 #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);
+      }
    }
 }