wglMakeCurrent(hdc,hrc) fail if called within OnDestroy()

Hi

In my MDI application, when close a view, I select context in order to destroy lists… before destroy context. (like this sample http://www.codeguru.com/Cpp/G-M/opengl/article.php/c2689 )

This work perfecty on Nvidia card, but on ATI wglMakeCurrent() return FALSE :frowning:

any ideas ?

thanks

void CMyView::OnDestroy()
{

if (!wglMakeCurrent(m_pCDC->GetSafeHdc(), m_hRC)
{
// Fail !!!
}

glDeleteLists(…

wglDeleteContext(m_hRC);
}

You should do it just before calling DestroyWindow. If you don’t call DestroyWindow explicitly, the OnClose handler is the right place to do it.

Rationale: when receiving the WM_DESTROY message, according to MSDN, the window has already been “removed from the screen”, which I take to mean that the device context is already invalidated, hence the GL context is either just as dead as the dc or “dangling”.

Almost the same issue (minus MFC) has been discussed in a bit more detail in the advanced forum a couple of months ago IIRC. You should be able to dig it up with a quick forum search.

Just out of curiosity, are you setting the CS_OWNDC class style bit for your view?

I’m interested to see this issue resolved myself. I’ve developed a fair number of apps with MFC, and have never experienced this problem before on NVIDIA hardware.

The thing is, during WM_DESTROY, I can GetDC() and retrieve the window’s own DC, leading me to believe that my window is still valid in that respect.

Anyway, I’ve found that the CS_OWNDC bit can eliminate a few problems under MFC, and windows in general.

Hi

Yes my class view have already CS_OWNDC bit :frowning:

But i thing it’s not a invalid dc problem : I try wglMakeCurrent(NULL, NULL) and it return FALSE too !

I need this context to call glDeleteLists ( I think it need selected context ) …
but if i just call wglDeleteContext(hrc), are lists and texture destroy automaticaly ?

I made a post about this in the advanced forum not too long ago.
wglMakeCurrent fails on ATI but not Nvidia, but in principal I think it should work.

I moved the code to WM_CLOSE handler.

Hmmm … what does GetLastError() tell you? Have you tried other WGL calls, such as wglGetCurrentDC or wglGetCurrentContext? Do any GL calls succeed?

Perhaps, in yielding to an irresistable sense of inevitability, the ATI driver hooks the app’s window proc and deletes the context on WM_DESTROY. I’m not a driver writer, and I’m not entirely certain this is even possible, but if by some twist of fate this is the reason, then I presume the driver would free all the context’s resources (if it’s not shared, or it’s the last in a shared list-space). In this case, the problem could be attributed to an undisclosed “feature” of the driver.

if it is returning false, its because when you get the destroy message, all that stuff has been lost when the window was destroyed, it may or may not have been freed though

always call wglmakecurrent(hdc,NULL)
before the window closes
if you dont have a hrc, you cant dlete list or textures, so that probably oesnt work either, make this happen before the window closes, and call makecurrent(NULL,NULL) after you delete the stuff

lists and textures are stored with thier hrc, switching hrcs means you dont have access to the lists and textures that were created while that hrc was active

thats what hrc’s are for, you can even create multiple hrc’s and each having different pixelformats, lists, textures, etc

deleteing a hrc comes last but it happens before the hdc gets deleted, basic rule

quoted of msdn

The wglCreateContext function takes a device context handle as its parameter and returns a rendering context handle. The created rendering context is suitable for drawing on the device referenced by the device context handle. In particular, its pixel format is the same as the device context’s pixel format. After you create a rendering context, you can release or dispose of the device context. See Device Contexts for more details on creating, obtaining, releasing, and disposing of a device context.

Note The device context sent to wglCreateContext must be a display device context, a memory device context, or a color printer device context that uses four or more bits per pixel. The device context cannot be a monochrome printer device context.

The wglMakeCurrent function takes a rendering context handle and a device context handle as parameters. All subsequent OpenGL calls made by the thread are made through that rendering context, and are drawn on the device referenced by that device context. The device context does not have to be the same one passed to wglCreateContext when the rendering context was created, but it must be on the same device and have the same pixel format. The call to wglMakeCurrent creates an association between the supplied rendering context and device context. You cannot release or dispose of the device context associated with a current rendering context until after you make the rendering context not current.

Once a thread has a current rendering context, it can make OpenGL graphics calls. All calls must pass through a rendering context. Nothing happens if you make OpenGL graphics calls from a thread that lacks a current rendering context.

The wglGetCurrentContext function takes no parameters, and returns a handle to the calling thread’s current rendering context. If the thread has no current rendering context, the return value is NULL.

When you obtain a handle to the device context associated with a thread’s current rendering context by calling wglGetCurrentDC, the association is created when a rendering context is made current.

You can break the association between a current rendering context and a thread by calling wglMakeCurrent with either of two handles:

A null rendering context handle
A handle other than the one originally called
After calling wglMakeCurrent with the rendering context handle parameter set to NULL, the calling thread has no current rendering context. The rendering context is released from its connection to the thread, and the rendering context’s association to a device context ends. OpenGL flushes all drawing commands, and may release some resources. No OpenGL drawing will be done until the next call to wglMakeCurrent, because the thread can make no OpenGL graphics calls until it regains a current rendering context.

The second way to break the association between a rendering context and a thread is to call wglMakeCurrent with a different rendering context. After such a call, the calling thread has a new current rendering context, the former current rendering context is released from its connection to the thread, and the former current rendering context’s association to a device context ends.

The wglDeleteContext function takes a single parameter, the handle to the rendering context to be deleted. Before calling wglDeleteContext, make the rendering context not current by calling wglMakeCurrent, and delete or release the associated device context by calling DeleteDC or ReleaseDC as appropriate.

It is an error for a thread to delete a rendering context that is another thread’s current rendering context. However, if a rendering context is the calling thread’s current rendering context, wglDeleteContext flushes all OpenGL drawing commands and makes the rendering context not current before deleting it. In this case, relying on wglDeleteContext to make a rendering context not current requires the programmer to delete or release the associated device context.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.