[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