2.8 branch: Support for OS X 10.6. Several changes to GraphicsWIndowCocoa and DarwinUtils. The following trunk revisions were merged in this commit: 9879, 9895, 10208, 10340, 10417, 10456, 10622, 10858, and 10887.

This commit is contained in:
Paul MARTZ
2010-03-15 17:20:43 +00:00
parent da79cd85e4
commit 5be809ab04
8 changed files with 2650 additions and 59 deletions

View File

@@ -65,87 +65,105 @@ IF(WIN32)
ELSE(WIN32)
IF(APPLE)
SET(OSG_WINDOWING_SYSTEM "Carbon" CACHE STRING "Windowing system type for graphics window creation, options Carbon or X11.")
SET(OSG_WINDOWING_SYSTEM "Carbon" CACHE STRING "Windowing system type for graphics window creation, options Carbon, Cocoa or X11.")
ELSE(APPLE)
SET(OSG_WINDOWING_SYSTEM "X11" CACHE STRING "Windowing system type for graphics window creation. options only X11")
ENDIF(APPLE)
IF(${OSG_WINDOWING_SYSTEM} STREQUAL "Carbon")
# FIXME: OS X needs selection mechanism for Cocoa, Carbon, X11
IF(${OSG_WINDOWING_SYSTEM} STREQUAL "Cocoa")
ADD_DEFINITIONS(-DUSE_DARWIN_COCOA_IMPLEMENTATION)
SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS}
${HEADER_PATH}/api/Carbon/GraphicsWindowCarbon
${HEADER_PATH}/api/Carbon/PixelBufferCarbon
${HEADER_PATH}/api/Cocoa/GraphicsHandleCocoa
${HEADER_PATH}/api/Cocoa/GraphicsWindowCocoa
${HEADER_PATH}/api/Cocoa/PixelBufferCocoa
)
SET(LIB_COMMON_FILES ${LIB_COMMON_FILES}
GraphicsWindowCarbon.cpp
PixelBufferCarbon.cpp
GraphicsWindowCocoa.mm
DarwinUtils.h
DarwinUtils.mm
PixelBufferCocoa.mm
)
ELSE(${OSG_WINDOWING_SYSTEM} STREQUAL "Carbon")
SET(LIB_EXTRA_LIBS ${COCOA_LIBRARY} ${LIB_EXTRA_LIBS})
# X11 for everybody else
ELSE(${OSG_WINDOWING_SYSTEM} STREQUAL "Cocoa")
IF(${OSG_WINDOWING_SYSTEM} STREQUAL "Carbon")
ADD_DEFINITIONS(-DUSE_DARWIN_CARBON_IMPLEMENTATION)
SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS}
${HEADER_PATH}/api/Carbon/GraphicsWindowCarbon
${HEADER_PATH}/api/Carbon/PixelBufferCarbon
)
SET(LIB_COMMON_FILES ${LIB_COMMON_FILES}
GraphicsWindowCarbon.cpp
DarwinUtils.h
DarwinUtils.mm
PixelBufferCarbon.cpp
)
SET(LIB_EXTRA_LIBS ${COCOA_LIBRARY} ${LIB_EXTRA_LIBS})
ELSE(${OSG_WINDOWING_SYSTEM} STREQUAL "Carbon")
# X11 for everybody else
INCLUDE(FindPkgConfig OPTIONAL)
IF (PKG_CONFIG_FOUND)
INCLUDE(FindPkgConfig OPTIONAL)
IF (PKG_CONFIG_FOUND)
PKG_CHECK_MODULES(XRANDR xrandr)
IF (XRANDR_FOUND)
OPTION(OSGVIEWER_USE_XRANDR "Set to ON to enable Xrandr support for GraphicsWindowX11." ON)
ELSE(XRANDR_FOUND)
PKG_CHECK_MODULES(XRANDR xrandr)
IF (XRANDR_FOUND)
OPTION(OSGVIEWER_USE_XRANDR "Set to ON to enable Xrandr support for GraphicsWindowX11." ON)
ELSE(XRANDR_FOUND)
SET(OSGVIEWER_USE_XRANDR OFF)
ENDIF (XRANDR_FOUND)
ELSE(PKG_CONFIG_FOUND)
SET(OSGVIEWER_USE_XRANDR OFF)
ENDIF (XRANDR_FOUND)
ELSE(PKG_CONFIG_FOUND)
SET(OSGVIEWER_USE_XRANDR OFF)
ENDIF(PKG_CONFIG_FOUND)
ENDIF(PKG_CONFIG_FOUND)
SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS}
${HEADER_PATH}/api/X11/GraphicsWindowX11
${HEADER_PATH}/api/X11/PixelBufferX11
)
SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS}
${HEADER_PATH}/api/X11/GraphicsWindowX11
${HEADER_PATH}/api/X11/PixelBufferX11
)
SET(LIB_COMMON_FILES ${LIB_COMMON_FILES}
GraphicsWindowX11.cpp
PixelBufferX11.cpp
)
IF(OSGVIEWER_USE_XRANDR)
ADD_DEFINITIONS(-DOSGVIEWER_USE_XRANDR)
SET(LIB_PRIVATE_HEADERS ${LIB_PRIVATE_HEADERS} ${XRANDR_INCLUDE_DIRS} )
IF (X11_Xrandr_LIB)
SET(LIB_EXTRA_LIBS ${X11_Xrandr_LIB} ${LIB_EXTRA_LIBS})
ELSE(X11_Xrandr_LIB)
SET(LIB_EXTRA_LIBS ${XRANDR_LIBRARIES} ${LIB_EXTRA_LIBS})
ENDIF(X11_Xrandr_LIB)
SET(LIB_COMMON_FILES ${LIB_COMMON_FILES}
GraphicsWindowX11.cpp
PixelBufferX11.cpp
)
ENDIF(OSGVIEWER_USE_XRANDR)
# X11 on Apple requires X11 library plus OpenGL linking hack on Leopard
IF(APPLE)
# Find GL/glx.h
IF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11/include/GL/glx.h)
SET(OPENGL_INCLUDE_DIR /usr/X11/include)
SET(OPENGL_LIBRARIES /usr/X11/lib/libGL.dylib)
ELSEIF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11R6/include/GL/glx.h)
SET(OPENGL_INCLUDE_DIR /usr/X11R6/include)
SET(OPENGL_LIBRARIES /usr/X11R6/lib/libGL.dylib)
ENDIF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11/include/GL/glx.h)
INCLUDE_DIRECTORIES(BEFORE SYSTEM ${OPENGL_INCLUDE_DIR})
SET(LIB_EXTRA_LIBS ${X11_X11_LIB} ${OPENGL_LIBRARIES} ${LIB_EXTRA_LIBS})
SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib")
ENDIF(APPLE)
IF(OSGVIEWER_USE_XRANDR)
ADD_DEFINITIONS(-DOSGVIEWER_USE_XRANDR)
SET(LIB_PRIVATE_HEADERS ${LIB_PRIVATE_HEADERS} ${XRANDR_INCLUDE_DIRS} )
ENDIF(${OSG_WINDOWING_SYSTEM} STREQUAL "Carbon")
IF (X11_Xrandr_LIB)
SET(LIB_EXTRA_LIBS ${X11_Xrandr_LIB} ${LIB_EXTRA_LIBS})
ELSE(X11_Xrandr_LIB)
SET(LIB_EXTRA_LIBS ${XRANDR_LIBRARIES} ${LIB_EXTRA_LIBS})
ENDIF(X11_Xrandr_LIB)
ENDIF(OSGVIEWER_USE_XRANDR)
# X11 on Apple requires X11 library plus OpenGL linking hack on Leopard
IF(APPLE)
# Find GL/glx.h
IF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11/include/GL/glx.h)
SET(OPENGL_INCLUDE_DIR /usr/X11/include)
SET(OPENGL_LIBRARIES /usr/X11/lib/libGL.dylib)
ELSEIF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11R6/include/GL/glx.h)
SET(OPENGL_INCLUDE_DIR /usr/X11R6/include)
SET(OPENGL_LIBRARIES /usr/X11R6/lib/libGL.dylib)
ENDIF(EXISTS ${CMAKE_OSX_SYSROOT}/usr/X11/include/GL/glx.h)
INCLUDE_DIRECTORIES(BEFORE SYSTEM ${OPENGL_INCLUDE_DIR})
SET(LIB_EXTRA_LIBS ${X11_X11_LIB} ${OPENGL_LIBRARIES} ${LIB_EXTRA_LIBS})
SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib")
ENDIF(APPLE)
ENDIF(${OSG_WINDOWING_SYSTEM} STREQUAL "Carbon")
ENDIF(${OSG_WINDOWING_SYSTEM} STREQUAL "Cocoa")
ENDIF(WIN32)

