changing resolution in fullscreen

ghettotek
Unregistered
 
Post: #1
im trying to get my openGL context to go into full screen and change the screen resolution. so far, i can achieve full screen using this:

pixel format attribs:

NSOpenGLPixelFormatAttribute attr[] =
{
NSOpenGLPFAAllRenderers,//
NSOpenGLPFANoRecovery,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFAAlphaSize, 2,//
NSOpenGLPFAColorSize, 32,
NSOpenGLPFADepthSize, 32,
0 };

enter full screen:

unsigned int windowStyle;
NSRect contentRect;

StartingWindow=[NSApp keyWindow];
windowStyle=NSBorderlessWindowMask;
contentRect=[[NSScreen mainScreen] frame];
FullScreenWindow=[[NSWindow alloc] initWithContentRect:contentRect styleMask:windowStyle backing:NSBackingStoreBuffered defer:NO];
if(FullScreenWindow!=nil)
{
[FullScreenWindow setTitle:@""];
[FullScreenWindow setReleasedWhenClosed:YES];
[FullScreenWindow setContentView:self];
[FullScreenWindow makeKeyAndOrderFront:self];
[FullScreenWindow setLevel:NSScreenSaverWindowLevel-1];
[FullScreenWindow makeFirstResponder:self];
FullScreenOn=true;
}

now what i dont know how to do is change the resolution. can someone explain how? also, does [NSOpenGLContext setFullScreen] work? when i try it i get 'invalid drawable' but the view still works in window mode. any ideas? thanks.
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #2
Here's some code excerpts from CocoaBlitz:

my pixelformat.
Code:
NSOpenGLPixelFormatAttribute attr[] = {
            NSOpenGLPFADoubleBuffer,
            NSOpenGLPFAAccelerated,
            NSOpenGLPFAColorSize, BITS_PER_PIXEL,
            NSOpenGLPFADepthSize, DEPTH_SIZE,
            NSOpenGLPFAFullScreen,
            NSOpenGLPFAScreenMask,CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),​
            0 };
BITS_PER_PIXEL and DEPTH_SIZE are just the 32 in this case.
You'll need to include the ApplicationServices framework to do this next part.

for the switch to fullscreen I did this:
Code:
CFDictionaryRef newMode = CGDisplayBestModeForParameters(kCGDirectMainDisplay, BITS_PER_PIXEL, width, height, 0);
    NSAssert(newMode, @"Couldn't find display mode");
    
    savedMode = CGDisplayCurrentMode(kCGDirectMainDisplay);

    //fade out
    CGDisplayReservationInterval seconds = 2.0;
    CGDisplayFadeReservationToken newToken;
    CGAcquireDisplayFadeReservation(seconds, &newToken); // reserve display hardware time

    CGDisplayFade(newToken,
                  0.3,                // 0.3 seconds
                  kCGDisplayBlendNormal,    // Starting state
                  kCGDisplayBlendSolidColor,     // Ending state
                  0.0, 0.0, 0.0,        // black
                  true);            // wait for completion

    CGDisplayCapture(kCGDirectMainDisplay);        //capture main display

    //Switch to selected resolution.
    CGDisplayErr err = CGDisplaySwitchToMode(kCGDirectMainDisplay, newMode);
    NSAssert(err == CGDisplayNoErr, @"Error switching resolution.");

    [context setFullScreen];                //set openGL context to draw to screen
  

    CGDisplayFade(newToken,
                  0.5,                // 0.5 seconds
                  kCGDisplayBlendSolidColor,     // Starting state
                  kCGDisplayBlendNormal,    // Ending state
                  0.0, 0.0, 0.0,        // black
                  false);            // Don't wait for completion
    
    CGReleaseDisplayFadeReservation(newToken);

And another thing: be careful with fullscreen. I've had times when the app crashes in debug mode and project builder doesn't release the screen capture. I've had to do a hard reboot a couple of times now because of this.

Of course, if you want an easy solution, you can just use my CocoaBlitz framework to manage your OpenGL context.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
ghettotek
Unregistered
 
