/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+static int xrandr_resize(int xsz, int ysz, int just_checking)
+{
+ int res = -1;
+
+#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ int event_base, error_base;
+ Status st;
+ XRRScreenConfiguration *xrr_config;
+ XRRScreenSize *ssizes;
+ Rotation rot;
+ int i, ssizes_count, curr;
+ Time timestamp, cfg_timestamp;
+
+ /* must check at runtime for the availability of the extension */
+ if(!XRRQueryExtension(fgDisplay.Display, &event_base, &error_base)) {
+ return -1;
+ }
+
+ if(!(xrr_config = XRRGetScreenInfo(fgDisplay.Display, fgDisplay.RootWindow))) {
+ fgWarning("XRRGetScreenInfo failed");
+ return -1;
+ }
+ ssizes = XRRConfigSizes(xrr_config, &ssizes_count);
+ curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
+ timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp);
+
+ if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) {
+ /* no need to switch, we're already in the requested mode */
+ res = 0;
+ goto done;
+ }
+
+ for(i=0; i<ssizes_count; i++) {
+ if(ssizes[i].width == xsz && ssizes[i].height == ysz) {
+ break; /* found it */
+ }
+ }
+ if(i == ssizes_count)
+ goto done;
+
+ if(just_checking) {
+ res = 0;
+ goto done;
+ }
+
+ if((st = XRRSetScreenConfig(fgDisplay.Display, xrr_config, fgDisplay.RootWindow,
+ i, rot, timestamp)) != 0) {
+ fgWarning("XRRSetScreenConfig failed");
+ goto done;
+ }
+ res = 0;
+
+done:
+ XRRFreeScreenConfigInfo(xrr_config);
+#endif
+ return res;
+}
+
+
/*
* Remembers the current visual settings, so that
* we can change them and restore later...
*/
static void fghRememberState( void )
{
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
+ int event_base, error_base;
+
+# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ if(XRRQueryExtension(fgDisplay.Display, &event_base, &error_base)) {
+ XRRScreenConfiguration *xrr_config;
+ XRRScreenSize *ssizes;
+ Rotation rot;
+ int ssize_count, curr;
+
+ if((xrr_config = XRRGetScreenInfo(fgDisplay.Display, fgDisplay.RootWindow))) {
+ ssizes = XRRConfigSizes(xrr_config, &ssize_count);
+ curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
+
+ fgDisplay.prev_xsz = ssizes[curr].width;
+ fgDisplay.prev_ysz = ssizes[curr].height;
+ fgDisplay.prev_size_valid = 1;
+ XRRFreeScreenConfigInfo(xrr_config);
+ return;
+ }
+ }
+# endif
/*
* This highly depends on the XFree86 extensions,
* not approved as X Consortium standards
*/
-# ifdef X_XF86VidModeGetModeLine
-
+# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+ if(!XF86VidModeQueryExtension(fgDisplay.Display, &event_base, &error_base)) {
+ return;
+ }
/*
* Remember the current ViewPort location of the screen to be able to
if( !fgDisplay.DisplayModeValid )
fgWarning( "XF86VidModeGetModeLine failed" );
-
-# else
- /*
- * XXX warning fghRememberState: missing XFree86 video mode extensions,
- * XXX game mode will not change screen resolution when activated
- */
# endif
-#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+#elif TARGET_HOST_MS_WINDOWS
/* DEVMODE devMode; */
/* hack to get around my stupid cross-gcc headers */
#define FREEGLUT_ENUM_CURRENT_SETTINGS -1
- EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS,
+ EnumDisplaySettings( fgDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS,
&fgDisplay.DisplayMode );
/* Make sure we will be restoring all settings needed */
*/
static void fghRestoreState( void )
{
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
+
+# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ if(fgDisplay.prev_size_valid) {
+ if(xrandr_resize(fgDisplay.prev_xsz, fgDisplay.prev_ysz, 0) != -1) {
+ fgDisplay.prev_size_valid = 0;
+ return;
+ }
+ }
+# endif
-# ifdef X_XF86VidModeGetAllModeLines
+
+# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
/* Restore the remembered pointer position: */
XWarpPointer(
fgDisplay.Display, None, fgDisplay.RootWindow, 0, 0, 0, 0,
fgDisplay.Screen,
fgDisplay.DisplayViewPortX,
fgDisplay.DisplayViewPortY ) )
- fgWarning( "XF86VidModeSetViewPort failed" );
+ fgWarning( "HAVE_X11_EXTENSIONS_XF86VMODE_H failed" );
/*
XFree( displayModes );
}
-# else
- /*
- * XXX warning fghRestoreState: missing XFree86 video mode extensions,
- * XXX game mode will not change screen resolution when activated
- */
# endif
-#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+#elif TARGET_HOST_MS_WINDOWS
- /* Restore the previously rememebered desktop display settings */
- ChangeDisplaySettings( &fgDisplay.DisplayMode, 0 );
+ /* Restore the previously remembered desktop display settings */
+ ChangeDisplaySettingsEx( fgDisplay.DisplayName,&fgDisplay.DisplayMode, 0,0,0 );
#endif
}
-#if TARGET_HOST_UNIX_X11
-#ifdef X_XF86VidModeGetAllModeLines
+#if TARGET_HOST_POSIX_X11
+#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
/*
* Checks a single display mode settings against user's preferences.
displayModes[ i ]->vdisplay,
fgState.GameModeDepth,
( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) {
+ if (!exactMatch)
+ {
+ /* Update the chosen refresh rate, otherwise a
+ * glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE) would not
+ * return the right values
+ */
+ fgState.GameModeRefresh = refresh;
+ }
+
return i;
}
}
static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
{
GLboolean success = GL_FALSE;
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
+
+ /* first try to use XRandR, then fallback to XF86VidMode */
+# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ if(xrandr_resize(fgState.GameModeSize.X, fgState.GameModeSize.Y, haveToTest) != -1) {
+ return GL_TRUE;
+ }
+# endif
+
/*
* This highly depends on the XFree86 extensions,
* not approved as X Consortium standards
*/
-# ifdef X_XF86VidModeGetAllModeLines
+# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
/*
* This is also used by applcations which check modes by calling
# endif
-#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+#elif TARGET_HOST_MS_WINDOWS
DEVMODE devMode;
char *fggmstr = NULL;
success = GL_FALSE;
- EnumDisplaySettings( NULL, -1, &devMode );
- devMode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+ EnumDisplaySettings( fgDisplay.DisplayName, -1, &devMode );
+ devMode.dmFields = 0;
- devMode.dmPelsWidth = fgState.GameModeSize.X;
- devMode.dmPelsHeight = fgState.GameModeSize.Y;
- devMode.dmBitsPerPel = fgState.GameModeDepth;
- devMode.dmDisplayFrequency = fgState.GameModeRefresh;
- devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+ if (fgState.GameModeSize.X!=-1)
+ {
+ devMode.dmPelsWidth = fgState.GameModeSize.X;
+ devMode.dmFields |= DM_PELSWIDTH;
+ }
+ if (fgState.GameModeSize.Y!=-1)
+ {
+ devMode.dmPelsHeight = fgState.GameModeSize.Y;
+ devMode.dmFields |= DM_PELSHEIGHT;
+ }
+ if (fgState.GameModeDepth!=-1)
+ {
+ devMode.dmBitsPerPel = fgState.GameModeDepth;
+ devMode.dmFields |= DM_BITSPERPEL;
+ }
+ if (fgState.GameModeRefresh!=-1)
+ {
+ devMode.dmDisplayFrequency = fgState.GameModeRefresh;
+ devMode.dmFields |= DM_DISPLAYFREQUENCY;
+ }
- switch ( ChangeDisplaySettingsEx(NULL, &devMode, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) )
+ switch ( ChangeDisplaySettingsEx(fgDisplay.DisplayName, &devMode, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) )
{
case DISP_CHANGE_SUCCESSFUL:
success = GL_TRUE;
/* update vars in case if windows switched to proper mode */
- EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS, &devMode );
+ EnumDisplaySettings( fgDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS, &devMode );
fgState.GameModeSize.X = devMode.dmPelsWidth;
fgState.GameModeSize.Y = devMode.dmPelsHeight;
fgState.GameModeDepth = devMode.dmBitsPerPel;
*/
void FGAPIENTRY glutGameModeString( const char* string )
{
- int width = 640, height = 480, depth = 16, refresh = 72;
+ int width = -1, height = -1, depth = -1, refresh = -1;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGameModeString" );
);
/* Hopefully it worked, and if not, we still have the default values */
- fgState.GameModeSize.X = width;
- fgState.GameModeSize.Y = height;
- fgState.GameModeDepth = depth;
- fgState.GameModeRefresh = refresh;
+ if ( width > 0 ) fgState.GameModeSize.X = width;
+ if ( height > 0 ) fgState.GameModeSize.Y = height;
+ if ( depth > 0 ) fgState.GameModeDepth = depth;
+ if ( refresh > 0 ) fgState.GameModeRefresh = refresh;
}
+
+
/*
* Enters the game mode
*/
}
fgStructure.GameModeWindow = fgCreateWindow(
- NULL, "FREEGLUT", 0, 0,
- fgState.GameModeSize.X, fgState.GameModeSize.Y, GL_TRUE, GL_FALSE
+ NULL, "FREEGLUT", GL_TRUE, 0, 0,
+ GL_TRUE, fgState.GameModeSize.X, fgState.GameModeSize.Y,
+ GL_TRUE, GL_FALSE
);
fgStructure.GameModeWindow->State.Width = fgState.GameModeSize.X;
fgStructure.GameModeWindow->State.Height = fgState.GameModeSize.Y;
fgStructure.GameModeWindow->State.NeedToResize = GL_TRUE;
- fgStructure.GameModeWindow->State.IsGameMode = GL_TRUE;
-
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
/*
* Sync needed to avoid a real race, the Xserver must have really created
fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
);
-# ifdef X_XF86VidModeSetViewPort
+# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
if( fgDisplay.DisplayModeValid )
{
freeglut_return_if_fail( fgStructure.GameModeWindow );
- fgStructure.GameModeWindow->State.IsGameMode = GL_FALSE;
-
fgAddToWindowDestroyList( fgStructure.GameModeWindow );
fgStructure.GameModeWindow = NULL;
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
XUngrabPointer( fgDisplay.Display, CurrentTime );
XUngrabKeyboard( fgDisplay.Display, CurrentTime );