AGL rendering on a separate thread


I encountered a problem while trying to render in a thread other than the main one. I currently have different threads running in my app, each one with its shared AGL context, and everything was working fine…

But now I also have to switch rendering to one of those threads on some occasions. When that happens, I’m just hiding my ‘main’ AGL context. Then I create a new AGL context for my thread that will do the rendering, on the fly, bind it to my HIView using aglSetHIViewRef, and then everything goes on using the new AGL context.

Unfortunately, when swapping the buffers, nothing is displayed. I checked that the rendering is done and correct using the GL Profiler, the only thing that is not done is the display of what’s rendered.

I suspect that the cause is the GUI not being thread-safe, but what should I do to go around that (given that the rendering should stay in a separate thread when requested, and I can’t really change that) ?

Thanks for your help !

If you create a new context then none of the assets from your original context will be available without some additional work.

Ideally if you must share your drawing across different threads, you’ll need to share the one context between threads, and make sure that only one thread at a time is actually using it. I don’t use any of the AGL stuff directly, and there is some confusion as to whether you can have a context current in two threads and so on… In my experience you can, but the BIG caveat is that you must never ever access them at the same time from different threads. Another thing you should never do in my experience is Release a context. I tried this a few times when trying to keep things neat and tidy. i.e. Get the context in one thread and then release it in the other. But all this does it kill the context for everyone!!

You’ll have the best chance of success with multithreading if you design your program with threading in mind. It’s difficult, and often risky, to retrofit an existing OpenGL application to use multiple threads. Before you write any threading code, choose a strategy for dividing work among threads.

Consider using one of the following strategies for your OpenGL application:

Move OpenGL onto a separate thread.
Split OpenGL texture and vertex processing onto separate threads. You gain performance advantages by applying threads on single processor machines but threads are most efficient on computers with multiple CPUs since each processor can devote itself to a thread, potentially doubling the throughput.
For contexts on separate threads, share surfaces or OpenGL object state: display lists, textures, vertex and fragment programs, vertex array objects, and so on.

I would really advise reading this a few times… (If you haven’t already).…_threading.html

As a matter of fact, this is already the case. This is a port of an engine from Win32, and multi threading is already in place.

Basically I have :

  • a main thread that does the rendering most of the time (let’s call it A)
  • some separate threads that do some loading (textures, …)
  • a separate thread that sometimes does rendering (let’s call it B)

For each of those threads, I have a GL context. All GL contexts are shared with a master “dummy” context that does absolutely nothing but hold the data. When I create a new GL context for a thread, sharing is immediately activated with the master context, and thus it gains access to all the data. As a matter of fact, my rendering is correct (the back buffer as inspected in GL profiler looks OK), it’s just that the rendered scene is not displayed in the window.

As for rendering, threads A and B don’t even render at the same time. Thread A has the rendering most of the time, but may ‘give’ it to thread B sometimes. Rendering is just passed from one to the other.

Didn’t know this one, I’ll take a look at it anyway, I might learn something :wink: