From Sukender and Robert Osfield, introduced GraphicsContext::ScreenSettings & WindowingSystemInterface::enumerateScreenSettings.

This commit is contained in:
Robert Osfield
2008-12-16 15:08:04 +00:00
parent aad0a2a2ba
commit 4511281f04
5 changed files with 297 additions and 100 deletions

View File

@@ -86,7 +86,22 @@ ELSE(WIN32)
ELSE(${OSG_WINDOWING_SYSTEM} STREQUAL "Carbon")
# X11 for everybody else
OPTION(OSGVIEWER_USE_XRANDR "Set to ON to enable Xrandr support for GraphicsWindowX11." OFF)
INCLUDE(FindPkgConfig)
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)
SET(OSGVIEWER_USE_XRANDR OFF)
ENDIF (XRANDR_FOUND)
ELSE(PKG_CONFIG_FOUND)
SET(OSGVIEWER_USE_XRANDR OFF)
ENDIF(PKG_CONFIG_FOUND)
SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS}
${HEADER_PATH}/api/X11/GraphicsWindowX11
@@ -99,8 +114,6 @@ ELSE(WIN32)
)
IF(OSGVIEWER_USE_XRANDR)
INCLUDE(FindPkgConfig)
PKG_CHECK_MODULES(XRANDR REQUIRED xrandr)
ADD_DEFINITIONS(-DOSGVIEWER_USE_XRANDR)
SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS} ${XRANDR_INCLUDE_DIRS})
LINK_LIBRARIES(Xrandr)

View File

