You should be doing something clearly wrong, as OpenGL multi-threaded rendering works fine on iPhone. I canβt tell you what is wrong with your code, but I can show you how we do it. It took me a few iterations to get there, because Apple's OpenGL code sample brings it all together.
In the end, I came up with three classes: Stage, Framebuffer, and GLView. The stage contains the game's playback logic and knows how to display itself in the framebuffer. The framebuffer class is a wrapper around an OpenGL framebuffer and displays a EAGLDrawable or EAGLDrawable . GLView is the ability to draw a framebuffer; it contains all the OpenGL settings. At the application entry point, I create an OpenGL context, GLView, a framebuffer that displays this GLView, and a stage that displays using the framebuffer. The Stage update method works in a separate thread and looks something like this:
- (void) mainLoop { [fbuffer bind]; [currentScene visit]; [[EAGLContext currentContext] presentRenderbuffer:GL_RENDERBUFFER_OES]; [fbuffer unbind]; }
In plain English, it links the framebuffer, looks at the graph of the game object (= creates a scene), presents the contents of the framebuffer on the screen, and unties the framebuffer. The call to presentRenderbuffer little out of place, it is somewhere higher in the design - the Stage should just render into the framebuffer and let you do whatever you want to do with the framebuffer. But I could not find a suitable place, so I just left the call there.
Otherwise, I am satisfied with the design: all classes are simple, consistent, and verifiable. Theres also a Scheduler class that creates a thread and calls Stages mainLoop as quickly as possible:
- (void) loop { [EAGLContext setCurrentContext:context]; while (running) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @synchronized (context) { [stage mainLoop]; } [fpsCounter update]; [pool release]; } } - (void) run { NSAssert(!running, @"Scheduler already running."); running = YES; [fpsCounter reset]; context = [EAGLContext currentContext]; [NSThread detachNewThreadSelector:@selector(loop) toTarget:self withObject:nil]; }
No game updates are synchronized using the OpenGL context, so we can be sure that we have not messed up the context in the main thread. (A simple rule: the whole picture must be executed in the game update cycle or synchronized in the GL context.)
Hope this helps.