Win32 multiple OpenGL windows, one window fails

Started by
8 comments, last by leonard2012 11 years, 10 months ago
We are developing a public transportation desktop application. It's a win32 C++ project using OpenGL or GDI as rendering toolkit. It's a multiple top-level window application. In detail, a map is shown in the main window, and one or more street views are shown in auxiliary windows. The graphics in all windows are rendered with either OpenGL or GDI, the choice of which toolkit to use is determined by users' preference or compatibility of graphics adaptor, and can be switched back and force at application runtime on the fly. Each window has its own device context (HDC hdc) and OpenGL rendering context (HGLRC hglrc), and we call the wglMakeCurrent method whenever a window is activiated (when receiving a WM_ACTIVATE message).
wglMakeCurrent(hdc, hglrc);

My problem is that, after switching the rendering toolkit from GDI to OpenGL, one window fails as the window is black and nothing is drawn inside the window. The failing window is unpredictable and can be the main window, or one of the auxiliary windows. This problem does not occur when GDI is not used. The only work when switching the rendering toolkit is to generate OpenGL display lists for the graphics objects (switching from GDI to OpenGL), or delete OpenGL display lists for the graphics objects (switching from OpenGL to GDI).

I've spent a couple of days trying to fix this issue but failed so far. Could someone kindly give me some hints, or give some possible reasons why nothing but a black background is drawn in the window. Thanks in advance.
Advertisement
You should call wglMakeCurrent whenever you're switching the target window for your rendering, (either on WM_PAINT or twice each frame depending on how your rendering is done)

wglMakeCurrent sets the current target render context and only one context per thread can be active at any given time, The last activated OpenGL Window is most likely the one that is working for you.
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

You should call wglMakeCurrent whenever you're switching the target window for your rendering, (either on WM_PAINT or twice each frame depending on how your rendering is done)

wglMakeCurrent sets the current target render context and only one context per thread can be active at any given time, The last activated OpenGL Window is most likely the one that is working for you.

Thank you for your quick response Simon. I am sure I called wglMakeCurrent on WM_PAINT and WM_ACTIVATE. Note that the issue only occurs after switching from GDI to OpenGL, I suspect the device context or GL rendering context is corrupted. I also wonder what are the possible causes leading to a black GL window.

[quote name='SimonForsman' timestamp='1340123366' post='4950626']
You should call wglMakeCurrent whenever you're switching the target window for your rendering, (either on WM_PAINT or twice each frame depending on how your rendering is done)

wglMakeCurrent sets the current target render context and only one context per thread can be active at any given time, The last activated OpenGL Window is most likely the one that is working for you.

Thank you for your quick response Simon. I am sure I called wglMakeCurrent on WM_PAINT and WM_ACTIVATE. Note that the issue only occurs after switching from GDI to OpenGL, I suspect the device context or GL rendering context is corrupted. I also wonder what are the possible causes leading to a black GL window.
[/quote]

Are you doing all your rendering from WM_PAINT aswell then ?
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
Yes, I am.
Hi Simon, I've spent another day trying to tackle this issue, and found that wglMakeCurrent fails for the main window. I use OutputDebugString to get runtime information and am sure to pass the right hdc and hglrc to wglMakeCurrent. The error code is 2004, which is "the requested transformation operation is not supported".The strange things are: First, wglMakeCurrent only fails for main window, not for auxiliary windows. Second, wglMakeCurrent only fails after switch from GDI to OpenGL. Third, if no auxiliary windows are created, the issue does not occur (or wglMakeCurrent always succeeds for main window).
Only one OpenGL window can be 'current' on a thread at a time.
In order for a new window to become 'current' the old window must first release its claim to being current (iirc you call wglMakeCurrent with null parameters); only then can the second window make itself current.

So, given two windows A & B the correct sequence is;

A::makeCurrent
A::do opengl operations
A::makeCurrent(null, null)
B::makeCurrent
B::do OpenGL operations
B::makeCurrent(null, null)

Make sure this is happening as its the most likely source of the problem.
Thank you for your help phantom.
I've gained some more insight into this issue though still fail to solve it. The latest debugging make me believe that some GDI functions might make the device context no longer supported by the rendering context. The MSDN on wglMakeCurrent function says:

The hdc parameter must refer to a drawing surface supported by OpenGL. It need not be the same hdc that was passed to wglCreateContext when hglrc was created, but it must be on the same device and have the same pixel format. GDI transformation and clipping in hdc are not supported by the rendering context. The current rendering context uses the hdc device context until the rendering context is no longer current.

This may match the error message of wglMakeCurrent (error code 2004, which means "the requested transformation operation is not supported").
I also found this issue has nothing to do with the auxiliary windows. When no auxiliary windows are created, the current rendering context (RC) remains the same (the RC of main window) even if wglMakeCurrent fails. So the rendering is sill OK. When auxiliary windows are created and shown, the current RC is changed to one of the RCs of auxiliary windows. So I end up with a black main window.

Thank you for your help phantom.
I've gained some more insight into this issue though still fail to solve it. The latest debugging make me believe that some GDI functions might make the device context no longer supported by the rendering context. The MSDN on wglMakeCurrent function says:

The hdc parameter must refer to a drawing surface supported by OpenGL. It need not be the same hdc that was passed to wglCreateContext when hglrc was created, but it must be on the same device and have the same pixel format. GDI transformation and clipping in hdc are not supported by the rendering context. The current rendering context uses the hdc device context until the rendering context is no longer current.

This may match the error message of wglMakeCurrent (error code 2004, which means "the requested transformation operation is not supported").
I also found this issue has nothing to do with the auxiliary windows. When no auxiliary windows are created, the current rendering context (RC) remains the same (the RC of main window) even if wglMakeCurrent fails. So the rendering is sill OK. When auxiliary windows are created and shown, the current RC is changed to one of the RCs of auxiliary windows. So I end up with a black main window.


You could try using ChoosePixelFormat on the dc/rc when switching renderer http://msdn.microsoft.com/en-us/library/windows/desktop/dd318284%28v=vs.85%29.aspx to set an appropriate pixelformat, if that still doesn't work you could always destroy the window and create a new one.
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
Thanks again, Simon.

This topic is closed to new replies.

Advertisement