| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- /*
- -----------------------------------------------------------------------------
- This source file is part of OGRE
- (Object-oriented Graphics Rendering Engine)
- For the latest info, see http://www.ogre3d.org/
- Copyright (c) 2000-2011 Torus Knot Software Ltd
- 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.
- -----------------------------------------------------------------------------
- */
- #include "CmOSXWindow.h"
- #include "CmOSXCGLContext.h"
- #include "CmGLRenderSystem.h"
- #include "CmException.h"
- #include "CmStringConverter.h"
- #include "CmGLPixelFormat.h"
- #include <OpenGL/gl.h>
- #define GL_EXT_texture_env_combine 1
- #include <OpenGL/glext.h>
- #include <OpenGL/glu.h>
- namespace CamelotEngine
- {
- #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- uint32 OSXWindow::bitDepthFromDisplayMode(CGDisplayModeRef mode)
- {
- uint32 depth = 0;
- CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode);
- if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
- depth = 32;
- else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
- depth = 16;
- else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
- depth = 8;
- return depth;
- }
- #endif
- //-------------------------------------------------------------------------------------------------//
- OSXWindow::OSXWindow() : mContext(NULL), mCGLContextObj(NULL), mOriginalDisplayMode(NULL)
- {
- }
-
- //-------------------------------------------------------------------------------------------------//
- OSXWindow::~OSXWindow()
- {
- }
-
- //-------------------------------------------------------------------------------------------------//
- void OSXWindow::copyContentsToMemory(const PixelBox &dst, FrameBuffer buffer)
- {
- if ((dst.left < 0) || (dst.right > mWidth) ||
- (dst.top < 0) || (dst.bottom > mHeight) ||
- (dst.front != 0) || (dst.back != 1))
- {
- OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
- "Invalid box.",
- "OSXWindow::copyContentsToMemory" );
- }
-
- if (buffer == FB_AUTO)
- {
- buffer = mIsFullScreen? FB_FRONT : FB_BACK;
- }
-
- GLenum format = Ogre::GLPixelUtil::getGLOriginFormat(dst.format);
- GLenum type = Ogre::GLPixelUtil::getGLOriginDataType(dst.format);
-
- if ((format == GL_NONE) || (type == 0))
- {
- OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
- "Unsupported format.",
- "OSXWindow::copyContentsToMemory" );
- }
-
- if((dst.getWidth()*Ogre::PixelUtil::getNumElemBytes(dst.format)) & 3)
- {
- // Standard alignment of 4 is not right
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- }
-
- glReadBuffer((buffer == FB_FRONT)? GL_FRONT : GL_BACK);
- glReadPixels((GLint)dst.left, (GLint)dst.top,
- (GLsizei)dst.getWidth(), (GLsizei)dst.getHeight(),
- format, type, dst.data);
-
- glPixelStorei(GL_PACK_ALIGNMENT, 4);
-
- //vertical flip
- {
- size_t rowSpan = dst.getWidth() * PixelUtil::getNumElemBytes(dst.format);
- size_t height = dst.getHeight();
- uchar *tmpData = (uchar *)OGRE_MALLOC_ALIGN(rowSpan * height, MEMCATEGORY_GENERAL, false);
- uchar *srcRow = (uchar *)dst.data, *tmpRow = tmpData + (height - 1) * rowSpan;
-
- while (tmpRow >= tmpData)
- {
- memcpy(tmpRow, srcRow, rowSpan);
- srcRow += rowSpan;
- tmpRow -= rowSpan;
- }
- memcpy(dst.data, tmpData, rowSpan * height);
-
- OGRE_FREE_ALIGN(tmpData, MEMCATEGORY_GENERAL, false);
- }
- }
-
- //-------------------------------------------------------------------------------------------------//
- void OSXWindow::createCGLFullscreen(unsigned int width, unsigned int height, unsigned int depth, unsigned int fsaa, CGLContextObj sharedContext)
- {
- // Find the best match to what was requested
- boolean_t exactMatch = 0;
- unsigned int reqWidth = 0, reqHeight = 0, reqDepth = 0;
- CGLError cglErr = kCGLNoError;
- CGError cgErr = kCGErrorSuccess;
-
- #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- // Get a copy of the current display mode
- CGDisplayModeRef displayMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
-
- // Loop through all display modes to determine the closest match.
- // CGDisplayBestModeForParameters is deprecated on 10.6 so we will emulate it's behavior
- // Try to find a mode with the requested depth and equal or greater dimensions first.
- // If no match is found, try to find a mode with greater depth and same or greater dimensions.
- // If still no match is found, just use the current mode.
- CFArrayRef allModes = CGDisplayCopyAllDisplayModes(kCGDirectMainDisplay, NULL);
- for(int i = 0; i < CFArrayGetCount(allModes); i++)
- {
- CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i);
- String modeString = StringConverter::toString(CGDisplayModeGetWidth(mode)) + String(" x ") +
- StringConverter::toString(CGDisplayModeGetHeight(mode)) + String(" @ ") +
- StringConverter::toString(bitDepthFromDisplayMode(mode)) + "bpp.";
-
- // LogManager::getSingleton().logMessage(modeString);
- if(bitDepthFromDisplayMode(mode) != depth)
- continue;
-
- if((CGDisplayModeGetWidth(mode) == width) && (CGDisplayModeGetHeight(mode) == height))
- {
- displayMode = mode;
- exactMatch = 1;
- break;
- }
- }
-
- // No depth match was found
- if(!exactMatch)
- {
- for(int i = 0; i < CFArrayGetCount(allModes); i++)
- {
- CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i);
- if(bitDepthFromDisplayMode(mode) >= depth)
- continue;
-
- if((CGDisplayModeGetWidth(mode) >= width) && (CGDisplayModeGetHeight(mode) >= height))
- {
- displayMode = mode;
- exactMatch = 1;
- break;
- }
- }
- }
-
- reqWidth = CGDisplayModeGetWidth(displayMode);
- reqHeight = CGDisplayModeGetHeight(displayMode);
- reqDepth = bitDepthFromDisplayMode(displayMode);
- #else
- const void *value = NULL;
- CFDictionaryRef displayMode = CGDisplayBestModeForParameters(kCGDirectMainDisplay, depth, width, height, &exactMatch);
-
- value = CFDictionaryGetValue(displayMode, kCGDisplayWidth);
- CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &reqWidth);
-
- value = CFDictionaryGetValue(displayMode, kCGDisplayHeight);
- CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &reqHeight);
-
- value = CFDictionaryGetValue(displayMode, kCGDisplayBitsPerPixel);
- CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &reqDepth);
- #endif
- if(!exactMatch)
- {
- // That mode is not available, using the closest match
- String request = StringConverter::toString(width) + String(" x ") + StringConverter::toString(height) + String(" @ ") +
- StringConverter::toString(depth) + "bpp. ";
- String received = StringConverter::toString(reqWidth) + String(" x ") +
- StringConverter::toString(reqHeight) + String(" @ ") +
- StringConverter::toString(reqDepth) + "bpp. ";
-
- LogManager::getSingleton().logMessage(String("RenderSystem Warning: You requested a fullscreen mode of ") + request +
- String(" This mode is not available and you will receive the closest match. The best display mode for the parameters requested is: ")
- + received);
- }
- // Do the fancy display fading
- CGDisplayFadeReservationToken reservationToken = 0;
- cgErr = CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval,
- &reservationToken);
- if(reservationToken)
- {
- cgErr = CGDisplayFade(reservationToken,
- 0.5f,
- kCGDisplayBlendNormal,
- kCGDisplayBlendSolidColor,
- 0.0f, 0.0f, 0.0f,
- true);
- CG_CHECK_ERROR(cgErr)
-
- cgErr = CGReleaseDisplayFadeReservation(reservationToken);
- reservationToken = 0;
- CG_CHECK_ERROR(cgErr)
- }
-
- // Grab the main display and save it for later.
- // You could render to any display, but picking what display
- // to render to could be interesting.
- cgErr = CGDisplayCapture(kCGDirectMainDisplay);
- CG_CHECK_ERROR(cgErr)
-
- // Switch to the correct resolution
- #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- mOriginalDisplayMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
- cgErr = CGDisplaySetDisplayMode(kCGDirectMainDisplay, displayMode, NULL);
- #else
- mOriginalDisplayMode = CGDisplayCurrentMode(kCGDirectMainDisplay);
- cgErr = CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode);
- #endif
- CG_CHECK_ERROR(cgErr)
-
- // Get a pixel format that best matches what we are looking for
- CGLPixelFormatAttribute attribs[] = {
- kCGLPFADoubleBuffer,
- kCGLPFAAlphaSize, (CGLPixelFormatAttribute)8,
- kCGLPFADepthSize, (CGLPixelFormatAttribute)reqDepth,
- kCGLPFAStencilSize, (CGLPixelFormatAttribute)8,
- kCGLPFASampleBuffers, (CGLPixelFormatAttribute)0,
- kCGLPFASamples, (CGLPixelFormatAttribute)0,
- kCGLPFAFullScreen,
- kCGLPFASingleRenderer,
- kCGLPFAAccelerated,
- kCGLPFADisplayMask, (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
- (CGLPixelFormatAttribute)0
- };
-
- // Set up FSAA if it was requested
- if(fsaa > 1)
- {
- // Turn on kCGLPFASampleBuffers
- attribs[8] = (CGLPixelFormatAttribute)1;
- // Set the samples for kCGLPFASamples
- attribs[10] = (CGLPixelFormatAttribute)fsaa;
- }
-
- CGLPixelFormatObj pixelFormatObj = NULL;
- #if defined(MAC_OS_X_VERSION_10_4) && MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
- long numPixelFormats = 0;
- cglErr = CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats);
- #else
- GLint numPixelFormats = 0;
- cglErr = CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats);
- #endif
- CGL_CHECK_ERROR(cglErr)
-
- if(pixelFormatObj && !mCGLContextObj)
- {
- // Create the CGL context from our pixel format, share it with the sharedContext passed in
- cglErr = CGLCreateContext(pixelFormatObj, sharedContext, &mCGLContextObj);
- CGL_CHECK_ERROR(cglErr)
- }
- if(mCGLContextObj)
- {
- // Set the context as current
- cglErr = CGLSetCurrentContext(mCGLContextObj);
- CGL_CHECK_ERROR(cglErr)
-
- // Set the context to full screen
- #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- cglErr = CGLSetFullScreenOnDisplay(mCGLContextObj, CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay));
- #else
- cglErr = CGLSetFullScreen(mCGLContextObj);
- #endif
- CGL_CHECK_ERROR(cglErr)
-
- // This synchronizes CGL with the vertical retrace
- // Apple docs suggest that OpenGL blocks rendering calls when waiting for
- // a vertical retrace anyhow.
- #if defined(MAC_OS_X_VERSION_10_4) && MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
- long swapInterval = 1;
- cgErr = CGLSetParameter(mCGLContextObj, kCGLCPSwapInterval, &swapInterval);
- #else
- GLint swapInterval = 1;
- cgErr = CGLSetParameter(mCGLContextObj, kCGLCPSwapInterval, &swapInterval);
- #endif
- CG_CHECK_ERROR(cgErr)
-
- // Give a copy of our context to the rendersystem
- if(!mContext)
- mContext = OGRE_NEW OSXCGLContext(mCGLContextObj, pixelFormatObj);
- // Once we have the context we can destroy the pixel format
- // In order to share contexts you must keep a pointer to the context object around
- // Our context class will now manage the life of the pixelFormatObj
- cglErr = CGLDestroyPixelFormat(pixelFormatObj);
- CGL_CHECK_ERROR(cglErr)
-
- // Let everyone know we are fullscreen now
- mIsFullScreen = true;
- }
- // Set some other variables. Just in case we got a different value from CGDisplayBestModeForParameters than we requested
- mWidth = reqWidth;
- mHeight = reqHeight;
- mColourDepth = reqDepth;
- cgErr = CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval,
- &reservationToken);
- if(cgErr == kCGErrorSuccess)
- {
- cgErr = CGDisplayFade(reservationToken,
- 2.0f,
- kCGDisplayBlendSolidColor,
- kCGDisplayBlendNormal,
- 0.0f, 0.0f, 0.0f,
- false);
- CG_CHECK_ERROR(cgErr)
- cgErr = CGReleaseDisplayFadeReservation(reservationToken);
- CG_CHECK_ERROR(cgErr)
- }
- }
-
- //-------------------------------------------------------------------------------------------------//
- void OSXWindow::destroyCGLFullscreen(void)
- {
- CGError cgErr = kCGErrorSuccess;
- // Do the fancy display fading
- CGDisplayFadeReservationToken reservationToken = 0;
- cgErr = CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval,
- &reservationToken);
- if(cgErr == kCGErrorSuccess)
- {
- cgErr = CGDisplayFade(reservationToken,
- 2.0f,
- kCGDisplayBlendSolidColor,
- kCGDisplayBlendNormal,
- 0.0f, 0.0f, 0.0f,
- false);
- CG_CHECK_ERROR(cgErr)
-
- cgErr = CGReleaseDisplayFadeReservation(reservationToken);
- reservationToken = 0;
- CG_CHECK_ERROR(cgErr)
- }
-
- // Release the main display
- cgErr = CGDisplayRelease( kCGDirectMainDisplay );
- CG_CHECK_ERROR(cgErr)
-
- cgErr = CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval,
- &reservationToken);
- if(cgErr == kCGErrorSuccess)
- {
- cgErr = CGDisplayFade(reservationToken,
- 0.5f,
- kCGDisplayBlendNormal,
- kCGDisplayBlendSolidColor,
- 0.0f, 0.0f, 0.0f,
- true);
- CG_CHECK_ERROR(cgErr)
-
- cgErr = CGReleaseDisplayFadeReservation(reservationToken);
- CG_CHECK_ERROR(cgErr)
- }
- if(mCGLContextObj)
- {
- CGLDestroyContext(mCGLContextObj);
- mCGLContextObj = 0;
- }
- // Switch back to the original screen resolution
- #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- CGDisplaySetDisplayMode(kCGDirectMainDisplay, mOriginalDisplayMode, NULL);
- #else
- CGDisplaySwitchToMode(kCGDirectMainDisplay, mOriginalDisplayMode);
- #endif
- }
-
- //-------------------------------------------------------------------------------------------------//
- void OSXWindow::swapCGLBuffers(void)
- {
- CGLFlushDrawable(mCGLContextObj);
- CGLContextObj curCtx = CGLGetCurrentContext();
- if(curCtx != mCGLContextObj)
- {
- CGLSetCurrentContext(mCGLContextObj);
- #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- CGLSetFullScreenOnDisplay(mCGLContextObj, CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay));
- #else
- CGLSetFullScreen(mCGLContextObj);
- #endif
- }
- }
-
- }
|