Move compiler.h and imports.h/c from src/mesa/main into src/util
[mesa.git] / src / mesa / drivers / x11 / xm_buffer.c
index f104d44d051e75132c527f5102b92d2b7ee0958c..9e16726535c130991b4389e706cbf969fbab72a5 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.2
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 
 
 
 #include "glxheader.h"
-#include "GL/xmesa.h"
 #include "xmesaP.h"
-#include "main/imports.h"
+#include "main/errors.h"
+#include "util/imports.h"
+#include "main/formats.h"
 #include "main/framebuffer.h"
 #include "main/renderbuffer.h"
+#include "swrast/s_renderbuffer.h"
 
 
-#if defined(USE_XSHM) && !defined(XFree86Server)
+#define XMESA_RENDERBUFFER 0x1234
+
+
+#if defined(USE_XSHM) 
 static volatile int mesaXErrorFlag = 0;
 
 /**
@@ -84,8 +89,9 @@ alloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height)
       return GL_FALSE;
    }
 
+   /* 0600 = user read+write */
    b->shminfo.shmid = shmget(IPC_PRIVATE, b->backxrb->ximage->bytes_per_line
-                            * b->backxrb->ximage->height, IPC_CREAT|0777);
+                             * b->backxrb->ximage->height, IPC_CREAT | 0600);
    if (b->shminfo.shmid < 0) {
       _mesa_warning(NULL, "shmget failed while allocating back buffer.\n");
       XDestroyImage(b->backxrb->ximage);
@@ -170,7 +176,7 @@ alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
    if (b->db_mode == BACK_XIMAGE) {
       /* Deallocate the old backxrb->ximage, if any */
       if (b->backxrb->ximage) {
-#if defined(USE_XSHM) && !defined(XFree86Server)
+#if defined(USE_XSHM) 
         if (b->shm) {
            XShmDetach(b->xm_visual->display, &b->shminfo);
            XDestroyImage(b->backxrb->ximage);
@@ -188,10 +194,6 @@ alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
       /* Allocate new back buffer */
       if (b->shm == 0 || !alloc_back_shm_ximage(b, width, height)) {
         /* Allocate a regular XImage for the back buffer. */
-#ifdef XFree86Server
-        b->backxrb->ximage = XMesaCreateImage(b->xm_visual->BitsPerPixel,
-                                               width, height, NULL);
-#else
         b->backxrb->ximage = XCreateImage(b->xm_visual->display,
                                       b->xm_visual->visinfo->visual,
                                       GET_VISUAL_DEPTH(b->xm_visual),
@@ -199,12 +201,11 @@ alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
                                      NULL,
                                       width, height,
                                      8, 0);  /* pad, bytes_per_line */
-#endif
         if (!b->backxrb->ximage) {
            _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed.\n");
             return;
         }
-         b->backxrb->ximage->data = (char *) MALLOC(b->backxrb->ximage->height
+         b->backxrb->ximage->data = malloc(b->backxrb->ximage->height
                                         * b->backxrb->ximage->bytes_per_line);
          if (!b->backxrb->ximage->data) {
             _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed.\n");
@@ -230,18 +231,19 @@ alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
       }
 
       b->backxrb->ximage = NULL;
+      b->backxrb->drawable = b->backxrb->pixmap;
    }
 }
 
 
 static void
-xmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
+xmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
 {
    /* XXX Note: the ximage or Pixmap attached to this renderbuffer
     * should probably get freed here, but that's currently done in
     * XMesaDestroyBuffer().
     */
-   _mesa_free(rb);
+   free(rb);
 }
 
 
@@ -250,13 +252,12 @@ xmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
  * Called via gl_renderbuffer::AllocStorage()
  */
 static GLboolean
-xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+xmesa_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
                           GLenum internalFormat, GLuint width, GLuint height)
 {
    struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
 
    /* just clear these to be sure we don't accidentally use them */
-   xrb->origin1 = NULL;
    xrb->origin2 = NULL;
    xrb->origin3 = NULL;
    xrb->origin4 = NULL;
@@ -277,7 +278,7 @@ xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
  * Called via gl_renderbuffer::AllocStorage()
  */
 static GLboolean
-xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+xmesa_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
                          GLenum internalFormat, GLuint width, GLuint height)
 {
    struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
@@ -292,10 +293,6 @@ xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
 
    /* plus... */
    if (xrb->ximage) {
-      /* Needed by PIXELADDR1 macro */
-      xrb->width1 = xrb->ximage->bytes_per_line;
-      xrb->origin1 = (GLubyte *) xrb->ximage->data + xrb->width1 * (height - 1);
-
       /* Needed by PIXELADDR2 macro */
       xrb->width2 = xrb->ximage->bytes_per_line / 2;
       xrb->origin2 = (GLushort *) xrb->ximage->data + xrb->width2 * (height - 1);
@@ -310,8 +307,7 @@ xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
    }
    else {
       /* out of memory or buffer size is 0 x 0 */
-      xrb->width1 = xrb->width2 = xrb->width3 = xrb->width4 = 0;
-      xrb->origin1 = NULL;
+      xrb->width2 = xrb->width3 = xrb->width4 = 0;
       xrb->origin2 = NULL;
       xrb->origin3 = NULL;
       xrb->origin4 = NULL;
@@ -321,36 +317,51 @@ xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
 }
 
 
+/**
+ * Used for allocating front/back renderbuffers for an X window.
+ */
 struct xmesa_renderbuffer *
-xmesa_new_renderbuffer(GLcontext *ctx, GLuint name, const GLvisual *visual,
+xmesa_new_renderbuffer(struct gl_context *ctx, GLuint name,
+                       const struct xmesa_visual *xmvis,
                        GLboolean backBuffer)
 {
    struct xmesa_renderbuffer *xrb = CALLOC_STRUCT(xmesa_renderbuffer);
    if (xrb) {
       GLuint name = 0;
-      _mesa_init_renderbuffer(&xrb->Base, name);
+      _mesa_init_renderbuffer(&xrb->Base.Base, name);
 
-      xrb->Base.Delete = xmesa_delete_renderbuffer;
+      xrb->Base.Base.Delete = xmesa_delete_renderbuffer;
       if (backBuffer)
-         xrb->Base.AllocStorage = xmesa_alloc_back_storage;
+         xrb->Base.Base.AllocStorage = xmesa_alloc_back_storage;
       else
-         xrb->Base.AllocStorage = xmesa_alloc_front_storage;
-
-      if (visual->rgbMode) {
-         xrb->Base.InternalFormat = GL_RGBA;
-         xrb->Base._BaseFormat = GL_RGBA;
-         xrb->Base.DataType = GL_UNSIGNED_BYTE;
-         xrb->Base.RedBits = visual->redBits;
-         xrb->Base.GreenBits = visual->greenBits;
-         xrb->Base.BlueBits = visual->blueBits;
-         xrb->Base.AlphaBits = visual->alphaBits;
-      }
-      else {
-         xrb->Base.InternalFormat = GL_COLOR_INDEX;
-         xrb->Base._BaseFormat = GL_COLOR_INDEX;
-         xrb->Base.DataType = GL_UNSIGNED_INT;
-         xrb->Base.IndexBits = visual->indexBits;
+         xrb->Base.Base.AllocStorage = xmesa_alloc_front_storage;
+
+      xrb->Base.Base.InternalFormat = GL_RGBA;
+      xrb->Base.Base._BaseFormat = GL_RGBA;
+      xrb->Base.Base.ClassID = XMESA_RENDERBUFFER;
+
+      switch (xmvis->undithered_pf) {
+      case PF_8R8G8B:
+         /* This will really only happen for pixmaps.  We'll access the
+          * pixmap via a temporary XImage which will be 32bpp.
+          */
+         xrb->Base.Base.Format = MESA_FORMAT_B8G8R8X8_UNORM;
+         break;
+      case PF_8A8R8G8B:
+         xrb->Base.Base.Format = MESA_FORMAT_B8G8R8A8_UNORM;
+         break;
+      case PF_8A8B8G8R:
+         xrb->Base.Base.Format = MESA_FORMAT_R8G8B8A8_UNORM;
+         break;
+      case PF_5R6G5B:
+         xrb->Base.Base.Format = MESA_FORMAT_B5G6R5_UNORM;
+         break;
+      default:
+         _mesa_warning(ctx, "Bad pixel format in xmesa_new_renderbuffer");
+         xrb->Base.Base.Format = MESA_FORMAT_B8G8R8A8_UNORM;
+         break;
       }
+
       /* only need to set Red/Green/EtcBits fields for user-created RBs */
    }
    return xrb;
@@ -369,16 +380,8 @@ xmesa_delete_framebuffer(struct gl_framebuffer *fb)
    if (b->num_alloced > 0) {
       /* If no other buffer uses this X colormap then free the colors. */
       if (!xmesa_find_buffer(b->display, b->cmap, b)) {
-#ifdef XFree86Server
-         int client = 0;
-         if (b->frontxrb->drawable)
-            client = CLIENT_ID(b->frontxrb->drawable->id);
-         (void)FreeColors(b->cmap, client,
-                          b->num_alloced, b->alloced_colors, 0);
-#else
          XFreeColors(b->display, b->cmap,
                      b->alloced_colors, b->num_alloced, 0);
-#endif
       }
    }
 
@@ -392,7 +395,7 @@ xmesa_delete_framebuffer(struct gl_framebuffer *fb)
    if (fb->Visual.doubleBufferMode) {
       /* free back ximage/pixmap/shmregion */
       if (b->backxrb->ximage) {
-#if defined(USE_XSHM) && !defined(XFree86Server)
+#if defined(USE_XSHM) 
          if (b->shm) {
             XShmDetach( b->display, &b->shminfo );
             XDestroyImage( b->backxrb->ximage );
@@ -405,20 +408,153 @@ xmesa_delete_framebuffer(struct gl_framebuffer *fb)
       }
       if (b->backxrb->pixmap) {
          XMesaFreePixmap( b->display, b->backxrb->pixmap );
-         if (b->xm_visual->hpcr_clear_flag) {
-            XMesaFreePixmap( b->display,
-                             b->xm_visual->hpcr_clear_pixmap );
-            XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
+      }
+   }
+
+   _mesa_free_framebuffer_data(fb);
+   free(fb);
+}
+
+
+/**
+ * Called via ctx->Driver.MapRenderbuffer()
+ */
+void
+xmesa_MapRenderbuffer(struct gl_context *ctx,
+                      struct gl_renderbuffer *rb,
+                      GLuint x, GLuint y, GLuint w, GLuint h,
+                      GLbitfield mode,
+                      GLubyte **mapOut, GLint *rowStrideOut,
+                      bool flip_y)
+{
+   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
+
+   if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) {
+      XImage *ximage = xrb->ximage;
+
+      assert(!xrb->map_mode); /* only a single mapping allowed */
+
+      xrb->map_mode = mode;
+      xrb->map_x = x;
+      xrb->map_y = y;
+      xrb->map_w = w;
+      xrb->map_h = h;
+
+      if (ximage) {
+         int y2 = rb->Height - y - 1;
+
+         *mapOut = (GLubyte *) ximage->data
+            + y2 * ximage->bytes_per_line
+            + x * ximage->bits_per_pixel / 8;
+      }
+      else {
+         /* this must be a pixmap/window renderbuffer */
+         int (*old_handler)(XMesaDisplay *, XErrorEvent *);
+         int y2 = rb->Height - y - h;
+
+         assert(xrb->pixmap);
+
+         /* Install error handler for XGetImage() in case the window
+          * isn't mapped.  If we fail we'll create a temporary XImage.
+          */
+         mesaXErrorFlag = 0;
+         old_handler = XSetErrorHandler(mesaHandleXError);
+
+         /* read pixel data out of the pixmap/window into an XImage */
+         ximage = XGetImage(xrb->Parent->display,
+                            xrb->pixmap, x, y2, w, h,
+                            AllPlanes, ZPixmap);
+
+         XSetErrorHandler(old_handler);
+
+         if (mesaXErrorFlag) {
+            /* create new, temporary XImage */
+            int bytes_per_line =
+               _mesa_format_row_stride(xrb->Base.Base.Format,
+                                       xrb->Base.Base.Width);
+            char *image = malloc(bytes_per_line *
+                                          xrb->Base.Base.Height);
+            ximage = XCreateImage(xrb->Parent->display,
+                                  xrb->Parent->xm_visual->visinfo->visual,
+                                  xrb->Parent->xm_visual->visinfo->depth,
+                                  ZPixmap, /* format */
+                                  0, /* offset */
+                                  image, /* data */
+                                  xrb->Base.Base.Width,
+                                  xrb->Base.Base.Height,
+                                  8, /* pad */
+                                  bytes_per_line);
+         }
+
+         if (!ximage) {
+            *mapOut = NULL;
+            *rowStrideOut = 0;
+            return;
          }
+
+         xrb->map_ximage = ximage;
+
+         /* the first row of the OpenGL image is last row of the XImage */
+         *mapOut = (GLubyte *) ximage->data
+            + (h - 1) * ximage->bytes_per_line;
       }
+
+      /* We return a negative stride here since XImage data is upside down
+       * with respect to OpenGL images.
+       */
+      *rowStrideOut = -ximage->bytes_per_line;
+      return;
    }
 
-   if (b->rowimage) {
-      _mesa_free( b->rowimage->data );
-      b->rowimage->data = NULL;
-      XMesaDestroyImage( b->rowimage );
+   /* otherwise, this is an ordinary malloc-based renderbuffer */
+   _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
+                                 mapOut, rowStrideOut, false);
+}
+
+
+/**
+ * Called via ctx->Driver.UnmapRenderbuffer()
+ */
+void
+xmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
+{
+   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
+
+   if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) {
+      XImage *ximage = xrb->ximage;
+
+      if (!ximage) {
+         /* this must be a pixmap/window renderbuffer */
+         assert(xrb->pixmap);
+         assert(xrb->map_ximage);
+         if (xrb->map_ximage) {
+            if (xrb->map_mode & GL_MAP_WRITE_BIT) {
+               /* put modified ximage data back into the pixmap/window */
+               int y2 = rb->Height - xrb->map_y - xrb->map_h;
+               GC gc = XCreateGC(xrb->Parent->display, xrb->pixmap, 0, NULL);
+
+               XPutImage(xrb->Parent->display,
+                         xrb->pixmap,              /* dest */
+                         gc,
+                         xrb->map_ximage,          /* source */
+                         0, 0,                     /* src x, y */
+                         xrb->map_x, y2,           /* dest x, y */
+                         xrb->map_w, xrb->map_h);  /* size */
+
+               XFreeGC(xrb->Parent->display, gc);
+            }
+            XMesaDestroyImage(xrb->map_ximage);
+            xrb->map_ximage = NULL;
+         }
+      }
+
+      xrb->map_mode = 0x0;
+
+      return;
    }
 
-   _mesa_free_framebuffer_data(fb);
-   _mesa_free(fb);
+   /* otherwise, this is an ordinary malloc-based renderbuffer */
+   _swrast_unmap_soft_renderbuffer(ctx, rb);
 }
+
+