Post: #3
that fades the screen nicely, and even changes the resolution perfectly. but i still get invalid drawable and nothing shows up in full screen.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #4
You need to add NSOpenGLPFAFullScreen to your attributes. Note that you can't use the context for windowed mode once you do this.
Quote this message in a reply
ghettotek
Unregistered
 
Post: #5
i added the fullscreen attribute already, still invalid drawable.
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #6
try using my pixelformat verbatim. The allrenderers option is probably your problem. Also make sure that your screen depth matches your context depth (i.e. BITS_PER_PIXEL).

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
ghettotek
Unregistered
 
Post: #7
heres the code im using:

[SOURCECODE]
- (id)initWithFrame:(NSRect) frameRect
{

NSOpenGLPixelFormatAttribute attr[] = {
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFAColorSize, 32,
NSOpenGLPFADepthSize, 32,
NSOpenGLPFAFullScreen,
NSOpenGLPFAScreenMask,CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
0 };


// Create our pixel format
nsglFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];

// If the format isn't valid...
if(!nsglFormat)
NSLog(@"Pixel format is nil");
// Otherwise create the context...
self = [super initWithFrame:frameRect pixelFormat:nsglFormat];
// If we don't get a context...
if(!self)
NSLog(@"initWithFrame failed");

[self enterFullScreen];
// Otherwise, make the context current and continue
[[self openGLContext] makeCurrentContext];

return self;
}

-(void)enterFullScreen
{
CFDictionaryRef newMode = CGDisplayBestModeForParameters(kCGDirectMainDisplay, 32, 640, 480, 0);
NSAssert(newMode, @"Couldn't find display mode");

CFDictionaryRef savedMode = CGDisplayCurrentMode(kCGDirectMainDisplay);

//fade out
CGDisplayReservationInterval seconds = 2.0;
CGDisplayFadeReservationToken newToken;
CGAcquireDisplayFadeReservation(seconds, &newToken); // reserve display hardware time

CGDisplayFade(newToken,
0.3, // 0.3 seconds
kCGDisplayBlendNormal, // Starting state
kCGDisplayBlendSolidColor, // Ending state
0.0, 0.0, 0.0, // black
true); // wait for completion

CGDisplayCapture(kCGDirectMainDisplay); //capture main display

//Switch to selected resolution.
CGDisplayErr err = CGDisplaySwitchToMode(kCGDirectMainDisplay, newMode);
NSAssert(err == CGDisplayNoErr, @"Error switching resolution.");

[[self openGLContext] setFullScreen]; //set openGL context to draw to screen


CGDisplayFade(newToken,
0.5, // 0.5 seconds
kCGDisplayBlendSolidColor, // Starting state
kCGDisplayBlendNormal, // Ending state
0.0, 0.0, 0.0, // black
false); // Don't wait for completion

CGReleaseDisplayFadeReservation(newToken);





/*
unsigned int windowStyle;
NSRect contentRect;

StartingWindow=[NSApp keyWindow];
windowStyle=NSBorderlessWindowMask;
contentRect=[[NSScreen mainScreen] frame];
FullScreenWindow=[[NSWindow alloc] initWithContentRect:contentRect styleMask:windowStyle backing:NSBackingStoreBuffered defer:NO];
if(FullScreenWindow!=nil)
{
[FullScreenWindow setTitle:@""];
[FullScreenWindow setReleasedWhenClosed:YES];
[FullScreenWindow setContentView:self];
[FullScreenWindow makeKeyAndOrderFront:self];
[FullScreenWindow setLevel:NSScreenSaverWindowLevel-1];
[FullScreenWindow makeFirstResponder:self];
FullScreenOn=true;
}
*/

}

[/SOURCECODE]

the /*....*/ commented code at the end is what i used to actually get the NSOpenGLView to draw in full screen mode, but it doesnt change the resolution, and runs horribly slow (+-50% drop in frame rate).

im calling your enterFullScreen code before [[self openGLContext] makeCurrentContext]; in the initWithFrame() method. that causes the screen to fade black and the resolution to change to 640x480. but i still get "invalid drawable" in the log and nothing shows up. when i quit, a little bit of beachball action and then the screen goes wacko as it switches from 640x480 back to the original resolution. if i call the enterFullScreen() code after [[self openGLContext] makeCurrentContext];, then i just get "invalid drawable" in the log and my window shows regularly but with nothing in the NSOpenGLView (but white). thanks for your help.

