iDevGames Forums
Full-screen with NSOpenGLView not working - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Game Programming Fundamentals (/forum-7.html)
+--- Thread: Full-screen with NSOpenGLView not working (/thread-7697.html)



Full-screen with NSOpenGLView not working - forseti - Jun 19, 2002 01:37 PM

Hi,

I posted a help on macosxdev at Omnigroup about my problem but so far haven't received any help. One person also had this problem and suggests just using CGDirectDisplay for the whole procress. Unless NSOpenGLView is not meant to work with full-screen (but there IS a setFullScreen method, and some documentation about it in the OpenGL section of programming topics at Apple's developer site), I'd like to go with NSOpenGLView.

Here's the thread:
http://cocoa.mamasam.com/MACOSXDEV/2002/06/2/37154.php

Thanks for any suggestions / possible solutions!

-forseti


Full-screen with NSOpenGLView not working - Jeff Binder - Jun 19, 2002 03:14 PM

NSOpenGLView isn't for full screen. If you're looking for fullscreen OpenGL, then what you should do is just use NSOpenGLContext alone and forget the whole Window/View structure. After calling setFullScreen and makeCurrentContext, any OpenGL calls go to that context, whether there's a view or not.


Full-screen with NSOpenGLView not working - wally - Jun 19, 2002 05:51 PM

Check out Omni's GDC 2001 slides, they show how to get the underlying CGContext of the NSOpenGLView so you can check the error code when calling CGSetFullScreen().

http://www.omnigroup.com/developer/gamedevelopment/gdc2001/

I haven't been able to get this (fullscreen OpenGL) to work for software OpenGL contexts, that may be what your problem is. I kept getting an invalid drawable error when using my Rage Pro card.


Full-screen with NSOpenGLView not working - OneSadCookie - Jun 19, 2002 06:32 PM

The software renderer doesn't support fullscreen contexts; you have to use a window as big as the screen.


Full-screen with NSOpenGLView not working - Feanor - Jun 20, 2002 07:06 AM

It's on my idisk. Download the project called "Light Box". What you might have missed is that "-setFullScreen" is an NSOpenGLContext method, and NSOpenGLView doesn't respond to it.

You have to use Core Graphics calls to capture the screen as well. I learned how to do this thanks to sample code by GoodDoug, but I don't know where he keeps his. -- FÎanor


Full-screen with NSOpenGLView not working - forseti - Jun 21, 2002 01:30 AM

Thanks for the example!
The full-screen mode doesn't work as expected though, does it for others?
Maybe it's just the screen positioning problem with my monitor... but I don't have that problem with other programs in 800x600 resolution. Graphics are drawn just fine though.

Anyway, I used bits of code from your example, and I also implemented a drawScene method with the gameWorld object. It works great in windowed mode, but with full-screen, just garbage is drawn and flashes everytime drawScene is called. I've been wondering why it wouldn't work for mine, and for your project it works (at least graphics are drawn properly).

Is it posible to just use CGDirectDisplay for full-screen and get the full-screen context wrapped in NSOpenGLContext? Otherwise I'd have to make 2 separate drawing operations for 2 different types of contexts... and no one would want to do that.

I'll examine it more tommorow and try to get graphics drawn properly for my project...


Here's my code if anyone is willing to help me!

Code:
- (id)initWithFrame:(NSRect)frame
{
    NSOpenGLPixelFormatAttribute windowedAttributes[] =
    {
        NSOpenGLPFADoubleBuffer,
        NSOpenGLPFAAccelerated,
        NSOpenGLPFAColorSize, [[[NSUserDefaults standardUserDefaults] objectForKey:@"colorDepth"] intValue],
        NSOpenGLPFAAlphaSize, 16,
        NSOpenGLPFADepthSize, 16,
        0
    };

    //  Create pixel format from attributes.
    NSOpenGLPixelFormat * windowedPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:windowedAttributes];
    NSAssert(windowedPixelFormat, @"Error: windowedPixelFormat is nil.");
    
    NSLog(@"Setting up main window.");
    
    //  Initialize NSOpenGLView with the pixel format.
    [super initWithFrame:frame pixelFormat:windowedPixelFormat];
    
    //  No longer needed.
    [windowedPixelFormat release];

    //  Initialize our variables.
    isFullScreen = NO;
    
    //  Create the game world and pass the context.
    theWorld = [[VSGameWorld alloc] initWithContext:[self openGLContext]];

    //  Set the current OpenGL context.
    [[self openGLContext] makeCurrentContext];

    //  Prepare OpenGL (viewport setup done in -drawRect:).
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);
    
    //  User wants full-screen mode.
    if([[[NSUserDefaults standardUserDefaults] objectForKey:@"displayMode"] isEqualToString:@"fullScreen"])
    {
        NSOpenGLPixelFormatAttribute fullScreenAttributes[] =
        {
            NSOpenGLPFADoubleBuffer,
            NSOpenGLPFAFullScreen,
            NSOpenGLPFAAccelerated,
            NSOpenGLPFAColorSize, [[[NSUserDefaults standardUserDefaults] objectForKey:@"colorDepth"] intValue],
            NSOpenGLPFAAlphaSize, 16,
            NSOpenGLPFADepthSize, 16,
            0
        };
        
        //  Create pixel format from attributes.
        NSOpenGLPixelFormat * fullScreenPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:fullScreenAttributes];
        NSAssert(fullScreenPixelFormat, @"Error: fullScreenPixelFormat is nil.");
        
        NSLog(@"Setting up full-screen context.");
        
        //  Initialize an NSOpenGLContext for full-screen.
        fullScreenContext = [[NSOpenGLContext alloc] initWithFormat:fullScreenPixelFormat shareContext:nil];
        
        //  No longer needed.
        [fullScreenPixelFormat release];
        
        //  Make current.
        [fullScreenContext makeCurrentContext];
        
        //  Prepare OpenGL.
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glEnable(GL_DEPTH_TEST);
        
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        glViewport(0, 0, [[[NSUserDefaults standardUserDefaults] objectForKey:@"viewWidth"] intValue],
            [[[NSUserDefaults standardUserDefaults] objectForKey:@"viewHeight"] intValue]);
        
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
        
        //  Use CGDirectDisplay for full-screen.
        {
            CGDisplayErr        err;
            
            [self setupGamma];
            CGDisplayHideCursor(kCGDirectMainDisplay);
            [self fadeOutGamma];
            
            //  Capture display first.
            CGDisplayCapture(kCGDirectMainDisplay);
            
            //  Save previous mode so we know how to restore.
            prevDisplayMode = CGDisplayCurrentMode(kCGDirectMainDisplay);
            
            //  Also save new mode.
            newDisplayMode = CGDisplayBestModeForParameters(kCGDirectMainDisplay, 24,
                [[[NSUserDefaults standardUserDefaults] objectForKey:@"viewWidth"] intValue],
                [[[NSUserDefaults standardUserDefaults] objectForKey:@"viewHeight"] intValue], 0);
            NSAssert(newDisplayMode, @"Error: newDisplayMode is nil.");
            
            err = CGDisplaySwitchToMode(kCGDirectMainDisplay, newDisplayMode);
            NSAssert(err == CGDisplayNoErr, @"Error switching resolution.");
            
            [fullScreenContext makeCurrentContext];
            [fullScreenContext setFullScreen];
            [theWorld setContext:fullScreenContext];
            
            isFullScreen = YES;
            
            [self fadeInGamma];
            CGDisplayShowCursor(kCGDirectMainDisplay);
        }
    }
    
    //  Create a timer and retain it, because we need it running all the time.
    drawTimer = [[NSTimer scheduledTimerWithTimeInterval:kFramePause
        target:self selector:@selector(drawScene) userInfo:nil repeats:YES] retain];
    
    return self;
}

