« Straight Alpha and Bilinear Filtering | Main | Fragment Programs-ATI R3xx vs NVidia NV34 »
May 10, 2005
Mac OpenGL contexts
A context is a container for the GL state information, things like the current color, transformation matrix, texture ID and anything else that needs to be remembered by OpenGL.
One of the things the context remembers is which frame buffer you're drawing to, known as the attached surface. The key thing to understand is that a context is not the same as a surface, a context is just a housekeeping structure to hold the information GL needs to remember. A surface is where you actually draw into, and you can change what surface a context draws into (for example, swapping the back and front buffers points the context to a different surface), or even not attach it to any surface.
Normally, texture IDs are local to each context:

if you've created a texture in one context, you can't use it in another. To share textures, you need to use a shared context.
Shared contexts are places to store texture IDs, and other IDs for things like draw lists and programs. Creating a context with a shared context means using that shared context to store those IDs, and information about the objects they point to.

A shared context doesn't even need to be pointing to a surface, since its only purpose is to store all those IDs. The easiest way to use a shared context is to create a single global one when your app starts, don't attach it to any window or pbuffer, and pass it into all create context calls.
Once you've done that, all of the texture IDs you create in any of your contexts will be usable in all of them, and you never need to think about the shared context again.
You can use OpenGL on the Mac in a multithreaded app, but you must never call GL functions on the same context from different threads at the same time.
Think of a GL context like a C++ object, if you call a member function on an object whilst another thread is halfway through another member function on the same object, you may end up with a corrupted object. Corrupting a context by a threading mistake will often cause a kernel panic.
If you're writing a multi-threaded GL app, make sure you periodically run the OpenGL Profiler, and enable 'break on thread errors'. This will stop the app and give a stack trace whenever two threads call into the same context. To find out what the other threads are doing, run the command line gdb with 'gdb -p ' and the process number of your app, and do the command 'thread apply all bt' for a complete thread listing.
CGLMacro.h exposes some of the implementation details of Mac OpenGL calls. Normally, every gl*() call actually ends up doing something like a CGLGetCurrentContext() call internally, and then passing that on to the function that does the actual work.
CGLGetCurrentContext() has to do some magic to figure out which thread it's in, and return the correct context for that thread, so it's a good optimisation to cache the current context if you know it's not changing, and you're making a lot of GL calls. CGLMacros let you do this optimisation but change very little of your code, by letting you specify a variable to use for the CGL context. Then, including the header into a source file will automatically switch all GL calls to use that instead of the standard context system.
Posted by petewarden at May 10, 2005 05:02 PM