On Tue, Sep 8, 2009 at 9:17 AM, Brian Paul <firstname.lastname@example.org>
Dimitar Kodjabachev wrote:mesa3d-dev is OK since there may be a bug in the Mesa wgl code. I'm
> I sent this to mesa3d-dev, which was probably not the right place.
A rendering context is not the same as a drawing surface. So deleting
> I have the following situation (pseudocode) with Mesa 7.4.4:
> hglrc1 = wglCreateContext(hdc1)
> hglrc2 = wglCreateContext(hdc2)
> As a result of this sequence of calls, a WMesaFramebuffer structure is leaked.
> The call causing the leak is wglMakeCurrent(hdc3,hglrc2). This is what I know
> so far:
> -> wglMakeCurrent(hdc3,hglrc2) calls
> -> WMesaMakeCurrent(hglrc2,hdc3) which calls
> -> wmesa_lookup_framebuffer(hdc3) which returns NULL, as the hdc given to
> wglMakeCurrent is different from the one given at the time
> of wglCreateContext
> -> wmesa_new_framebuffer() is called and a new frame buffer is allocated
> This new frame buffer is not released upon wglDeleteContext(hglrc2).
a rendering context does not imply deleting a surface.
My understanding is that the context passed to wglMakeCurrent() must
> As far as
> I know, the device context passed to wglMakeCurrent does not have to
> be the same as the one passed to wglCreateContext as long as the the actual
> device and the pixel formats are. Is this correct or is my usage wrong?
have been created by a call to wglCreateContext().
Right, but there are two contexts passed in wglMakeCurrent(). Here the GL context (rendering context) is hglrc2, created by wglCreateContext(). But the Window context (device context) is hdc3, which is just a Windows Win32 handle.
I don't think I can help with this memory leak. Maybe someone else
who works on Windows can help you.
The problem is that wglMakeCurrent() will lazily allocate the framebuffer when a device context is made current for the first time. The created framebuffer gets added onto a list and is tagged with the device context that it was just associated with. When a rendering context is destroyed, this list is searched for a framebuffer tagged with the device context that is current at the time the rendering context was destroyed, and if found, the framebuffer is freed.
Note that this conflicts with what Brian said above about deleting surfaces. I imagine that this was added to wgl as a way to free the framebuffer *somehow*.
The leak is caused here because the rendering context is associated with two device contexts. A framebuffer is created for each device. Later, when the rendering context is destroyed, only one framebuffer is freed, because only one device context can be current when destroying the rendering context, and only the framebuffer tagged with that device context is freed.
Since destroying a rendering context shouldn't destroy any surfaces, it isn't an option to tag all framebuffers with the rendering context id and then delete all framebuffers tagged that way when a rendering context is destroyed. Although this would fix the leak.
The right way, I think, is to destroy the framebuffer associated with a device context when the device context is destroyed. This might involve hooking Windows somehow to get a notification when it is destroyed or setting up a message handler to get WM_DESTROY messages so that we can free resources associated with the device.
The wgl code hasn't been all that robust or complete, and I don't know right now if this design/approach is even correct. I'd have to dig into this more.
Right now, I don't have much of a workaround to suggest for the current implementation except to try to destroy hglrc2 and recreate it before making current with hdc3.