- (void)drawRect:(NSRect)frame
{
    NSLog(@"drawRect called.");
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glViewport(0, 0, frame.size.width, frame.size.height);
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

-(void)drawScene
{
    if(isFullScreen == NO)
    {
        [self lockFocus];
        [theWorld drawScene];
        [self unlockFocus];
    }
    else
        [theWorld drawScene];
}
;

And the drawScene in gameWorld:

Code:
- (void)drawScene
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    
    glBegin(GL_QUADS);
    glColor4f(1.0, 0.0, 0.0, 1.0);
    glVertex3f(-0.5, -0.5, 0.0);

    glColor4f(0.0, 1.0, 0.0, 1.0);
    glVertex3f(0.5, -0.5, 0.0);

    glColor4f(0.0, 0.0, 1.0, 1.0);
    glVertex3f(0.5, 0.5, 0.0);

    glColor4f(1.0, 0.0, 1.0, 1.0);
    glVertex3f(-0.5, 0.5, 0.0);
    glEnd();
    
    glRotatef(-0.5, 0.6, -0.6, 0.5);

    // Update the GL context
    [[self worldContext] flushBuffer];
}



Full-screen with NSOpenGLView not working - forseti - Jun 22, 2002 10:10 PM

Oh my god... I just tracked down the bug I couldn't figure out for 3 days! I'm so happy.
You could say it's stupid... but I realized that in my code, drawRect was being called AFTER the full-screen context was set up, and after it ENETERED full-screen mode. So I'm assuming drawRect couldn't find it's proper windowed context and messed things up. So I want to enter full-screen mode after drawRect is being called... which means I have to initially draw things on the windowed view. But then if I showed it and entered full-screen right after, my contents would be drawn in the windowed view for just a millisecond and then immediately switch to full-screen, having my contents drawn for the second time. How should I avoid this? Unlike Feanor's example code, I want my app to run full-screen or windowed mode based on preferences, not by user interaction in windowed mode.

Thanks. Smile


Full-screen with NSOpenGLView not working - forseti - Jun 22, 2002 10:20 PM

Maybe I should separate the class into two, one for windowed (NSOpenGLView) and one for full-screen (NSObject), and have my delegate control the two. Or call orderOut on the window to hide the windowed drawing before entering full-creen. But if there are any other ideas... it's welcome.


Full-screen with NSOpenGLView not working - Feanor - Jun 23, 2002 09:19 PM

If you are using a captured display and a fullscreen context, you can't use NSOpenGLView, as Jeff Binder noted in his post. You don't want to do any fullscreen setup in your view object at all. You would want to do that in a custom object. The view should only manage its own contexts.

In Light Box, the drawable is controlled in a controller object, not the view itself. In the other sample called CocoaFullScreen, the view controls both contexts, because both are used by that view, which gets move back and forth between two windows -- one from the Nib, the other created programmatically. Let me know if this helps clarify things. -- FÎanor


Full-screen with NSOpenGLView not working - forseti - Jun 24, 2002 01:53 AM

Thanks,
I thought LightBox attempted to set up both windowed and full-screen in the same NSOpenGLView subclass (athough the drawing was done in the game world object), but if that's wrong, that would probably be why my code is not working... attempting to set up two completely different views in the same class.
I learned how to separate the two using multiple Nibs just now, so this will be the way to go for me.. not to mention just to avoid unnecessary confusion. Smile