Fullscreen windowed OpenGL mode

Member
Posts: 129
Joined: 2005.02
Post: #1
Does anyone know of any source code examples that use fullscreen windows in a fullscreen mode, as opposed to a fullscreen context in a fullscreen mode, with no windows.

I'm trying to implement fullscreen/windowed, but I'm going on some ideas from the Mac-games-dev@lists.apple.com--so I'm implementing a borderless window in a fullscreen.

Now... I know I've seen example code of this, but I've gone through so much Cocoa OpenGL sample code, I'm not sure which one it was. Does anyone recall?

Thanks,
Quote this message in a reply
Sage
Posts: 1,234
Joined: 2002.10
Post: #2
Here's a bit of code that handles creating a window, or going fullscreen with either a real fullscreen context or a borderless window. It supports weird things like running the software renderer fullscreen on a second display. Modify as you see fit:
Code:
- (id)initWithMode:(NSDictionary *)mode format:(cglPixFormat *)format fullscreen:(BOOL)fullscreen {
    NSDictionary *dict = [mode objectForKey:@"mode"];
    if (!mode || !format || !dict) return nil;    // programmer err
    
    // CG -> Cocoa mumbo jumbo, for getting the proper screen
    display = *(CGDirectDisplayID *)[[mode objectForKey:@"displayID"] longValue];
    originalDisplayMode = (NSDictionary *)CGDisplayCurrentMode(display);        
    NSArray *screens = [NSScreen screens];
    int i, count = [screens count];
    for (i = 0; i < count; i++) {
        CGDirectDisplayID id = (CGDirectDisplayID)[[[[screens objectAtIndex:i] deviceDescription] objectForKey:@"NSScreenNumber"] longValue];
        if (id == display) break;
    }
    if (i >= count) i = 0;

    // change display modes BEFORE creating pixel format to avoid invalid drawables
    CGRect owner = CGDisplayBounds(kCGDirectMainDisplay);
    if(fullscreen) {
        runningFullScreen = YES;
        CGDisplayHideCursor(display);
        CGCaptureAllDisplays();            // capturing only one display causes various problems, so capture all of them
        CGDisplaySwitchToMode(display, (CFDictionaryRef)dict);
    }

    // make window bounds, using new screen dimensions and adjusting for global positioning
    CGRect space = CGDisplayBounds(display);
    if(fullscreen) {
        frame = NSMakeRect(space.origin.x, (owner.size.height-space.size.height)-space.origin.y, space.size.width, space.size.height);
    } else {
        frame = NSMakeRect(0, 0, [[dict objectForKey:@"Width"] intValue], [[dict objectForKey:@"Height"] intValue]);
    }
    
    // create the window
    self = [super initWithContentRect:frame
        styleMask:(fullscreen?(NSBorderlessWindowMask):(NSTitledWindowMask | NSClosableWindowMask))
        backing:(fullscreen?NSBackingStoreRetained:NSBackingStoreBuffered)
        defer:NO
        screen:[screens objectAtIndex:i]];
    if (self) {
        BOOL failed = NO;

        // create the pixel format
        NSOpenGLPixelFormatAttribute *attr = g_PFAttr;
        int a = 0;
        attr[a++] = NSOpenGLPFARendererID; attr[a++] = format->rendererID;
#if FAST_HW
        if (fullscreen&&format->fullScreen) {
            attr[a++] = NSOpenGLPFAFullScreen;
            attr[a++] = NSOpenGLPFANoRecovery;
            attr[a++] = NSOpenGLPFAScreenMask; attr[a++] = CGDisplayIDToOpenGLDisplayMask(display);
        } else
#endif
        {
            attr[a++] = NSOpenGLPFAWindow;
        }
        if (m_Options.option & WGLDIAG_OPTION_MULTISAMPLE) {
            attr[a++] = NSOpenGLPFASampleBuffers; attr[a++] = 1;
            attr[a++] = NSOpenGLPFASamples; attr[a++] = m_Options.multisample;
        }
        attr[a++] = NSOpenGLPFADoubleBuffer;
        attr[a++] = NSOpenGLPFAColorSize; attr[a++] = [[dict objectForKey:@"BitsPerPixel"] intValue];
        attr[a++] = NSOpenGLPFADepthSize; attr[a++] = 16;
        attr[a++] = 0;
        
        NSOpenGLPixelFormat *pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];    
        
        if (pixFmt) {
            // create the view
            g_pGLView = view = [[NSOpenGLView alloc] initWithFrame:frame pixelFormat:pixFmt];
            if (view) {
                g_pNSGLC = [view openGLContext];
                [g_pNSGLC makeCurrentContext];

                // fix up for fullscreen mode
                if(fullscreen) {
                    [self setBackgroundColor:[NSColor blackColor]];
                    [self setHasShadow:NO];
                    [self setLevel:CGShieldingWindowLevel()];
                    [self setFrame:frame display:NO];        // center window on display in global coordinates
                }
                                
                // show the view, using HW pageflipping if possible
#if FAST_HW
                if (fullscreen&&format->fullScreen) {
                    CGLError err = CGLSetFullScreen(CGLGetCurrentContext());    // use CGL so we can trap the error
                    if (display == kCGDirectMainDisplay) [NSMenu setMenuBarVisible:NO];
                    if (err) failed = YES;
                } else
#endif
                {
                    [self setContentView:view];
                    [self makeKeyAndOrderFront:self];
                    if (![g_pNSGLC view])                                        // trap error
                        failed = YES;
                }
                        
                if (failed)        // i.e. "invalid memory allocation"
                    NSLog(@"Error attaching drawable");

                else             // prepare for rendering
                    [self initGL];
            }
            else { failed = YES; NSLog(@"Error creating view"); }
            [pixFmt release];
        }
        else { failed = YES; NSLog(@"Error creating pixel format"); }
        
        if (failed) {
            [self release];        // close window/exit fullscreen
            self = nil;
        }
    }
    return self;
}
Quote this message in a reply
Moderator
Posts: 102
Joined: 2003.07
Post: #3
The Thunder Blast source code from uDG uses this method for fullscreen...

