123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #import "platformOSX/platformOSX.h"
- #import "platformOSX/osxOpenGLDevice.h"
- #import "platformOSX/platformGL.h"
- #include "console/console.h"
- #include "game/gameInterface.h"
- #include "graphics/dgl.h"
- //-----------------------------------------------------------------------------
- osxOpenGLDevice::osxOpenGLDevice()
- {
- mDeviceName = "OpenGL";
- mFullScreenOnly = false;
- // pick a monitor to run on
- enumMonitors();
- platState = [osxPlatState sharedPlatState];
- CGDirectDisplayID display = chooseMonitor();
- [platState setCgDisplay:display];
- enumDisplayModes(display);
- }
- //------------------------------------------------------------------------------
- bool osxOpenGLDevice::enumDisplayModes( CGDirectDisplayID display )
- {
- // Clear the resolution list.
- mResolutionList.clear();
- // Fetch a list of all available modes for the specified display.
- CFArrayRef modeArray = CGDisplayCopyAllDisplayModes(display, NULL);
- // Fetch the mode count.
- const S32 modeCount = (const S32)CFArrayGetCount(modeArray);
- // Iterate the modes.
- for( S32 modeIndex = 0; modeIndex < modeCount; modeIndex++ )
- {
- // Fetch the display mode.
- CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modeArray, modeIndex);
- // Get the mode width.
- const S32 width = (const S32)CGDisplayModeGetWidth(mode);
- // Get the mode height.
- const S32 height = (const S32)CGDisplayModeGetHeight(mode);
- // Get the pixel encoding.
- CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode);
- // Is it a 32 bpp?
- S32 bitDepth;
- if ( CFStringCompare( pixelEncoding, CFSTR(IO32BitDirectPixels), 0 ) == kCFCompareEqualTo )
- {
- bitDepth = 32;
- }
- else if ( CFStringCompare( pixelEncoding, CFSTR(IO16BitDirectPixels), 0 ) == kCFCompareEqualTo )
- {
- bitDepth = 16;
- }
- else
- {
- // Skip the mode.
- continue;
- }
- // Prepare the resolution.
- Resolution foundResolution( width, height, bitDepth );
- // Ensure this isn't already in the list.
- bool alreadyPresent = false;
- for( Vector<Resolution>::iterator itr = mResolutionList.begin(); itr != mResolutionList.end(); ++itr )
- {
- if ( *itr == foundResolution )
- {
- alreadyPresent = true;
- break;
- }
- }
- // Skip if already present.
- if ( alreadyPresent )
- continue;
- // Store the resolution.
- mResolutionList.push_back( Resolution( width, height, bitDepth ) );
- }
- return true;
- }
- //-----------------------------------------------------------------------------
- // Unused for new OS X platform. The constructor handles initialization now
- void osxOpenGLDevice::initDevice()
- {
- }
- //-----------------------------------------------------------------------------
- // This will fully clear the OpenGL context
- bool osxOpenGLDevice::cleanUpContext()
- {
- bool needResurrect = false;
- platState = [osxPlatState sharedPlatState];
- if ([[platState torqueView] contextInitialized])
- {
- if (!Video::smNeedResurrect)
- {
- Con::printf( "Killing the texture manager..." );
- Game->textureKill();
- needResurrect = true;
- }
- [[platState torqueView] clearContext];
- }
- // clear the Resolution state, so setScreenMode() will know not to early-out.
- smCurrentRes = Resolution(0, 0, 0);
- return needResurrect;
- }
- //-----------------------------------------------------------------------------
- //
- bool osxOpenGLDevice::activate( U32 width, U32 height, U32 bpp, bool fullScreen )
- {
- Con::printf( " OpenGLDevice activating..." );
- // gets opengl rendering capabilities of the screen pointed to by platState.hDisplay
- // sets up dgl with the capabilities info, & reports opengl status.
- getGLCapabilities();
- // Create the window or capture fullscreen
- if(!setScreenMode(width, height, bpp, fullScreen, true, false))
- return false;
- // set the displayDevice pref to "OpenGL"
- Con::setVariable( "$pref::Video::displayDevice", mDeviceName );
- // set vertical sync now because it doesnt need setting every time we setScreenMode()
- setVerticalSync( !Con::getBoolVariable( "$pref::Video::disableVerticalSync" ));
- return true;
- }
- //-----------------------------------------------------------------------------
- void osxOpenGLDevice::shutdown()
- {
- Con::printf( "Shutting down the OpenGL display device..." );
- cleanUpContext();
- }
- //-----------------------------------------------------------------------------
- NSOpenGLPixelFormat* osxOpenGLDevice::generateValidPixelFormat(bool fullscreen, U32 bpp, U32 samples)
- {
- AssertWarn(samples <= 6, "An unusual multisample depth was requested in findValidPixelFormat(). clamping to 0...6");
- samples = samples > 6 ? 6 : samples;
- int i = 0;
- NSOpenGLPixelFormatAttribute attr[64];
- attr[i++] = NSOpenGLPFADoubleBuffer;
- attr[i++] = NSOpenGLPFANoRecovery;
- attr[i++] = NSOpenGLPFAAccelerated;
- if(bpp != 0)
- {
- // native pixel formats are argb 1555 & argb 8888.
- U32 colorbits = 0;
- U32 alphabits = 0;
- if(bpp == 16)
- {
- colorbits = 5; // ARGB 1555
- alphabits = 1;
- }
- else if(bpp == 32)
- colorbits = alphabits = 8; // ARGB 8888
- attr[i++] = NSOpenGLPFADepthSize;
- attr[i++] = (NSOpenGLPixelFormatAttribute)bpp;
- attr[i++] = NSOpenGLPFAColorSize;
- attr[i++] = (NSOpenGLPixelFormatAttribute)colorbits;
- attr[i++] = NSOpenGLPFAAlphaSize;
- attr[i++] = (NSOpenGLPixelFormatAttribute)alphabits;
- }
- if (samples != 0)
- {
- attr[i++] = NSOpenGLPFAMultisample;
- attr[i++] = (NSOpenGLPixelFormatAttribute)1;
- attr[i++] = NSOpenGLPFASamples;
- attr[i++] = (NSOpenGLPixelFormatAttribute)samples;
- }
- attr[i++] = 0;
- NSOpenGLPixelFormat* format = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attr] autorelease];
- return format;
- }
- //-----------------------------------------------------------------------------
- bool osxOpenGLDevice::setScreenMode( U32 width, U32 height, U32 bpp, bool fullScreen, bool forceIt, bool repaint )
- {
- // Print to the console that we are setting the screen mode
- Con::printf(" set screen mode %i x %i x %i, %s, %s, %s",width, height, bpp,
- fullScreen ? "fullscreen" : "windowed",
- forceIt ? "force it" : "dont force it",
- repaint ? "repaint" : "dont repaint");
- bool needResurrect = cleanUpContext();
- // Get the global OSX platform state
- osxPlatState * platState = [osxPlatState sharedPlatState];
- // Validation, early outs
- // Sanity check. Some scripts are liable to pass in bad values.
- if (!bpp)
- bpp = [platState desktopBitsPixel];
- if (bpp)
- bpp = bpp > 16 ? 32 : 16;
- Resolution newRes = Resolution(width, height, bpp);
- // If no values changing and we're not forcing a change, kick out. prevents thrashing.
- if (!forceIt && smIsFullScreen == fullScreen && smCurrentRes == newRes)
- return true;
- // Create a pixel format to be used with the context
- NSOpenGLPixelFormat* pixelFormat = generateValidPixelFormat(fullScreen, bpp, 0);
- if (!pixelFormat)
- {
- Con::printf("osxOpenGLDevice::setScreenMode error: No OpenGL pixel format");
- return false;
- }
- [platState setFullScreen:fullScreen];
- if (fullScreen)
- {
- NSRect mainDisplayRect = [[NSScreen mainScreen] frame];
- newRes.w = mainDisplayRect.size.width;
- newRes.h = mainDisplayRect.size.height;
- [[platState window] setStyleMask:NSBorderlessWindowMask];
- [[platState window] setFrame:mainDisplayRect display:YES];
- [[platState window] setLevel:NSMainMenuWindowLevel+1];
- }
- else
- {
- #if __MAC_OS_X_VERSION_MAX_ALLOWED < 1070
- [[platState window] setStyleMask:NSTitledWindowMask | NSClosableWindowMask] ;
- // Calculate the actual center
- CGFloat x = ([[NSScreen mainScreen] frame].size.width - width) / 2;
- CGFloat y = ([[NSScreen mainScreen] frame].size.height - height) / 2;
- // Create a rect to send to the window
- NSRect newFrame = NSMakeRect(x, y, width, height);
- // Send message to the window to resize/relocate
- [[platState window] setFrame:newFrame display:YES animate:NO];
- #else
- [[platState window] setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable];
- #endif
- }
- [[platState torqueView] createContextWithPixelFormat:pixelFormat];
- [platState setWindowSize:newRes.w height:newRes.h];
- // clear out garbage from the gl window.
- glClearColor(0,0,0,1);
- glClear(GL_COLOR_BUFFER_BIT );
- // set opengl options & other options ---------------------------------------
- // ensure data is packed tightly in memory. this defaults to 4.
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- // TODO: set gl arb multisample enable & hint
- //dglSetFSAASamples(gFSAASamples);
- // update smIsFullScreen and pref
- smIsFullScreen = fullScreen;
- Con::setBoolVariable( "$pref::Video::fullScreen", smIsFullScreen );
- // save resolution
- smCurrentRes = newRes;
- // save resolution to prefs
- char buf[32];
- if (fullScreen)
- {
- dSprintf( buf, sizeof(buf), "%d %d %d", newRes.w, newRes.h, newRes.bpp);
- Con::setVariable("$pref::Video::resolution", buf);
- }
- else
- {
- dSprintf( buf, sizeof(buf), "%d %d", newRes.w, newRes.h);
- Con::setVariable("$pref::Video::windowedRes", buf);
- }
- if (needResurrect)
- {
- // Reload the textures gl names
- Con::printf( "Resurrecting the texture manager..." );
- Game->textureResurrect();
- }
- if( repaint )
- Video::resetCanvas();
- return true;
- }
- //-----------------------------------------------------------------------------
- void osxOpenGLDevice::swapBuffers()
- {
- if ([[platState torqueView] contextInitialized])
- [[platState torqueView] flushBuffer];
- #if defined(TORQUE_DEBUG)
- if (gOutlineEnabled)
- glClear(GL_COLOR_BUFFER_BIT);
- #endif
- }
- //-----------------------------------------------------------------------------
- const char* osxOpenGLDevice::getDriverInfo()
- {
- // Prepare some driver info for the console:
- const char* vendorString = (const char*) glGetString( GL_VENDOR );
- const char* rendererString = (const char*) glGetString( GL_RENDERER );
- const char* versionString = (const char*) glGetString( GL_VERSION );
- const char* extensionsString = (const char*) glGetString( GL_EXTENSIONS );
- U32 bufferLen = ( vendorString ? dStrlen( vendorString ) : 0 )
- + ( rendererString ? dStrlen( rendererString ) : 0 )
- + ( versionString ? dStrlen( versionString ) : 0 )
- + ( extensionsString ? dStrlen( extensionsString ) : 0 )
- + 4;
- char* returnString = Con::getReturnBuffer( bufferLen );
- dSprintf( returnString, bufferLen, "%s\t%s\t%s\t%s",
- ( vendorString ? vendorString : "" ),
- ( rendererString ? rendererString : "" ),
- ( versionString ? versionString : "" ),
- ( extensionsString ? extensionsString : "" ) );
- return( returnString );
- }
- //-----------------------------------------------------------------------------
- // Not yet implemented. Will resolve in the next video update
- bool osxOpenGLDevice::getGammaCorrection(F32 &g)
- {
- return false;
- }
- //-----------------------------------------------------------------------------
- // Not yet implemented. Will resolve in the next video update
- bool osxOpenGLDevice::setGammaCorrection(F32 g)
- {
- return false;
- }
- //-----------------------------------------------------------------------------
- bool osxOpenGLDevice::getVerticalSync()
- {
- if (!gGLState.suppSwapInterval)
- {
- return false;
- }
- //Note that this returns the number of frames between Swaps.
- //The function returns 0 / false if SwapInterval has not been specified.
- return false;//getVerticalSync();
- }
- //-----------------------------------------------------------------------------
- bool osxOpenGLDevice::setVerticalSync( bool sync )
- {
- if ([[platState torqueView] contextInitialized])
- {
- [[platState torqueView] setVerticalSync:sync];
- return true;
- }
- else
- {
- return false;
- }
- }
- //------------------------------------------------------------------------------
- // Fill mMonitorList with list of supported modes
- // Guaranteed to include at least the main device.
- //------------------------------------------------------------------------------
- bool osxOpenGLDevice::enumMonitors()
- {
- mMonitorList.clear();
- nAllDevs = 0;
- CGDirectDisplayID _displayIDs[32];
- uint32_t _displayCount;
- CGGetActiveDisplayList (32, _displayIDs, &_displayCount);
- for (int ii = 0 ; ii < _displayCount ; ii++)
- {
- mMonitorList.push_back(_displayIDs[ii]);
- allDevs[nAllDevs++] = _displayIDs[ii];
- }
- return true;
- }
- //------------------------------------------------------------------------------
- // Chooses a monitor based on $pref, on the results of tors(), & on the
- // current window's screen.
- //------------------------------------------------------------------------------
- CGDirectDisplayID osxOpenGLDevice::chooseMonitor()
- {
- // TODO: choose monitor based on which one contains most of the window.
- // NOTE: do not call cleanup before calling choose, or we won't have a window to consider.
- AssertFatal(!mMonitorList.empty(), "Cannot choose a monitor if the list is empty!");
- U32 monNum = Con::getIntVariable("$pref::Video::monitorNum", 0);
- if (monNum >= mMonitorList.size())
- {
- Con::errorf("invalid monitor number %i", monNum);
- monNum = 0;
- Con::setIntVariable("$pref::Video::monitorNum", 0);
- }
- Con::printf("using display 0x%x", mMonitorList[monNum]);
- return mMonitorList[monNum];
- }
|