intel: Fix performance regression in Lightsmark since HiZ changes.
[mesa.git] / src / mesa / drivers / x11 / xm_buffer.c
index fb6815ae1eb81b61b3ed842d458cf608a4470b67..84e6fcd795c37bed9ab1dc7d47b915c5207cfda4 100644 (file)
 
 
 #include "glxheader.h"
-#include "GL/xmesa.h"
 #include "xmesaP.h"
-#include "imports.h"
-#include "framebuffer.h"
-#include "renderbuffer.h"
-#include "pipe/p_state.h"
-#include "pipe/p_defines.h"
-#include "state_tracker/st_context.h"
+#include "main/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;
 
 /**
@@ -173,7 +174,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);
@@ -191,10 +192,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),
@@ -202,7 +199,6 @@ 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;
@@ -233,6 +229,7 @@ alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
       }
 
       b->backxrb->ximage = NULL;
+      b->backxrb->drawable = b->backxrb->pixmap;
    }
 }
 
@@ -244,7 +241,7 @@ xmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
     * should probably get freed here, but that's currently done in
     * XMesaDestroyBuffer().
     */
-   _mesa_free(rb);
+   free(rb);
 }
 
 
@@ -253,13 +250,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;
@@ -271,11 +267,6 @@ xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
    rb->Height = height;
    rb->InternalFormat = internalFormat;
 
-   if (!xrb->St.surface)
-      xrb->St.surface = xmesa_new_surface(ctx, xrb);
-   xrb->St.surface->width = width;
-   xrb->St.surface->height = height;
-
    return GL_TRUE;
 }
 
@@ -285,7 +276,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);
@@ -300,10 +291,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);
@@ -318,108 +305,66 @@ 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;
    }
 
-   if (!xrb->St.surface)
-      xrb->St.surface = xmesa_new_surface(ctx, xrb);
-   xrb->St.surface->width = width;
-   xrb->St.surface->height = height;
-
    return GL_TRUE;
 }
 
 
 /**
- * Called to create the front/back color renderbuffers, not user-created
- * renderbuffers.
+ * Used for allocating front/back renderbuffers for an X window.
  */
 struct xmesa_renderbuffer *