p.s.
how do i properly exit fullscreen mode?
Quote this message in a reply
blb
Unregistered
 
Post: #8
One thing to know for fullscreen, you need to switch modes prior to creating your NSOpenGLPixelFormat object.

To return to windowed mode, you can either use CGRestorePermanentDisplayConfiguration() (which I believe is 10.2-specific), or save off the display's current mode (with CGDisplayCurrentMode()) before switching to fullscreen, and use that to switch back.
Quote this message in a reply
ghettotek
Unregistered
 
Post: #9
ok i call the enterFullScreen code before i do the pixelFormat stuff (in initWithFrameSmile. now it fades to black, changes resolution, and i get "invalid drawable" still, and nothing shows in full screen mode. when i exit fullscreen however, the screen goes nuts, and then it goes back to normal, but in 640x480, and the window view has the 3D view and updates it fine. am i missing something?
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #10
Quote:One thing to know for fullscreen, you need to switch modes prior to creating your NSOpenGLPixelFormat object.
This is not the case. Instantiating a pixel format has nothing to do with the state of the screen or any drawables.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #11
I think I know your problem. The OpenGLContext that the NSOpenGLView creates can't be used for fullscreen. My code creates its own context, which is what I thought you were doing. Anyhow, to fix the problem alloc and init your own context and use that instead of the NSOpenGLView.
Code:
context = [[NSOpenGLContext alloc] initWithFormat:nsglFormat shareContext:nil];

Send all your gl to this context and everything should work fine. You will of course have to call context flushBuffer and such for drawing.

As for exiting from fullscreen use the following code:
Code:
CGDisplayReservationInterval seconds = 2.0;
    CGDisplayFadeReservationToken newToken;
    CGAcquireDisplayFadeReservation(seconds, &newToken); // reserve display hardware time

    CGDisplayFade(newToken,
                  0.3,                // 0.3 seconds
                  kCGDisplayBlendNormal,    // Starting state
                  kCGDisplayBlendSolidColor,     // Ending state
                  0.0, 0.0, 0.0,        // black
                  true);            // wait for completion
    
    [context clearDrawable];
    CGDisplaySwitchToMode(kCGDirectMainDisplay, savedMode);
    
    CGDisplayFade(newToken,
                  0.5,                // 0.5 seconds
                  kCGDisplayBlendSolidColor,     // Starting state
                  kCGDisplayBlendNormal,    // Ending state
                  0.0, 0.0, 0.0,        // black
                  true);            // Don't wait for completion

    CGReleaseDisplayFadeReservation(newToken);
    CGDisplayRelease(kCGDirectMainDisplay);

have fun

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
blb
Unregistered
 
Post: #12
Quote:Originally posted by kelvin
This is not the case. Instantiating a pixel format has [b]nothing to do with the state of the screen or any drawables. [/b]

Has for me for months (including two minutes ago). If I capture, hide cursor, and switch mode after instantiating an NSOpenGLPixelFormat, I receive the fun "invalid drawable" error. As soon as I rearrange the code to capture, hide, and switch first, all works.
Quote this message in a reply
ghettotek
Unregistered
 
Post: #13
ok kelvin. if in instantiate my own context, how would i do so and still be able to use my custom NSOpenGLView class?

[self openGLContext] = [[NSOpenGLContext alloc] initWithFormat:nsglFormat shareContext:nil]; ?
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #14
it's full screen. you don't need an NSView. just make the context, set it fullscreen, make it current, send your GL to it, and flushContext. Remember that OpenGL is not thread safe, so if you are multithreading, you need to use NSLocks.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
ghettotek
Unregistered
 
Post: #15
ok i got it to stop saying "invalid drawble", but still nothing but black shows up in full screen. heres my new code:

i have 1 window made in Interface Builder, and in the window code, i have an object, OGLView *mainview;. OGLView is my custom NSOpenGLView.

first, the OGLWindow awakeFromNib() event starts everything
[sourcecode]
@implementation OGLWindow
-(void) awakeFromNib
{
mainView = [[OGLView alloc] initWithFrame:[self frame]];
[mainView initialize]; //initGL
[mainView enterFullScreen:NSMakeRect( 0, 0, 800, 600 )];
}
.....
[/sourcecode]

the custom OGLView is created by OGLWindow, then the OGLView is initialized, then the OGLView goes into full screen.
[sourcecode]
@implementation OGLView
- (id)initWithFrame:(NSRect) frameRect
{
NSOpenGLPixelFormat *pixelFormat;

runningFullScreen = TRUE;

originalDisplayMode = (NSDictionary *) CGDisplayCurrentMode(kCGDirectMainDisplay);
pixelFormat = [ self createPixelFormat:frameRect ];

self = [super initWithFrame:frameRect pixelFormat:pixelFormat];
[pixelFormat release];

[[self openGLContext] makeCurrentContext];
[[ self openGLContext] setFullScreen];
[self reshape];

return self;
}

- (NSOpenGLPixelFormat *) createPixelFormat:(NSRect)frame
{
NSOpenGLPixelFormatAttribute pixelAttribs[ 16 ];
int pixNum = 0;
NSDictionary *fullScreenMode;
NSOpenGLPixelFormat *pixelFormat;

pixelAttribs[ pixNum++ ] = NSOpenGLPFADoubleBuffer;
pixelAttribs[ pixNum++ ] = NSOpenGLPFAAccelerated;
pixelAttribs[ pixNum++ ] = NSOpenGLPFAColorSize;
pixelAttribs[ pixNum++ ] = 32;
pixelAttribs[ pixNum++ ] = NSOpenGLPFADepthSize;
pixelAttribs[ pixNum++ ] = 32;

if( runningFullScreen==TRUE ) // Do this before getting the pixel format
{
pixelAttribs[ pixNum++ ] = NSOpenGLPFAFullScreen;
fullScreenMode = (NSDictionary *) CGDisplayBestModeForParameters(
kCGDirectMainDisplay,
32, frame.size.width,
frame.size.height, NULL );
CGDisplayCapture( kCGDirectMainDisplay );
CGDisplayHideCursor( kCGDirectMainDisplay );
CGDisplaySwitchToMode( kCGDirectMainDisplay,
(CFDictionaryRef) fullScreenMode );
}
pixelAttribs[ pixNum ] = 0;
pixelFormat = [ [ NSOpenGLPixelFormat alloc ]
initWithAttributes:pixelAttribs ];

return pixelFormat;
}

-(void)enterFullScreen:(NSRect)frame
{
BOOL success = FALSE;
NSOpenGLPixelFormat *pixelFormat;
NSOpenGLContext *newContext;

[ [ self openGLContext ] clearDrawable ];
pixelFormat = [ self createPixelFormat:frame ];
if( pixelFormat != nil )
{
newContext = [ [ NSOpenGLContext alloc ] initWithFormat:pixelFormat
shareContext:nil ];
if( newContext != nil )
{
[ self setFrame:frame ];
[ self setOpenGLContext:newContext ];
[ newContext makeCurrentContext ];
[ newContext setFullScreen ];
[ self reshape ];
}
[ pixelFormat release ];
}
}

-(void)exitFullScreen
{
CGDisplaySwitchToMode( kCGDirectMainDisplay,
(CFDictionaryRef) originalDisplayMode );
CGDisplayShowCursor( kCGDirectMainDisplay );
CGDisplayRelease( kCGDirectMainDisplay );
}
[/sourcecode]

when i exitFullScreen, the screen goes wacko still, but thats nothing. id just like to see everything in full screen.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  DPI and Resolution for Graphics mickyg 9 8,124 Apr 27, 2012 03:02 PM
Last Post: Andres Calil
  Changing Pixel Values using CG LIPH700 1 4,323 Nov 25, 2010 03:17 PM
Last Post: SethWillits
  Changing resolution while already in full-screen mode? Malarkey 1 2,498 Jun 10, 2008 07:49 PM
Last Post: AnotherJake
  Fullscreen/resolution switch causes texture loss IBethune 4 4,006 Feb 21, 2008 01:37 PM
Last Post: OneSadCookie
  Effifcient State Changing Nick 7 3,384 Apr 6, 2006 06:33 AM
Last Post: TomorrowPlusX