# OpenGL Another multithreading problems with OpenGL

This topic is 4236 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

##### Share on other sites
Are you calling glXMakeCurrent, aglSetCurrentContext or the Windows equivalent in a thread before you start issuing drawing commands? Also you can try having multiple contexts and sharing data, a good reference on this (if you're on Mac OS X) is this.

##### Share on other sites
Update:

Uhhh, alright... when reading, it seems that the answer is the call to the wglMakeCurrent. But there is still one thing that bothers me. wglMakeCurrent needs hdc, in which hdc means the handle to the device context. Isn't the hdc is only one: the current and the only window's handle that display my game screen? If I need to make a call of wglMakeCurrent in the new thread, which new "handle" I supposed to pass? Is it the old handle? Or I must create a new window and get it's display context? I don't really understand either how was the wglMakeCurrent related to the Multithreading by reading the MSDN documentation about wglMakeCurrent.

##### Share on other sites
@Abdulla:

I don't really sure what you mean. Are you talking about wglMakeCurrent (glXMakeCurrent in windows) in the Foreground thread or wglMakeCurrent in Background thread?

If you are talking about wglMakeCurrent in foreground thread, absolutely I've already called that. But if it's in background thread, I haven't yet. Because I think that once the context has been already set, all the gl and glu successive calls will used the current context, regardless which thread calls. Is it true, or not?

##### Share on other sites
Another update:

I've read more thoroughly that to use multithread with wglMakeCurrent, I *must* have a rendering context for each thread. But a new rendering context means a new device context, and a new device context means a new window, is it right? I don't really get it...

##### Share on other sites
The following is written w/o knowledge especially of WGL, so there might be something better out there.

The GL context stores the state of GL. Each thread can have its own GL context, allowing the use of GL also in multi-threaded environments.

Making a GL context current defines its use by the calling thread! AFAIK it should be possible to use the same GL context in several threads but it can be made current for at most one thread at a time. So if you want to "share" the context you have to ensure exclusive use, e.g. by protecting the context with a semaphore. This also requires the owning thread to release the context as soon as possible to make it available to other threads.

On invocations of wglMakeCurrent the device context and the render context need not always be the same. However, there are constraints like that the device context supports GL (of course) and has a matching pixel format.

Normally a context sharing is provided for display lists, textures, and buffer objects, but I don't found such a thing in WGL (what doesn't mean there isn't one).

##### Share on other sites
As previous posters said: the OpenGL context is only current for one thread at the time.

The most sensible solution to your problem (I think, since I'm using it [wink]) is to load and decode the texture in the resource thread. Then, give the render thread a signal that there is an image waiting to be uploaded to video memory. The render thread can then look at the list of waiting textures and upload them at the start of each frame.
That way you have the CPU and I/O-intensive stuff in a separate thread, and on-screen textures.

##### Share on other sites

@Haegarr:

but I'll try your valuable advice that stated that the previous thread must release the context before the new thread use it. I didn't know that!

@DaBono:

- If I must call wglMakeCurrent for every frame, doesn't it means that the animation will not run smoothly when the signal is set? because what I render in foreground is not merely a "loading animation", but a full game opening.

##### Share on other sites
In general, the device context defines where the output will be written to, e.g. which window will show the graphics. The render context is OpenGL's collection of all made textures, display lists, VBOs, and so on. It also stores the current depth comparison function, background clear color, whether or not you've currently invoked a glBegin but not a glEnd yet, and much more of those things. In short: It stores the OpenGL rendering state.

Each thread has the possibility to have at most 1 OpenGL context current. When a thread invokes wglMakeCurrent, it binds the overhanded rendering context to the device context, what means that output generated by using the rendering context has to go to the device context. Moreover, the context is set for the thread from which wglMakeCurrent was called. That means that exactly that thread is now using that rendering context. Until the thread releases the context no other thread is allowed to invoke wglMakeCurrent with just that context.

In fact, wglMakeCurrent binds 3 parts together: The device context, the rendering context, and the invoking thread. The latter dependency is of interest in multi-threaded environments only, and is hence often mentioned with less emphasis.

A thread can deal with multiple device contexts. It is also able to deal with several rendering contexts, but only 1 can be made current at a time. And that rendering context can only be current to 1 thread at a time.

EDIT: I bet that performance will suffer from often rebinding contexts. Since WGL seems to lack support of native context sharing, I think an approach as supposed by DaBono would be best if the desire is just to decouple loading and using of a texture, so at most the texture resource may be needed to be protected by a semaphore.

##### Share on other sites
Quote:
 Original post by MightyMartin@DaBono:- If I must call wglMakeCurrent for every frame, doesn't it means that the animation will not run smoothly when the signal is set? because what I render in foreground is not merely a "loading animation", but a full game opening.

You don't need to call wglMakeCurrent each frame, but just once. I'll try to make myself a bit clearer. Your resource thread in pseudo-code will do something like:
while( resourcesToLoad ) {   FileHandle fp = filesystem.open( textureName );   Image *image  = JPGLoader::load(fp);   textureQueue.push( image );}
createWindow();wglMakeCurrent( hwnd, ... );InitGL();while( gameRunning ) {   while( textureQueue.size() > 0 )      glTexImage2D( textureQueue.front(), .... );   renderFrame();}

So you see, only one call for wglMakeCurrent is needed.
Unfortunately, the code above is a bit too simple (e.g. you need to do proper locking around the queue), but I think you can get started with this.

1. 1
2. 2
Rutin
24
3. 3
4. 4
JoeJ
18
5. 5

• 14
• 17
• 11
• 11
• 9
• ### Forum Statistics

• Total Topics
631758
• Total Posts
3002155
×