/* * DarwinUtils.cpp * OpenSceneGraph * * Created by Stephan Huber on 27.06.08. * Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved. * */ #include #include #include #import #include "IOSUtils.h" namespace osgIOS { class AutoReleasePoolHelper { public: AutoReleasePoolHelper() { pool = [[NSAutoreleasePool alloc] init]; } ~AutoReleasePoolHelper() { [pool release]; } private: NSAutoreleasePool* pool; }; /** ctor, get a list of all attached displays */ IOSWindowingSystemInterface::IOSWindowingSystemInterface() : osg::GraphicsContext::WindowingSystemInterface() { } /** dtor */ IOSWindowingSystemInterface::~IOSWindowingSystemInterface() { if (osg::Referenced::getDeleteHandler()) { osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } } /** @return count of attached screens */ unsigned int IOSWindowingSystemInterface::getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) { AutoReleasePoolHelper auto_release_pool_helper; return [[UIScreen screens] count]; } void IOSWindowingSystemInterface::getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return;} //get the screens array from the UIScreen class NSArray* screens = [UIScreen screens]; //iterate to the desired screen num UIScreen* screen = [screens objectAtIndex:si.screenNum]; if (si.screenNum == 0) { //internal display supports only one mode, UiScreenMode reports wrong sizes for internal display at least for iOS 3.2 float scale = 1.0f; #ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) scale = [screen scale]; #endif resolution.width = [screen bounds].size.width * scale; resolution.height = [screen bounds].size.height * scale; resolution.colorDepth = 24; resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true } else { //get the screen mode NSArray* modesArray = [screen availableModes]; if(modesArray) { //for this method we copy the first mode (default) then return UIScreenMode* mode = [modesArray objectAtIndex:0]; CGSize size = [mode size]; resolution.width = size.width; resolution.height = size.height; resolution.colorDepth = 24; resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true OSG_INFO << "new resolution for screen " << si.screenNum << ": " << size.width << "x" << size.height << std::endl; } } } // //Due to the weird void IOSWindowingSystemInterface::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return;} //get the screens array from the UIScreen class NSArray* screens = [UIScreen screens]; //get the desired screen num UIScreen* screen = [screens objectAtIndex:si.screenNum]; if (si.screenNum == 0) { //internal display supports only one mode, UiScreenMode reports wrong sizes for internal screen at least for iOS 3.2 osg::GraphicsContext::ScreenSettings resolution; float scale = 1.0f; #ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) scale = [screen scale]; #endif resolution.width = [screen bounds].size.width * scale; resolution.height = [screen bounds].size.height * scale; resolution.colorDepth = 24; resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true resolutionList.push_back(resolution); } else { // external display may support more resolutions: //get the screen mode NSArray* modesArray = [screen availableModes]; NSEnumerator* modesEnum = [modesArray objectEnumerator]; UIScreenMode* mode; //iterate over modes and get their size property while ( mode = [modesEnum nextObject] ) { osg::GraphicsContext::ScreenSettings resolution; CGSize size = [mode size]; resolution.width = size.width; resolution.height = size.height; resolution.colorDepth = 24; resolution.refreshRate = 60; //i've read 60 is max, not sure if thats true resolutionList.push_back(resolution); OSG_INFO << "new resolution: " << size.width << "x" << size.height << std::endl; } } } bool IOSWindowingSystemInterface::setScreenSettings(const osg::GraphicsContext::ScreenIdentifier &si, const osg::GraphicsContext::ScreenSettings & settings) { bool result = setScreenResolutionImpl(si, settings.width, settings.height); if (result) setScreenRefreshRateImpl(si, settings.refreshRate); return result; } /** implementation of setScreenResolution */ //IPad can have extenal screens which we can request a res for //the main screen screenNum 0 can not currently have its res changed //as it only has one mode (might change though and this should still handle it) // bool IOSWindowingSystemInterface::setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return false;} //get the screens array from the UIScreen class NSArray* screens = [UIScreen screens]; //iterate to the desired screen num UIScreen* screen = [screens objectAtIndex:si.screenNum]; //get the screen mode NSArray* modesArray = [screen availableModes]; NSEnumerator* modesEnum = [modesArray objectEnumerator]; UIScreenMode* mode; //iterate over modes and get their size property while ( mode = [modesEnum nextObject] ) { osg::GraphicsContext::ScreenSettings resolution; CGSize size = [mode size]; //if the modes size/resolution matches the passed width/height then assign this //mode as the screens current mode if(size.width == width && size.height == height) { screen.currentMode = mode; OSG_INFO << "IOSWindowingSystemInterface::setScreenResolutionImpl: Set resolution of screen '" << si.screenNum << "', to '" << width << ", " << height << "'." << std::endl; return true; } } OSG_WARN << "IOSWindowingSystemInterface::setScreenResolutionImpl: Failed to set resolution of screen '" << si.screenNum << "', to '" << width << ", " << height << "'." << std::endl; return false; } /** implementation of setScreenRefreshRate, don't think you can do this on IOS */ bool IOSWindowingSystemInterface::setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate) { return true; } unsigned int IOSWindowingSystemInterface::getScreenContaining(int x, int y, int w, int h) { return 1; } // //return the UIScreen object asscoiated with the passed ScreenIdentifier //returns nil if si isn't found // UIScreen* IOSWindowingSystemInterface::getUIScreen(const osg::GraphicsContext::ScreenIdentifier& si) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return nil;} UIScreen* screen = [[UIScreen screens] objectAtIndex:si.screenNum]; return screen; } // //Returns the contents scale factor of the screen, this is the scale factor required //to convert points to pixels on this screen // bool IOSWindowingSystemInterface::getScreenContentScaleFactor(const osg::GraphicsContext::ScreenIdentifier& si, float& scaleFactor) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return false;} UIScreen* screen = this->getUIScreen(si); if(screen != nil) { scaleFactor = 1.0f; #ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0) CGFloat scale = [screen scale]; scaleFactor = scale; #endif return true; } return false; } // //Returns the screens size in points, docs state a point is roughly 1/160th of an inch // bool IOSWindowingSystemInterface::getScreenSizeInPoints(const osg::GraphicsContext::ScreenIdentifier& si, osg::Vec2& pointSize) { AutoReleasePoolHelper auto_release_pool_helper; if(si.screenNum >= [[UIScreen screens] count]){return false;} UIScreen* screen = this->getUIScreen(si); if(screen != nil) { CGRect bounds = [screen bounds]; pointSize.x() = bounds.size.width; pointSize.y() = bounds.size.height; return true; } return false; } }