152
src/osgViewer/DarwinUtils.h Executable file
View File

@@ -0,0 +1,152 @@
/*
* DarwinUtils.h
* OpenSceneGraph
*
* Created by Stephan Huber on 27.06.08.
* Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved.
*
*/
#ifdef __APPLE__
#ifndef DARWIN_UTILS_HEADER_
#define DARWIN_UTILS_HEADER_
#include <osg/DeleteHandler>
#include <osg/GraphicsContext>
#include <osgViewer/GraphicsWindow>
#include <Carbon/Carbon.h>
//#define USE_DARWIN_COCOA_IMPLEMENTATION 1
//#define USE_DARWIN_CARBON_IMPLEMENTATION 1
namespace osgDarwin {
/** the MenubarController class checks all open windows if they intersect with the menubar / dock and hide the menubar/dock if necessary */
class MenubarController : public osg::Referenced
{
public:
class WindowAdapter : public osg::Referenced {
public:
WindowAdapter() : osg::Referenced() {}
virtual bool valid() = 0;
virtual void getWindowBounds(CGRect& rect) = 0;
virtual osgViewer::GraphicsWindow* getWindow() = 0;
protected:
virtual ~WindowAdapter() {}
};
MenubarController();
static MenubarController* instance();
void attachWindow(WindowAdapter* win);
void update();
void detachWindow(osgViewer::GraphicsWindow* win);
private:
typedef std::list< osg::ref_ptr< WindowAdapter > > WindowList;
WindowList _list;
bool _menubarShown;
CGRect _availRect;
CGRect _mainScreenBounds;
OpenThreads::Mutex _mutex;
};
struct DarwinWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
{
public:
DarwinWindowingSystemInterface();
/** dtor */
~DarwinWindowingSystemInterface();
/** @return a CGDirectDisplayID for a ScreenIdentifier */
CGDirectDisplayID getDisplayID(const osg::GraphicsContext::ScreenIdentifier& si);
/** @return count of attached screens */
virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) ;
virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution);
virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList);
virtual bool setScreenSettings (const osg::GraphicsContext::ScreenIdentifier & si, const osg::GraphicsContext::ScreenSettings & settings);
/** return the top left coord of a specific screen in global screen space */
void getScreenTopLeft(const osg::GraphicsContext::ScreenIdentifier& si, int& x, int& y);
/** returns screen-ndx containing rect x,y,w,h */
unsigned int getScreenContaining(int x, int y, int w, int h);
protected:
/** implementation of setScreenResolution */
bool setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height) ;
/** implementation of setScreenRefreshRate */
bool setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate);
template<class PixelBufferImplementation, class GraphicsWindowImplementation>
osg::GraphicsContext* createGraphicsContextImplementation(osg::GraphicsContext::Traits* traits)
{
if (traits->pbuffer)
{
osg::ref_ptr<PixelBufferImplementation> pbuffer = new PixelBufferImplementation(traits);
if (pbuffer->valid()) return pbuffer.release();
else return 0;
}
else
{
osg::ref_ptr<GraphicsWindowImplementation> window = new GraphicsWindowImplementation(traits);
if (window->valid()) return window.release();
else return 0;
}
}
private:
CGDisplayCount _displayCount;
CGDirectDisplayID* _displayIds;
};
template <class WSI>
struct RegisterWindowingSystemInterfaceProxy
{
RegisterWindowingSystemInterfaceProxy()
{
osg::GraphicsContext::setWindowingSystemInterface(new WSI);
}
~RegisterWindowingSystemInterfaceProxy()
{
if (osg::Referenced::getDeleteHandler())
{
osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
osg::Referenced::getDeleteHandler()->flushAll();
}
osg::GraphicsContext::setWindowingSystemInterface(0);
}
};
}
#endif
#endif // __APPLE__

