iDevGames Forums
Full Screen OpenGL Crashes - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Graphics & Audio Programming (/forum-9.html)
+--- Thread: Full Screen OpenGL Crashes (/thread-1749.html)



Full Screen OpenGL Crashes - Blacktiger - Feb 16, 2009 05:40 PM

I designed an NSOpenGLView subclass to support switching to full screen rendering. I based the class on one from OSC and the one from the InkuGame project. After getting it working, I then copied the classes to a new project and hooked everything up the same in InterfaceBuilder, but when I try to go full screen in the new project my system just hangs and I have to force a restart! Anyone have any ideas as to what may be causing this? Here some possibly relevant code.

Code:
- (void)drawRect:(NSRect)rect
{
    if(isFirstFrame)
    {
        isFirstFrame = NO;
        if(isFullScreen) [fullScreenContext setFullScreen];
        else [windowedContext setView:self];
    }

    [delegate drawRect:rect];

    [[self openGLContext] flushBuffer];
}

- (IBAction) toggleFullScreen:(id)sender
{
    isFirstFrame = YES;
    CGDisplayFadeReservationToken fadeReservation;
    CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval,
                                    &fadeReservation);
    CGDisplayFade(fadeReservation, 0.5, kCGDisplayBlendNormal,
                  kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true);

    [NSOpenGLContext clearCurrentContext];

    if(isFullScreen)
    {
        isFullScreen = NO;
        [fullScreenContext clearDrawable];
        
        CGReleaseAllDisplays();
        CGDisplaySwitchToMode(kCGDirectMainDisplay, (CFDictionaryRef)desktopMode);
        
        [self setOpenGLContext:windowedContext];
        [[self window] makeKeyAndOrderFront:self];
        
        [NSCursor unhide];
        [NSMenu setMenuBarVisible:YES];
    }
    else
    {
        isFullScreen = YES;
        isFirstFrame = YES;
        [windowedContext clearDrawable];
        
        // Store the desktop mode before we change modes.
        [desktopMode release];
        desktopMode = [(NSDictionary*)CGDisplayCurrentMode(kCGDirectMainDisplay) retain];

        CGCaptureAllDisplays();
        CGDisplaySwitchToMode(kCGDirectMainDisplay, (CFDictionaryRef)fullScreenMode);

        [fullScreenContext setFullScreen];
        [self setOpenGLContext:fullScreenContext];
        
        [NSCursor hide];
        [NSMenu setMenuBarVisible:NO];
    }
    [self display];
    
    CGDisplayFade(fadeReservation, 2.0, kCGDisplayBlendSolidColor,
                  kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false);
    CGReleaseDisplayFadeReservation(fadeReservation);
}



Full Screen OpenGL Crashes - AnotherJake - Feb 16, 2009 06:18 PM

Switching into/out of full screen can be a total pain. All I remember is that it was confusing to figure out. Wacko I don't see anything that sticks out immediately. I forgot if setOpenGLContext will make the context current as well. You might want to try calling makeCurrentContext right after setOpenGLContext in your full screen switch just to be sure, since you called clearCurrentContext earlier.


Full Screen OpenGL Crashes - DoG - Feb 17, 2009 09:08 AM

I'd also wager that you need to make the new context current. I'd also suggest using a shared context approach, unless you do already (not evident from code snippet), otherwise you have to reload all OpenGL resources, such as textures and vertex buffers, for the new context. It's also not clear from that snippet if the contexts are set up correctly.

You definitely should not be getting a kernel panic, so file a radr with Apple, but I've seen OSX KP quite a few times when an invalid OpenGL context is accessed, or with threads stepping on each other's toes.


Full Screen OpenGL Crashes - backslash - Feb 17, 2009 10:11 AM

It may not be a kernel panic. It is possible to put an OpenGL context into fullscreen mode, not make it current, and not have it attached to any other objects. Once you've done that nothing you do has any visible effect and you cannot easily get out of fullscreen mode. I have managed to set this up in such a way that even pressing command-q didn't send a terminate message to my app controller and force-quitting blind was the only way out.
It is also possible to crash the video card without crashing the OS by sending it a bad pointer, which kills the visuals without stopping any software from running (although I'm pretty sure that isn't happening here).


Full Screen OpenGL Crashes - Blacktiger - Feb 17, 2009 01:06 PM

I haven't even been able to force quit blind. I'm not sure I have a shared context set up, so I'll check into that and also check to make sure the correct context is current. Thanks for the help.