@@ -389,11 +389,14 @@ struct OSXCarbonWindowingSystemInterface : public osg::GraphicsContext::Windowin
}
/** returns the resolution of a specific display */
virtual void getScreenResolution(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& width, unsigned int& height)
virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution)
{
CGDirectDisplayID id = getDisplayID(si);
width = CGDisplayPixelsWide(id);
height = CGDisplayPixelsHigh(id);
resolution.width = CGDisplayPixelsWide(id);
resolution.height = CGDisplayPixelsHigh(id);
resolution.colorDepth = CGDisplayBitsPerPixel(id);
resolution.refreshRate = getDictDouble (CGDisplayCurrentMode(displayID), kCGDisplayRefreshRate); // Not tested
if (resolution.refreshRate<0) resolution.refreshRate = 0;
}
/** return the top left coord of a specific screen in global screen space */
@@ -405,66 +408,75 @@ struct OSXCarbonWindowingSystemInterface : public osg::GraphicsContext::Windowin
// osg::notify(osg::DEBUG_INFO) << "topleft of screen " << si.screenNum <<" " << bounds.origin.x << "/" << bounds.origin.y << std::endl;
}
/** helper method to get a value out of a CFDictionary */
/** Helper method to get a double value out of a CFDictionary */
static double getDictDouble (CFDictionaryRef refDict, CFStringRef key)
{
double 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, &double_value)) // or if cant convert it
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, &double_value)) // or if cant convert it
return -1; // fail
return double_value; // otherwise return the long value
return value; // otherwise return the long value
}
/** implementation of setScreenResolution */
virtual bool setScreenResolution(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height)
/** 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;
}
/** implementation of setScreenSettings */
virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, const osg::GraphicsContext::ScreenSettings & resolution)
{
CGDirectDisplayID displayID = getDisplayID(screenIdentifier);
// add next line and on following line replace hard coded depth and refresh rate
CGRefreshRate refresh = getDictDouble (CGDisplayCurrentMode(displayID), kCGDisplayRefreshRate);
CGRefreshRate refresh = resolution.refreshRate>0 ? resolution.refreshRate : getDictDouble (CGDisplayCurrentMode(displayID), kCGDisplayRefreshRate);
sizt_t depth = resolution.colorDepth>0 ? resolution.colorDepth : CGDisplayBitsPerPixel(displayID);
CFDictionaryRef display_mode_values =
CGDisplayBestModeForParametersAndRefreshRate(
displayID,
CGDisplayBitsPerPixel(displayID),
width, height,
depth,
resolution.width, resolution.height,
refresh,
NULL);
CGDisplaySwitchToMode(displayID, display_mode_values);
return true;
}
/** implementation of setScreenRefreshRate */
virtual bool setScreenRefreshRate(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);
virtual void 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);
}
}
virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
{
if (traits->pbuffer)

View File

@@ -237,17 +237,17 @@ class Win32WindowingSystem : public osg::GraphicsContext::WindowingSystemInterfa
// Return the resolution of specified screen
// (0,0) is returned if screen is unknown
virtual void getScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& width, unsigned int& height );
virtual void getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution );
// Return the bits per pixel of specified screen
// (0) is returned if screen is unknown
virtual void getScreenColorDepth( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& dmBitsPerPel );
// Set the resolution for given screen
virtual bool setScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height );
virtual bool setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution );
// Set the refresh rate for given screen
virtual bool setScreenRefreshRate( const osg::GraphicsContext::ScreenIdentifier& si, double refreshRate );
// Enumerates available resolutions
virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolution);
// Return the screen position and width/height.
// all zeros returned if screen is unknown
@@ -800,21 +800,40 @@ bool Win32WindowingSystem::getScreenInformation( const osg::GraphicsContext::Scr
return true;
}
void Win32WindowingSystem::getScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& width, unsigned int& height )
void Win32WindowingSystem::getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution )
{
DISPLAY_DEVICE displayDevice;
DEVMODE deviceMode;
if (getScreenInformation(si, displayDevice, deviceMode))
{
width = deviceMode.dmPelsWidth;
height = deviceMode.dmPelsHeight;
if (!getScreenInformation(si, displayDevice, deviceMode))
deviceMode.dmFields = 0; // Set the fields to 0 so that it says 'nothing'.
// Get resolution
if ((deviceMode.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != 0) {
resolution.width = deviceMode.dmPelsWidth;
resolution.height = deviceMode.dmPelsHeight;
} else {
resolution.width = 0;
resolution.height = 0;
}
// Get refersh rate
if ((deviceMode.dmFields & DM_DISPLAYFREQUENCY) != 0) {
resolution.refreshRate = deviceMode.dmDisplayFrequency;
if (resolution.refreshRate == 0 || resolution.refreshRate == 1) {
// Windows specific: 0 and 1 represent the hhardware's default refresh rate.
// If someone knows how to get this refresh rate (in Hz)...
osg::notify(osg::NOTICE) << "Win32WindowingSystem::getScreenSettings() is not fully implemented (cannot retreive the hardware's default refresh rate)."<<std::endl;
resolution.refreshRate = 0;
}
} else
resolution.refreshRate = 0;
// Get bits per pixel for color buffer
if ((deviceMode.dmFields & DM_BITSPERPEL) != 0)
resolution.colorDepth = deviceMode.dmBitsPerPel;
else
{
width = 0;
height = 0;
}
resolution.colorDepth = 0;
}
void Win32WindowingSystem::getScreenColorDepth( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& dmBitsPerPel )
@@ -859,36 +878,65 @@ bool Win32WindowingSystem::changeScreenSettings( const osg::GraphicsContext::Scr
return false;
}
bool Win32WindowingSystem::setScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height )
bool Win32WindowingSystem::setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution )
{
DISPLAY_DEVICE displayDevice;
DEVMODE deviceMode;
if (!getScreenInformation(si, displayDevice, deviceMode)) return false;
deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
deviceMode.dmPelsWidth = width;
deviceMode.dmPelsHeight = height;
deviceMode.dmFields = 0;
// Set resolution
if (resolution.width>0 && resolution.height>0) {
deviceMode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
deviceMode.dmPelsWidth = static_cast<DWORD>(resolution.width);
deviceMode.dmPelsHeight = static_cast<DWORD>(resolution.height);
}
// Set refersh rate
if (resolution.refreshRate>0) {
deviceMode.dmFields |= DM_DISPLAYFREQUENCY;
deviceMode.dmDisplayFrequency = static_cast<DWORD>(resolution.refreshRate);
}
// Set bits per pixel for color buffer
if (resolution.colorDepth>0) {
deviceMode.dmFields |= DM_BITSPERPEL;
deviceMode.dmBitsPerPel = static_cast<DWORD>(resolution.colorDepth);
}
return changeScreenSettings(si, displayDevice, deviceMode);
}
bool Win32WindowingSystem::setScreenRefreshRate( const osg::GraphicsContext::ScreenIdentifier& si, double refreshRate )
{
DISPLAY_DEVICE displayDevice;
DEVMODE deviceMode;
void Win32WindowingSystem::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList) {
resolutionList.clear();
unsigned int width, height;
getScreenResolution(si, width, height);
if (si.displayNum>0)
{
osg::notify(osg::WARN) << "Win32WindowingSystem::enumerateScreenSettings() - The screen identifier on the Win32 platform must always use display number 0. Value received was " << si.displayNum << std::endl;
return;
}
if (!getScreenInformation(si, displayDevice, deviceMode)) return false;
DisplayDevices displayDevices;
enumerateDisplayDevices(displayDevices);
deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
deviceMode.dmPelsWidth = width;
deviceMode.dmPelsHeight = height;
deviceMode.dmDisplayFrequency = (DWORD)refreshRate;
return changeScreenSettings(si, displayDevice, deviceMode);
if (si.screenNum>=static_cast<int>(displayDevices.size()))
{
osg::notify(osg::WARN) << "Win32WindowingSystem::enumerateScreenSettings() - Cannot get information for screen " << si.screenNum << " because it does not exist." << std::endl;
return;
}
DISPLAY_DEVICE displayDevice = displayDevices[si.screenNum];
// Do the enumeration
DEVMODE deviceMode;
static const unsigned int MAX_RESOLUTIONS = 4046; // Upper limit to avoid infinite (= very long) loop.
for (unsigned int i=0; i<MAX_RESOLUTIONS; ++i)
{
if (!::EnumDisplaySettings(displayDevice.DeviceName, i, &deviceMode))
break;
deviceMode.dmSize = sizeof(deviceMode);
deviceMode.dmDriverExtra = 0;
resolutionList.push_back(osg::GraphicsContext::ScreenSettings(deviceMode.dmPelsWidth, deviceMode.dmPelsHeight, deviceMode.dmDisplayFrequency, deviceMode.dmBitsPerPel));
}
}
void Win32WindowingSystem::getScreenPosition( const osg::GraphicsContext::ScreenIdentifier& si, int& originX, int& originY, unsigned int& width, unsigned int& height )