-xmesa_create_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);
-   struct pipe_context *pipe = NULL;/*ctx->st->pipe;*/
    if (xrb) {
       GLuint name = 0;
-      GLuint pipeFormat = 0;
-      struct xmesa_surface *xms;
+      _mesa_init_renderbuffer(&xrb->Base, name);
 
-      _mesa_init_renderbuffer(&xrb->St.Base, name);
-
-      xrb->St.Base.Delete = xmesa_delete_renderbuffer;
+      xrb->Base.Delete = xmesa_delete_renderbuffer;
       if (backBuffer)
-         xrb->St.Base.AllocStorage = xmesa_alloc_back_storage;
+         xrb->Base.AllocStorage = xmesa_alloc_back_storage;
       else
-         xrb->St.Base.AllocStorage = xmesa_alloc_front_storage;
-
-      if (visual->rgbMode) {
-         xrb->St.Base.InternalFormat = GL_RGBA;
-         xrb->St.Base._BaseFormat = GL_RGBA;
-         xrb->St.Base.DataType = GL_UNSIGNED_BYTE;
-         xrb->St.Base.RedBits = visual->redBits;
-         xrb->St.Base.GreenBits = visual->greenBits;
-         xrb->St.Base.BlueBits = visual->blueBits;
-         xrb->St.Base.AlphaBits = visual->alphaBits;
-         pipeFormat = PIPE_FORMAT_U_A8_R8_G8_B8;
-      }
-      else {
-         xrb->St.Base.InternalFormat = GL_COLOR_INDEX;
-         xrb->St.Base._BaseFormat = GL_COLOR_INDEX;
-         xrb->St.Base.DataType = GL_UNSIGNED_INT;
-         xrb->St.Base.IndexBits = visual->indexBits;
+         xrb->Base.AllocStorage = xmesa_alloc_front_storage;
+
+      xrb->Base.InternalFormat = GL_RGBA;
+      xrb->Base._BaseFormat = GL_RGBA;
+      xrb->Base.DataType = GL_UNSIGNED_BYTE;
+      xrb->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.Format = MESA_FORMAT_XRGB8888;
+         break;
+      case PF_8A8R8G8B:
+         xrb->Base.Format = MESA_FORMAT_ARGB8888;
+         break;
+      case PF_8A8B8G8R:
+         xrb->Base.Format = MESA_FORMAT_RGBA8888_REV;
+         break;
+      case PF_5R6G5B:
+         xrb->Base.Format = MESA_FORMAT_RGB565;
+         break;
+      default:
+         _mesa_warning(ctx, "Bad pixel format in xmesa_new_renderbuffer");
+         xrb->Base.Format = MESA_FORMAT_ARGB8888;
+         break;
       }
-      /* only need to set Red/Green/EtcBits fields for user-created RBs */
-
-      xrb->St.surface = xmesa_surface_alloc(pipe, pipeFormat);
-      xms = (struct xmesa_surface *) xrb->St.surface;
-      xms->xrb = xrb;
-
-   }
-   return xrb;
-}
-
-
-#if 0
-struct gl_renderbuffer *
-xmesa_new_renderbuffer(GLcontext *ctx, struct gl_renderbuffer *rb,
-                       GLenum internalFormat, GLuint width, GLuint height)
-{
-   struct xmesa_renderbuffer *xrb = CALLOC_STRUCT(xmesa_renderbuffer);
-   if (xrb) {
-      GLuint name = 0;
-      _mesa_init_renderbuffer(&xrb->St.Base, name);
 
-      xrb->St.Base.Delete = xmesa_delete_renderbuffer;
-      if (backBuffer)
-         xrb->St.Base.AllocStorage = xmesa_alloc_back_storage;
-      else
-         xrb->St.Base.AllocStorage = xmesa_alloc_front_storage;
-
-      if (visual->rgbMode) {
-         xrb->St.Base.InternalFormat = GL_RGBA;
-         xrb->St.Base._BaseFormat = GL_RGBA;
-         xrb->St.Base.DataType = GL_UNSIGNED_BYTE;
-         xrb->St.Base.RedBits = visual->redBits;
-         xrb->St.Base.GreenBits = visual->greenBits;
-         xrb->St.Base.BlueBits = visual->blueBits;
-         xrb->St.Base.AlphaBits = visual->alphaBits;
-      }
-      else {
-         xrb->St.Base.InternalFormat = GL_COLOR_INDEX;
-         xrb->St.Base._BaseFormat = GL_COLOR_INDEX;
-         xrb->St.Base.DataType = GL_UNSIGNED_INT;
-         xrb->St.Base.IndexBits = visual->indexBits;
-      }
       /* only need to set Red/Green/EtcBits fields for user-created RBs */
    }
    return xrb;
 }
-#endif
 
 
 /**
@@ -434,16 +379,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
       }
    }
 
@@ -457,7 +394,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 );
@@ -470,20 +407,129 @@ 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 );
-         }
       }
    }
 
    if (b->rowimage) {
-      _mesa_free( b->rowimage->data );
+      free( b->rowimage->data );
       b->rowimage->data = NULL;
       XMesaDestroyImage( b->rowimage );
    }
 
    _mesa_free_framebuffer_data(fb);
-   _mesa_free(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)
+{
+   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
+
+   if (xrb->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 y2 = rb->Height - y - h;
+
+         assert(xrb->pixmap);
+
+         /* read pixel data out of the pixmap/window into an XImage */
+         ximage = XGetImage(xrb->Parent->display,
+                            xrb->pixmap, x, y2, w, h,
+                            AllPlanes, ZPixmap);
+         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;
+   }
+
+   /* otherwise, this is an ordinary malloc-based renderbuffer */
+   _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
+                                 mapOut, rowStrideOut);
+}
+
+
+/**
+ * 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.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;
+   }
+
+   /* otherwise, this is an ordinary malloc-based renderbuffer */
+   _swrast_unmap_soft_renderbuffer(ctx, rb);
+}
+
+