318 lines
9.8 KiB
Diff
318 lines
9.8 KiB
Diff
|
commit 928a70e4354d4884e2918ec67ddc6d8baf942c8a
|
||
|
Author: Brian <brian@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,
|