[wxGLCanvas] GL commands don't work

Carsten Fuchs CarstenFuchs at T-Online.de
Wed Jul 25 01:46:24 PDT 2007


Hi David,

David Donaldson wrote:
> Unfortunately the MSDN page is a big vague on the subject:
> 
> http://msdn2.microsoft.com/en-us/library/ms537558.aspx
> 
> "A rendering context can be current to only one thread at a time. You
> cannot make a rendering context current to multiple threads. "
> 
> This implies that you can't call wglMakeCurrent on a context that is
> already current in another thread. Also, I think it would be poor
> design to allow one thread to steal the context out from under
> another.

Well, I don't know much and have little experience with multi-threading, but "stealing" an OpenGL 
context from another Windows Device Context is common practise, i.e. you just call

	// Let hglrc be the OpenGL rendering context currently
	// current with the Windows device context OldDC.
	// Let NewDC be another suitable Windows Device Context.
	wglMakeCurrent(NewDC, hglrc);

instead of a sequence like

	wglMakeCurrent(NULL, NULL);   // Make it uncurrent from OldDC.
	wglMakeCurrent(NewDC, hglrc);

So I guess (at least it's my understanding of the MSDN link you provided) that the same is true for 
multiple threads, but of course only one thread can use the hglrc at a time.
That means that thread control must not switch in the mid of an OpenGL call, and that before another 
thread starts using OpenGL, it must make the hglrc current again. Then, while that thread is using 
OpenGL, no other thread must attempt to call wglMakeCurrent() and other OpenGL calls.


> More importantly, I've tested this. Try creating a couple threads and
> have each run this code (one at a time). With the lines commented out,
> the program fails when the second thread calls wglMakeCurrent (mine
> actually crashes).
> 
> bool makeGLCalls( HDC hdc, HGLRC hglrc, float draw_angle )
> {
>    bool result = true;
>    result = result && wglGetCurrentContext() == NULL;  // (a)
>    result = result && wglMakeCurrent( hdc, hglrc );
>    result = result && wglGetCurrentContext() == hglrc;  // (b)
>    //result = result && wglMakeCurrent( NULL, NULL );
>    //result = result && wglGetCurrentContext() == NULL;
>    return result;
> }

Does it also crash when you comment out the first and second calls to wglGetcurrentContext(), the 
ones I marked with (a) and (b) (and possibly run some arbitrary OpenGL code before the return)?

I think that when the second thread calls wglGetCurrentContext() in line (a), it might get a 
non-NULL result that is still invalid in terms of the MSDN specification of wglMakeCurrent, i.e. a 
non-NULL result from wglGetCurrentContext() not necessarily indicates a valid OpenGL RC.

Again, I have no prove or supplementary code sample for this, but would be surprised if the 
wglMakeCurrent(NULL, NULL) before thread switching would be a requirement.

> The code from SetCurrent is a thin wrapper for wglMakeCurrent, and it
> doesn't allow you to specify the HGLRC argument to wglMakeCurrent as
> NULL, so it is not possible to release the context from wxWidgets (on
> Windows, at least).

True, the wrapper is intentionally thin, and if it turns out that in the above situation the glrc 
must indeed be made explicitly uncurrent before it is made current in another thread, we should 
probably add a method like
	void wxGLContext::ForceUncurrent()
to the wxGLContext class.

Best regards,
Carsten



-- 
Ca3D - Engine    http://www.Ca3D-Engine.de
Carsten Fuchs    http://www.Ca3D-Engine.de/c_Carsten.php




More information about the wx-users mailing list