(234) Fixed part of bug #926883 (Video mode matching code, memory leaks,
[freeglut] / src / freeglut_gamemode.c
index 09e38ab..7d5a1ef 100644 (file)
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <GL/freeglut.h>
 #include "freeglut_internal.h"
 
@@ -48,7 +44,7 @@
  * Remembers the current visual settings, so that
  * we can change them and restore later...
  */
-void fghRememberState( void )
+static void fghRememberState( void )
 {
 #if TARGET_HOST_UNIX_X11
 
@@ -86,9 +82,7 @@ void fghRememberState( void )
         );
     }
 
-    /*
-     * Query the current display settings:
-     */
+    /* Query the current display settings: */
     fgDisplay.DisplayModeValid =
       XF86VidModeGetModeLine(
         fgDisplay.Display,
@@ -98,7 +92,7 @@ void fghRememberState( void )
     );
 
     if( !fgDisplay.DisplayModeValid )
-            fgWarning( "Runtime use of XF86VidModeGetModeLine failed.\n" );
+            fgWarning( "Runtime use of XF86VidModeGetModeLine failed." );
 
 #   else
     /*
@@ -111,9 +105,7 @@ void fghRememberState( void )
 
 /*    DEVMODE devMode; */
 
-    /*
-     * Grab the current desktop settings...
-     */
+    /* Grab the current desktop settings... */
 
 /* hack to get around my stupid cross-gcc headers */
 #define FREEGLUT_ENUM_CURRENT_SETTINGS -1
@@ -121,9 +113,7 @@ void fghRememberState( void )
     EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS,
                          &fgDisplay.DisplayMode );
 
-    /*
-     * Make sure we will be restoring all settings needed
-     */
+    /* Make sure we will be restoring all settings needed */
     fgDisplay.DisplayMode.dmFields |=
         DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
 
@@ -133,14 +123,12 @@ void fghRememberState( void )
 /*
  * Restores the previously remembered visual settings
  */
-void fghRestoreState( void )
+static void fghRestoreState( void )
 {
 #if TARGET_HOST_UNIX_X11
 
 #   ifdef X_XF86VidModeGetAllModeLines
-    /*
-     * Restore the remembered pointer position:
-     */
+    /* Restore the remembered pointer position: */
     XWarpPointer(
         fgDisplay.Display, None, fgDisplay.RootWindow, 0, 0, 0, 0,
         fgDisplay.DisplayPointerX, fgDisplay.DisplayPointerY
@@ -192,9 +180,10 @@ void fghRestoreState( void )
                  */
                 XFlush( fgDisplay.Display );
 
-                return;
+                break;
             }
         }
+        XFree( displayModes );
     }
 
 #   else
@@ -206,9 +195,7 @@ void fghRestoreState( void )
 
 #elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
 
-    /*
-     * Restore the previously rememebered desktop display settings
-     */
+    /* Restore the previously rememebered desktop display settings */
     ChangeDisplaySettings( &fgDisplay.DisplayMode, 0 );
 
 #endif
@@ -217,11 +204,9 @@ void fghRestoreState( void )
 /*
  * Checks the display mode settings against user's preferences
  */
-GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )
+static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )
 {
-    /*
-     * The desired values should be stored in fgState structure...
-     */
+    /* The desired values should be stored in fgState structure... */
     return ( width == fgState.GameModeSize.X ) &&
            ( height == fgState.GameModeSize.Y ) &&
            ( depth == fgState.GameModeDepth ) &&
@@ -231,8 +216,9 @@ GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )
 /*
  * Changes the current display mode to match user's settings
  */
-GLboolean fghChangeDisplayMode( GLboolean haveToTest )
+static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
 {
+    GLboolean success = GL_FALSE;
 #if TARGET_HOST_UNIX_X11
 
     /*
@@ -248,7 +234,7 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
     if( haveToTest || fgDisplay.DisplayModeValid )
     {
         XF86VidModeModeInfo** displayModes;
-        int i, displayModesCount;
+        int i, ignoreRefreshRate, displayModesCount;
 
         XF86VidModeGetAllModeLines(
             fgDisplay.Display,
@@ -258,34 +244,34 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
         );
 
         /*
-         * Check every of the modes looking for one that matches our demands
+         * Check every of the modes looking for one that matches our demands,
+         * ignoring the refresh rate if no exact match could be found.
          */
-        for( i = 0; i < displayModesCount; i++ )
+        for( ignoreRefreshRate = 0;
+             !success && ( ignoreRefreshRate <= 1 );
+             ignoreRefreshRate++)
         {
-            if( fghCheckDisplayMode( displayModes[ i ]->hdisplay,
-                                     displayModes[ i ]->vdisplay,
-                                     fgState.GameModeDepth,
-                                     fgState.GameModeRefresh ) )
+            for( i = 0;
+                 !success && ( i < displayModesCount );
+                 i++ )
             {
-                if( haveToTest )
-                    return GL_TRUE;
-                /*
-                 * OKi, this is the display mode we have been looking for...
-                 */
-                XF86VidModeSwitchToMode(
-                    fgDisplay.Display,
-                    fgDisplay.Screen,
-                    displayModes[ i ]
-                );
-                return GL_TRUE;
+                /* Compute the displays refresh rate, dotclock comes in kHz. */
+                int refresh = ( displayModes[ i ]->dotclock * 1000 ) /
+                              ( displayModes[ i ]->htotal * displayModes[ i ]->vtotal );
+
+                success = fghCheckDisplayMode( displayModes[ i ]->hdisplay,
+                                               displayModes[ i ]->vdisplay,
+                                               fgState.GameModeDepth,
+                                               ( ignoreRefreshRate ? fgState.GameModeRefresh : refresh ) );
             }
         }
-    }
 