View File

@@ -1487,7 +1487,10 @@ class X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystem
// TODO: Investigate whether or not Robert thinks we should store/restore the original
// resolution in the destructor; I'm not sure the other ones do this, and it may be the
// responsibility of the user.
bool _setScreen(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned height, double rate) {
bool _setScreen(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height, unsigned int colorDepth, double rate) {
if (colorDepth>0)
osg::notify(osg::NOTICE) << "X11WindowingSystemInterface::_setScreen() is not fully implemented (missing depth)."<<std::endl;
Display* display = XOpenDisplay(si.displayName().c_str());
if(display)
@@ -1607,8 +1610,11 @@ public:
osg::notify(osg::INFO) << "X11WindowingSystemInterface, xInitThreads() multi-threaded X support initialized.\n";
}
#endif
}
~X11WindowingSystemInterface()
{
if (osg::Referenced::getDeleteHandler())
@@ -1654,41 +1660,109 @@ public:
}
}
virtual void getScreenResolution(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& width, unsigned int& height)
bool supportsRandr(Display* display) const
{
#ifdef OSGVIEWER_USE_XRANDR
int event_basep;
int error_basep;
bool supports_randr = XRRQueryExtension( display, &event_basep, &error_basep );
if( supports_randr )
{
int major, minor;
XRRQueryVersion( display, &major, &minor );
return ( major > 1 || ( major == 1 && minor >= 2 ) );
}
#endif
return false;
}
virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution )
{
Display* display = XOpenDisplay(si.displayName().c_str());
if(display)
{
width = DisplayWidth(display, si.screenNum);
height = DisplayHeight(display, si.screenNum);
resolution.width = DisplayWidth(display, si.screenNum);
resolution.height = DisplayHeight(display, si.screenNum);
resolution.colorDepth = DefaultDepth(display, si.screenNum);
resolution.refreshRate = 0; // Missing call. Need a X11 expert.
XCloseDisplay(display);
}
else
{
osg::notify(osg::NOTICE) << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
width = 0;
height = 0;
resolution.width = 0;
resolution.height = 0;
resolution.colorDepth = 0;
resolution.refreshRate = 0;
}
}
virtual bool setScreenResolution(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height)
virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution )
{
#ifdef OSGVIEWER_USE_XRANDR
return _setScreen(si, width, height, 0.0f);
_setScreen(si, resolution.width, resolution.height, resolution.colorDepth, resolution.refreshRate);
#else
osg::notify(osg::NOTICE) << "You must build osgViewer with Xrandr 1.2 or higher for setScreenResolution support!" << std::endl;
return false;
osg::notify(osg::NOTICE) << "You must build osgViewer with Xrandr 1.2 or higher for setScreenSettings support!" << std::endl;
#endif
return false;
}
virtual bool setScreenRefreshRate(const osg::GraphicsContext::ScreenIdentifier& si, double rate)
virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList)
{
resolutionList.clear();
Display* display = XOpenDisplay(si.displayName().c_str());
if(display)
{
#ifdef OSGVIEWER_USE_XRANDR
return _setScreen(si, 0, 0, rate);
#else
osg::notify(osg::NOTICE) << "You must build osgViewer with Xrandr 1.2 or higher for setScreenRefreshRate support!" << std::endl;
return false;
#endif
int defaultDepth = DefaultDepth(display, si.screenNum);
if (supportsRandr(display))
{
int nsizes = 0;
XRRScreenSize * screenSizes = XRRSizes(display, si.screenNum, &nsizes);
if (screenSizes && nsizes>0)
{
for(int i=0; i<nsizes; ++i)
{
osg::notify(osg::INFO)<<"Screen size "<<screenSizes[i].width<<" "<<screenSizes[i].height<<" "<<screenSizes[i].mwidth<<" "<<screenSizes[i].mheight<<std::endl;
int nrates;
short * rates = XRRRates (display, si.screenNum, i, &nrates);
if (rates && nrates>0)
{
for(int j=0; j<nrates; ++j)
{
osg::notify(osg::INFO)<<" rates "<<rates[j]<<std::endl;
resolutionList.push_back(osg::GraphicsContext::ScreenSettings(
screenSizes[i].width,
screenSizes[i].height,
double(rates[j]),
defaultDepth));
}
}
else
{
resolutionList.push_back(osg::GraphicsContext::ScreenSettings(
screenSizes[i].width,
screenSizes[i].height,
0.0,
defaultDepth));
}
}
}
}
#endif
XCloseDisplay(display);
}
if (resolutionList.empty())
{
osg::notify(osg::NOTICE) << "X11WindowingSystemInterface::enumerateScreenSettings() not supported." << std::endl;
}
}
virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)