Thunder Blast Source

-CarbonX
Quote this message in a reply
Member
Posts: 129
Joined: 2005.02
Post: #4
Any reason why I wouldn't see my colored clear screen in fullscreen window, but I would in a regular window, with this code:

Code:
    if (_fullscreen)
    {
        glWindow = [[NSWindow alloc] initWithContentRect: windowRect
                styleMask: NSBorderlessWindowMask
                backing: NSBackingStoreBuffered
                 defer: NO];
                                                                
        [glWindow setReleasedWhenClosed: YES];
        [glWindow setLevel: NSScreenSaverWindowLevel - 1];
    }
    else
    {
        glWindow = [[NSWindow alloc] initWithContentRect: windowRect
                styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask
                    backing: NSBackingStoreBuffered
                 defer: NO];
    }

        [glWindow setTitle: @"Title here"];
    [glContext_ setView: [glWindow contentView]];
    
    // position window & make Mac OS X / Cocoa friendly
    [glWindow center];
    [glWindow setReleasedWhenClosed: YES];
    [glWindow setAcceptsMouseMovedEvents: YES];
    [glWindow makeKeyAndOrderFront: nil];
    //[glWindow makeFirstResponder:glWindow];
    [glWindow flushWindow];
    
    [glContext_ makeCurrentContext];
                
    // draw something right away so we don't get garbage.
    //glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    glClearColor(0.8, 0.8, 1.0, 0.0);

    glClear(GL_COLOR_BUFFER_BIT);
    [glContext_ flushBuffer];
    glClearColor(0.8, 0.8, 1.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    [glContext_ flushBuffer];


Do I have to flag something special.
Quote this message in a reply
Member
Posts: 129
Joined: 2005.02
Post: #5
Also, the code is not shown, but I do capture displays and etc.
Quote this message in a reply
Member
Posts: 129
Joined: 2005.02
Post: #6
Ok, I figured it out actually. I had to implement that CGShieldingWindow()... I figured the screensaver level would be in front of this, but I guess its not?
Quote this message in a reply
Tasnu Arakun
Unregistered
 
Post: #7
here's an easy solution. at least it suits my needs.
http://www.cocoadevcentral.com/articles/000028.php
Quote this message in a reply
Member
Posts: 129
Joined: 2005.02
Post: #8
Well I got the whole thing working... I just ran into a bug(?)/error (see Obj-C thread)
Quote this message in a reply
Member
Posts: 129
Joined: 2005.02
Post: #9
If anyone cares, or runs into the same problem I did...
If you do not return to the main event loop after you switch your display. [[NSScreen maindisplay] frame]; WILL RETURN WRONG VALUES.

For example, if I am in 1600x1200, and switch to 640x480, and then back to 1600x1200, NSScreen will report that I am still in 640x480, making setting window coordinates a small pain. You just have to compensate by adjusting origin.y.

This only seems to be a problem if you initallly create your window in fullscreen mode... as opposed to a windowed mode, and toggle between window/fullscreen.
Quote this message in a reply
Post Reply