-    /*
-     * Something must have went wrong
-     */
-    return GL_FALSE;
+        if( !haveToTest && success ) {
+          XF86VidModeSwitchToMode( fgDisplay.Display, fgDisplay.Screen, displayModes[ i ] );
+        }
+
+        XFree( displayModes );
+    }
 
 #   else
     /*
@@ -297,7 +283,6 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
 #elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
 
     unsigned int    displayModes = 0, mode = 0xffffffff;
-    GLboolean success = GL_FALSE;
     /* HDC      desktopDC; */
     DEVMODE  devMode;
 
@@ -307,9 +292,7 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
      */
     while( EnumDisplaySettings( NULL, displayModes, &devMode ) )
     {
-        /*
-         * Does the enumerated display mode match the user's preferences?
-         */
+        /* Does the enumerated display mode match the user's preferences? */
         if( fghCheckDisplayMode( devMode.dmPelsWidth,  devMode.dmPelsHeight,
                                  devMode.dmBitsPerPel,
                                  devMode.dmDisplayFrequency ) )
@@ -325,9 +308,7 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
         /* then try without Display Frequency */
         displayModes = 0;
 
-        /*
-         * Enumerate the available display modes
-         */
+        /* Enumerate the available display modes */
         while( EnumDisplaySettings( NULL, displayModes, &devMode ) )
         {
             /* then try without Display Frequency */
@@ -343,24 +324,18 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
         }
     }
 
-    /*
-     * Did we find a matching display mode?
-     */
+    /* Did we find a matching display mode? */
     if( mode != 0xffffffff )
     {
         int retVal = DISP_CHANGE_SUCCESSFUL;
 
-        /*
-         * Mark the values we want to modify in the display change call
-         */
+        /* Mark the values we want to modify in the display change call */
         devMode.dmFields |=
             DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
 
         retVal = ChangeDisplaySettings( &devMode, haveToTest ? CDS_TEST : 0 );
 
-        /*
-         * I don't know if it's really needed, but looks nice:
-         */
+        /* I don't know if it's really needed, but looks nice: */
         success = (retVal == DISP_CHANGE_SUCCESSFUL) ||
             (retVal == DISP_CHANGE_NOTUPDATED);
 
@@ -373,9 +348,9 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
         }
     }
 
-    return success;
-
 #endif
+
+    return success;
 }
 
 
@@ -388,6 +363,8 @@ void FGAPIENTRY glutGameModeString( const char* string )
 {
     int width = 640, height = 480, depth = 16, refresh = 72;
 
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGameModeString" );
+
     /*
      * This one seems a bit easier than glutInitDisplayString. The bad thing
      * about it that I was unable to find the game mode string definition, so
@@ -407,9 +384,7 @@ void FGAPIENTRY glutGameModeString( const char* string )
                                     string
                                 );
 
-    /*
-     * Hopefully it worked, and if not, we still have the default values
-     */
+    /* Hopefully it worked, and if not, we still have the default values */
     fgState.GameModeSize.X  = width;
     fgState.GameModeSize.Y  = height;
     fgState.GameModeDepth   = depth;
@@ -421,6 +396,8 @@ void FGAPIENTRY glutGameModeString( const char* string )
  */
 int FGAPIENTRY glutEnterGameMode( void )
 {
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEnterGameMode" );
+
     if( fgStructure.GameMode )
         fgAddToWindowDestroyList( fgStructure.GameMode );
     else
@@ -495,9 +472,7 @@ int FGAPIENTRY glutEnterGameMode( void )
         int x, y;
         Window child;
 
-        /*
-         * Change to viewport to the window topleft edge:
-         */
+        /* Change to viewport to the window topleft edge: */
         XF86VidModeSetViewPort( fgDisplay.Display, fgDisplay.Screen, 0, 0 );
 
         /*
@@ -522,9 +497,7 @@ int FGAPIENTRY glutEnterGameMode( void )
 
 #endif
 
-    /*
-     * Grab the keyboard, too
-     */
+    /* Grab the keyboard, too */
     XGrabKeyboard(
         fgDisplay.Display,
         fgStructure.GameMode->Window.Handle,
@@ -543,13 +516,14 @@ int FGAPIENTRY glutEnterGameMode( void )
  */
 void FGAPIENTRY glutLeaveGameMode( void )
 {
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLeaveGameMode" );
+
     freeglut_return_if_fail( fgStructure.GameMode );
 
     fgStructure.GameMode->State.IsGameMode = GL_FALSE;
 
     fgAddToWindowDestroyList( fgStructure.GameMode );
-
-    fgStructure.GameMode = NULL ;
+    fgStructure.GameMode = NULL;
 
 #if TARGET_HOST_UNIX_X11
 
@@ -566,6 +540,8 @@ void FGAPIENTRY glutLeaveGameMode( void )
  */
 int FGAPIENTRY glutGameModeGet( GLenum eWhat )
 {
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGameModeGet" );
+
     switch( eWhat )
     {
     case GLUT_GAME_MODE_ACTIVE:
@@ -593,6 +569,7 @@ int FGAPIENTRY glutGameModeGet( GLenum eWhat )
         return !!fgStructure.GameMode;
     }
 
+    fgWarning( "Unknown gamemode get: %d", eWhat );
     return -1;
 }