bug in OpenGL setup for NSOpenGL subclass (I think)
or "I've managed to write a Universal Binary that doesn't work on Intel!"
Having just bought a shiny new MacBook, I decided to try out my pre-pre-alpha game (there's actually no gameplay whatsoever at the moment) on it. Amazingly, it runs, everything initialises and all behaviour is working as it does on my G4 Mac Mini, except that my graphics don't draw unless I cover the window with another app or push it off the side of the screen.
I've subclassed NSOpenGLView and used a Custom View thingy in Interface Builder to plant it in a window. An NSTimer fires off my game loop every 20ms, and the game loop tells the NSOpenGLView subclass to setNeedsDisplay:YES.
I've verified that drawRect is getting called, and there are no OpenGL errors. I've spent many hours scouring Google and trying various plausible solutions, but with no success. I thought it might be something to do with my previous strategy of putting the NSOpenGLView into an NSPanel and setting that to be the content of the NSWindow, but changing that has made no difference. I stripped the project to a version with only the GameController and TNeb_OpenGLView classes and no third party libraries, and the same thing happened, so I think it must be something to do with the way I'm setting up my OpenGL context or the view, but I'm a bit stumped as to what it might be. So I thought maybe a fresh pair of eyes (attached to someone who actually knows what they're doing!) might be able to point the obvious mistake for me.
Here's the relevant bits of TNeb_OpenGLView.m
Having just bought a shiny new MacBook, I decided to try out my pre-pre-alpha game (there's actually no gameplay whatsoever at the moment) on it. Amazingly, it runs, everything initialises and all behaviour is working as it does on my G4 Mac Mini, except that my graphics don't draw unless I cover the window with another app or push it off the side of the screen.
I've subclassed NSOpenGLView and used a Custom View thingy in Interface Builder to plant it in a window. An NSTimer fires off my game loop every 20ms, and the game loop tells the NSOpenGLView subclass to setNeedsDisplay:YES.
I've verified that drawRect is getting called, and there are no OpenGL errors. I've spent many hours scouring Google and trying various plausible solutions, but with no success. I thought it might be something to do with my previous strategy of putting the NSOpenGLView into an NSPanel and setting that to be the content of the NSWindow, but changing that has made no difference. I stripped the project to a version with only the GameController and TNeb_OpenGLView classes and no third party libraries, and the same thing happened, so I think it must be something to do with the way I'm setting up my OpenGL context or the view, but I'm a bit stumped as to what it might be. So I thought maybe a fresh pair of eyes (attached to someone who actually knows what they're doing!) might be able to point the obvious mistake for me.
Here's the relevant bits of TNeb_OpenGLView.m
Code:
static NSOpenGLPixelFormatAttribute MyAttributes[] =
{
NSOpenGLPFAAccelerated,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAColorSize, 8,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADepthSize, 8,
0
};
@implementation TNeb_OpenGLView
- (id)initWithFrame:(NSRect)frameRect //this is the init method used on PPC Mac OS X 10.4.9
{
NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:MyAttributes];
if (pixelFormat == nil)
{
NSLog(@"Error in OpenGl pixel format");
return nil;
}
[pixelFormat autorelease];
self = [super initWithFrame:frameRect pixelFormat:pixelFormat];
if (self == nil)
{
NSLog(@"openGl initialisation error in -initWithFrame:");
return nil;
}
[ [ self openGLContext ] makeCurrentContext ];
[self prepareOpenGL];
leftDrag = NO;
draw3D = NO;
return self;
}
- (void)prepareOpenGL /* do one-off OpenGL initialization stuff here */
{
glShadeModel( GL_SMOOTH ); // Enable smooth shading
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); // Black background
glClearDepth( 1.0f ); // Depth buffer setup
glDepthFunc( GL_LESS ); // Type of depth test to do
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); // Really nice perspective calculations
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
glDrawBuffer(GL_FRONT);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
- (void)reshape
{
NSLog(@"-reshape");
bounds = [self bounds];
//set up the 3D matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, bounds.size.width, bounds.size.height);
gluPerspective( 45.0f, bounds.size.width / bounds.size.height, 0.1f, 200.0f );
if (glGetError()) NSLog(@"OpenGL error detected in -reshape");
glPushMatrix(); // -drawrect: pops it when it wants to do 3D drawing
//setup 2D stuff (it won't be done unless 3D drawing was done previously in the loop)
glDisable( GL_DEPTH_TEST );
glMatrixMode( GL_PROJECTION );
glPushMatrix(); //save the 3D setup for later
glLoadIdentity();
glOrtho(0.0, bounds.size.width, 0.0, bounds.size.height, 0.0, 100.0);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
- (BOOL) isOpaque
{
return YES;
}
/* RENDERING FUNCTIONS */
- (void)drawRect:(NSRect)rect
{
[ [ self openGLContext ] makeCurrentContext ];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Do the 3D stuff
if (draw3D)
{
glEnable( GL_DEPTH_TEST );
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glPushMatrix(); //save it for next time round
gluLookAt( camera.eye.x, camera.eye.y, camera.eye.z,
camera.centre.x, camera.centre.y, camera.centre.z,
camera.up.x, camera.up.y, camera.up.z );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
objc_msgSend(gameData, gameDataDraw3Dsel); //this gets the objects to draw themselves in different ways depending on the engine state
if (glGetError()) NSLog(@"OpenGL error detected in -drawRect: after 3D drawing");
//Do the 2D stuff
//first reload the 2D setup
glDisable( GL_DEPTH_TEST );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(0.0, bounds.size.width, 0.0, bounds.size.height, 0.0, 100.0);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
[gui drawInterface]; //call to my Interface object which draws all my onscreen controls
if (glGetError()) NSLog(@"OpenGL error detected in -drawRect: after 2D drawing (gui)");
glFlush();
}
Replace
glFlush()
with
[[self openGLContext] flushBuffer];
glFlush only flushes the command queue, it does not swap back buffer to the display. Since you have a double buffered context, all of your rendering stays in the back buffer (until you drag a another window on top of yours, then the compositor picks up partially drawn bits.)
glFlush()
with
[[self openGLContext] flushBuffer];
glFlush only flushes the command queue, it does not swap back buffer to the display. Since you have a double buffered context, all of your rendering stays in the back buffer (until you drag a another window on top of yours, then the compositor picks up partially drawn bits.)
Thank you - that's worked great... on the MacBook. The Mac Mini started giving me a window full of garbage after that change. At that point I remember not being able to figure out how to swap the buffers a while back and putting in the line glDrawBuffer(GL_FRONT) as a temporary hack, which I forgot about. I changed it to glDrawBuffer(GL_BACK) and now all is happy on both machines. Does the GMA950 refuse to draw to the front buffer, or something.
I've also just discovered that my Mac Mini has updated to 10.4.10 when I wasn't paying attention, but I doubt that is it.
Anyway, buffering never even occurred to me. You are indeed a genius.
I've also just discovered that my Mac Mini has updated to 10.4.10 when I wasn't paying attention, but I doubt that is it.
Anyway, buffering never even occurred to me. You are indeed a genius.
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| OpenGL Pixel Buffer Object setup issue | dotbianry | 2 | 1,083 |
Jan 6, 2013 11:03 AM Last Post: dotbianry |
|
| OpenGL ES2 matrix setup (humbly crawling back) | Fenris | 2 | 5,231 |
Aug 31, 2011 06:47 AM Last Post: Fenris |
|
| multiple nsopengl subviews problem | NelsonMandella | 0 | 1,828 |
Nov 9, 2009 09:44 PM Last Post: NelsonMandella |
|
| When to create custom OpenGL view instead of subclass NSOpenGL view | Coyote | 37 | 16,925 |
Oct 20, 2009 08:16 PM Last Post: Coyote |
|
| xCode/SDL Setup | hammonjj | 2 | 4,295 |
Mar 2, 2007 06:37 AM Last Post: hammonjj |
|

