GLFWAPI void GLFWAPIENTRY glfwCloseWindow( void ) { if( !_glfwInitialized ) { return; } // Show mouse pointer again (if hidden) glfwEnable( GLFW_MOUSE_CURSOR ); _glfwPlatformCloseWindow(); memset( &_glfwWin, 0, sizeof(_glfwWin) ); }
GLFWAPI void GLFWAPIENTRY glfwCloseWindow( void ) { // Is GLFW initialized? if( !_glfwInitialized ) { return; } // Show mouse pointer again (if hidden) glfwEnable( GLFW_MOUSE_CURSOR ); // Close window _glfwPlatformCloseWindow(); // Window is no longer opened _glfwWin.Opened = GL_FALSE; }
int _glfwPlatformOpenWindow( int width, int height, int redbits, int greenbits, int bluebits, int alphabits, int depthbits, int stencilbits, int mode, _GLFWhints* hints ) { OSStatus error; ProcessSerialNumber psn; unsigned int windowAttributes; // TO DO: Refactor this function! _glfwWin.WindowFunctions = ( _glfwWin.Fullscreen ? &_glfwMacFSWindowFunctions : &_glfwMacDWWindowFunctions ); // Windowed or fullscreen; AGL or CGL? Quite the mess... // AGL appears to be the only choice for attaching OpenGL contexts to // Carbon windows, but it leaves the user no control over fullscreen // mode stretching. Solution: AGL for windowed, CGL for fullscreen. if( !_glfwWin.Fullscreen ) { // create AGL pixel format attribute list GLint AGLpixelFormatAttributes[256]; int numAGLAttrs = 0; AGLpixelFormatAttributes[numAGLAttrs++] = AGL_RGBA; AGLpixelFormatAttributes[numAGLAttrs++] = AGL_DOUBLEBUFFER; if( hints->Stereo ) { AGLpixelFormatAttributes[numAGLAttrs++] = AGL_STEREO; } _setAGLAttribute( AGL_AUX_BUFFERS, hints->AuxBuffers); _setAGLAttribute( AGL_RED_SIZE, redbits ); _setAGLAttribute( AGL_GREEN_SIZE, greenbits ); _setAGLAttribute( AGL_BLUE_SIZE, bluebits ); _setAGLAttribute( AGL_ALPHA_SIZE, alphabits ); _setAGLAttribute( AGL_DEPTH_SIZE, depthbits ); _setAGLAttribute( AGL_STENCIL_SIZE, stencilbits ); _setAGLAttribute( AGL_ACCUM_RED_SIZE, hints->AccumRedBits ); _setAGLAttribute( AGL_ACCUM_GREEN_SIZE, hints->AccumGreenBits ); _setAGLAttribute( AGL_ACCUM_BLUE_SIZE, hints->AccumBlueBits ); _setAGLAttribute( AGL_ACCUM_ALPHA_SIZE, hints->AccumAlphaBits ); if( hints->Samples > 1 ) { _setAGLAttribute( AGL_SAMPLE_BUFFERS_ARB, 1 ); _setAGLAttribute( AGL_SAMPLES_ARB, hints->Samples ); AGLpixelFormatAttributes[numAGLAttrs++] = AGL_NO_RECOVERY; } AGLpixelFormatAttributes[numAGLAttrs++] = AGL_NONE; // create pixel format descriptor AGLDevice mainMonitor = GetMainDevice(); AGLPixelFormat pixelFormat = aglChoosePixelFormat( &mainMonitor, 1, AGLpixelFormatAttributes ); if( pixelFormat == NULL ) { fprintf( stderr, "glfwOpenWindow failing because it can't create a pixel format\n" ); return GL_FALSE; } // store pixel format's values for _glfwPlatformGetWindowParam's use _getAGLAttribute( AGL_ACCELERATED, _glfwWin.Accelerated ); _getAGLAttribute( AGL_RED_SIZE, _glfwWin.RedBits ); _getAGLAttribute( AGL_GREEN_SIZE, _glfwWin.GreenBits ); _getAGLAttribute( AGL_BLUE_SIZE, _glfwWin.BlueBits ); _getAGLAttribute( AGL_ALPHA_SIZE, _glfwWin.AlphaBits ); _getAGLAttribute( AGL_DEPTH_SIZE, _glfwWin.DepthBits ); _getAGLAttribute( AGL_STENCIL_SIZE, _glfwWin.StencilBits ); _getAGLAttribute( AGL_ACCUM_RED_SIZE, _glfwWin.AccumRedBits ); _getAGLAttribute( AGL_ACCUM_GREEN_SIZE, _glfwWin.AccumGreenBits ); _getAGLAttribute( AGL_ACCUM_BLUE_SIZE, _glfwWin.AccumBlueBits ); _getAGLAttribute( AGL_ACCUM_ALPHA_SIZE, _glfwWin.AccumAlphaBits ); _getAGLAttribute( AGL_AUX_BUFFERS, _glfwWin.AuxBuffers ); _getAGLAttribute( AGL_STEREO, _glfwWin.Stereo ); _getAGLAttribute( AGL_SAMPLES_ARB, _glfwWin.Samples ); _glfwWin.RefreshRate = hints->RefreshRate; // create AGL context _glfwWin.AGLContext = aglCreateContext( pixelFormat, NULL ); aglDestroyPixelFormat( pixelFormat ); if( _glfwWin.AGLContext == NULL ) { fprintf( stderr, "glfwOpenWindow failing because it can't create an OpenGL context\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } if (_glfwLibrary.Unbundled) { if( GetCurrentProcess( &psn ) != noErr ) { fprintf( stderr, "glfwOpenWindow failing because it can't get its PSN\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } if( TransformProcessType( &psn, kProcessTransformToForegroundApplication ) != noErr ) { fprintf( stderr, "glfwOpenWindow failing because it can't become a foreground application\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } /* Keith Bauer 2007-07-12 - I don't believe this is desirable if( SetFrontProcess( &psn ) != noErr ) { fprintf( stderr, "glfwOpenWindow failing because it can't become the front process\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } */ } // create window Rect windowContentBounds; windowContentBounds.left = 0; windowContentBounds.top = 0; windowContentBounds.right = width; windowContentBounds.bottom = height; windowAttributes = ( kWindowCloseBoxAttribute \ | kWindowCollapseBoxAttribute \ | kWindowStandardHandlerAttribute ); if( hints->WindowNoResize ) { windowAttributes |= kWindowLiveResizeAttribute; } else { windowAttributes |= ( kWindowFullZoomAttribute | kWindowResizableAttribute ); } error = CreateNewWindow( kDocumentWindowClass, windowAttributes, &windowContentBounds, &( _glfwWin.MacWindow ) ); if( ( error != noErr ) || ( _glfwWin.MacWindow == NULL ) ) { fprintf( stderr, "glfwOpenWindow failing because it can't create a window\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } _glfwWin.WindowUPP = NewEventHandlerUPP( _glfwWindowEventHandler ); error = InstallWindowEventHandler( _glfwWin.MacWindow, _glfwWin.WindowUPP, GetEventTypeCount( GLFW_WINDOW_EVENT_TYPES ), GLFW_WINDOW_EVENT_TYPES, NULL, NULL ); if( error != noErr ) { fprintf( stderr, "glfwOpenWindow failing because it can't install window event handlers\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } // Don't care if we fail here (void)SetWindowTitleWithCFString( _glfwWin.MacWindow, CFSTR( "GLFW Window" ) ); (void)RepositionWindow( _glfwWin.MacWindow, NULL, kWindowCenterOnMainScreen ); if( !aglSetDrawable( _glfwWin.AGLContext, GetWindowPort( _glfwWin.MacWindow ) ) ) { fprintf( stderr, "glfwOpenWindow failing because it can't draw to the window\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } // Make OpenGL context current if( !aglSetCurrentContext( _glfwWin.AGLContext ) ) { fprintf( stderr, "glfwOpenWindow failing because it can't make the OpenGL context current\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } // show window ShowWindow( _glfwWin.MacWindow ); return GL_TRUE; } else { CGDisplayErr cgErr; CGLError cglErr; CFDictionaryRef optimalMode; CGLPixelFormatObj CGLpfObj; long numCGLvs = 0; CGLPixelFormatAttribute CGLpixelFormatAttributes[64]; int numCGLAttrs = 0; // variables for enumerating color depths GLint rgbColorDepth; GLint rgbaAccumDepth = 0; int rgbChannelDepth = 0; // CGL pixel format attributes _setCGLAttribute( kCGLPFADisplayMask, CGDisplayIDToOpenGLDisplayMask( kCGDirectMainDisplay ) ); if( hints->Stereo ) { CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAStereo; } if( hints->Samples > 1 ) { _setCGLAttribute( kCGLPFASamples, (CGLPixelFormatAttribute)hints->Samples ); _setCGLAttribute( kCGLPFASampleBuffers, (CGLPixelFormatAttribute)1 ); CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFANoRecovery; } CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAFullScreen; CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFADoubleBuffer; CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAAccelerated; CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFANoRecovery; CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAMinimumPolicy; _setCGLAttribute( kCGLPFAAccumSize, (CGLPixelFormatAttribute)( hints->AccumRedBits \ + hints->AccumGreenBits \ + hints->AccumBlueBits \ + hints->AccumAlphaBits ) ); _setCGLAttribute( kCGLPFAAlphaSize, (CGLPixelFormatAttribute)alphabits ); _setCGLAttribute( kCGLPFADepthSize, (CGLPixelFormatAttribute)depthbits ); _setCGLAttribute( kCGLPFAStencilSize, (CGLPixelFormatAttribute)stencilbits ); _setCGLAttribute( kCGLPFAAuxBuffers, (CGLPixelFormatAttribute)hints->AuxBuffers ); CGLpixelFormatAttributes[ numCGLAttrs++ ] = (CGLPixelFormatAttribute)NULL; // create a suitable pixel format with above attributes.. cglErr = CGLChoosePixelFormat( CGLpixelFormatAttributes, &CGLpfObj, &numCGLvs ); if( cglErr != kCGLNoError ) { return GL_FALSE; } // ..and create a rendering context using that pixel format cglErr = CGLCreateContext( CGLpfObj, NULL, &_glfwWin.CGLContext ); if( cglErr != kCGLNoError ) { return GL_FALSE; } // enumerate depth of RGB channels - unlike AGL, CGL works with // a single parameter reflecting the full depth of the frame buffer (void)CGLDescribePixelFormat( CGLpfObj, 0, kCGLPFAColorSize, &rgbColorDepth ); if( rgbColorDepth == 24 || rgbColorDepth == 32 ) { rgbChannelDepth = 8; } if( rgbColorDepth == 16 ) { rgbChannelDepth = 5; } // get pixel depth of accumulator - I haven't got the slightest idea // how this number conforms to any other channel depth than 8 bits, // so this might end up giving completely knackered results... (void)CGLDescribePixelFormat( CGLpfObj, 0, kCGLPFAAccumSize, &rgbaAccumDepth ); if( rgbaAccumDepth == 32 ) { rgbaAccumDepth = 8; } // store values of pixel format for _glfwPlatformGetWindowParam's use _getCGLAttribute( kCGLPFAAccelerated, _glfwWin.Accelerated ); _getCGLAttribute( rgbChannelDepth, _glfwWin.RedBits ); _getCGLAttribute( rgbChannelDepth, _glfwWin.GreenBits ); _getCGLAttribute( rgbChannelDepth, _glfwWin.BlueBits ); _getCGLAttribute( kCGLPFAAlphaSize, _glfwWin.AlphaBits ); _getCGLAttribute( kCGLPFADepthSize, _glfwWin.DepthBits ); _getCGLAttribute( kCGLPFAStencilSize, _glfwWin.StencilBits ); _getCGLAttribute( rgbaAccumDepth, _glfwWin.AccumRedBits ); _getCGLAttribute( rgbaAccumDepth, _glfwWin.AccumGreenBits ); _getCGLAttribute( rgbaAccumDepth, _glfwWin.AccumBlueBits ); _getCGLAttribute( rgbaAccumDepth, _glfwWin.AccumAlphaBits ); _getCGLAttribute( kCGLPFAAuxBuffers, _glfwWin.AuxBuffers ); _getCGLAttribute( kCGLPFAStereo, _glfwWin.Stereo ); _glfwWin.RefreshRate = hints->RefreshRate; // destroy our pixel format (void)CGLDestroyPixelFormat( CGLpfObj ); // capture the display for our application cgErr = CGCaptureAllDisplays(); if( cgErr != kCGErrorSuccess ) { return GL_FALSE; } // find closest matching NON-STRETCHED display mode.. optimalMode = CGDisplayBestModeForParametersAndRefreshRateWithProperty( kCGDirectMainDisplay, rgbColorDepth, width, /* Check further to the right -> */ height, hints->RefreshRate, NULL, NULL ); if( optimalMode == NULL ) { return GL_FALSE; } // ..and switch to that mode cgErr = CGDisplaySwitchToMode( kCGDirectMainDisplay, optimalMode ); if( cgErr != kCGErrorSuccess ) { return GL_FALSE; } // switch to our OpenGL context, and bring it up fullscreen cglErr = CGLSetCurrentContext( _glfwWin.CGLContext ); if( cglErr != kCGLNoError ) { return GL_FALSE; } cglErr = CGLSetFullScreen( _glfwWin.CGLContext ); if( cglErr != kCGLNoError ) { return GL_FALSE; } return GL_TRUE; } }
int _glfwPlatformOpenWindow( int width, int height, int redbits, int greenbits, int bluebits, int alphabits, int depthbits, int stencilbits, int mode, int accumredbits, int accumgreenbits, int accumbluebits, int accumalphabits, int auxbuffers, int stereo, int refreshrate ) { struct TagItem tagList[ 25 ]; int tagNR, accumbits; // Calculate sum of accumulator bits accumbits = accumredbits + accumgreenbits + accumbluebits + accumalphabits; // Clear window state _glfwWin.Screen = NULL; _glfwWin.Window = NULL; _glfwWin.Context = NULL; _glfwWin.PointerHidden = 0; _glfwWin.PointerSprite = NULL; _glfwWin.InputMP = NULL; _glfwWin.InputIO = NULL; // Create input.device message port if( !(_glfwWin.InputMP = CreatePort( NULL, 0 )) ) { _glfwPlatformCloseWindow(); return GL_FALSE; } // Create input.device I/O request if( !(_glfwWin.InputIO = (struct IOStdReq *) CreateExtIO( _glfwWin.InputMP, sizeof(struct IOStdReq) )) ) { _glfwPlatformCloseWindow(); return GL_FALSE; } // Open input.device (for pointer position manipulation) if( OpenDevice( "input.device", 0, (struct IORequest *)_glfwWin.InputIO, 0 ) ) { DeleteExtIO( (struct IORequest *) _glfwWin.InputIO ); _glfwWin.InputIO = NULL; _glfwPlatformCloseWindow(); return GL_FALSE; } // Do we want fullscreen? if( _glfwWin.Fullscreen ) { // Open a new Amiga screen if( !_glfwOpenScreen( &width, &height, &redbits, &greenbits, &bluebits, refreshrate ) ) { _glfwWin.Fullscreen = GL_FALSE; } } // Select window properties tagNR = 0; tagList[ tagNR ].ti_Tag = WA_Left; tagList[ tagNR++ ].ti_Data = 0; tagList[ tagNR ].ti_Tag = WA_Top; tagList[ tagNR++ ].ti_Data = 0; tagList[ tagNR ].ti_Tag = WA_IDCMP; tagList[ tagNR++ ].ti_Data = IDCMP_REFRESHWINDOW | IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_RAWKEY | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS; tagList[ tagNR ].ti_Tag = WA_ReportMouse; tagList[ tagNR++ ].ti_Data = TRUE; tagList[ tagNR ].ti_Tag = WA_RMBTrap; tagList[ tagNR++ ].ti_Data = TRUE; tagList[ tagNR ].ti_Tag = WA_NoCareRefresh; tagList[ tagNR++ ].ti_Data = FALSE; tagList[ tagNR ].ti_Tag = WA_SimpleRefresh; tagList[ tagNR++ ].ti_Data = TRUE; tagList[ tagNR ].ti_Tag = WA_Activate; tagList[ tagNR++ ].ti_Data = TRUE; tagList[ tagNR ].ti_Tag = WA_CloseGadget; tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? FALSE : TRUE; tagList[ tagNR ].ti_Tag = WA_SizeGadget; tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? FALSE : ( _glfwWinHints.WindowNoResize ? FALSE : TRUE ); tagList[ tagNR ].ti_Tag = WA_DepthGadget; tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? FALSE : TRUE; tagList[ tagNR ].ti_Tag = WA_DragBar; tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? FALSE : TRUE; tagList[ tagNR ].ti_Tag = WA_Borderless; tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? TRUE : FALSE; tagList[ tagNR ].ti_Tag = WA_Backdrop; tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? TRUE : FALSE; if( _glfwWin.Fullscreen ) { tagList[ tagNR ].ti_Tag = WA_CustomScreen; tagList[ tagNR++ ].ti_Data = (ULONG) _glfwWin.Screen; tagList[ tagNR ].ti_Tag = WA_Width; tagList[ tagNR++ ].ti_Data = width; tagList[ tagNR ].ti_Tag = WA_Height; tagList[ tagNR++ ].ti_Data = height; } else { tagList[ tagNR ].ti_Tag = WA_GimmeZeroZero; tagList[ tagNR++ ].ti_Data = TRUE; tagList[ tagNR ].ti_Tag = WA_InnerWidth; tagList[ tagNR++ ].ti_Data = width; tagList[ tagNR ].ti_Tag = WA_InnerHeight; tagList[ tagNR++ ].ti_Data = height; tagList[ tagNR ].ti_Tag = WA_MinWidth; tagList[ tagNR++ ].ti_Data = 20; tagList[ tagNR ].ti_Tag = WA_MinHeight; tagList[ tagNR++ ].ti_Data = 20; tagList[ tagNR ].ti_Tag = WA_MaxWidth; tagList[ tagNR++ ].ti_Data = 9999; tagList[ tagNR ].ti_Tag = WA_MaxHeight; tagList[ tagNR++ ].ti_Data = 9999; tagList[ tagNR ].ti_Tag = WA_Title; tagList[ tagNR++ ].ti_Data = (ULONG) "GLFW Window"; tagList[ tagNR ].ti_Tag = WA_ScreenTitle; tagList[ tagNR++ ].ti_Data = (ULONG) "GLFW Application"; } tagList[ tagNR ].ti_Tag = TAG_DONE; // Open window _glfwWin.Window = OpenWindowTagList( NULL, tagList ); if( !_glfwWin.Window ) { _glfwPlatformCloseWindow(); return GL_FALSE; } // Fullscreen/windowed post fixups if( _glfwWin.Fullscreen ) { // Don't show screen title ShowTitle( _glfwWin.Screen, FALSE ); // Remember window size _glfwWin.Width = _glfwWin.Window->Width; _glfwWin.Height = _glfwWin.Window->Height; } else { // If we are not in fullscreen mode, get screen handle from window _glfwWin.Screen = _glfwWin.Window->WScreen; // Get ModeID for the current video mode _glfwWin.ModeID = GetVPModeID( &_glfwWin.Screen->ViewPort ); // Remember window size _glfwWin.Width = _glfwWin.Window->GZZWidth; _glfwWin.Height = _glfwWin.Window->GZZHeight; } // Put window on top WindowToFront( _glfwWin.Window ); // Create OpenGL context #ifdef _GLFW_STORMMESA tagNR = 0; tagList[ tagNR ].ti_Tag = AMA_Window; tagList[ tagNR++ ].ti_Data = (ULONG) _glfwWin.Window; tagList[ tagNR ].ti_Tag = AMA_RastPort; tagList[ tagNR++ ].ti_Data = (ULONG) _glfwWin.Window->RPort; tagList[ tagNR ].ti_Tag = AMA_Screen; tagList[ tagNR++ ].ti_Data = (ULONG) _glfwWin.Screen; tagList[ tagNR ].ti_Tag = AMA_Left; tagList[ tagNR++ ].ti_Data = 0; tagList[ tagNR ].ti_Tag = AMA_Bottom; tagList[ tagNR++ ].ti_Data = 0; tagList[ tagNR ].ti_Tag = AMA_Width; tagList[ tagNR++ ].ti_Data = _glfwWin.Width; tagList[ tagNR ].ti_Tag = AMA_Height; tagList[ tagNR++ ].ti_Data = _glfwWin.Height; tagList[ tagNR ].ti_Tag = AMA_DoubleBuf; tagList[ tagNR++ ].ti_Data = GL_TRUE; tagList[ tagNR ].ti_Tag = AMA_RGBMode; tagList[ tagNR++ ].ti_Data = GL_TRUE; tagList[ tagNR ].ti_Tag = AMA_AlphaFlag; tagList[ tagNR++ ].ti_Data = alphabits ? GL_TRUE : GL_FALSE; tagList[ tagNR ].ti_Tag = AMA_NoDepth; tagList[ tagNR++ ].ti_Data = depthbits ? GL_FALSE : GL_TRUE; tagList[ tagNR ].ti_Tag = AMA_NoStencil; tagList[ tagNR++ ].ti_Data = stencilbits ? GL_FALSE : GL_TRUE; tagList[ tagNR ].ti_Tag = AMA_NoAccum; tagList[ tagNR++ ].ti_Data = accumbits ? GL_FALSE : GL_TRUE; tagList[ tagNR ].ti_Tag = AMA_DirectRender; tagList[ tagNR++ ].ti_Data = GL_TRUE; tagList[ tagNR ].ti_Tag = AMA_DrawMode; tagList[ tagNR++ ].ti_Data = AMESA_AGA_C2P; tagList[ tagNR ].ti_Tag = TAG_DONE; _glfwWin.Context = AmigaMesaCreateContext( tagList ); #endif if( !_glfwWin.Context ) { _glfwPlatformCloseWindow(); return GL_FALSE; } // Make current #ifdef _GLFW_STORMMESA AmigaMesaMakeCurrent( _glfwWin.Context, _glfwWin.Context->buffer ); #endif return GL_TRUE; }
GLFWAPI int GLFWAPIENTRY glfwOpenWindow( int width, int height, int redbits, int greenbits, int bluebits, int alphabits, int depthbits, int stencilbits, int mode ) { _GLFWfbconfig fbconfig; _GLFWwndconfig wndconfig; // Is GLFW initialized? if( !_glfwInitialized || _glfwWin.opened ) { return GL_FALSE; } // Set up desired framebuffer config fbconfig.redBits = Max( redbits, 0 ); fbconfig.greenBits = Max( greenbits, 0 ); fbconfig.blueBits = Max( bluebits, 0 ); fbconfig.alphaBits = Max( alphabits, 0 ); fbconfig.depthBits = Max( depthbits, 0 ); fbconfig.stencilBits = Max( stencilbits, 0 ); fbconfig.accumRedBits = Max( _glfwLibrary.hints.accumRedBits, 0 ); fbconfig.accumGreenBits = Max( _glfwLibrary.hints.accumGreenBits, 0 ); fbconfig.accumBlueBits = Max( _glfwLibrary.hints.accumBlueBits, 0 ); fbconfig.accumAlphaBits = Max( _glfwLibrary.hints.accumAlphaBits, 0 ); fbconfig.auxBuffers = Max( _glfwLibrary.hints.auxBuffers, 0 ); fbconfig.stereo = _glfwLibrary.hints.stereo ? GL_TRUE : GL_FALSE; fbconfig.samples = Max( _glfwLibrary.hints.samples, 0 ); // Set up desired window config wndconfig.mode = mode; wndconfig.refreshRate = Max( _glfwLibrary.hints.refreshRate, 0 ); wndconfig.windowNoResize = _glfwLibrary.hints.windowNoResize ? GL_TRUE : GL_FALSE; wndconfig.glMajor = Max( _glfwLibrary.hints.glMajor, 1 ); wndconfig.glMinor = Max( _glfwLibrary.hints.glMinor, 0 ); wndconfig.glForward = _glfwLibrary.hints.glForward ? GL_TRUE : GL_FALSE; wndconfig.glDebug = _glfwLibrary.hints.glDebug ? GL_TRUE : GL_FALSE; wndconfig.glProfile = _glfwLibrary.hints.glProfile; if( wndconfig.glMajor == 1 && wndconfig.glMinor > 5 ) { // OpenGL 1.x series ended with version 1.5 return GL_FALSE; } else if( wndconfig.glMajor == 2 && wndconfig.glMinor > 1 ) { // OpenGL 2.x series ended with version 2.1 return GL_FALSE; } else if( wndconfig.glMajor == 3 && wndconfig.glMinor > 3 ) { // OpenGL 3.x series ended with version 3.3 return GL_FALSE; } else { // For now, let everything else through } if( wndconfig.glProfile && ( wndconfig.glMajor < 3 || ( wndconfig.glMajor == 3 && wndconfig.glMinor < 2 ) ) ) { // Context profiles are only defined for OpenGL version 3.2 and above return GL_FALSE; } if( wndconfig.glForward && wndconfig.glMajor < 3 ) { // Forward-compatible contexts are only defined for OpenGL version 3.0 and above return GL_FALSE; } // Clear for next open call _glfwClearWindowHints(); // Check input arguments if( mode != GLFW_WINDOW && mode != GLFW_FULLSCREEN ) { return GL_FALSE; } // Clear GLFW window state _glfwWin.active = GL_TRUE; _glfwWin.iconified = GL_FALSE; _glfwWin.mouseLock = GL_FALSE; _glfwWin.autoPollEvents = GL_TRUE; _glfwClearInput(); // Unregister all callback functions _glfwWin.windowSizeCallback = NULL; _glfwWin.windowCloseCallback = NULL; _glfwWin.windowRefreshCallback = NULL; _glfwWin.keyCallback = NULL; _glfwWin.charCallback = NULL; _glfwWin.mousePosCallback = NULL; _glfwWin.mouseButtonCallback = NULL; _glfwWin.mouseWheelCallback = NULL; // Check width & height if( width > 0 && height <= 0 ) { // Set the window aspect ratio to 4:3 height = (width * 3) / 4; } else if( width <= 0 && height > 0 ) { // Set the window aspect ratio to 4:3 width = (height * 4) / 3; } else if( width <= 0 && height <= 0 ) { // Default window size width = 640; height = 480; } // Remember window settings _glfwWin.width = width; _glfwWin.height = height; _glfwWin.fullscreen = (mode == GLFW_FULLSCREEN ? GL_TRUE : GL_FALSE); // Platform specific window opening routine if( !_glfwPlatformOpenWindow( width, height, &wndconfig, &fbconfig ) ) { return GL_FALSE; } // Flag that window is now opened _glfwWin.opened = GL_TRUE; // Get window parameters (such as color buffer bits etc) _glfwPlatformRefreshWindowParams(); // Get OpenGL version _glfwParseGLVersion( &_glfwWin.glMajor, &_glfwWin.glMinor, &_glfwWin.glRevision ); if( _glfwWin.glMajor < wndconfig.glMajor || ( _glfwWin.glMajor == wndconfig.glMajor && _glfwWin.glMinor < wndconfig.glMinor ) ) { _glfwPlatformCloseWindow(); return GL_FALSE; } // Do we have non-power-of-two textures (added to core in version 2.0)? _glfwWin.has_GL_ARB_texture_non_power_of_two = ( _glfwWin.glMajor >= 2 ) || glfwExtensionSupported( "GL_ARB_texture_non_power_of_two" ); // Do we have automatic mipmap generation (added to core in version 1.4)? _glfwWin.has_GL_SGIS_generate_mipmap = ( _glfwWin.glMajor >= 2 ) || ( _glfwWin.glMinor >= 4 ) || glfwExtensionSupported( "GL_SGIS_generate_mipmap" ); if( _glfwWin.glMajor > 2 ) { _glfwWin.GetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress( "glGetStringi" ); if( !_glfwWin.GetStringi ) { _glfwPlatformCloseWindow(); return GL_FALSE; } } // If full-screen mode was requested, disable mouse cursor if( mode == GLFW_FULLSCREEN ) { glfwDisable( GLFW_MOUSE_CURSOR ); } // Start by clearing the front buffer to black (avoid ugly desktop // remains in our OpenGL window) glClear( GL_COLOR_BUFFER_BIT ); _glfwPlatformSwapBuffers(); return GL_TRUE; }
int _glfwPlatformOpenWindow( int width, int height, const _GLFWwndconfig *wndconfig, const _GLFWfbconfig *fbconfig ) { OSStatus error; unsigned int windowAttributes; ProcessSerialNumber psn; // TODO: Break up this function! _glfwWin.windowUPP = NULL; _glfwWin.mouseUPP = NULL; _glfwWin.keyboardUPP = NULL; _glfwWin.commandUPP = NULL; _glfwWin.window = NULL; _glfwWin.aglContext = NULL; _glfwWin.aglPixelFormat = NULL; _glfwWin.cglContext = NULL; _glfwWin.cglPixelFormat = NULL; _glfwWin.refreshRate = wndconfig->refreshRate; // Fail if OpenGL 3.0 or above was requested if( wndconfig->glMajor > 2 ) { fprintf( stderr, "OpenGL 3.0+ is not yet supported on Mac OS X\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } if( _glfwLibrary.Unbundled ) { if( GetCurrentProcess( &psn ) != noErr ) { fprintf( stderr, "Failed to get the process serial number\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } if( TransformProcessType( &psn, kProcessTransformToForegroundApplication ) != noErr ) { fprintf( stderr, "Failed to become a foreground application\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } if( wndconfig->mode == GLFW_FULLSCREEN ) { if( SetFrontProcess( &psn ) != noErr ) { fprintf( stderr, "Failed to become the front process\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } } } if( !installEventHandlers() ) { fprintf( stderr, "Failed to install Carbon application event handlers\n" ); _glfwPlatformTerminate(); return GL_FALSE; } // Windowed or fullscreen; AGL or CGL? Quite the mess... // AGL appears to be the only choice for attaching OpenGL contexts to // Carbon windows, but it leaves the user no control over fullscreen // mode stretching. Solution: AGL for windowed, CGL for fullscreen. if( wndconfig->mode == GLFW_WINDOW ) { // create AGL pixel format attribute list GLint AGLpixelFormatAttributes[256]; int numAGLAttrs = 0; AGLpixelFormatAttributes[numAGLAttrs++] = AGL_RGBA; AGLpixelFormatAttributes[numAGLAttrs++] = AGL_DOUBLEBUFFER; AGLpixelFormatAttributes[numAGLAttrs++] = AGL_CLOSEST_POLICY; if( fbconfig->stereo ) { AGLpixelFormatAttributes[numAGLAttrs++] = AGL_STEREO; } _setAGLAttribute( AGL_AUX_BUFFERS, fbconfig->auxBuffers); _setAGLAttribute( AGL_RED_SIZE, fbconfig->redBits ); _setAGLAttribute( AGL_GREEN_SIZE, fbconfig->greenBits ); _setAGLAttribute( AGL_BLUE_SIZE, fbconfig->blueBits ); _setAGLAttribute( AGL_ALPHA_SIZE, fbconfig->alphaBits ); _setAGLAttribute( AGL_DEPTH_SIZE, fbconfig->depthBits ); _setAGLAttribute( AGL_STENCIL_SIZE, fbconfig->stencilBits ); _setAGLAttribute( AGL_ACCUM_RED_SIZE, fbconfig->accumRedBits ); _setAGLAttribute( AGL_ACCUM_GREEN_SIZE, fbconfig->accumGreenBits ); _setAGLAttribute( AGL_ACCUM_BLUE_SIZE, fbconfig->accumBlueBits ); _setAGLAttribute( AGL_ACCUM_ALPHA_SIZE, fbconfig->accumAlphaBits ); if( fbconfig->samples > 1 ) { _setAGLAttribute( AGL_SAMPLE_BUFFERS_ARB, 1 ); _setAGLAttribute( AGL_SAMPLES_ARB, fbconfig->samples ); AGLpixelFormatAttributes[numAGLAttrs++] = AGL_NO_RECOVERY; } AGLpixelFormatAttributes[numAGLAttrs++] = AGL_NONE; // create pixel format descriptor AGLDevice mainMonitor = GetMainDevice(); _glfwWin.aglPixelFormat = aglChoosePixelFormat( &mainMonitor, 1, AGLpixelFormatAttributes ); if( _glfwWin.aglPixelFormat == NULL ) { fprintf( stderr, "Failed to choose AGL pixel format: %s\n", aglErrorString( aglGetError() ) ); _glfwPlatformCloseWindow(); return GL_FALSE; } // create AGL context _glfwWin.aglContext = aglCreateContext( _glfwWin.aglPixelFormat, NULL ); if( _glfwWin.aglContext == NULL ) { fprintf( stderr, "Failed to create AGL context: %s\n", aglErrorString( aglGetError() ) ); _glfwPlatformCloseWindow(); return GL_FALSE; } // create window Rect windowContentBounds; windowContentBounds.left = 0; windowContentBounds.top = 0; windowContentBounds.right = width; windowContentBounds.bottom = height; windowAttributes = ( kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | kWindowStandardHandlerAttribute ); if( wndconfig->windowNoResize ) { windowAttributes |= kWindowLiveResizeAttribute; } else { windowAttributes |= ( kWindowFullZoomAttribute | kWindowResizableAttribute ); } error = CreateNewWindow( kDocumentWindowClass, windowAttributes, &windowContentBounds, &( _glfwWin.window ) ); if( ( error != noErr ) || ( _glfwWin.window == NULL ) ) { fprintf( stderr, "Failed to create Carbon window\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } _glfwWin.windowUPP = NewEventHandlerUPP( windowEventHandler ); error = InstallWindowEventHandler( _glfwWin.window, _glfwWin.windowUPP, GetEventTypeCount( GLFW_WINDOW_EVENT_TYPES ), GLFW_WINDOW_EVENT_TYPES, NULL, NULL ); if( error != noErr ) { fprintf( stderr, "Failed to install Carbon window event handler\n" ); _glfwPlatformCloseWindow(); return GL_FALSE; } // Don't care if we fail here (void)SetWindowTitleWithCFString( _glfwWin.window, CFSTR( "GLFW Window" ) ); (void)RepositionWindow( _glfwWin.window, NULL, kWindowCenterOnMainScreen ); if( !aglSetDrawable( _glfwWin.aglContext, GetWindowPort( _glfwWin.window ) ) ) { fprintf( stderr, "Failed to set the AGL context as the Carbon window drawable: %s\n", aglErrorString( aglGetError() ) ); _glfwPlatformCloseWindow(); return GL_FALSE; } // Make OpenGL context current if( !aglSetCurrentContext( _glfwWin.aglContext ) ) { fprintf( stderr, "Failed to make AGL context current: %s\n", aglErrorString( aglGetError() ) ); _glfwPlatformCloseWindow(); return GL_FALSE; } ShowWindow( _glfwWin.window ); } else { CGDisplayErr cgErr; CGLError cglErr; CFDictionaryRef optimalMode; GLint numCGLvs = 0; CGLPixelFormatAttribute CGLpixelFormatAttributes[64]; int numCGLAttrs = 0; // variables for enumerating color depths GLint rgbColorDepth; // CGL pixel format attributes _setCGLAttribute( kCGLPFADisplayMask, CGDisplayIDToOpenGLDisplayMask( kCGDirectMainDisplay ) ); if( fbconfig->stereo ) { CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAStereo; } if( fbconfig->samples > 1 ) { _setCGLAttribute( kCGLPFASamples, (CGLPixelFormatAttribute)fbconfig->samples ); _setCGLAttribute( kCGLPFASampleBuffers, (CGLPixelFormatAttribute)1 ); CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFANoRecovery; } CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAFullScreen; CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFADoubleBuffer; CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAAccelerated; CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFANoRecovery; CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAMinimumPolicy; _setCGLAttribute( kCGLPFAAccumSize, (CGLPixelFormatAttribute)( fbconfig->accumRedBits \ + fbconfig->accumGreenBits \ + fbconfig->accumBlueBits \ + fbconfig->accumAlphaBits ) ); _setCGLAttribute( kCGLPFAAlphaSize, (CGLPixelFormatAttribute)fbconfig->alphaBits ); _setCGLAttribute( kCGLPFADepthSize, (CGLPixelFormatAttribute)fbconfig->depthBits ); _setCGLAttribute( kCGLPFAStencilSize, (CGLPixelFormatAttribute)fbconfig->stencilBits ); _setCGLAttribute( kCGLPFAAuxBuffers, (CGLPixelFormatAttribute)fbconfig->auxBuffers ); CGLpixelFormatAttributes[ numCGLAttrs++ ] = (CGLPixelFormatAttribute)NULL; // create a suitable pixel format with above attributes.. cglErr = CGLChoosePixelFormat( CGLpixelFormatAttributes, &_glfwWin.cglPixelFormat, &numCGLvs ); if( cglErr != kCGLNoError ) { fprintf( stderr, "Failed to choose CGL pixel format: %s\n", CGLErrorString( cglErr ) ); _glfwPlatformCloseWindow(); return GL_FALSE; } // ..and create a rendering context using that pixel format cglErr = CGLCreateContext( _glfwWin.cglPixelFormat, NULL, &_glfwWin.cglContext ); if( cglErr != kCGLNoError ) { fprintf( stderr, "Failed to create CGL context: %s\n", CGLErrorString( cglErr ) ); _glfwPlatformCloseWindow(); return GL_FALSE; } // enumerate depth of RGB channels - unlike AGL, CGL works with // a single parameter reflecting the full depth of the frame buffer (void)CGLDescribePixelFormat( _glfwWin.cglPixelFormat, 0, kCGLPFAColorSize, &rgbColorDepth ); // capture the display for our application cgErr = CGCaptureAllDisplays(); if( cgErr != kCGErrorSuccess ) { fprintf( stderr, "Failed to capture Core Graphics displays\n"); _glfwPlatformCloseWindow(); return GL_FALSE; } // find closest matching NON-STRETCHED display mode.. optimalMode = CGDisplayBestModeForParametersAndRefreshRateWithProperty( kCGDirectMainDisplay, rgbColorDepth, width, height, wndconfig->refreshRate, NULL, NULL ); if( optimalMode == NULL ) { fprintf( stderr, "Failed to retrieve Core Graphics display mode\n"); _glfwPlatformCloseWindow(); return GL_FALSE; } // ..and switch to that mode cgErr = CGDisplaySwitchToMode( kCGDirectMainDisplay, optimalMode ); if( cgErr != kCGErrorSuccess ) { fprintf( stderr, "Failed to switch to Core Graphics display mode\n"); _glfwPlatformCloseWindow(); return GL_FALSE; } // switch to our OpenGL context, and bring it up fullscreen cglErr = CGLSetCurrentContext( _glfwWin.cglContext ); if( cglErr != kCGLNoError ) { fprintf( stderr, "Failed to make CGL context current: %s\n", CGLErrorString( cglErr ) ); _glfwPlatformCloseWindow(); return GL_FALSE; } cglErr = CGLSetFullScreen( _glfwWin.cglContext ); if( cglErr != kCGLNoError ) { fprintf( stderr, "Failed to set CGL fullscreen mode: %s\n", CGLErrorString( cglErr ) ); _glfwPlatformCloseWindow(); return GL_FALSE; } } return GL_TRUE; }
int _glfwPlatformOpenWindow( int width, int height, int redbits, int greenbits, int bluebits, int alphabits, int depthbits, int stencilbits, int mode, int accumredbits, int accumgreenbits, int accumbluebits, int accumalphabits, int auxbuffers, int stereo, int refreshrate ) { OSStatus error; // TO DO: Refactor this function! _glfwWin.WindowFunctions = (mode == GLFW_FULLSCREEN ? &_glfwMacFSWindowFunctions : &_glfwMacDWWindowFunctions); // create pixel format attribute list GLint pixelFormatAttributes[256]; int numAttrs = 0; pixelFormatAttributes[numAttrs++] = AGL_RGBA; pixelFormatAttributes[numAttrs++] = AGL_DOUBLEBUFFER; if ( mode == GLFW_FULLSCREEN ) { pixelFormatAttributes[numAttrs++] = AGL_FULLSCREEN; } if ( stereo ) { pixelFormatAttributes[numAttrs++] = AGL_STEREO; } _setAGLAttribute( AGL_AUX_BUFFERS, auxbuffers); _setAGLAttribute( AGL_RED_SIZE, redbits ); _setAGLAttribute( AGL_GREEN_SIZE, greenbits ); _setAGLAttribute( AGL_BLUE_SIZE, bluebits ); _setAGLAttribute( AGL_ALPHA_SIZE, alphabits ); _setAGLAttribute( AGL_DEPTH_SIZE, depthbits ); _setAGLAttribute( AGL_STENCIL_SIZE, stencilbits ); _setAGLAttribute( AGL_ACCUM_RED_SIZE, accumredbits ); _setAGLAttribute( AGL_ACCUM_GREEN_SIZE, accumgreenbits ); _setAGLAttribute( AGL_ACCUM_BLUE_SIZE, accumbluebits ); _setAGLAttribute( AGL_ACCUM_ALPHA_SIZE, accumalphabits ); pixelFormatAttributes[numAttrs++] = AGL_NONE; // create pixel format. AGLDevice mainMonitor = GetMainDevice(); AGLPixelFormat pixelFormat = aglChoosePixelFormat( &mainMonitor, 1, pixelFormatAttributes ); if ( pixelFormat == NULL ) { return GL_FALSE; } // store pixel format's values for _glfwPlatformGetWindowParam's use _getAGLAttribute( AGL_ACCELERATED, _glfwWin.Accelerated ); _getAGLAttribute( AGL_RED_SIZE, _glfwWin.RedBits ); _getAGLAttribute( AGL_GREEN_SIZE, _glfwWin.GreenBits ); _getAGLAttribute( AGL_BLUE_SIZE, _glfwWin.BlueBits ); _getAGLAttribute( AGL_ALPHA_SIZE, _glfwWin.AlphaBits ); _getAGLAttribute( AGL_DEPTH_SIZE, _glfwWin.DepthBits ); _getAGLAttribute( AGL_STENCIL_SIZE, _glfwWin.StencilBits ); _getAGLAttribute( AGL_ACCUM_RED_SIZE, _glfwWin.AccumRedBits ); _getAGLAttribute( AGL_ACCUM_GREEN_SIZE, _glfwWin.AccumGreenBits ); _getAGLAttribute( AGL_ACCUM_BLUE_SIZE, _glfwWin.AccumBlueBits ); _getAGLAttribute( AGL_ACCUM_ALPHA_SIZE, _glfwWin.AccumAlphaBits ); _getAGLAttribute( AGL_AUX_BUFFERS, _glfwWin.AuxBuffers ); _getAGLAttribute( AGL_STEREO, _glfwWin.Stereo ); _glfwWin.RefreshRate = refreshrate; // create AGL context _glfwWin.AGLContext = aglCreateContext( pixelFormat, NULL ); aglDestroyPixelFormat( pixelFormat ); if ( _glfwWin.AGLContext == NULL ) { _glfwPlatformCloseWindow(); return GL_FALSE; } // create window Rect windowContentBounds; windowContentBounds.left = 0; windowContentBounds.top = 0; windowContentBounds.right = width; windowContentBounds.bottom = height; error = CreateNewWindow( kDocumentWindowClass, GLFW_WINDOW_ATTRIBUTES, &windowContentBounds, &( _glfwWin.MacWindow ) ); if ( ( error != noErr ) || ( _glfwWin.MacWindow == NULL ) ) { _glfwPlatformCloseWindow(); return GL_FALSE; } if ( !_glfwWin.Fullscreen ) { _glfwWin.WindowUPP = NewEventHandlerUPP( _glfwWindowEventHandler ); error = InstallWindowEventHandler( _glfwWin.MacWindow, _glfwWin.WindowUPP, GetEventTypeCount( GLFW_WINDOW_EVENT_TYPES ), GLFW_WINDOW_EVENT_TYPES, NULL, NULL ); if ( error != noErr ) { _glfwPlatformCloseWindow(); return GL_FALSE; } } // Don't care if we fail here (void)SetWindowTitleWithCFString( _glfwWin.MacWindow, CFSTR( "GLFW Window" ) ); (void)RepositionWindow( _glfwWin.MacWindow, NULL, kWindowCenterOnMainScreen ); // TO DO: put this somewhere else; this is a bit too soon ShowWindow( _glfwWin.MacWindow ); // show window, attach OpenGL context, &c if ( mode == GLFW_FULLSCREEN ) { CGDisplayErr cgError; cgError = CGCaptureAllDisplays(); if ( cgError != CGDisplayNoErr ) { _glfwPlatformCloseWindow(); return GL_FALSE; } HideMenuBar(); // I have no idea if this will work at all, particularly on // multi-monitor systems. Might need to use CGL for full-screen // setup and AGL for windowed (ugh!). if ( !aglSetFullScreen( _glfwWin.AGLContext, width, height, refreshrate, 0 ) ) { _glfwPlatformCloseWindow(); return GL_FALSE; } } else { if ( !aglSetDrawable( _glfwWin.AGLContext, GetWindowPort( _glfwWin.MacWindow ) ) ) { _glfwPlatformCloseWindow(); return GL_FALSE; } } // Make OpenGL context current; if ( !aglSetCurrentContext( _glfwWin.AGLContext ) ) { _glfwPlatformCloseWindow(); return GL_FALSE; } return GL_TRUE; }