Implementing John Tsiombikas' game mode patch per e-mail dated 3/15/11 8:04 PM
authorJohn F. Fay <johnffay@nettally.com>
Wed, 16 Mar 2011 03:22:49 +0000 (03:22 +0000)
committerJohn F. Fay <johnffay@nettally.com>
Wed, 16 Mar 2011 03:22:49 +0000 (03:22 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@897 7f0cb862-5218-0410-a997-914c9d46530a

configure.ac
src/freeglut_gamemode.c
src/freeglut_init.c
src/freeglut_internal.h
src/freeglut_window.c

index 5c47541..ce6cd9b 100644 (file)
@@ -29,9 +29,8 @@ if test "x$no_x" = xyes; then
   EXPORT_FLAGS="-DFREEGLUT_EXPORTS"
 else
   GL_LIBS="-lGL -lXext -lX11"
-  AC_CHECK_LIB([Xxf86vm], [XF86VidModeSwitchToMode],
-               [LIBXXF86VM=-lXxf86vm], [LIBXXF86VM=],
-               [$X_LIBS -lXext -lX11])
+  AC_CHECK_LIB([Xxf86vm], [XF86VidModeSwitchToMode])
+  AC_CHECK_LIB([Xrandr], [XRRQueryExtension])
   LIBXI=-lXi
   VERSION_INFO="-version-info 12:0:9"
   EXPORT_FLAGS=
@@ -49,6 +48,7 @@ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
 AC_CHECK_HEADERS([usbhid.h errno.h GL/gl.h GL/glu.h GL/glx.h fcntl.h limits.h sys/ioctl.h sys/param.h sys/time.h])
 AC_HEADER_TIME
 AC_CHECK_HEADERS([X11/extensions/xf86vmode.h], [], [], [#include <X11/Xlib.h>])
+AC_CHECK_HEADERS([X11/extensions/Xrandr.h])
 AC_CHECK_HEADERS([X11/extensions/XI.h X11/extensions/XInput.h])
 CPPFLAGS="$save_CPPFLAGS"
 
index 01086b3..137f1ea 100644 (file)
 
 /* -- 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_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
@@ -93,12 +175,6 @@ static void fghRememberState( void )
 
     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_MS_WINDOWS
@@ -127,7 +203,17 @@ static void fghRestoreState( void )
 {
 #if TARGET_HOST_POSIX_X11
 
-#   ifdef X_XF86VidModeGetAllModeLines
+#   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 HAVE_X11_EXTENSIONS_XF86VMODE_H
     /* Restore the remembered pointer position: */
     XWarpPointer(
         fgDisplay.Display, None, fgDisplay.RootWindow, 0, 0, 0, 0,
@@ -179,7 +265,7 @@ static void fghRestoreState( void )
                          fgDisplay.Screen,
                          fgDisplay.DisplayViewPortX,
                          fgDisplay.DisplayViewPortY ) )
-                    fgWarning( "XF86VidModeSetViewPort failed" );
+                    fgWarning( "HAVE_X11_EXTENSIONS_XF86VMODE_H failed" );
 
 
                 /*
@@ -195,11 +281,6 @@ static void fghRestoreState( void )
         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_MS_WINDOWS
@@ -211,7 +292,7 @@ static void fghRestoreState( void )
 }
 
 #if TARGET_HOST_POSIX_X11
-#ifdef X_XF86VidModeGetAllModeLines
+#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
 
 /*
  * Checks a single display mode settings against user's preferences.
@@ -268,11 +349,19 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
     GLboolean success = GL_FALSE;
 #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
@@ -510,7 +599,7 @@ int FGAPIENTRY glutEnterGameMode( void )
         fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
     );
 
-#   ifdef X_XF86VidModeSetViewPort
+#   ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
 
     if( fgDisplay.DisplayModeValid )
     {
index 877b3ab..bbe9ec8 100644 (file)
@@ -389,6 +389,7 @@ static void fghInitialize( const char* displayName )
 #endif
 
     fgState.Initialised = GL_TRUE;
+    atexit(fgDeinitialize);
 
     /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */
     fgInitialiseInputDevices();
@@ -403,8 +404,6 @@ void fgDeinitialize( void )
 
     if( !fgState.Initialised )
     {
-        fgWarning( "fgDeinitialize(): "
-                   "no valid initialization has been performed" );
         return;
     }
 
index 2a5a4db..f7634df 100644 (file)
 #    include <X11/Xatom.h>
 #    include <X11/keysym.h>
 #    include <X11/extensions/XInput.h>
-#    ifdef HAVE_XXF86VM
+#    ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
 #        include <X11/extensions/xf86vmode.h>
 #    endif
+#    ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+#        include <X11/extensions/Xrandr.h>
+#    endif
 /* If GLX is too old, we will fail during runtime when multisampling
    is requested, but at least freeglut compiles. */
 #    ifndef GLX_SAMPLE_BUFFERS
@@ -355,7 +358,12 @@ struct tagSFG_Display
     Atom            State;              /* The state atom                    */
     Atom            StateFullScreen;    /* The full screen atom              */
 
-#ifdef X_XF86VidModeGetModeLine
+#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+    int prev_xsz, prev_ysz;
+    int prev_size_valid;
+#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */
+
+#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
     /*
      * XF86VidMode may be compilable even if it fails at runtime.  Therefore,
      * the validity of the VidMode has to be tracked
@@ -368,7 +376,7 @@ struct tagSFG_Display
     int             DisplayPointerX;    /* saved X location of the pointer   */
     int             DisplayPointerY;    /* saved Y location of the pointer   */
 
-#endif /* X_XF86VidModeGetModeLine */
+#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */
 
 #elif TARGET_HOST_MS_WINDOWS
     HINSTANCE        Instance;          /* The application's instance        */
index 800342d..fc9fc55 100644 (file)
@@ -1316,6 +1316,12 @@ void fgOpenWindow( SFG_Window* window, const char* title,
  */
 void fgCloseWindow( SFG_Window* window )
 {
+    /* if we're in gamemode, call glutLeaveGameMode first to make sure the
+     * gamemode is properly closed before closing the window
+     */
+    if (fgStructure.GameModeWindow != NULL)
+        glutLeaveGameMode();
+
 #if TARGET_HOST_POSIX_X11
 
     if( window->Window.Context )