Full Screen OpenGL Crashes - Blacktiger - Feb 17, 2009 09:23 PM

I am using a shared context and I modified drawRect to ensure the correct context is current, but my app still crashes when switching to fullscreen.

Code:
- (void)drawRect:(NSRect)rect
{
    if(isFirstFrame)
    {
        isFirstFrame = NO;
        if(isFullScreen)
        {
            [fullScreenContext setFullScreen];
            [fullScreenContext makeCurrentContext];
        }
        else
        {
            [windowedContext setView:self];
            [windowedContext makeCurrentContext];
        }
    }

    [delegate drawRect:rect];

    [[self openGLContext] flushBuffer];
}



Full Screen OpenGL Crashes - backslash - Feb 18, 2009 03:55 AM

The OS might make other things current in between frames so you might need to make the correct context current every frame, not just on the first one.
Try this:
Code:
- (void)drawRect:(NSRect)rect
{
    if(isFirstFrame)
    {
        isFirstFrame = NO;
        if(isFullScreen)
        {
            [fullScreenContext setFullScreen];
            openGLContext  = fullScreenContext;
        }
        else
        {
            [windowedContext setView:self];
            openGLContext  = windowedContext;
        }
    }

    [openGLContext makeCurrentContext];
    [delegate drawRect:rect];

    [[self openGLContext] flushBuffer];
}
I seem to remember doing something extra in an NSApplication subclass to intercept keyboard events in fullscreen mode, but I don't have the code handy at the moment.


Full Screen OpenGL Crashes - Blacktiger - Feb 18, 2009 09:23 AM

Good point, I fixed it so the correct context is made current every time drawRect is called. Unfortunately it doesn't fix the problem.
Code:
- (void)drawRect:(NSRect)rect
{
    if(isFirstFrame)
    {
        isFirstFrame = NO;
        if(isFullScreen) [fullScreenContext setFullScreen];
        else [windowedContext setView:self];
    }
    [[self openGLContext] makeCurrentContext];

    [delegate drawRect:rect];

    [[self openGLContext] flushBuffer];
}



Full Screen OpenGL Crashes - macnib - Feb 18, 2009 10:39 AM

Debugging fullscreen can be a pain. If you have two monitors that can make it a lot easier. You can have xcode running in one monitor with the debugger and the fullscreen going on the other monitor. Seemed to make things easier for me...


Full Screen OpenGL Crashes - Blacktiger - Feb 18, 2009 08:10 PM

macnib Wrote:Debugging fullscreen can be a pain. If you have two monitors that can make it a lot easier. You can have xcode running in one monitor with the debugger and the fullscreen going on the other monitor. Seemed to make things easier for me...
That's a good idea, I'll have to commandeer the TV for that. I thought that when you went full screen both monitors became black, is that true? Is there anything special I need to do?


Full Screen OpenGL Crashes - macnib - Feb 18, 2009 08:38 PM

You can use CG calls like CGGetOnlineDisplayList .

Also, if you use cocoa there is :

[self enterFullScreenMode: [NSScreen mainScreen] withOptions: nil ];
[self exitFullScreenModeWithOptions: nil];


Full Screen OpenGL Crashes - AnotherJake - Feb 18, 2009 08:52 PM

Blacktiger Wrote:That's a good idea, I'll have to commandeer the TV for that. I thought that when you went full screen both monitors became black, is that true? Is there anything special I need to do?

Hehe... You might notice in GameBase, in performToggleFullScreen:

Code:
        #ifdef DEBUG
            err = CGDisplayCapture(preferredDisplayID);
        #else
            err = CGCaptureAllDisplays();
        #endif

That is specifically there because I had such a hell of a time debugging full screen problems like this that I used two monitors. Only the captured one goes black (or at least stays black). The other one was able to mouse around and be used normally. That saved a lot of time.


Full Screen OpenGL Crashes - Blacktiger - Feb 18, 2009 10:28 PM

Thanks for the help. As I messed around with my code, it suddenly started working again! (Well, I'm not drawing anything in full screen mode yet, but I can go in and out without problems.) The only major thing I seem to have changed is to remove the timers that I had to run drawRect at a constant frequency. I can't see how that would make a difference and maybe it didn't. Seems like this stuff should be straight forward, but for some reason it just isn't.


Full Screen OpenGL Crashes - backslash - Feb 19, 2009 02:39 PM

Does that mean you're not calling drawrect: any more? If so, don't assume that the problem is actually fixed - it may be that something in drawrect: is causing the issue (do you definitely have a valid context?).