390
src/osgViewer/DarwinUtils.mm Executable file
View File

@@ -0,0 +1,390 @@
/*
* DarwinUtils.cpp
* OpenSceneGraph
*
* Created by Stephan Huber on 27.06.08.
* Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved.
*
*/
#include <osg/Referenced>
#include <osg/DeleteHandler>
#include "DarwinUtils.h"
#include <Cocoa/Cocoa.h>
@interface MenubarToggler : NSObject {
}
-(void) show: (id) data;
-(void) hide: (id) data;
@end
@implementation MenubarToggler
-(void) hide:(id) data
{
OSErr error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
if (error) {
osg::notify(osg::DEBUG_INFO) << "MenubarToggler::hide failed with " << error << std::endl;
}
}
-(void) show:(id) data
{
OSErr error = SetSystemUIMode(kUIModeNormal, 0);
if (error) {
osg::notify(osg::DEBUG_INFO) << "MenubarToggler::show failed with " << error << std::endl;
}
}
@end
namespace osgDarwin {
static inline CGRect toCGRect(NSRect nsRect)
{
CGRect cgRect;
cgRect.origin.x = nsRect.origin.x;
cgRect.origin.y = nsRect.origin.y;
cgRect.size.width = nsRect.size.width;
cgRect.size.height = nsRect.size.height;
return cgRect;
}
MenubarController::MenubarController()
: osg::Referenced(),
_list(),
_menubarShown(false),
_mutex()
{
// the following code will query the system for the available rect on the main-display (typically the displaying showing the menubar + the dock
NSRect rect = [[[NSScreen screens] objectAtIndex: 0] visibleFrame];
_availRect = toCGRect(rect);
// now we need the rect of the main-display including the menubar and the dock
_mainScreenBounds = CGDisplayBounds( CGMainDisplayID() );
// NSRect 0/0 is bottom/left, _mainScreenBounds 0/0 is top/left
_availRect.origin.y = _mainScreenBounds.size.height - _availRect.size.height - _availRect.origin.y;
// hide the menubar initially
SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
}
MenubarController* MenubarController::instance()
{
static osg::ref_ptr<MenubarController> s_menubar_controller = new MenubarController();
return s_menubar_controller.get();
}
void MenubarController::attachWindow(WindowAdapter* win)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
_list.push_back(win);
update();
}
void MenubarController::detachWindow(osgViewer::GraphicsWindow* win)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
for(WindowList::iterator i = _list.begin(); i != _list.end(); ) {
if ((*i)->getWindow() == win)
i = _list.erase(i);
else
++i;
}
update();
}
// iterate through all open windows and check, if they intersect the area occupied by the menubar/dock, and if so, hide the menubar/dock
void MenubarController::update()
{
unsigned int windowsCoveringMenubarArea = 0;
unsigned int windowsIntersectingMainScreen = 0;
for(WindowList::iterator i = _list.begin(); i != _list.end(); ) {
WindowAdapter* wi = (*i).get();
if (wi->valid()) {
CGRect windowBounds;
wi->getWindowBounds(windowBounds);
if (CGRectIntersectsRect(_mainScreenBounds, windowBounds))
{
++windowsIntersectingMainScreen;
// osg::notify(osg::ALWAYS) << "testing rect " << windowBounds.origin.x << "/" << windowBounds.origin.y << " " << windowBounds.size.width << "x" << windowBounds.size.height << std::endl;
// osg::notify(osg::ALWAYS) << "against " << _availRect.origin.x << "/" << _availRect.origin.y << " " << _availRect.size.width << "x" << _availRect.size.height << std::endl;
// the window intersects the main-screen, does it intersect with the menubar/dock?
if (((_availRect.origin.y > _mainScreenBounds.origin.y) && (_availRect.origin.y > windowBounds.origin.y)) ||
((_availRect.origin.x > _mainScreenBounds.origin.x) && (_availRect.origin.x > windowBounds.origin.x)) ||
((_availRect.size.width < _mainScreenBounds.size.width) && (_availRect.origin.x + _availRect.size.width < windowBounds.origin.x + windowBounds.size.width)) ||
((_availRect.size.height < _mainScreenBounds.size.height) && (_availRect.origin.y + _availRect.size.height < windowBounds.origin.y + windowBounds.size.height) ))
{
++windowsCoveringMenubarArea;
}
}
++i;
}
else
i = _list.erase(i);
}
// if we use the cocoa implementation then we have a NSRunLoop in place, and so we can use the deferred menubar-toggling which is thread safe
#ifdef USE_DARWIN_COCOA_IMPLEMENTATION
// SetSystemUIMode is not threadsafe, you'll get crashes if you call this method from other threads
// so use a small NSObject to switch the menubar on the main thread via performSelectorOnMainThread
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
if (windowsCoveringMenubarArea && _menubarShown)
{
//error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
MenubarToggler* toggler = [[MenubarToggler alloc] init];
[toggler performSelectorOnMainThread: @selector(hide:) withObject:NULL waitUntilDone: YES];
[toggler autorelease];
}
if (!windowsCoveringMenubarArea && !_menubarShown)
{
//error = SetSystemUIMode(kUIModeNormal, 0);
MenubarToggler* toggler = [[MenubarToggler alloc] init];
[toggler performSelectorOnMainThread: @selector(show:) withObject:NULL waitUntilDone: YES];
[toggler autorelease];
}
[pool release];
#else
OSErr error;
// see http://developer.apple.com/technotes/tn2002/tn2062.html for hiding the dock+menubar
if (windowsCoveringMenubarArea && _menubarShown)
{
error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
}
if (!windowsCoveringMenubarArea && !_menubarShown)
{
error = SetSystemUIMode(kUIModeNormal, 0);
}
#endif
_menubarShown = !windowsCoveringMenubarArea;
}
/** Helper method to get a double value out of a CFDictionary */
static double getDictDouble (CFDictionaryRef refDict, CFStringRef key)
{
double value;
CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key);
if (!number_value) // if can't get a number for the dictionary
return -1; // fail
if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &value)) // or if cant convert it
return -1; // fail
return value; // otherwise return the long value
}
/** Helper method to get a long value out of a CFDictionary */
static long getDictLong(CFDictionaryRef refDict, CFStringRef key) // const void* key?
{
long value = 0;
CFNumberRef number_value = (CFNumberRef)CFDictionaryGetValue(refDict, key);
if (!number_value) // if can't get a number for the dictionary
return -1; // fail
if (!CFNumberGetValue(number_value, kCFNumberLongType, &value)) // or if cant convert it
return -1; // fail
return value;
}
/** ctor, get a list of all attached displays */
DarwinWindowingSystemInterface::DarwinWindowingSystemInterface() :
_displayCount(0),
_displayIds(NULL)
{
ProcessSerialNumber sn = { 0, kCurrentProcess };
TransformProcessType(&sn,kProcessTransformToForegroundApplication);
SetFrontProcess(&sn);
if( CGGetActiveDisplayList( 0, NULL, &_displayCount ) != CGDisplayNoErr )
osg::notify(osg::WARN) << "DarwinWindowingSystemInterface: could not get # of screens" << std::endl;
_displayIds = new CGDirectDisplayID[_displayCount];
if( CGGetActiveDisplayList( _displayCount, _displayIds, &_displayCount ) != CGDisplayNoErr )
osg::notify(osg::WARN) << "DarwinWindowingSystemInterface: CGGetActiveDisplayList failed" << std::endl;
}
/** dtor */
DarwinWindowingSystemInterface::~DarwinWindowingSystemInterface()
{
if (osg::Referenced::getDeleteHandler())
{
osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
osg::Referenced::getDeleteHandler()->flushAll();
}
if (_displayIds) delete[] _displayIds;
_displayIds = NULL;
}
/** @return a CGDirectDisplayID for a ScreenIdentifier */
CGDirectDisplayID DarwinWindowingSystemInterface::getDisplayID(const osg::GraphicsContext::ScreenIdentifier& si) {
if (si.screenNum < static_cast<int>(_displayCount))
return _displayIds[si.screenNum];
else {
osg::notify(osg::WARN) << "GraphicsWindowCarbon :: invalid screen # " << si.screenNum << ", returning main-screen instead" << std::endl;
return _displayIds[0];
}
}
/** @return count of attached screens */
unsigned int DarwinWindowingSystemInterface::getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si)
{
return _displayCount;
}
void DarwinWindowingSystemInterface::getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution)
{
CGDirectDisplayID id = getDisplayID(si);
resolution.width = CGDisplayPixelsWide(id);
resolution.height = CGDisplayPixelsHigh(id);
resolution.colorDepth = CGDisplayBitsPerPixel(id);
resolution.refreshRate = getDictDouble (CGDisplayCurrentMode(id), kCGDisplayRefreshRate); // Not tested
if (resolution.refreshRate<0) resolution.refreshRate = 0;
}
void DarwinWindowingSystemInterface::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList) {
// Warning! This method has not been tested.
resolutionList.clear();
CGDirectDisplayID displayid = getDisplayID(screenIdentifier);
CFArrayRef availableModes = CGDisplayAvailableModes(displayid);
unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes);
for (unsigned int i=0; i<numberOfAvailableModes; ++i) {
// look at each mode in the available list
CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, i);
osg::GraphicsContext::ScreenSettings tmpSR;
long width = getDictLong(mode, kCGDisplayWidth);
tmpSR.width = width<=0 ? 0 : width;
long height = getDictLong(mode, kCGDisplayHeight);
tmpSR.height = height<=0 ? 0 : height;
long rate = getDictLong(mode, kCGDisplayRefreshRate);
tmpSR.refreshRate = rate<=0 ? 0 : rate;
long depth = getDictLong(mode, kCGDisplayBitsPerPixel);
tmpSR.colorDepth = depth<=0 ? 0 : depth;
resolutionList.push_back(tmpSR);
}
}
/** return the top left coord of a specific screen in global screen space */
void DarwinWindowingSystemInterface::getScreenTopLeft(const osg::GraphicsContext::ScreenIdentifier& si, int& x, int& y) {
CGRect bounds = CGDisplayBounds( getDisplayID(si) );
x = static_cast<int>(bounds.origin.x);
y = static_cast<int>(bounds.origin.y);
// osg::notify(osg::DEBUG_INFO) << "topleft of screen " << si.screenNum <<" " << bounds.origin.x << "/" << bounds.origin.y << std::endl;
}
bool DarwinWindowingSystemInterface::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 */
bool DarwinWindowingSystemInterface::setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height)
{
CGDirectDisplayID displayid = getDisplayID(screenIdentifier);
// add next line and on following line replace hard coded depth and refresh rate
CGRefreshRate refresh = getDictDouble (CGDisplayCurrentMode(displayid), kCGDisplayRefreshRate);
CFDictionaryRef display_mode_values =
CGDisplayBestModeForParametersAndRefreshRate(
displayid,
CGDisplayBitsPerPixel(displayid),
width, height,
refresh,
NULL);
CGDisplaySwitchToMode(displayid, display_mode_values);
return true;
}
/** implementation of setScreenRefreshRate */
bool DarwinWindowingSystemInterface::setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate) {
boolean_t success(false);
unsigned width, height;
getScreenResolution(screenIdentifier, width, height);
CGDirectDisplayID displayid = getDisplayID(screenIdentifier);
// add next line and on following line replace hard coded depth and refresh rate
CFDictionaryRef display_mode_values =
CGDisplayBestModeForParametersAndRefreshRate(
displayid,
CGDisplayBitsPerPixel(displayid),
width, height,
refreshRate,
&success);
if (success)
CGDisplaySwitchToMode(displayid, display_mode_values);
return (success != 0);
}
unsigned int DarwinWindowingSystemInterface::getScreenContaining(int x, int y, int w, int h)
{
CGRect rect = CGRectMake(x,y,w,h);
for(unsigned int i = 0; i < _displayCount; ++i) {
CGRect bounds = CGDisplayBounds( getDisplayID(i) );
if (CGRectIntersectsRect(bounds, rect)) {
return i;
}
}
return 0;
}
}

