mesa: Branch 'master' - 3 commits

Brian Paul brianp at kemper.freedesktop.org
Mon Feb 26 18:39:30 UTC 2007


 src/mesa/drivers/x11/xm_api.c    |  100 ++++++++++-----------------------------
 src/mesa/drivers/x11/xm_buffer.c |   68 ++++++++++++++++++++++++++
 src/mesa/drivers/x11/xmesaP.h    |    7 ++
 src/mesa/main/context.c          |   14 +++++
 src/mesa/main/framebuffer.c      |   39 ++++++++-------
 src/mesa/main/mtypes.h           |    1 
 src/mesa/swrast/s_readpix.c      |   26 ++++++----
 7 files changed, 156 insertions(+), 99 deletions(-)

New commits:
diff-tree 928a70e4354d4884e2918ec67ddc6d8baf942c8a (from f30e8a4bdf8338dc3f8e985a9c91af61a3301990)
Author: Brian <brian at yutani.localnet.net>
Date:   Mon Feb 26 11:39:17 2007 -0700

    Rewrite code related to buffer destruction.
    
    Do proper reference counting so that we don't wind up with dangling
    references to deleted windows/framebuffers.  Should help with bug 7205.

diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c
index b0ef422..2cd7d8a 100644
--- a/src/mesa/drivers/x11/xm_api.c
+++ b/src/mesa/drivers/x11/xm_api.c
@@ -345,7 +345,7 @@ xmesa_get_window_size(XMesaDisplay *dpy,
 /*****                Linked list of XMesaBuffers                 *****/
 /**********************************************************************/
 
-static XMesaBuffer XMesaBufferList = NULL;
+XMesaBuffer XMesaBufferList = NULL;
 
 
 /**
@@ -378,6 +378,7 @@ create_xmesa_buffer(XMesaDrawable d, Buf
    b->cmap = cmap;
 
    _mesa_initialize_framebuffer(&b->mesa_buffer, &vis->mesa_visual);
+   b->mesa_buffer.Delete = xmesa_delete_framebuffer;
 
    /*
     * Front renderbuffer
@@ -451,8 +452,8 @@ create_xmesa_buffer(XMesaDrawable d, Buf
  * Find an XMesaBuffer by matching X display and colormap but NOT matching
  * the notThis buffer.
  */
-static XMesaBuffer
-find_xmesa_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis)
+XMesaBuffer
+xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis)
 {
    XMesaBuffer b;
    for (b=XMesaBufferList; b; b=b->Next) {
@@ -465,38 +466,27 @@ find_xmesa_buffer(XMesaDisplay *dpy, XMe
 
 
 /**
- * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
- * entries.
+ * Remove buffer from linked list, delete if no longer referenced.
  */
 static void
-free_xmesa_buffer(int client, XMesaBuffer buffer)
+xmesa_free_buffer(XMesaBuffer buffer)
 {
    XMesaBuffer prev = NULL, b;
-   (void) client;
-   for (b=XMesaBufferList; b; b=b->Next) {
-      if (b==buffer) {
-         /* unlink bufer from list */
+
+   for (b = XMesaBufferList; b; b = b->Next) {
+      if (b == buffer) {
+         struct gl_framebuffer *fb = &buffer->mesa_buffer;
+
+         /* unlink buffer from list */
          if (prev)
             prev->Next = buffer->Next;
          else
             XMesaBufferList = buffer->Next;
-         /* Check to free X colors */
-         if (buffer->num_alloced>0) {
-            /* If no other buffer uses this X colormap then free the colors. */
-            if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) {
-#ifdef XFree86Server
-               (void)FreeColors(buffer->cmap, client,
-				buffer->num_alloced, buffer->alloced_colors,
-				0);
-#else
-               XFreeColors(buffer->display, buffer->cmap,
-                           buffer->alloced_colors, buffer->num_alloced, 0);
-#endif
-            }
-         }
 
-         _mesa_free_framebuffer_data(&buffer->mesa_buffer);
-         _mesa_free(buffer);
+         /* mark as delete pending */
+         fb->DeletePending = GL_TRUE;
+         /* Dereference.  If count = zero we'll really delete the buffer */
+         _mesa_dereference_framebuffer(&fb);
 
          return;
       }
@@ -504,7 +494,7 @@ free_xmesa_buffer(int client, XMesaBuffe
       prev = b;
    }
    /* buffer not found in XMesaBufferList */
-   _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n");
+   _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
 }
 
 
@@ -686,7 +676,7 @@ setup_grayscale(int client, XMesaVisual 
          return GL_FALSE;
       }
 
-      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
+      prevBuffer = xmesa_find_buffer(v->display, cmap, buffer);
       if (prevBuffer &&
           (buffer->xm_visual->mesa_visual.rgbMode ==
            prevBuffer->xm_visual->mesa_visual.rgbMode)) {
@@ -775,7 +765,7 @@ setup_dithered_color(int client, XMesaVi
          return GL_FALSE;
       }
 
-      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
+      prevBuffer = xmesa_find_buffer(v->display, cmap, buffer);
       if (prevBuffer &&
           (buffer->xm_visual->mesa_visual.rgbMode ==
            prevBuffer->xm_visual->mesa_visual.rgbMode)) {
@@ -1666,7 +1656,7 @@ XMesaCreateWindowBuffer2(XMesaVisual v, 
 
    if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode,
                                       (XMesaDrawable) w, cmap )) {
-      free_xmesa_buffer(client, b);
+      xmesa_free_buffer(b);
       return NULL;
    }
 
@@ -1787,7 +1777,7 @@ XMesaCreatePixmapBuffer(XMesaVisual v, X
 
    if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
 				     (XMesaDrawable) p, cmap)) {
-      free_xmesa_buffer(client, b);
+      xmesa_free_buffer(b);
       return NULL;
    }
 
@@ -1821,7 +1811,7 @@ XMesaCreatePBuffer(XMesaVisual v, XMesaC
 
    if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
 				     drawable, cmap)) {
-      free_xmesa_buffer(client, b);
+      xmesa_free_buffer(b);
       return NULL;
    }
 
@@ -1834,48 +1824,10 @@ XMesaCreatePBuffer(XMesaVisual v, XMesaC
 /*
  * Deallocate an XMesaBuffer structure and all related info.
  */
-void XMesaDestroyBuffer( XMesaBuffer b )
+void
+XMesaDestroyBuffer(XMesaBuffer b)
 {
-   int client = 0;
-
-#ifdef XFree86Server
-   if (b->frontxrb->drawable)
-       client = CLIENT_ID(b->frontxrb->drawable->id);
-#endif
-
-   if (b->gc)  XMesaFreeGC( b->xm_visual->display, b->gc );
-   if (b->cleargc)  XMesaFreeGC( b->xm_visual->display, b->cleargc );
-   if (b->swapgc)  XMesaFreeGC( b->xm_visual->display, b->swapgc );
-
-   if (b->xm_visual->mesa_visual.doubleBufferMode)
-   {
-      if (b->backxrb->ximage) {
-#if defined(USE_XSHM) && !defined(XFree86Server)
-         if (b->shm) {
-            XShmDetach( b->xm_visual->display, &b->shminfo );
-            XDestroyImage( b->backxrb->ximage );
-            shmdt( b->shminfo.shmaddr );
-         }
-         else
-#endif
-            XMesaDestroyImage( b->backxrb->ximage );
-      }
-      if (b->backxrb->pixmap) {
-         XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap );
-         if (b->xm_visual->hpcr_clear_flag) {
-            XMesaFreePixmap( b->xm_visual->display,
-                             b->xm_visual->hpcr_clear_pixmap );
-            XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
-         }
-      }
-   }
-   if (b->rowimage) {
-      _mesa_free( b->rowimage->data );
-      b->rowimage->data = NULL;
-      XMesaDestroyImage( b->rowimage );
-   }
-
-   free_xmesa_buffer(client, b);
+   xmesa_free_buffer(b);
 }
 
 
@@ -2436,7 +2388,7 @@ void xmesa_destroy_buffers_on_display(XM
    for (b = XMesaBufferList; b; b = next) {
       next = b->Next;
       if (b->display == dpy) {
-         free_xmesa_buffer(0, b);
+         xmesa_free_buffer(b);
       }
    }
 }
diff --git a/src/mesa/drivers/x11/xm_buffer.c b/src/mesa/drivers/x11/xm_buffer.c
index 490c479..187ae51 100644
--- a/src/mesa/drivers/x11/xm_buffer.c
+++ b/src/mesa/drivers/x11/xm_buffer.c
@@ -33,6 +33,7 @@
 #include "GL/xmesa.h"
 #include "xmesaP.h"
 #include "imports.h"
+#include "framebuffer.h"
 #include "renderbuffer.h"
 
 
@@ -352,5 +353,72 @@ xmesa_new_renderbuffer(GLcontext *ctx, G
 }
 
 
+/**
+ * Called via gl_framebuffer::Delete() method when this buffer
+ * is _really_ being
+ * deleted.
+ */
+void
+xmesa_delete_framebuffer(struct gl_framebuffer *fb)
+{
+   XMesaBuffer b = XMESA_BUFFER(fb);
 
+#ifdef XFree86Server
+   int client = 0;
+   if (b->frontxrb->drawable)
+       client = CLIENT_ID(b->frontxrb->drawable->id);
+#endif
 
+   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
+         (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
+      }
+   }
+
+   if (b->gc)
+      XMesaFreeGC(b->xm_visual->display, b->gc);
+   if (b->cleargc)
+      XMesaFreeGC(b->xm_visual->display, b->cleargc);
+   if (b->swapgc)
+      XMesaFreeGC(b->xm_visual->display, b->swapgc);
+
+   if (b->xm_visual->mesa_visual.doubleBufferMode) {
+      /* free back ximage/pixmap/shmregion */
+      if (b->backxrb->ximage) {
+#if defined(USE_XSHM) && !defined(XFree86Server)
+         if (b->shm) {
+            XShmDetach( b->xm_visual->display, &b->shminfo );
+            XDestroyImage( b->backxrb->ximage );
+            shmdt( b->shminfo.shmaddr );
+         }
+         else
+#endif
+            XMesaDestroyImage( b->backxrb->ximage );
+         b->backxrb->ximage = NULL;
+      }
+      if (b->backxrb->pixmap) {
+         XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap );
+         if (b->xm_visual->hpcr_clear_flag) {
+            XMesaFreePixmap( b->xm_visual->display,
+                             b->xm_visual->hpcr_clear_pixmap );
+            XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
+         }
+      }
+   }
+
+   if (b->rowimage) {
+      _mesa_free( b->rowimage->data );
+      b->rowimage->data = NULL;
+      XMesaDestroyImage( b->rowimage );
+   }
+
+   _mesa_free_framebuffer_data(fb);
+   _mesa_free(fb);
+}
diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h
index e332fb5..5516031 100644
--- a/src/mesa/drivers/x11/xmesaP.h
+++ b/src/mesa/drivers/x11/xmesaP.h
@@ -42,6 +42,7 @@
 
 extern _glthread_Mutex _xmesa_lock;
 
+extern XMesaBuffer XMesaBufferList;
 
 /* for PF_8R8G8B24 pixel format */
 typedef struct {
@@ -489,6 +490,12 @@ extern struct xmesa_renderbuffer *
 xmesa_new_renderbuffer(GLcontext *ctx, GLuint name, const GLvisual *visual,
                        GLboolean backBuffer);
 
+extern void
+xmesa_delete_framebuffer(struct gl_framebuffer *fb);
+
+extern XMesaBuffer
+xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis);
+
 extern unsigned long
 xmesa_color_to_pixel( GLcontext *ctx,
                       GLubyte r, GLubyte g, GLubyte b, GLubyte a,
diff-tree f30e8a4bdf8338dc3f8e985a9c91af61a3301990 (from e6a9381f78605072cab52447fce35eaa98c1e75c)
Author: Brian <brian at yutani.localnet.net>
Date:   Mon Feb 26 11:37:52 2007 -0700

    if renderbuffer ptr is null, just return

diff --git a/src/mesa/swrast/s_readpix.c b/src/mesa/swrast/s_readpix.c
index 27f4736..15dc810 100644
--- a/src/mesa/swrast/s_readpix.c
+++ b/src/mesa/swrast/s_readpix.c
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.2
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -54,7 +54,8 @@ read_index_pixels( GLcontext *ctx,
    struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
    GLint i;
 
-   ASSERT(rb);
+   if (!rb)
+      return;
 
    /* width should never be > MAX_WIDTH since we did clipping earlier */
    ASSERT(width <= MAX_WIDTH);
@@ -91,6 +92,9 @@ read_depth_pixels( GLcontext *ctx,
    const GLboolean biasOrScale
       = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
 
+   if (!rb)
+      return;
+
    /* clipping should have been done already */
    ASSERT(x >= 0);
    ASSERT(y >= 0);
@@ -99,8 +103,6 @@ read_depth_pixels( GLcontext *ctx,
    /* width should never be > MAX_WIDTH since we did clipping earlier */
    ASSERT(width <= MAX_WIDTH);
 
-   ASSERT(rb);
-
    if (type == GL_UNSIGNED_SHORT && fb->Visual.depthBits == 16
        && !biasOrScale && !packing->SwapBytes) {
       /* Special case: directly read 16-bit unsigned depth values. */
@@ -171,7 +173,8 @@ read_stencil_pixels( GLcontext *ctx,
    struct gl_renderbuffer *rb = fb->_StencilBuffer;
    GLint j;
 
-   ASSERT(rb);
+   if (!rb)
+      return;
 
    /* width should never be > MAX_WIDTH since we did clipping earlier */
    ASSERT(width <= MAX_WIDTH);
@@ -195,6 +198,7 @@ read_stencil_pixels( GLcontext *ctx,
 /**
  * Optimized glReadPixels for particular pixel formats when pixel
  * scaling, biasing, mapping, etc. are disabled.
+ * \return GL_TRUE if success, GL_FALSE if unable to do the readpixels
  */
 static GLboolean
 fast_read_rgba_pixels( GLcontext *ctx,
@@ -207,6 +211,9 @@ fast_read_rgba_pixels( GLcontext *ctx,
 {
    struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
 
+   if (!rb)
+      return GL_FALSE;
+
    ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
 
    /* clipping should have already been done */
@@ -316,7 +323,8 @@ read_rgba_pixels( GLcontext *ctx,
    struct gl_framebuffer *fb = ctx->ReadBuffer;
    struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
 
-   ASSERT(rb);
+   if (!rb)
+      return;
 
    if (type == GL_FLOAT && ((ctx->Color.ClampReadColor == GL_TRUE) ||
                             (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB &&
@@ -457,8 +465,8 @@ read_depth_stencil_pixels(GLcontext *ctx
    depthRb = ctx->ReadBuffer->_DepthBuffer;
    stencilRb = ctx->ReadBuffer->_StencilBuffer;
 
-   ASSERT(depthRb);
-   ASSERT(stencilRb);
+   if (!depthRb || !stencilRb)
+      return;
 
    depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
    stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
diff-tree e6a9381f78605072cab52447fce35eaa98c1e75c (from 344c3f7379ab4db749e7e8513be9be8fbb9f126c)
Author: Brian <brian at yutani.localnet.net>
Date:   Mon Feb 26 11:37:37 2007 -0700

    Do proper framebuffer refcounting in _mesa_make_current().
    
    Also, added DeletePending field to gl_framebuffer used when a window has been
    deleted, but there still may be rendering contexts attached to the
    gl_framebuffer object.

diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 9b3759b..1245c10 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -95,6 +95,7 @@
 #include "fbobject.h"
 #include "feedback.h"
 #include "fog.h"
+#include "framebuffer.h"
 #include "get.h"
 #include "glthread.h"
 #include "glapioffsets.h"
@@ -1666,6 +1667,8 @@ void
 _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
                     GLframebuffer *readBuffer )
 {
+   GET_CURRENT_CONTEXT(oldCtx);
+
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(newCtx, "_mesa_make_current()\n");
 
@@ -1690,6 +1693,15 @@ _mesa_make_current( GLcontext *newCtx, G
    _glapi_set_context((void *) newCtx);
    ASSERT(_mesa_get_current_context() == newCtx);
 
+   if (oldCtx) {
+      if (oldCtx->WinSysDrawBuffer) {
+         _mesa_dereference_framebuffer(&oldCtx->WinSysDrawBuffer);
+      }
+      if (oldCtx->WinSysReadBuffer) {
+         _mesa_dereference_framebuffer(&oldCtx->WinSysReadBuffer);
+      }
+   }
+         
    if (!newCtx) {
       _glapi_set_dispatch(NULL);  /* none current */
    }
@@ -1703,6 +1715,8 @@ _mesa_make_current( GLcontext *newCtx, G
          ASSERT(readBuffer->Name == 0);
          newCtx->WinSysDrawBuffer = drawBuffer;
          newCtx->WinSysReadBuffer = readBuffer;
+         drawBuffer->RefCount++;
+         readBuffer->RefCount++;
 
          /*
           * Only set the context's Draw/ReadBuffer fields if they're NULL
diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c
index 4651974..d061d22 100644
--- a/src/mesa/main/framebuffer.c
+++ b/src/mesa/main/framebuffer.c
@@ -166,6 +166,8 @@ _mesa_initialize_framebuffer(struct gl_f
 
    _glthread_INIT_MUTEX(fb->Mutex);
 
+   fb->RefCount = 1;
+
    /* save the visual */
    fb->Visual = *visual;
 
@@ -198,7 +200,6 @@ void
 _mesa_destroy_framebuffer(struct gl_framebuffer *fb)
 {
    if (fb) {
-      _glthread_DESTROY_MUTEX(fb->Mutex);
       _mesa_free_framebuffer_data(fb);
       _mesa_free(fb);
    }
@@ -216,6 +217,8 @@ _mesa_free_framebuffer_data(struct gl_fr
 
    assert(fb);
 
+   _glthread_DESTROY_MUTEX(fb->Mutex);
+
    for (i = 0; i < BUFFER_COUNT; i++) {
       struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
       if (att->Renderbuffer) {
@@ -605,21 +608,25 @@ update_color_draw_buffers(GLcontext *ctx
       GLbitfield bufferMask = fb->_ColorDrawBufferMask[output];
       GLuint count = 0;
       GLuint i;
-      /* We need the inner loop here because glDrawBuffer(GL_FRONT_AND_BACK)
-       * can specify writing to two or four color buffers (for example).
-       */
-      for (i = 0; bufferMask && i < BUFFER_COUNT; i++) {
-         const GLuint bufferBit = 1 << i;
-         if (bufferBit & bufferMask) {
-            struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
-            if (rb) {
-               fb->_ColorDrawBuffers[output][count] = rb;
-               count++;
-            }
-            else {
-               /*_mesa_warning(ctx, "DrawBuffer names a missing buffer!\n");*/
+      if (!fb->DeletePending) {
+         /* We need the inner loop here because glDrawBuffer(GL_FRONT_AND_BACK)
+          * can specify writing to two or four color buffers (for example).
+          */
+         for (i = 0; bufferMask && i < BUFFER_COUNT; i++) {
+            const GLuint bufferBit = 1 << i;
+            if (bufferBit & bufferMask) {
+               struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
+               if (rb) {
+                  fb->_ColorDrawBuffers[output][count] = rb;
+                  count++;
+               }
+               else {
+                  /*
+                  _mesa_warning(ctx, "DrawBuffer names a missing buffer!\n");
+                  */
+               }
+               bufferMask &= ~bufferBit;
             }
-            bufferMask &= ~bufferBit;
          }
       }
       fb->_NumColorDrawBuffers[output] = count;
@@ -635,7 +642,7 @@ static void
 update_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
 {
    (void) ctx;
-   if (fb->_ColorReadBufferIndex == -1) {
+   if (fb->_ColorReadBufferIndex == -1 || fb->DeletePending) {
       fb->_ColorReadBuffer = NULL; /* legal! */
    }
    else {
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index e8f0f45..422d176 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2243,6 +2243,7 @@ struct gl_framebuffer
    _glthread_Mutex Mutex;		   /**< for thread safety */
    GLuint Name;      /* if zero, this is a window system framebuffer */
    GLint RefCount;
+   GLboolean DeletePending;
 
    GLvisual Visual;	/**< The framebuffer's visual.
                              Immutable if this is a window system buffer.



More information about the mesa-commit mailing list