move surface clear functions to xm_buffer.c
[mesa.git] / src / mesa / pipe / xlib / xm_buffer.c
index 56b797a6a98244242229826bcf73addf42f50297..183a7ec8f5c428989f7c961b7297b90b54b0a2e7 100644 (file)
@@ -261,6 +261,146 @@ finish_surface_init(GLcontext *ctx, struct xmesa_renderbuffer *xrb)
 }
 
 
+/**
+ * Clear the front or back color buffer, if it's implemented with a pixmap.
+ */
+static void
+clear_pixmap(GLcontext *ctx, struct xmesa_renderbuffer *xrb, GLuint value)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+
+   assert(xmbuf);
+   assert(xrb->pixmap);
+   assert(xmesa);
+   assert(xmesa->display);
+   assert(xrb->pixmap);
+   assert(xmbuf->cleargc);
+
+   XMesaSetForeground( xmesa->display, xmbuf->cleargc, value );
+
+   XMesaFillRectangle( xmesa->display, xrb->pixmap, xmbuf->cleargc,
+                       0, 0, xrb->St.Base.Width, xrb->St.Base.Height);
+}
+
+
+static void
+clear_8bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb, GLuint value)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GLint width = xrb->St.Base.Width;
+   GLint height = xrb->St.Base.Height;
+   GLint i;
+   for (i = 0; i < height; i++) {
+      GLubyte *ptr = PIXEL_ADDR1(xrb, 0, i);
+      MEMSET( ptr, xmesa->clearpixel, width );
+   }
+}
+
+
+static void
+clear_16bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb, GLuint value)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GLint width = xrb->St.Base.Width;
+   GLint height = xrb->St.Base.Height;
+   GLint i, j;
+
+   if (xmesa->swapbytes) {
+      value = ((value >> 8) & 0x00ff) | ((value << 8) & 0xff00);
+   }
+
+   for (j = 0; j < height; j++) {
+      GLushort *ptr2 = PIXEL_ADDR2(xrb, 0, j);
+      for (i = 0; i < width; i++) {
+         ptr2[i] = value;
+      }
+   }
+}
+
+
+/* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
+static void
+clear_24bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+                   GLuint value)
+{
+   GLint width = xrb->St.Base.Width;
+   GLint height = xrb->St.Base.Height;
+   const GLubyte r = (value      ) & 0xff;
+   const GLubyte g = (value >>  8) & 0xff;
+   const GLubyte b = (value >> 16) & 0xff;
+
+   if (r == g && g == b) {
+      /* same value for all three components (gray) */
+      GLint j;
+      for (j = 0; j < height; j++) {
+         bgr_t *ptr3 = PIXEL_ADDR3(xrb, 0, j);
+         MEMSET(ptr3, r, 3 * width);
+      }
+   }
+   else {
+      /* non-gray clear color */
+      GLint i, j;
+      for (j = 0; j < height; j++) {
+         bgr_t *ptr3 = PIXEL_ADDR3(xrb, 0, j);
+         for (i = 0; i < width; i++) {
+            ptr3->r = r;
+            ptr3->g = g;
+            ptr3->b = b;
+            ptr3++;
+         }
+      }
+   }
+}
+
+
+static void
+clear_32bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+                   GLuint value)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GLint width = xrb->St.Base.Width;
+   GLint height = xrb->St.Base.Height;
+   const GLuint n = width * height;
+   GLuint *ptr4 = (GLuint *) xrb->ximage->data;
+
+   if (!xrb->ximage)
+      return;
+
+   if (xmesa->swapbytes) {
+      value = ((value >> 24) & 0x000000ff)
+            | ((value >> 8)  & 0x0000ff00)
+            | ((value << 8)  & 0x00ff0000)
+            | ((value << 24) & 0xff000000);
+   }
+
+   if (value == 0) {
+      /* common case */
+      _mesa_memset(ptr4, value, 4 * n);
+   }
+   else {
+      GLuint i;
+      for (i = 0; i < n; i++)
+         ptr4[i] = value;
+   }
+}
+
+
+static void
+clear_nbit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb, GLuint value)
+{
+   XMesaImage *img = xrb->ximage;
+   GLint width = xrb->St.Base.Width;
+   GLint height = xrb->St.Base.Height;
+   GLint i, j;
+   for (j = 0; j < height; j++) {
+      for (i = 0; i < width; i++) {
+         XMesaPutPixel(img, i, j, value);
+      }
+   }
+}
+
+
 /**
  * Reallocate renderbuffer storage for front color buffer.
  * Called via gl_renderbuffer::AllocStorage()
@@ -269,6 +409,7 @@ static GLboolean
 xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
                           GLenum internalFormat, GLuint width, GLuint height)
 {
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
    struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
 
    /* just clear these to be sure we don't accidentally use them */
@@ -287,6 +428,11 @@ xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
    if (!xrb->St.surface || !xrb->St.surface->region)
       finish_surface_init(ctx, xrb);
 
+   xmesa_set_renderbuffer_funcs(xrb, xmesa->pixelformat,
+                                xmesa->xm_visual->BitsPerPixel);
+
+   xrb->clearFunc = clear_pixmap;
+
    xrb->St.surface->width = width;
    xrb->St.surface->height = height;
 
@@ -302,6 +448,7 @@ static GLboolean
 xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
                          GLenum internalFormat, GLuint width, GLuint height)
 {
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
    struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
 
    /* reallocate the back buffer XImage or Pixmap */
@@ -339,6 +486,27 @@ xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
       xrb->origin4 = NULL;
    }
 
+   xmesa_set_renderbuffer_funcs(xrb, xmesa->pixelformat,
+                                xmesa->xm_visual->BitsPerPixel);
+
+   switch (xmesa->xm_visual->BitsPerPixel) {
+   case 8:
+      xrb->clearFunc = clear_8bit_ximage;
+      break;
+   case 16:
+      xrb->clearFunc = clear_16bit_ximage;
+      break;
+   case 24:
+      xrb->clearFunc = clear_24bit_ximage;
+      break;
+   case 32:
+      xrb->clearFunc = clear_32bit_ximage;
+      break;
+   default:
+      xrb->clearFunc = clear_nbit_ximage;
+      break;
+   }
+
    if (!xrb->St.surface || !xrb->St.surface->region)
       finish_surface_init(ctx, xrb);