From 0f2959ce6904157afff6c316f1d380de1ae44386 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 21 Dec 2007 13:32:13 +0000 Subject: [PATCH] From Jeremy Moles, "Here is a implementation of setScreeResolution and setScreenRefreshRate for systems support Xrandr. The include CMakeFile makes this optional, and turns it OFF by default, in which case any person trying to use these functions under Linux will be instructed to build osgViewer w/ Xrandr support. " --- src/osgViewer/CMakeLists.txt | 12 +++- src/osgViewer/GraphicsWindowX11.cpp | 107 +++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 2 deletions(-) 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)