/* =========================================================================== Wolfenstein: Enemy Territory GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Wolfenstein: Enemy Territory GPL Source Code (Β“Wolf ET Source CodeΒ”). Wolf ET Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Wolf ET Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Wolf ET Source Code. If not, see . In addition, the Wolf: ET Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Wolf ET Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ #include Q3DEF_BEGIN #include "../renderer/tr_local.h" #include "../client/client.h" #include "mac_local.h" Q3DEF_END #define MacWarning Sys_Warning #define MacFatalError Sys_Error #ifndef AGL_SAMPLES_ARB #define AGL_SAMPLE_BUFFERS_ARB 55 /* number of multi sample buffers */ #define AGL_SAMPLES_ARB 56 /* number of samples per multi sample buffer */ #endif #define USE_AGL_FULLSCREEN 0 //===================================================================== // Includes #include "AGLUtils.h" #include "CDrawSprocket.h" //===================================================================== // Global Variables Fixed aglFrequency; // Monitor frequency, set in main() from the prefs AGLContext gAGLContext; // The currently active drawing context, either primary or secondary AGLContext gAGLContext_Primary; // Primary context, used in non-SMP situations or in the main thread AGLContext gAGLContext_Secondary; // Secondary context, used mainly for an SMP thread AGLPixelFormat gPixelFormat; //===================================================================== // Local Variables static WindowRef sBlankingWindow; // Used only for AGL_FULLSCREEN cases, to blank out the desktop static WindowRef sGLWindow; // In non-AGL_FULLSCREEN cases, contains the GL drawable window static Rect sGLWindowRect; static RGBColor sRGBWhite = { 0xFFFF, 0xFFFF, 0xFFFF }; static RGBColor sRGBBlack = { 0x0000, 0x0000, 0x0000 }; static Boolean sAGLActive = false; // True if a drawable is active static long sSystemVersion; static CGrafPtr sCurrentAGLPort; static DisplayIDType glMonitor; /*static*/ short glWidth, glHeight; static int glFrequency; // Same as aglFrequency, only in int form static EventHandlerUPP sWindowEventHandlerUPP; // carbon window constrain event handler static EventHandlerRef sEventHandlerRef; // event handler reference //===================================================================== // Implementation OSStatus MySetWindowContentColor( WindowRef inWindow, RGBColor const *inRGB ) { OSStatus status = noErr; // LBO - the following routine requires 8.5 in non-Carbon builds (8.1 in Carbon) status = SetWindowContentColor( inWindow, inRGB ); return status; } //=============================================================================== // appWindowEventHandler // // This event handler is installed by InitCarbonEvents (below) to prevent // Carbon from moving our windows when they're offscreen. This is most noticable // when we've set up a blanking window that covers the entire gray region. //=============================================================================== static pascal OSStatus appWindowEventHandler( EventHandlerCallRef myHandler, EventRef event, void* userData ) { #pragma unused (myHandler, userData) OSStatus result = eventNotHandledErr; UInt32 eventKind; eventKind = GetEventKind( event ); switch ( eventKind ) { case kEventWindowConstrain: { // We handled the event, eat it result = noErr; break; } } return result; } void InstallCarbonWindowEvents( WindowRef inWindow ) { OSStatus status; EventTypeSpec list[] = { {kEventClassWindow, kEventWindowConstrain } }; // If we don't support Carbon events, bail if ( (Ptr) InstallEventHandler == (Ptr) kUnresolvedCFragSymbolAddress ) { return; } // Install an application event handler if ( sWindowEventHandlerUPP == NULL ) { sWindowEventHandlerUPP = NewEventHandlerUPP( appWindowEventHandler ); if ( !sWindowEventHandlerUPP ) { SysBeep( 0 ); return; } } status = InstallWindowEventHandler( inWindow, sWindowEventHandlerUPP, 1, list, 0, &sEventHandlerRef ); if ( status != noErr ) { SysBeep( 0 ); } } void DisposeCarbonWindowEvents( void ) { if ( sEventHandlerRef == NULL ) { return; } (void)RemoveEventHandler( sEventHandlerRef ); sEventHandlerRef = NULL; if ( sWindowEventHandlerUPP != NULL ) { DisposeEventHandlerUPP( sWindowEventHandlerUPP ); } sWindowEventHandlerUPP = NULL; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // _aglSetGameContext // // Given an already chosen AGL context and monitor, this routine will take care of the bs // involved with choosing a properly-sized window (on non-fullscreen devices) and it // will activate a fullscreen context if desired for those devices that support that option. //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ GLboolean _aglSetGameContext( short inWidth, short inHeight, short inDepth, short inAGLDepth, short inStencilDepth, Fixed inFreq, DisplayIDType inDevice, Boolean inWindow, int inFSAASamples ) { GLint result; GLboolean ok; GDHandle device; GLint attrib[] = { AGL_RGBA, AGL_DOUBLEBUFFER, AGL_NO_RECOVERY, AGL_FULLSCREEN, AGL_ACCELERATED, AGL_RED_SIZE, 8, AGL_GREEN_SIZE, 8, AGL_BLUE_SIZE, 8, AGL_ALPHA_SIZE, 0, AGL_DEPTH_SIZE, 16, AGL_STENCIL_SIZE, 0, #if TEST_SMP AGL_MP_SAFE, #endif #if TEST_FSAA AGL_SAMPLES_ARB, 4, AGL_SAMPLE_BUFFERS_ARB, 1, #endif AGL_NONE }; short depth, pageCount; Fixed frequency; OSErr err; WindowAttributes winAttrib; GLenum glErr; // Are we on 10? err = Gestalt( gestaltSystemVersion, &sSystemVersion ); #if MAC_DEBUG && SINGLE_BUFFER attrib[1] = AGL_NONE; #endif if ( !gDrawSprocket ) { return GL_FALSE; } glFrequency = Fix2X( inFreq ); glMonitor = inDevice; glWidth = inWidth; glHeight = inHeight; sCurrentAGLPort = NULL; #if !USE_AGL_FULLSCREEN attrib[3] = AGL_ACCELERATED; #endif // AGL_RED/GREEN/BLUE_SIZE if ( inDepth <= 16 ) { // 15/16 default to 555 RGB attrib[6] = attrib[8] = attrib[10] = 5; } // AGL_DEPTH_SIZE if ( inAGLDepth ) { attrib[14] = inAGLDepth; } else { attrib[14] = inDepth; } // AGL_STENCIL_SIZE if ( inStencilDepth ) { attrib[16] = inStencilDepth; } DMGetGDeviceByDisplayID( inDevice, &device, false ); if ( device == NULL ) { device = GetMainDevice(); } if ( gAGLContext ) { _aglDisposeGameContext(); } #if TEST_SMP // There is no AGL_MP_SAFE renderer on MacOS 8/9 if ( sSystemVersion < 0x01000 ) { attrib[17] = AGL_NONE; } #endif // If our monitor is set to 8-bit under MacOS 8 or 9, we have to change that for OpenGL to // find a valid context. if ( sSystemVersion < 0x01000 ) { int curDepth = ( **( ( **device ).gdPMap ) ).pixelSize; if ( curDepth == 8 ) { if ( err = HasDepth( device, 8, 1, 1 ) ) { if ( inDepth == 16 ) { err = SetDepth( device, 16, 1, 1 ); } else { err = SetDepth( device, 32, 1, 1 ); } } if ( err ) { MacWarning( "This game requires a color monitor that supports thousands or millions of colors" ); } } } #if TEST_FSAA // If < 10.2 or no samples, don't ask for them if ( ( sSystemVersion < 0x01020 ) || ( inFSAASamples == 0 ) ) { attrib[18] = AGL_NONE; attrib[19] = AGL_NONE; attrib[20] = AGL_NONE; attrib[21] = AGL_NONE; } else { attrib[19] = inFSAASamples; } #endif #if 1 // !USE_AGL_FULLSCREEN // attrib[5] = AGL_ACCELERATED; gPixelFormat = aglChoosePixelFormat( &device, 1, attrib ); #else if ( sSystemVersion < 0x01000 ) { // Under MacOS 8/9, the 3dfx driver is the only card to support agl // fullscreen. It's deprecated and buggy, so we must set it up the "wrong" way // to get agl fullscreen to work, otherwise the system will freak out and crash // badly in the aglChoosePixelFormat call below. attrib[3] = AGL_ACCELERATED; gPixelFormat = aglChoosePixelFormat( &device, 1, attrib ); } else { // Since we're trying for AGL_FULLSCREEN, we must set the first 2 params to 0 gPixelFormat = aglChoosePixelFormat( NULL, 0, attrib ); // If it failed, try again without AGL_FULLSCREEN if ( gPixelFormat == NULL ) { attrib[3] = AGL_ACCELERATED; gPixelFormat = aglChoosePixelFormat( &device, 1, attrib ); } } #endif if ( gPixelFormat == NULL ) { MacWarning( "aglChoosePixelFormat failed" ); return GL_FALSE; } // Create an AGL context gAGLContext_Primary = aglCreateContext( gPixelFormat, NULL ); if ( !gAGLContext_Primary ) { MacWarning( "aglCreateContext failed" ); return GL_FALSE; } #if TEST_SMP gAGLContext_Secondary = aglCreateContext( gPixelFormat, gAGLContext_Primary ); if ( !gAGLContext_Secondary ) { MacWarning( "aglCreateContext (alt) failed" ); } #endif // Make the primary context the current context _aglUsePrimaryContext(); // If we found a fullscreen device, see if the renderer supports it. // This is pretty dumb, but on OSX it can be mutually exclusive due to a bug in OpenGL if ( attrib[3] == AGL_FULLSCREEN ) { AGLRendererInfo info; info = aglQueryRendererInfo( &device, 1 ); if ( !info ) { MacWarning( "aglQueryRendererInfo failed" ); return GL_FALSE; } // is this a fullscreen device? ok = aglDescribeRenderer( info, AGL_FULLSCREEN, &result ); aglDestroyRendererInfo( info ); } else { result = 0; } if ( gUseCarbonEvents ) { winAttrib = kWindowStandardHandlerAttribute; } else { winAttrib = kWindowNoAttributes; } // Burp the agl error handler. We could have encountered errors above and worked around them // so we need to toss any errors currently pending. glErr = aglGetError(); // If it is a fullscreen renderer and we want to run fullscreen, set up a fullscreen context. // We don't use DrawSprocket for fullscreen contexts (e.g. 3dfx) because // a) it's not strictly necessary and b) the aglSetFullScreen call can // confuse DrawSprocket and cause the Finder to mangle the desktop icons // The downside of this is that there are no gamma fades around the res switch // when we're running on 3dfx hardware - yet. if ( result && !inWindow ) { OSStatus status; Rect desktopRect; CGrafPtr oldPort; // Get a rect that covers the entire desktop GetRegionBounds( GetGrayRgn(), &desktopRect ); // Create a blanking window to hide everything #if TARGET_API_MAC_CARBON { status = CreateNewWindow( kDocumentWindowClass, winAttrib, &desktopRect, &sBlankingWindow ); if ( status ) { MacWarning( "CreateNewWindow failed" ); return GL_FALSE; } glMonitor = 0; } #else sBlankingWindow = NewCWindow( NULL, &desktopRect, "\p", false, noGrowDocProc, ( WindowRef ) - 1, false, 0 ); if ( !sBlankingWindow ) { return GL_FALSE; } #endif GetPort( &oldPort ); // Clear the window to black, then show it SetPortWindowPort( sBlankingWindow ); RGBForeColor( &sRGBBlack ); RGBBackColor( &sRGBWhite ); status = MySetWindowContentColor( sBlankingWindow, &sRGBBlack ); ShowWindow( sBlankingWindow ); SetPort( oldPort ); sCurrentAGLPort = ( CGrafPtr ) - 1; ok = aglSetFullScreen( gAGLContext, glWidth, glHeight, glFrequency, glMonitor ); // That tanked, try a different frequency if ( !ok ) { ok = aglSetFullScreen( gAGLContext, glWidth, glHeight, 60.0, glMonitor ); } if ( !ok ) { ok = aglSetFullScreen( gAGLContext, glWidth, glHeight, 75.0, glMonitor ); } #if 0 // If that stuff failed, let's try leaving out the monitor if ( !ok ) { ok = aglSetFullScreen( gAGLContext, glWidth, glHeight, 60.0, 0 ); } if ( !ok ) { ok = aglSetFullScreen( gAGLContext, glWidth, glHeight, 75.0, 0 ); } #endif if ( !ok ) { MacFatalError( "aglSetFullScreen failed. Try specifying a different refresh rate." ); return GL_FALSE; } #if MAC_Q3 #if MAC_JKJA VID_Printf( PRINT_ALL, "...AGL_FULLSCREEN, %dx%d at %dHz\n", glWidth, glHeight, glFrequency ); #else ri.Printf( PRINT_ALL, "...AGL_FULLSCREEN, %dx%d at %dHz\n", glWidth, glHeight, glFrequency ); #endif #endif sAGLActive = true; sGLWindowRect.top = sGLWindowRect.left = 0; sGLWindowRect.right = glWidth; sGLWindowRect.bottom = glHeight; } else { short windowType; Str32 winTitle; OSStatus status; if ( !inWindow ) { GDHandle newDevice; short outWidth, outHeight, outDepth, outPageCount; Fixed outFreq; // if (!gDrawSprocket->SwitchToResolution (inWidth, inHeight, inDepth, inFreq, 1, true)) return GL_FALSE; gDrawSprocket->ConfigureGameContext( inWidth, inHeight, inDepth, inFreq, 1 ); gDrawSprocket->SwitchToGameContext( true ); newDevice = gDrawSprocket->GetGDevice(); if ( newDevice ) { sGLWindowRect.top = ( *newDevice )->gdRect.top; sGLWindowRect.left = ( *newDevice )->gdRect.left; } else { #if MAC_Q3 #if MAC_JKJA Cvar_Set( "r_mode", "3" ); #else ri.Cvar_Set( "r_mode", "3" ); #endif GLimp_Shutdown(); GLimp_Init(); #endif } gDrawSprocket->GetGameResolution( &outWidth, &outHeight, &outDepth, &outFreq, &outPageCount ); #if MAC_Q3 #if MAC_JKJA VID_Printf( PRINT_ALL, "...DSp context, %dx%d, %d bit, %d pages\n", outWidth, outHeight, outDepth, outPageCount ); #else ri.Printf( PRINT_ALL, "...DSp context, %dx%d, %d bit, %d pages\n", outWidth, outHeight, outDepth, outPageCount ); #endif #endif windowType = plainDBox; } else { // Center the window sGLWindowRect.left = ( ( ( *device )->gdRect.right - ( *device )->gdRect.left ) - glWidth ) / 2; sGLWindowRect.top = ( ( ( *device )->gdRect.bottom - ( *device )->gdRect.top ) - glHeight ) / 2; windowType = noGrowDocProc; } // create a window to draw into if ( !inWindow ) { DSpContextReference gameContext; gameContext = gDrawSprocket->GetCurrentContext(); // DSpContext_LocalToGlobal (gameContext, (Point *)&sGLWindowRect); gDrawSprocket->FadeGammaUp( true ); } else { sGLWindowRect.left += ( **device ).gdRect.left; sGLWindowRect.top += ( **device ).gdRect.top; } sGLWindowRect.right = sGLWindowRect.left + glWidth; sGLWindowRect.bottom = sGLWindowRect.top + glHeight; sprintf( (char *)winTitle, "%s", kGameName ); c2pstrcpy( winTitle, (const char *)winTitle ); #if TARGET_API_MAC_CARBON { // On 10, we can attach a drawable directly to a DSp CGrafPtr // On < 10, we have to use a blanking window instead. if ( inWindow ) { CreateNewWindow( kDocumentWindowClass, winAttrib, &sGLWindowRect, &sGLWindow ); } else if ( sSystemVersion < 0x01000 ) { // CreateNewWindow (kPlainWindowClass, winAttrib, &sGLWindowRect, &sGLWindow); // CreateNewWindow (kDocumentWindowClass, winAttrib, &sGLWindowRect, &sGLWindow); // Always create a window on classic sGLWindow = NewCWindow( NULL, &sGLWindowRect, winTitle, 0, windowType, ( WindowRef ) - 1, 0, 0 ); if ( sGLWindow == NULL ) { return GL_FALSE; } // InstallCarbonWindowEvents (sGLWindow); } else { sGLWindow = NULL; } } #else // Always create a window on classic sGLWindow = NewCWindow( NULL, &sGLWindowRect, winTitle, 0, windowType, ( WindowRef ) - 1, 0, 0 ); if ( sGLWindow == NULL ) { return GL_FALSE; } #endif // Attach the agl context if ( sGLWindow ) { CGrafPtr oldPort; GetPort( &oldPort ); SetPortWindowPort( sGLWindow ); RGBForeColor( &sRGBBlack ); RGBBackColor( &sRGBWhite ); SetPort( oldPort ); SetWTitle( sGLWindow, kGameNameP ); // status = MySetWindowContentColor (sGLWindow, &sRGBBlack); ShowWindow( sGLWindow ); BringToFront( sGLWindow ); sCurrentAGLPort = GetWindowPort( sGLWindow ); ok = aglSetDrawable( gAGLContext, sCurrentAGLPort ); #if 0 //TEST_SMP ok = aglSetDrawable( gAltAGLContext, sCurrentAGLPort ); #endif } else { // use DSp's front buffer on Mac OS X sCurrentAGLPort = gDrawSprocket->GetFrontBuffer(); if ( sCurrentAGLPort == NULL ) { // ReportError ("DSpContext_GetFrontBuffer() had an error."); return NULL; } // there is a problem in Mac OS X GM CoreGraphics that may not size the port pixmap correctly // this will check the vertical sizes and offset if required to fix the problem // this will not center ports that are smaller then a particular resolution { long deltaV, deltaH; Rect portBounds; PixMapHandle hPix = GetPortPixMap( sCurrentAGLPort ); Rect pixBounds = ( **hPix ).bounds; GetPortBounds( sCurrentAGLPort, &portBounds ); deltaV = ( portBounds.bottom - portBounds.top ) - ( pixBounds.bottom - pixBounds.top ) + ( portBounds.bottom - portBounds.top - glHeight ) / 2; deltaH = -( portBounds.right - portBounds.left - glWidth ) / 2; if ( deltaV || deltaH ) { GrafPtr pPortSave; GetPort( &pPortSave ); SetPort( (GrafPtr)sCurrentAGLPort ); // set origin to account for CG offset and if requested drawable smaller than screen rez SetOrigin( deltaH, deltaV ); SetPort( pPortSave ); } } ok = aglSetDrawable( gAGLContext, sCurrentAGLPort ); #if 0 //TEST_SMP ok = aglSetDrawable( gAltAGLContext, sCurrentAGLPort ); #endif } if ( !ok ) { MacWarning( "aglSetDrawable failed" ); return GL_FALSE; } sAGLActive = true; } return GL_TRUE; } void _aglDisposeGameContext( void ) { if ( gAGLContext_Primary ) { aglSetCurrentContext( NULL ); aglSetDrawable( gAGLContext_Primary, NULL ); aglDestroyContext( gAGLContext_Primary ); gAGLContext_Primary = NULL; } #if TEST_SMP if ( gAGLContext_Secondary ) { aglSetDrawable( gAGLContext_Secondary, NULL ); aglDestroyContext( gAGLContext_Secondary ); gAGLContext_Secondary = NULL; } #endif gAGLContext = NULL; sAGLActive = false; if ( sGLWindow ) { DisposeWindow( sGLWindow ); sGLWindow = NULL; } if ( sBlankingWindow ) { DisposeWindow( sBlankingWindow ); sBlankingWindow = NULL; } if ( gPixelFormat ) { // Pixel format is no longer needed aglDestroyPixelFormat( gPixelFormat ); gPixelFormat = NULL; } } GLboolean _aglSuspendGameContext( void ) { GLboolean result; if ( sAGLActive == false ) { return GL_TRUE; } if ( !gAGLContext ) { return GL_TRUE; } // gDrawSprocket->FadeGammaDownImmediate (true); result = aglSetDrawable( gAGLContext, NULL ); #if TEST_SMP // (void)aglSetDrawable (gAltAGLContext, NULL); #endif #if 0 if ( r_fullscreen->integer ) { // If we're using DSp on OSX, we need to pause the context so we can see dialogs if ( ( sSystemVersion >= 0x01000 ) && !sGLWindow && !sBlankingWindow ) { if ( gDrawSprocket->GetState() == kDSpContextState_Active ) { gDrawSprocket->SetState( kDSpContextState_Paused ); } } gDrawSprocket->FadeGammaUpImmediate( true ); } #endif #if 0 // Are we using AGL_FULLSCREEN? if ( sBlankingWindow ) { // Yes, give some time for the monitor to adjust to the new res. UInt32 tickCount; Delay( 60, &tickCount ); } #endif // InitCursor (); sAGLActive = false; return result; } CGrafPtr _aglGetCurrentPort( void ) { if ( sGLWindow ) { // Running in a window return GetWindowPort( sGLWindow ); } else if ( sBlankingWindow ) { // Using aglSetFullscreen return ( CGrafPtr ) - 1; } else { // Using DrawSprocket fullscreen return gDrawSprocket->GetFrontBuffer(); } } GLboolean _aglResumeGameContext( void ) { GLboolean result = GL_FALSE; if ( !gAGLContext ) { return GL_TRUE; } if ( r_fullscreen->integer ) { /* CGDirectDisplayID displayID; displayID = (CGDirectDisplayID)sys_gl.displayID; if ( displayID == 0 ) { displayID = kCGDirectMainDisplay; } CGDisplayHideCursor( displayID ); // HideCursor(); */ gDrawSprocket->FadeGammaDownImmediate( true ); } if ( sGLWindow ) { // the blanking window can get shoved offscreen when the movie context // becomes active, put it back where it belongs - jb, 3/25/01 #undef MoveWindow MoveWindow( sGLWindow, sGLWindowRect.left, sGLWindowRect.top, false ); // The blanking window can get moved in priority, bump it to the front BringToFront( sGLWindow ); result = aglSetDrawable( gAGLContext, GetWindowPort( sGLWindow ) ); } else if ( sBlankingWindow ) { // The blanking window can get moved in priority, bump it to the front BringToFront( sBlankingWindow ); // Set the agl context for fullscreen instead of a window result = aglSetFullScreen( gAGLContext, glWidth, glHeight, glFrequency, glMonitor ); // That tanked, try a different frequency if ( !result ) { result = aglSetFullScreen( gAGLContext, glWidth, glHeight, 60.0, glMonitor ); } if ( !result ) { result = aglSetFullScreen( gAGLContext, glWidth, glHeight, 75.0, glMonitor ); } } #if TARGET_API_MAC_CARBON else { #if 0 // If we're using DSp on OSX, we need to reactivate the context if ( ( sSystemVersion >= 0x01000 ) && ( r_fullscreen->integer ) ) { if ( gDrawSprocket->GetState() == kDSpContextState_Paused ) { gDrawSprocket->SetState( kDSpContextState_Active ); } } #endif { CGrafPtr pPort; // use DSp's front buffer on Mac OS X pPort = gDrawSprocket->GetFrontBuffer(); if ( pPort == NULL ) { // ReportError ("DSpContext_GetFrontBuffer() had an error."); return result; } // there is a problem in Mac OS X GM CoreGraphics that may not size the port pixmap correctly // this will check the vertical sizes and offset if required to fix the problem // this will not center ports that are smaller then a particular resolution { long deltaV, deltaH; Rect portBounds; PixMapHandle hPix = GetPortPixMap( pPort ); Rect pixBounds = ( **hPix ).bounds; GetPortBounds( pPort, &portBounds ); deltaV = ( portBounds.bottom - portBounds.top ) - ( pixBounds.bottom - pixBounds.top ) + ( portBounds.bottom - portBounds.top - glHeight ) / 2; deltaH = -( portBounds.right - portBounds.left - glWidth ) / 2; if ( deltaV || deltaH ) { GrafPtr pPortSave; GetPort( &pPortSave ); SetPort( (GrafPtr)pPort ); // set origin to account for CG offset and if requested drawable smaller than screen rez SetOrigin( deltaH, deltaV ); SetPort( pPortSave ); } } result = aglSetDrawable( gAGLContext, pPort ); } } #endif if ( r_fullscreen->integer ) { gDrawSprocket->FadeGammaUpImmediate( true ); } sAGLActive = true; return result; } void _aglUsePrimaryContext( void ) { GLboolean ok; if ( gAGLContext_Primary == NULL ) { #if MAC_DEBUG && TEST_SMP Debugger(); #endif return; } gAGLContext = gAGLContext_Primary; ok = aglSetDrawable( gAGLContext_Secondary, NULL ); ok = aglSetCurrentContext( gAGLContext ); if ( !ok ) { MacWarning( "aglSetCurrentContext failed" ); } } void _aglUseSecondaryContext( void ) { GLboolean ok; if ( gAGLContext_Secondary == NULL ) { #if MAC_DEBUG && TEST_SMP Debugger(); #endif return; } gAGLContext = gAGLContext_Secondary; ok = aglSetDrawable( gAGLContext_Primary, NULL ); ok = aglSetCurrentContext( gAGLContext ); if ( !ok ) { MacWarning( "aglSetCurrentContext failed" ); } ok = aglSetDrawable( gAGLContext, _aglGetCurrentPort() ); } void _aglSwapBuffers( void ) { if ( sAGLActive ) { aglSwapBuffers( gAGLContext ); } else { gDrawSprocket->SwapBuffers(); } } WindowRef _aglGetGLWindow( void ) { return sGLWindow; } AGLDrawable _aglGetDrawable( void ) { return aglGetDrawable( gAGLContext ); } Boolean _aglUsingFullscreen( void ) { if ( sBlankingWindow ) { return true; } else { return false; } }