From 60f25f7d4dc28fab928700891a8e3cdea66d57e2d68187fb21b1aeefa7f4d664 Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Tue, 20 Mar 2007 00:23:54 +0000 Subject: [PATCH] OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/Mesa?expand=0&rev=6 --- Mesa.changes | 7 + Mesa.spec | 34 +- bug-211314-patch-1.diff | 99 ++++ bug-211314-patch-10.diff | 19 + bug-211314-patch-11.diff | 218 ++++++++ bug-211314-patch-2.diff | 594 ++++++++++++++++++++++ bug-211314-patch-3.diff | 29 ++ bug-211314-patch-4.diff | 24 + bug-211314-patch-5.diff | 26 + bug-211314-patch-6.diff | 30 ++ bug-211314-patch-7.diff | 23 + bug-211314-patch-8.diff | 47 ++ bug-211314-patch-9.diff | 20 + bug-211314_mesa-context.diff | 27 - bug-211314_mesa-destroy_buffers.diff | 317 ++++++++++++ bug-211314_mesa-framebuffer-counting.diff | 147 ++++++ 16 files changed, 1631 insertions(+), 30 deletions(-) create mode 100644 bug-211314-patch-1.diff create mode 100644 bug-211314-patch-10.diff create mode 100644 bug-211314-patch-11.diff create mode 100644 bug-211314-patch-2.diff create mode 100644 bug-211314-patch-3.diff create mode 100644 bug-211314-patch-4.diff create mode 100644 bug-211314-patch-5.diff create mode 100644 bug-211314-patch-6.diff create mode 100644 bug-211314-patch-7.diff create mode 100644 bug-211314-patch-8.diff create mode 100644 bug-211314-patch-9.diff delete mode 100644 bug-211314_mesa-context.diff create mode 100644 bug-211314_mesa-destroy_buffers.diff create mode 100644 bug-211314_mesa-framebuffer-counting.diff diff --git a/Mesa.changes b/Mesa.changes index b177e70..d6817c9 100644 --- a/Mesa.changes +++ b/Mesa.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Mon Mar 19 21:42:44 CET 2007 - sndirsch@suse.de + +- no longer apply bug-211314_mesa-context.diff (Bug #211314, + commment #114) +- added different Mesa patches (Bug #211314, comments #114/#115) + ------------------------------------------------------------------- Wed Mar 14 08:12:52 CET 2007 - sndirsch@suse.de diff --git a/Mesa.spec b/Mesa.spec index ec99d56..a67283e 100644 --- a/Mesa.spec +++ b/Mesa.spec @@ -19,7 +19,7 @@ Provides: xorg-x11-Mesa Obsoletes: xorg-x11-Mesa Autoreqprov: on Version: 6.5.2 -Release: 20 +Release: 21 Summary: Mesa is a 3-D graphics library with an API which is very similar to that of OpenGL.* Source: Mesa-%{version}.tar.bz2 Source3: README.updates @@ -29,9 +29,21 @@ Source6: via.sh Patch0: disable-sis_dri.diff Patch1: dri_driver_dir.diff Patch2: i915-crossbar.diff -Patch3: bug-211314_mesa-context.diff Patch4: libIndirectGL.diff Patch5: static.diff +Patch6: bug-211314_mesa-destroy_buffers.diff +Patch7: bug-211314_mesa-framebuffer-counting.diff +Patch8: bug-211314-patch-1.diff +Patch9: bug-211314-patch-2.diff +Patch10: bug-211314-patch-3.diff +Patch11: bug-211314-patch-4.diff +Patch12: bug-211314-patch-5.diff +Patch13: bug-211314-patch-6.diff +Patch14: bug-211314-patch-7.diff +Patch15: bug-211314-patch-8.diff +Patch16: bug-211314-patch-9.diff +Patch17: bug-211314-patch-10.diff +Patch18: bug-211314-patch-11.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -114,8 +126,20 @@ rm -rf src/glw/ %patch0 %patch1 %patch2 -%patch3 %patch5 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 %build @@ -234,6 +258,10 @@ rm -rf $RPM_BUILD_ROOT /usr/%{_lib}/libMesaGL.a %changelog +* Mon Mar 19 2007 - sndirsch@suse.de +- no longer apply bug-211314_mesa-context.diff (Bug #211314, + commment #114) +- added different Mesa patches (Bug #211314, comments #114/#115) * Wed Mar 14 2007 - sndirsch@suse.de - removed libIndirectGL.so (Bug #254317) - README.updates: new location of DRI drivers (Bug #254318) diff --git a/bug-211314-patch-1.diff b/bug-211314-patch-1.diff new file mode 100644 index 0000000..8afc064 --- /dev/null +++ b/bug-211314-patch-1.diff @@ -0,0 +1,99 @@ +commit f30e8a4bdf8338dc3f8e985a9c91af61a3301990 +Author: Brian +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 --git a/bug-211314-patch-10.diff b/bug-211314-patch-10.diff new file mode 100644 index 0000000..ce4b923 --- /dev/null +++ b/bug-211314-patch-10.diff @@ -0,0 +1,19 @@ +commit f04979ae481acc9fdc423da06514c4d557edd7cd +Author: Mathias Hopf +Date: Fri Mar 16 08:28:34 2007 -0600 + + added null xmctx check to XMesaResizeBuffers(), bug 7205 + +diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c +index cbbbd56..ba020fc 100644 +--- a/src/mesa/drivers/x11/xm_api.c ++++ b/src/mesa/drivers/x11/xm_api.c +@@ -2499,6 +2499,8 @@ XMesaResizeBuffers( XMesaBuffer b ) + { + GET_CURRENT_CONTEXT(ctx); + XMesaContext xmctx = XMESA_CONTEXT(ctx); ++ if (!xmctx) ++ return; + xmesa_check_and_update_buffer_size(xmctx, b); + } + diff --git a/bug-211314-patch-11.diff b/bug-211314-patch-11.diff new file mode 100644 index 0000000..d9e31d2 --- /dev/null +++ b/bug-211314-patch-11.diff @@ -0,0 +1,218 @@ +commit e5070bc3ca75dee31034cc543f3d2ee04e5dc032 +Author: Brian +Date: Fri Mar 16 11:00:07 2007 -0600 + + Assorted fixes for dealing with zero-size frame/renderbuffers. + + In xmesa_check_and_update_buffer_size() handle xmctx==NULL correctly: still + call _mesa_resize_framebufer(). If we don't we can wind up in a situation + where the framebuffer size is non-zero but an attached renderbuffer size + is still initialized to zero. This inconsistancy can later cause problems. + Check for zero-size renderbuffers in update_color_draw_buffers() and + update_color_read_buffer(). + See bug 7205. + +diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c +index ba020fc..b513dc8 100644 +--- a/src/mesa/drivers/x11/xm_api.c ++++ b/src/mesa/drivers/x11/xm_api.c +@@ -1842,16 +1842,18 @@ XMesaDestroyBuffer(XMesaBuffer b) + * 1. the first time a buffer is bound to a context. + * 2. from glViewport to poll for window size changes + * 3. from the XMesaResizeBuffers() API function. ++ * Note: it's possible (and legal) for xmctx to be NULL. That can happen ++ * when resizing a buffer when no rendering context is bound. + */ + void + xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) + { + GLuint width, height; +- xmesa_get_window_size(xmctx->display, drawBuffer, &width, &height); ++ xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height); + if (drawBuffer->mesa_buffer.Width != width || + drawBuffer->mesa_buffer.Height != height) { +- _mesa_resize_framebuffer(&(xmctx->mesa), +- &(drawBuffer->mesa_buffer), width, height); ++ GLcontext *ctx = xmctx ? &xmctx->mesa : NULL; ++ _mesa_resize_framebuffer(ctx, &(drawBuffer->mesa_buffer), width, height); + } + drawBuffer->mesa_buffer.Initialized = GL_TRUE; /* XXX TEMPORARY? */ + } +@@ -2175,7 +2177,7 @@ void XMesaSwapBuffers( XMesaBuffer b ) + } + #endif + if (b->backxrb->ximage) { +- /* Copy Ximage from host's memory to server's window */ ++ /* Copy Ximage (back buf) from client memory to server window */ + #if defined(USE_XSHM) && !defined(XFree86Server) + if (b->shm) { + /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ +@@ -2197,8 +2199,8 @@ void XMesaSwapBuffers( XMesaBuffer b ) + /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ + } + } +- else { +- /* Copy pixmap to window on server */ ++ else if (b->backxrb->pixmap) { ++ /* Copy pixmap (back buf) to window (front buf) on server */ + /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ + XMesaCopyArea( b->xm_visual->display, + b->backxrb->pixmap, /* source drawable */ +diff --git a/src/mesa/drivers/x11/xm_buffer.c b/src/mesa/drivers/x11/xm_buffer.c +index 73c46b1..c1fa233 100644 +--- a/src/mesa/drivers/x11/xm_buffer.c ++++ b/src/mesa/drivers/x11/xm_buffer.c +@@ -168,9 +168,6 @@ alloc_back_shm_ximage(XMesaBuffer b, GLu + static void + alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height) + { +- if (width == 0 || height == 0) +- return; +- + if (b->db_mode == BACK_XIMAGE) { + /* Deallocate the old backxrb->ximage, if any */ + if (b->backxrb->ximage) { +@@ -186,6 +183,9 @@ alloc_back_buffer(XMesaBuffer b, GLuint + b->backxrb->ximage = NULL; + } + ++ if (width == 0 || height == 0) ++ return; ++ + /* Allocate new back buffer */ + #ifdef XFree86Server + /* Allocate a regular XImage for the back buffer. */ +@@ -218,20 +218,20 @@ alloc_back_buffer(XMesaBuffer b, GLuint + b->backxrb->pixmap = None; + } + else if (b->db_mode == BACK_PIXMAP) { +- if (!width) +- width = 1; +- if (!height) +- height = 1; +- + /* Free the old back pixmap */ + if (b->backxrb->pixmap) { +- XMesaFreePixmap(b->xm_visual->display, b->backxrb->pixmap); ++ XMesaFreePixmap(b->xm_visual->display, b->backxrb->pixmap); ++ b->backxrb->pixmap = 0; + } +- /* Allocate new back pixmap */ +- b->backxrb->pixmap = XMesaCreatePixmap(b->xm_visual->display, +- b->frontxrb->drawable, +- width, height, +- GET_VISUAL_DEPTH(b->xm_visual)); ++ ++ if (width > 0 && height > 0) { ++ /* Allocate new back pixmap */ ++ b->backxrb->pixmap = XMesaCreatePixmap(b->xm_visual->display, ++ b->frontxrb->drawable, ++ width, height, ++ GET_VISUAL_DEPTH(b->xm_visual)); ++ } ++ + b->backxrb->ximage = NULL; + } + } +@@ -250,6 +250,7 @@ xmesa_delete_renderbuffer(struct gl_rend + + /** + * Reallocate renderbuffer storage for front color buffer. ++ * Called via gl_renderbuffer::AllocStorage() + */ + static GLboolean + xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb, +@@ -260,6 +261,7 @@ xmesa_alloc_front_storage(GLcontext *ctx + /* just clear these to be sure we don't accidentally use them */ + xrb->origin1 = NULL; + xrb->origin2 = NULL; ++ xrb->origin3 = NULL; + xrb->origin4 = NULL; + + /* for the FLIP macro: */ +@@ -275,6 +277,7 @@ xmesa_alloc_front_storage(GLcontext *ctx + + /** + * Reallocate renderbuffer storage for back color buffer. ++ * Called via gl_renderbuffer::AllocStorage() + */ + static GLboolean + xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb, +@@ -309,8 +312,12 @@ xmesa_alloc_back_storage(GLcontext *ctx, + xrb->origin4 = (GLuint *) xrb->ximage->data + xrb->width4 * (height - 1); + } + else { +- /* this assertion will fail if we happend to run out of memory */ +- /*assert(xrb->pixmap);*/ ++ /* out of memory or buffer size is 0 x 0 */ ++ xrb->width1 = xrb->width2 = xrb->width3 = xrb->width4 = 0; ++ xrb->origin1 = NULL; ++ xrb->origin2 = NULL; ++ xrb->origin3 = NULL; ++ xrb->origin4 = NULL; + } + + return GL_TRUE; +diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c +index 3136a95..cd4f594 100644 +--- a/src/mesa/main/framebuffer.c ++++ b/src/mesa/main/framebuffer.c +@@ -647,7 +647,7 @@ update_color_draw_buffers(GLcontext *ctx + const GLuint bufferBit = 1 << i; + if (bufferBit & bufferMask) { + struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; +- if (rb) { ++ if (rb && rb->Width > 0 && rb->Height > 0) { + fb->_ColorDrawBuffers[output][count] = rb; + count++; + } +@@ -673,7 +673,10 @@ static void + update_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb) + { + (void) ctx; +- if (fb->_ColorReadBufferIndex == -1 || fb->DeletePending) { ++ if (fb->_ColorReadBufferIndex == -1 || ++ fb->DeletePending || ++ fb->Width == 0 || ++ fb->Height == 0) { + fb->_ColorReadBuffer = NULL; /* legal! */ + } + else { +diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c +index 1cc95a7..e387c42 100644 +--- a/src/mesa/main/renderbuffer.c ++++ b/src/mesa/main/renderbuffer.c +@@ -1192,18 +1192,22 @@ _mesa_soft_renderbuffer_storage(GLcontex + ASSERT(rb->PutMonoValues); + + /* free old buffer storage */ +- if (rb->Data) ++ if (rb->Data) { + _mesa_free(rb->Data); +- +- /* allocate new buffer storage */ +- rb->Data = _mesa_malloc(width * height * pixelSize); +- if (rb->Data == NULL) { +- rb->Width = 0; +- rb->Height = 0; +- _mesa_error(ctx, GL_OUT_OF_MEMORY, +- "software renderbuffer allocation (%d x %d x %d)", +- width, height, pixelSize); +- return GL_FALSE; ++ rb->Data = NULL; ++ } ++ ++ if (width > 0 && height > 0) { ++ /* allocate new buffer storage */ ++ rb->Data = _mesa_malloc(width * height * pixelSize); ++ if (rb->Data == NULL) { ++ rb->Width = 0; ++ rb->Height = 0; ++ _mesa_error(ctx, GL_OUT_OF_MEMORY, ++ "software renderbuffer allocation (%d x %d x %d)", ++ width, height, pixelSize); ++ return GL_FALSE; ++ } + } + + rb->Width = width; diff --git a/bug-211314-patch-2.diff b/bug-211314-patch-2.diff new file mode 100644 index 0000000..e7aa278 --- /dev/null +++ b/bug-211314-patch-2.diff @@ -0,0 +1,594 @@ +commit a510bc3ee1a696da120c09ee4ec33dc033f671ac +Author: Brian +Date: Tue Mar 6 10:07:59 2007 -0700 + + Fix/improve framebuffer object reference counting. + + Use _mesa_reference_framebuffer() and _mesa_unreference_framebuffer() functions + to be sure reference counting is done correctly. Additional assertions are + done too. Note _mesa_dereference_framebuffer() renamed to "unreference" as + that's more accurate. + +diff --git a/src/mesa/drivers/allegro/amesa.c b/src/mesa/drivers/allegro/amesa.c +index 594668a..518211c 100644 +--- a/src/mesa/drivers/allegro/amesa.c ++++ b/src/mesa/drivers/allegro/amesa.c +@@ -338,7 +338,7 @@ void AMesaDestroyBuffer(AMesaBuffer buff + { + if (buffer->Screen) destroy_bitmap(buffer->Screen); + if (buffer->Background) destroy_bitmap(buffer->Background); +- _mesa_destroy_framebuffer(buffer->GLBuffer); ++ _mesa_unreference_framebuffer(&buffer->GLBuffer); + free(buffer); + } + +diff --git a/src/mesa/drivers/dri/fb/fb_dri.c b/src/mesa/drivers/dri/fb/fb_dri.c +index 08b52b4..a6d7590 100644 +--- a/src/mesa/drivers/dri/fb/fb_dri.c ++++ b/src/mesa/drivers/dri/fb/fb_dri.c +@@ -480,11 +480,7 @@ fbCreateBuffer( __DRIscreenPrivate *driS + static void + fbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- struct gl_framebuffer *mesa_framebuffer = (struct gl_framebuffer *)driDrawPriv->driverPrivate; +- +- _mesa_free(mesa_framebuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer->Data); +- _mesa_destroy_framebuffer(mesa_framebuffer); +- driDrawPriv->driverPrivate = NULL; ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + +diff --git a/src/mesa/drivers/dri/ffb/ffb_xmesa.c b/src/mesa/drivers/dri/ffb/ffb_xmesa.c +index 215aaf8..4c5323d 100644 +--- a/src/mesa/drivers/dri/ffb/ffb_xmesa.c ++++ b/src/mesa/drivers/dri/ffb/ffb_xmesa.c +@@ -392,7 +392,7 @@ ffbCreateBuffer(__DRIscreenPrivate *driS + static void + ffbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + +diff --git a/src/mesa/drivers/dri/gamma/gamma_xmesa.c b/src/mesa/drivers/dri/gamma/gamma_xmesa.c +index e8922b1..f41682c 100644 +--- a/src/mesa/drivers/dri/gamma/gamma_xmesa.c ++++ b/src/mesa/drivers/dri/gamma/gamma_xmesa.c +@@ -97,7 +97,7 @@ gammaCreateBuffer( __DRIscreenPrivate *d + static void + gammaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + static void +diff --git a/src/mesa/drivers/dri/mach64/mach64_screen.c b/src/mesa/drivers/dri/mach64/mach64_screen.c +index 1014b8a..4e9e216 100644 +--- a/src/mesa/drivers/dri/mach64/mach64_screen.c ++++ b/src/mesa/drivers/dri/mach64/mach64_screen.c +@@ -435,7 +435,7 @@ mach64CreateBuffer( __DRIscreenPrivate * + static void + mach64DestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + +diff --git a/src/mesa/drivers/dri/mga/mga_xmesa.c b/src/mesa/drivers/dri/mga/mga_xmesa.c +index f024f73..67a6f8b 100644 +--- a/src/mesa/drivers/dri/mga/mga_xmesa.c ++++ b/src/mesa/drivers/dri/mga/mga_xmesa.c +@@ -831,7 +831,7 @@ mgaCreateBuffer( __DRIscreenPrivate *dri + static void + mgaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + static void +diff --git a/src/mesa/drivers/dri/r128/r128_screen.c b/src/mesa/drivers/dri/r128/r128_screen.c +index 4f1b20a..880dee8 100644 +--- a/src/mesa/drivers/dri/r128/r128_screen.c ++++ b/src/mesa/drivers/dri/r128/r128_screen.c +@@ -357,7 +357,7 @@ r128CreateBuffer( __DRIscreenPrivate *dr + static void + r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + +diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c +index fc5aa11..abb14fa 100644 +--- a/src/mesa/drivers/dri/radeon/radeon_screen.c ++++ b/src/mesa/drivers/dri/radeon/radeon_screen.c +@@ -901,7 +901,7 @@ radeonCreateBuffer( __DRIscreenPrivate * + static void + radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + #if RADEON_COMMON && defined(RADEON_COMMON_FOR_R300) +diff --git a/src/mesa/drivers/dri/s3v/s3v_xmesa.c b/src/mesa/drivers/dri/s3v/s3v_xmesa.c +index c451f74..c66fd6d 100644 +--- a/src/mesa/drivers/dri/s3v/s3v_xmesa.c ++++ b/src/mesa/drivers/dri/s3v/s3v_xmesa.c +@@ -131,7 +131,7 @@ s3vCreateBuffer( __DRIscreenPrivate *dri + static void + s3vDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + static void +diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c +index ad79b92..f859217 100644 +--- a/src/mesa/drivers/dri/savage/savage_xmesa.c ++++ b/src/mesa/drivers/dri/savage/savage_xmesa.c +@@ -710,7 +710,7 @@ savageCreateBuffer( __DRIscreenPrivate * + static void + savageDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + #if 0 +diff --git a/src/mesa/drivers/dri/sis/sis_screen.c b/src/mesa/drivers/dri/sis/sis_screen.c +index 8f52cfe..89d734b 100644 +--- a/src/mesa/drivers/dri/sis/sis_screen.c ++++ b/src/mesa/drivers/dri/sis/sis_screen.c +@@ -233,7 +233,7 @@ sisCreateBuffer( __DRIscreenPrivate *dri + static void + sisDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + static void sisCopyBuffer( __DRIdrawablePrivate *dPriv ) +diff --git a/src/mesa/drivers/dri/tdfx/tdfx_screen.c b/src/mesa/drivers/dri/tdfx/tdfx_screen.c +index 646f512..1f9ff4e 100644 +--- a/src/mesa/drivers/dri/tdfx/tdfx_screen.c ++++ b/src/mesa/drivers/dri/tdfx/tdfx_screen.c +@@ -233,7 +233,7 @@ tdfxCreateBuffer( __DRIscreenPrivate *dr + static void + tdfxDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + +diff --git a/src/mesa/drivers/dri/trident/trident_context.c b/src/mesa/drivers/dri/trident/trident_context.c +index dbbd1ac..8dc7f0d 100644 +--- a/src/mesa/drivers/dri/trident/trident_context.c ++++ b/src/mesa/drivers/dri/trident/trident_context.c +@@ -279,7 +279,7 @@ tridentCreateBuffer( __DRIscreenPrivate + static void + tridentDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + static void +diff --git a/src/mesa/drivers/dri/unichrome/via_screen.c b/src/mesa/drivers/dri/unichrome/via_screen.c +index 28e1f94..90f76be 100644 +--- a/src/mesa/drivers/dri/unichrome/via_screen.c ++++ b/src/mesa/drivers/dri/unichrome/via_screen.c +@@ -320,7 +320,7 @@ viaCreateBuffer(__DRIscreenPrivate *driS + static void + viaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) + { +- _mesa_destroy_framebuffer((GLframebuffer *)(driDrawPriv->driverPrivate)); ++ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); + } + + +diff --git a/src/mesa/drivers/glide/fxapi.c b/src/mesa/drivers/glide/fxapi.c +index e535e73..00b9d29 100644 +--- a/src/mesa/drivers/glide/fxapi.c ++++ b/src/mesa/drivers/glide/fxapi.c +@@ -728,7 +728,7 @@ errorhandler: + FREE(fxMesa->fogTable); + } + if (fxMesa->glBuffer) { +- _mesa_destroy_framebuffer(fxMesa->glBuffer); ++ _mesa_unreference_framebuffer(&fxMesa->glBuffer); + } + if (fxMesa->glVis) { + _mesa_destroy_visual(fxMesa->glVis); +@@ -828,7 +828,7 @@ fxMesaDestroyContext(fxMesaContext fxMes + fxDDDestroyFxMesaContext(fxMesa); /* must be before _mesa_destroy_context */ + _mesa_destroy_visual(fxMesa->glVis); + _mesa_destroy_context(fxMesa->glCtx); +- _mesa_destroy_framebuffer(fxMesa->glBuffer); ++ _mesa_unreference_framebuffer(&fxMesa->glBuffer); + fxTMClose(fxMesa); /* must be after _mesa_destroy_context */ + + FREE(fxMesa); +diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c +index c4fc882..96b9b5c 100644 +--- a/src/mesa/drivers/osmesa/osmesa.c ++++ b/src/mesa/drivers/osmesa/osmesa.c +@@ -1303,7 +1303,8 @@ OSMesaDestroyContext( OSMesaContext osme + _swrast_DestroyContext( &osmesa->mesa ); + + _mesa_destroy_visual( osmesa->gl_visual ); +- _mesa_destroy_framebuffer( osmesa->gl_buffer ); ++ _mesa_unreference_framebuffer( &osmesa->gl_buffer ); ++ + _mesa_free_context_data( &osmesa->mesa ); + _mesa_free( osmesa ); + } +diff --git a/src/mesa/drivers/svga/svgamesa.c b/src/mesa/drivers/svga/svgamesa.c +index 0dd9a14..d138587 100644 +--- a/src/mesa/drivers/svga/svgamesa.c ++++ b/src/mesa/drivers/svga/svgamesa.c +@@ -433,7 +433,6 @@ void SVGAMesaDestroyContext( SVGAMesaCon + if (ctx) { + _mesa_destroy_visual( ctx->gl_vis ); + _mesa_destroy_context( ctx->gl_ctx ); +- _mesa_destroy_framebuffer( ctx->gl_buffer ); + free( ctx ); + if (ctx==SVGAMesa) { + SVGAMesa = NULL; +diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c +index 2cd7d8a..a42de72 100644 +--- a/src/mesa/drivers/x11/xm_api.c ++++ b/src/mesa/drivers/x11/xm_api.c +@@ -485,8 +485,8 @@ xmesa_free_buffer(XMesaBuffer buffer) + + /* mark as delete pending */ + fb->DeletePending = GL_TRUE; +- /* Dereference. If count = zero we'll really delete the buffer */ +- _mesa_dereference_framebuffer(&fb); ++ /* Unreference. If count = zero we'll really delete the buffer */ ++ _mesa_unreference_framebuffer(&fb); + + return; + } +diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c +index 1245c10..135c814 100644 +--- a/src/mesa/main/context.c ++++ b/src/mesa/main/context.c +@@ -1408,6 +1408,13 @@ _mesa_free_context_data( GLcontext *ctx + if (ctx == _mesa_get_current_context()) { + _mesa_make_current(NULL, NULL, NULL); + } ++ else { ++ /* unreference WinSysDraw/Read buffers */ ++ _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer); ++ _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer); ++ _mesa_unreference_framebuffer(&ctx->DrawBuffer); ++ _mesa_unreference_framebuffer(&ctx->ReadBuffer); ++ } + + _mesa_free_lighting_data( ctx ); + _mesa_free_eval_data( ctx ); +@@ -1694,12 +1701,8 @@ _mesa_make_current( GLcontext *newCtx, G + ASSERT(_mesa_get_current_context() == newCtx); + + if (oldCtx) { +- if (oldCtx->WinSysDrawBuffer) { +- _mesa_dereference_framebuffer(&oldCtx->WinSysDrawBuffer); +- } +- if (oldCtx->WinSysReadBuffer) { +- _mesa_dereference_framebuffer(&oldCtx->WinSysReadBuffer); +- } ++ _mesa_unreference_framebuffer(&oldCtx->WinSysDrawBuffer); ++ _mesa_unreference_framebuffer(&oldCtx->WinSysReadBuffer); + } + + if (!newCtx) { +@@ -1713,20 +1716,18 @@ _mesa_make_current( GLcontext *newCtx, G + + ASSERT(drawBuffer->Name == 0); + ASSERT(readBuffer->Name == 0); +- newCtx->WinSysDrawBuffer = drawBuffer; +- newCtx->WinSysReadBuffer = readBuffer; +- drawBuffer->RefCount++; +- readBuffer->RefCount++; ++ _mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer); ++ _mesa_reference_framebuffer(&newCtx->WinSysReadBuffer, readBuffer); + + /* + * Only set the context's Draw/ReadBuffer fields if they're NULL + * or not bound to a user-created FBO. + */ + if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) { +- newCtx->DrawBuffer = drawBuffer; ++ _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer); + } + if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { +- newCtx->ReadBuffer = readBuffer; ++ _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); + } + + newCtx->NewState |= _NEW_BUFFERS; +diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c +index a99ff9d..6608eef 100644 +--- a/src/mesa/main/fbobject.c ++++ b/src/mesa/main/fbobject.c +@@ -602,7 +602,7 @@ _mesa_BindRenderbufferEXT(GLenum target, + + oldRb = ctx->CurrentRenderbuffer; + if (oldRb) { +- _mesa_dereference_renderbuffer(&oldRb); ++ _mesa_unreference_renderbuffer(&oldRb); + } + + ASSERT(newRb != &DummyRenderbuffer); +@@ -639,7 +639,7 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, + /* But the object will not be freed until it's no longer + * bound in any context. + */ +- _mesa_dereference_renderbuffer(&rb); ++ _mesa_unreference_renderbuffer(&rb); + } + } + } +@@ -998,12 +998,6 @@ _mesa_BindFramebufferEXT(GLenum target, + } + _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb); + } +- _glthread_LOCK_MUTEX(newFb->Mutex); +- if (bindReadBuf) +- newFb->RefCount++; +- if (bindDrawBuf) +- newFb->RefCount++; +- _glthread_UNLOCK_MUTEX(newFb->Mutex); + } + else { + /* Binding the window system framebuffer (which was originally set +@@ -1020,22 +1014,16 @@ _mesa_BindFramebufferEXT(GLenum target, + */ + + if (bindReadBuf) { +- oldFb = ctx->ReadBuffer; +- if (oldFb && oldFb->Name != 0) { +- _mesa_dereference_framebuffer(&oldFb); +- } +- ctx->ReadBuffer = newFb; ++ _mesa_unreference_framebuffer(&ctx->ReadBuffer); ++ _mesa_reference_framebuffer(&ctx->ReadBuffer, newFb); + } + + if (bindDrawBuf) { +- oldFb = ctx->DrawBuffer; +- if (oldFb && oldFb->Name != 0) { +- /* check if old FB had any texture attachments */ +- check_end_texture_render(ctx, oldFb); +- /* check if time to delete this framebuffer */ +- _mesa_dereference_framebuffer(&oldFb); +- } +- ctx->DrawBuffer = newFb; ++ /* check if old FB had any texture attachments */ ++ check_end_texture_render(ctx, ctx->DrawBuffer); ++ /* check if time to delete this framebuffer */ ++ _mesa_unreference_framebuffer(&ctx->DrawBuffer); ++ _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb); + if (newFb->Name != 0) { + /* check if newly bound framebuffer has any texture attachments */ + check_begin_texture_render(ctx, newFb); +@@ -1083,7 +1071,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, c + /* But the object will not be freed until it's no longer + * bound in any context. + */ +- _mesa_dereference_framebuffer(&fb); ++ _mesa_unreference_framebuffer(&fb); + } + } + } +diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c +index dabc96d..c97d2f0 100644 +--- a/src/mesa/main/framebuffer.c ++++ b/src/mesa/main/framebuffer.c +@@ -78,7 +78,7 @@ set_depth_renderbuffer(struct gl_framebu + struct gl_renderbuffer *rb) + { + if (fb->_DepthBuffer) { +- _mesa_dereference_renderbuffer(&fb->_DepthBuffer); ++ _mesa_unreference_renderbuffer(&fb->_DepthBuffer); + } + fb->_DepthBuffer = rb; + if (rb) { +@@ -96,7 +96,7 @@ set_stencil_renderbuffer(struct gl_frame + struct gl_renderbuffer *rb) + { + if (fb->_StencilBuffer) { +- _mesa_dereference_renderbuffer(&fb->_StencilBuffer); ++ _mesa_unreference_renderbuffer(&fb->_StencilBuffer); + } + fb->_StencilBuffer = rb; + if (rb) { +@@ -223,13 +223,7 @@ _mesa_free_framebuffer_data(struct gl_fr + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; + if (att->Renderbuffer) { +- struct gl_renderbuffer *rb = att->Renderbuffer; +- /* remove framebuffer's reference to renderbuffer */ +- _mesa_dereference_renderbuffer(&rb); +- if (rb && rb->Name == 0) { +- /* delete window system renderbuffer */ +- _mesa_dereference_renderbuffer(&rb); +- } ++ _mesa_unreference_renderbuffer(&att->Renderbuffer); + } + if (att->Texture) { + /* render to texture */ +@@ -236,6 +236,5 @@ _mesa_free_framebuffer_data(struct gl_fr + } + } + att->Type = GL_NONE; +- att->Renderbuffer = NULL; + } + +@@ -247,25 +246,44 @@ _mesa_free_framebuffer_data(struct gl_fr + + + /** +- * Decrement the reference count on a framebuffer and delete it when ++ * Set *ptr to point to fb, with refcounting and locking. ++ */ ++void ++_mesa_reference_framebuffer(struct gl_framebuffer **ptr, ++ struct gl_framebuffer *fb) ++{ ++ assert(ptr); ++ assert(!*ptr); ++ assert(fb); ++ _glthread_LOCK_MUTEX(fb->Mutex); ++ fb->RefCount++; ++ _glthread_UNLOCK_MUTEX(fb->Mutex); ++ *ptr = fb; ++} ++ ++ ++/** ++ * Undo/remove a reference to a framebuffer object. ++ * Decrement the framebuffer object's reference count and delete it when + * the refcount hits zero. +- * Note: we pass the address of a pointer and set it to NULL if we delete it. ++ * Note: we pass the address of a pointer and set it to NULL. + */ + void +-_mesa_dereference_framebuffer(struct gl_framebuffer **fb) ++_mesa_unreference_framebuffer(struct gl_framebuffer **fb) + { +- GLboolean deleteFlag = GL_FALSE; ++ assert(fb); ++ if (*fb) { ++ GLboolean deleteFlag = GL_FALSE; + +- _glthread_LOCK_MUTEX((*fb)->Mutex); +- { ++ _glthread_LOCK_MUTEX((*fb)->Mutex); + ASSERT((*fb)->RefCount > 0); + (*fb)->RefCount--; + deleteFlag = ((*fb)->RefCount == 0); +- } +- _glthread_UNLOCK_MUTEX((*fb)->Mutex); ++ _glthread_UNLOCK_MUTEX((*fb)->Mutex); ++ ++ if (deleteFlag) ++ (*fb)->Delete(*fb); + +- if (deleteFlag) { +- (*fb)->Delete(*fb); + *fb = NULL; + } + } +diff --git a/src/mesa/main/framebuffer.h b/src/mesa/main/framebuffer.h +index 7f3254f..4d76f3a 100644 +--- a/src/mesa/main/framebuffer.h ++++ b/src/mesa/main/framebuffer.h +@@ -43,7 +43,11 @@ extern void + _mesa_free_framebuffer_data(struct gl_framebuffer *buffer); + + extern void +-_mesa_dereference_framebuffer(struct gl_framebuffer **fb); ++_mesa_reference_framebuffer(struct gl_framebuffer **ptr, ++ struct gl_framebuffer *fb); ++ ++extern void ++_mesa_unreference_framebuffer(struct gl_framebuffer **fb); + + extern void + _mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb, +diff --git a/src/mesa/main/rbadaptors.c b/src/mesa/main/rbadaptors.c +index 313c8d4..60f4948 100644 +--- a/src/mesa/main/rbadaptors.c ++++ b/src/mesa/main/rbadaptors.c +@@ -1,8 +1,8 @@ + /* + * Mesa 3-D graphics library +- * Version: 6.5.1 ++ * 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"), +@@ -45,7 +45,7 @@ Delete_wrapper(struct gl_renderbuffer *r + /* Decrement reference count on the buffer we're wrapping and delete + * it if refcount hits zero. + */ +- _mesa_dereference_renderbuffer(&rb->Wrapped); ++ _mesa_unreference_renderbuffer(&rb->Wrapped); + + /* delete myself */ + _mesa_delete_renderbuffer(rb); +diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c +index 6b18d60..1cc95a7 100644 +--- a/src/mesa/main/renderbuffer.c ++++ b/src/mesa/main/renderbuffer.c +@@ -2089,32 +2089,33 @@ _mesa_remove_renderbuffer(struct gl_fram + if (!rb) + return; + +- _mesa_dereference_renderbuffer(&rb); ++ _mesa_unreference_renderbuffer(&rb); + + fb->Attachment[bufferName].Renderbuffer = NULL; + } + + + /** +- * Decrement the reference count on a renderbuffer and delete it when ++ * Decrement a renderbuffer object's reference count and delete it when + * the refcount hits zero. +- * Note: we pass the address of a pointer and set it to NULL if we delete it. ++ * Note: we pass the address of a pointer. + */ + void +-_mesa_dereference_renderbuffer(struct gl_renderbuffer **rb) ++_mesa_unreference_renderbuffer(struct gl_renderbuffer **rb) + { +- GLboolean deleteFlag = GL_FALSE; ++ assert(rb); ++ if (*rb) { ++ GLboolean deleteFlag = GL_FALSE; + +- _glthread_LOCK_MUTEX((*rb)->Mutex); +- { ++ _glthread_LOCK_MUTEX((*rb)->Mutex); + ASSERT((*rb)->RefCount > 0); + (*rb)->RefCount--; + deleteFlag = ((*rb)->RefCount == 0); +- } +- _glthread_UNLOCK_MUTEX((*rb)->Mutex); ++ _glthread_UNLOCK_MUTEX((*rb)->Mutex); ++ ++ if (deleteFlag) ++ (*rb)->Delete(*rb); + +- if (deleteFlag) { +- (*rb)->Delete(*rb); + *rb = NULL; + } + } +diff --git a/src/mesa/main/renderbuffer.h b/src/mesa/main/renderbuffer.h +index 74ca43c..e1a0a55 100644 +--- a/src/mesa/main/renderbuffer.h ++++ b/src/mesa/main/renderbuffer.h +@@ -99,7 +99,7 @@ extern void + _mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName); + + extern void +-_mesa_dereference_renderbuffer(struct gl_renderbuffer **rb); ++_mesa_unreference_renderbuffer(struct gl_renderbuffer **rb); + + extern struct gl_renderbuffer * + _mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name); diff --git a/bug-211314-patch-3.diff b/bug-211314-patch-3.diff new file mode 100644 index 0000000..2d94bef --- /dev/null +++ b/bug-211314-patch-3.diff @@ -0,0 +1,29 @@ +commit 955906aa647d0d233b422c979e1ee81dc32abb87 +Author: Brian +Date: Tue Mar 6 16:25:07 2007 -0700 + + fix renderbuffer mem leak + +diff --git a/src/mesa/drivers/x11/xm_buffer.c b/src/mesa/drivers/x11/xm_buffer.c +index a358ec2..747971a 100644 +--- a/src/mesa/drivers/x11/xm_buffer.c ++++ b/src/mesa/drivers/x11/xm_buffer.c +@@ -418,6 +418,18 @@ xmesa_delete_framebuffer(struct gl_frame + XMesaDestroyImage( b->rowimage ); + } + ++ /* Note that XMesaBuffer renderbuffers normally have a refcount of 2 ++ * (creation + binding) so we need to explicitly delete/unbind them here. ++ */ ++ if (b->frontxrb) { ++ _mesa_unreference_renderbuffer((struct gl_renderbuffer **) &b->frontxrb); ++ ASSERT(b->frontxrb == NULL); ++ } ++ if (b->backxrb) { ++ _mesa_unreference_renderbuffer((struct gl_renderbuffer **) &b->backxrb); ++ ASSERT(b->backxrb == NULL); ++ } ++ + _mesa_free_framebuffer_data(fb); + _mesa_free(fb); + } diff --git a/bug-211314-patch-4.diff b/bug-211314-patch-4.diff new file mode 100644 index 0000000..3409320 --- /dev/null +++ b/bug-211314-patch-4.diff @@ -0,0 +1,24 @@ +commit 1a6baf092b4c31d5fd30c934f1a17d69c9689f12 +Author: Brian +Date: Tue Mar 6 16:26:02 2007 -0700 + + unreference old framebuffer, if needed, in _mesa_reference_framebuffer() + +diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c +index c97d2f0..3136a95 100644 +--- a/src/mesa/main/framebuffer.c ++++ b/src/mesa/main/framebuffer.c +@@ -253,6 +253,13 @@ _mesa_reference_framebuffer(struct gl_fr + struct gl_framebuffer *fb) + { + assert(ptr); ++ if (*ptr == fb) { ++ /* no change */ ++ return; ++ } ++ if (*ptr) { ++ _mesa_unreference_framebuffer(ptr); ++ } + assert(!*ptr); + assert(fb); + _glthread_LOCK_MUTEX(fb->Mutex); diff --git a/bug-211314-patch-5.diff b/bug-211314-patch-5.diff new file mode 100644 index 0000000..6a38ae4 --- /dev/null +++ b/bug-211314-patch-5.diff @@ -0,0 +1,26 @@ +commit e69da9d02ecdf47d930276783f8b8df1a3cd99dd +Author: Brian +Date: Tue Mar 6 16:26:22 2007 -0700 + + explicit calls to _mesa_unreference_framebuffer() not always needed now + +diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c +index 6608eef..f7e870b 100644 +--- a/src/mesa/main/fbobject.c ++++ b/src/mesa/main/fbobject.c +@@ -1014,7 +1014,6 @@ _mesa_BindFramebufferEXT(GLenum target, + */ + + if (bindReadBuf) { +- _mesa_unreference_framebuffer(&ctx->ReadBuffer); + _mesa_reference_framebuffer(&ctx->ReadBuffer, newFb); + } + +@@ -1022,7 +1021,6 @@ _mesa_BindFramebufferEXT(GLenum target, + /* check if old FB had any texture attachments */ + check_end_texture_render(ctx, ctx->DrawBuffer); + /* check if time to delete this framebuffer */ +- _mesa_unreference_framebuffer(&ctx->DrawBuffer); + _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb); + if (newFb->Name != 0) { + /* check if newly bound framebuffer has any texture attachments */ diff --git a/bug-211314-patch-6.diff b/bug-211314-patch-6.diff new file mode 100644 index 0000000..bcbbd9a --- /dev/null +++ b/bug-211314-patch-6.diff @@ -0,0 +1,30 @@ +commit 47e0b606a85059ff29fe311dc2f1bcafdefe4cdb +Author: Brian +Date: Wed Mar 14 12:42:30 2007 -0600 + + move CLIENT_ID code in xmesa_delete_framebuffer(), see bug 7205 + +diff --git a/src/mesa/drivers/x11/xm_buffer.c b/src/mesa/drivers/x11/xm_buffer.c +index 747971a..73c46b1 100644 +--- a/src/mesa/drivers/x11/xm_buffer.c ++++ b/src/mesa/drivers/x11/xm_buffer.c +@@ -362,16 +362,13 @@ xmesa_delete_framebuffer(struct gl_frame + { + 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 ++ 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 diff --git a/bug-211314-patch-7.diff b/bug-211314-patch-7.diff new file mode 100644 index 0000000..b83696e --- /dev/null +++ b/bug-211314-patch-7.diff @@ -0,0 +1,23 @@ +commit 3049946fa742b654afa9b24f8bc79f387f01aea9 +Author: Brian +Date: Wed Mar 14 12:52:53 2007 -0600 + + clear the b->frontxrb->drawable field in xmesa_free_buffer(), see bug 7205 + +diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c +index 776928d..cbbbd56 100644 +--- a/src/mesa/drivers/x11/xm_api.c ++++ b/src/mesa/drivers/x11/xm_api.c +@@ -483,6 +483,12 @@ xmesa_free_buffer(XMesaBuffer buffer) + + /* mark as delete pending */ + fb->DeletePending = GL_TRUE; ++ ++ /* Since the X window for the XMesaBuffer is going away, we don't ++ * want to dereference this pointer in the future. ++ */ ++ b->frontxrb->drawable = 0; ++ + /* Unreference. If count = zero we'll really delete the buffer */ + _mesa_unreference_framebuffer(&fb); + diff --git a/bug-211314-patch-8.diff b/bug-211314-patch-8.diff new file mode 100644 index 0000000..d21e413 --- /dev/null +++ b/bug-211314-patch-8.diff @@ -0,0 +1,47 @@ +commit 038e981cacdc6f32588442666cde8a8fc16cfdfc +Author: Brian +Date: Thu Mar 15 11:11:41 2007 -0600 + + add some rb->Data null ptr checks (bug 7205) + +diff --git a/src/mesa/swrast/s_accum.c b/src/mesa/swrast/s_accum.c +index 69e9404..f53e7f5 100644 +--- a/src/mesa/swrast/s_accum.c ++++ b/src/mesa/swrast/s_accum.c +@@ -136,7 +136,9 @@ _swrast_clear_accum_buffer( GLcontext *c + return; + } + +- assert(rb); ++ if (!rb || !rb->Data) ++ return; ++ + assert(rb->_BaseFormat == GL_RGBA); + /* add other types in future? */ + assert(rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT); +diff --git a/src/mesa/swrast/s_depth.c b/src/mesa/swrast/s_depth.c +index 408174c..dde2b1d 100644 +--- a/src/mesa/swrast/s_depth.c ++++ b/src/mesa/swrast/s_depth.c +@@ -1350,7 +1350,7 @@ _swrast_clear_depth_buffer( GLcontext *c + GLuint clearValue; + GLint x, y, width, height; + +- if (!rb || !ctx->Depth.Mask) { ++ if (!rb || !ctx->Depth.Mask || !rb->Data) { + /* no depth buffer, or writing to it is disabled */ + return; + } +diff --git a/src/mesa/swrast/s_stencil.c b/src/mesa/swrast/s_stencil.c +index a8aa1d4..43475c0 100644 +--- a/src/mesa/swrast/s_stencil.c ++++ b/src/mesa/swrast/s_stencil.c +@@ -1154,7 +1154,7 @@ _swrast_clear_stencil_buffer( GLcontext + const GLuint stencilMax = (1 << stencilBits) - 1; + GLint x, y, width, height; + +- if (!rb || mask == 0) ++ if (!rb || mask == 0 || !rb->Data) + return; + + ASSERT(rb->DataType == GL_UNSIGNED_BYTE || diff --git a/bug-211314-patch-9.diff b/bug-211314-patch-9.diff new file mode 100644 index 0000000..28d4dc2 --- /dev/null +++ b/bug-211314-patch-9.diff @@ -0,0 +1,20 @@ +commit 4d2eb637a20e4fdf5d5f6c0ea4d4627894594661 +Author: Brian +Date: Thu Mar 15 11:16:41 2007 -0600 + + no-op clear if buffer width or height is zero (bug 7205) + +diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c +index 0e3ed15..11bd173 100644 +--- a/src/mesa/main/buffers.c ++++ b/src/mesa/main/buffers.c +@@ -140,6 +140,9 @@ _mesa_Clear( GLbitfield mask ) + return; + } + ++ if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0) ++ return; ++ + if (ctx->RenderMode == GL_RENDER) { + GLbitfield bufferMask; + diff --git a/bug-211314_mesa-context.diff b/bug-211314_mesa-context.diff deleted file mode 100644 index 3d6c94e..0000000 --- a/bug-211314_mesa-context.diff +++ /dev/null @@ -1,27 +0,0 @@ ---- src/mesa/drivers/x11/xm_api.c.orig 2006-11-30 20:45:42.000000000 +0100 -+++ src/mesa/drivers/x11/xm_api.c 2006-11-30 20:47:12.000000000 +0100 -@@ -2101,7 +2101,11 @@ static void FXgetImage( XMesaBuffer b ) - static unsigned short pixbuf[MAX_WIDTH]; - GLuint x, y; - GLuint width, height; -- XMesaContext xmesa = XMESA_CONTEXT(ctx); -+ XMesaContext xmesa; -+ -+ if (! ctx) -+ return; -+ xmesa = XMESA_CONTEXT(ctx); - - #ifdef XFree86Server - x = b->frontxrb->pixmap->x; -@@ -2535,7 +2539,9 @@ void - XMesaResizeBuffers( XMesaBuffer b ) - { - GET_CURRENT_CONTEXT(ctx); -- XMesaContext xmctx = XMESA_CONTEXT(ctx); -- xmesa_check_and_update_buffer_size(xmctx, b); -+ if (ctx) { -+ XMesaContext xmctx = XMESA_CONTEXT(ctx); -+ xmesa_check_and_update_buffer_size(xmctx, b); -+ } - } - diff --git a/bug-211314_mesa-destroy_buffers.diff b/bug-211314_mesa-destroy_buffers.diff new file mode 100644 index 0000000..e1c17b3 --- /dev/null +++ b/bug-211314_mesa-destroy_buffers.diff @@ -0,0 +1,317 @@ +commit 928a70e4354d4884e2918ec67ddc6d8baf942c8a +Author: Brian +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 --git a/bug-211314_mesa-framebuffer-counting.diff b/bug-211314_mesa-framebuffer-counting.diff new file mode 100644 index 0000000..ef80c39 --- /dev/null +++ b/bug-211314_mesa-framebuffer-counting.diff @@ -0,0 +1,147 @@ +commit e6a9381f78605072cab52447fce35eaa98c1e75c +Author: Brian +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.