File diff suppressed because it is too large Load Diff

144
src/osgViewer/PixelBufferCocoa.mm Executable file
View File

@@ -0,0 +1,144 @@
/*
* PixelBufferCocoa.cpp
* OpenSceneGraph
*
* Created by Stephan Huber on 27.06.08.
* Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved.
*
*/
#include <iostream>
#include <osgViewer/api/Cocoa/PixelBufferCocoa>
#include <osgViewer/api/Cocoa/GraphicsWindowCocoa>
#include <Cocoa/Cocoa.h>
namespace osgViewer {
void PixelBufferCocoa::init()
{
//std::cout << "PixelBufferCocoa :: init not implemented yet " << std::endl;
_valid = _initialized = true;
}
bool PixelBufferCocoa::realizeImplementation()
{
std::cout << "PixelBufferCocoa :: realizeImplementation not implemented yet " << std::endl;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSOpenGLPixelFormatAttribute attr[32];
int i = 0;
attr[i++] = NSOpenGLPFADepthSize;
attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->depth);
if (_traits->doubleBuffer) {
attr[i++] = NSOpenGLPFADoubleBuffer;
}
if (_traits->alpha) {
attr[i++] = NSOpenGLPFAAlphaSize;
attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->alpha);
}
if (_traits->stencil) {
attr[i++] = NSOpenGLPFAStencilSize;
attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->stencil);
}
if (_traits->sampleBuffers) {
attr[i++] = NSOpenGLPFASampleBuffers;
attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->sampleBuffers);
attr[i++] = NSOpenGLPFASamples;
attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->samples);
}
attr[i++] = NSOpenGLPFAPixelBuffer; // for pbuffer usage
attr[i++] = NSOpenGLPFAAccelerated;
attr[i] = static_cast<NSOpenGLPixelFormatAttribute>(0);
// create the context
NSOpenGLContext* sharedContext = NULL;
GraphicsHandleCocoa* graphicsHandleCocoa = dynamic_cast<GraphicsHandleCocoa*>(_traits->sharedContext);
if (graphicsHandleCocoa)
{
sharedContext = graphicsHandleCocoa->getNSOpenGLContext();
}
NSOpenGLPixelFormat* pixelformat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr ];
_context = [[NSOpenGLContext alloc] initWithFormat: pixelformat shareContext: sharedContext];
NSOpenGLPixelBuffer* pbuffer = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget: _traits->target textureInternalFormat: _traits->format textureMaxMipMapLevel: _traits->level pixelsWide: _traits->width pixelsHigh: _traits->height];
[_context setPixelBuffer: pbuffer cubeMapFace: _traits->face mipMapLevel:_traits->level currentVirtualScreen: nil];
[pool release];
_realized = (_context != nil);
return _realized;
}
void PixelBufferCocoa::closeImplementation()
{
_realized = false;
}
/** Make this graphics context current.*/
bool PixelBufferCocoa::makeCurrentImplementation()
{
// osg::notify(osg::INFO) << "PixelBufferCocoa::makeCurrentImplementation" << std::endl;
[_context makeCurrentContext];
return true;
}
/** Make this graphics context current with specified read context implementation. */
bool PixelBufferCocoa::makeContextCurrentImplementation(osg::GraphicsContext* readContext)
{
return makeCurrentImplementation();
}
/** Release the graphics context.*/
bool PixelBufferCocoa::releaseContextImplementation()
{
// osg::notify(osg::INFO) << "PixelBufferCocoa::releaseContextImplementation" << std::endl;
[NSOpenGLContext clearCurrentContext];
return true;
}
/** Bind the graphics context to associated texture implementation.*/
void PixelBufferCocoa::bindPBufferToTextureImplementation( GLenum buffer )
{
std::cout << "PixelBufferCocoa :: bindPBufferToTextureImplementation not implemented yet " << std::endl;
}
/** Swap the front and back buffers.*/
void PixelBufferCocoa::swapBuffersImplementation()
{
osg::notify(osg::INFO) << "PixelBufferCocoa::swapBuffersImplementation" << std::endl;
[_context flushBuffer];
}
PixelBufferCocoa::~PixelBufferCocoa()
{
[_context release];
}
}