diff --git a/src/osgViewer/CMakeLists.txt b/src/osgViewer/CMakeLists.txt index cbe3cff34..1228cbcc8 100644 --- a/src/osgViewer/CMakeLists.txt +++ b/src/osgViewer/CMakeLists.txt @@ -62,17 +62,27 @@ ELSE(WIN32) ) ELSE(APPLE) - # X11 for everybody else + OPTION(OSGVIEWER_USE_XRANDR "Set to ON to enable Xrandr support for GraphicsWindowX11." OFF) + SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS} ${HEADER_PATH}/api/X11/GraphicsWindowX11 ${HEADER_PATH}/api/X11/PixelBufferX11 + ${XRANDR_INCLUDE_DIRS} ) SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} GraphicsWindowX11.cpp PixelBufferX11.cpp ) + 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) + ENDIF(OSGVIEWER_USE_XRANDR) + ENDIF(APPLE) ENDIF(WIN32) diff --git a/src/osgViewer/GraphicsWindowX11.cpp b/src/osgViewer/GraphicsWindowX11.cpp index 3f3e0e0d0..b499044ee 100644 --- a/src/osgViewer/GraphicsWindowX11.cpp +++ b/src/osgViewer/GraphicsWindowX11.cpp @@ -30,6 +30,10 @@ #include /* For CARD16 */ +#ifdef OSGVIEWER_USE_XRANDR +#include +#endif + #include using namespace osgViewer; @@ -1293,9 +1297,90 @@ int X11ErrorHandling(Display* display, XErrorEvent* event) } -struct X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface +class X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface { +#ifdef OSGVIEWER_USE_XRANDR + // 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) { + Display* display = XOpenDisplay(si.displayName().c_str()); + + if(display) + { + XRRScreenConfiguration* sc = XRRGetScreenInfo(display, RootWindow(display, si.screenNum)); + if(!sc) + { + osg::notify(osg::NOTICE) << "Unable to create XRRScreenConfiguration on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<(width) && ss[i].height == static_cast(height)) + { + short* rates = XRRConfigRates(sc, i, &numRates); + bool rateFound = false; + + // Search for our rate in the list of acceptable rates given to us by Xrandr. + // If it's not found, rateFound will still be false and the call will never + // be made to XRRSetScreenConfigAndRate since the rate will be invalid. + for(int r = 0; r < numRates; r++) + { + if(rates[r] == static_cast(rate)) + { + rateFound = true; + break; + } + } + + if(rate > 0.0f && !rateFound) + { + osg::notify(osg::NOTICE) << "Unable to find valid refresh rate " << rate << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<(rate), CurrentTime) != RRSetConfigSuccess) + { + osg::notify(osg::NOTICE) << "Unable to set resolution to " << width << "x" << height << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<pbuffer)