(234) Fixed part of bug #926883 (Video mode matching code, memory leaks,
[freeglut] / src / freeglut_gamemode.c
index 11c24e6..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"
 
@@ -184,9 +180,10 @@ static void fghRestoreState( void )
                  */
                 XFlush( fgDisplay.Display );
 
-                return;
+                break;
             }
         }
+        XFree( displayModes );
     }
 
 #   else
@@ -221,6 +218,7 @@ static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refr
  */
 static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
 {
+    GLboolean success = GL_FALSE;
 #if TARGET_HOST_UNIX_X11
 
     /*
@@ -236,7 +234,7 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
     if( haveToTest || fgDisplay.DisplayModeValid )
     {
         XF86VidModeModeInfo** displayModes;
-        int i, displayModesCount;
+        int i, ignoreRefreshRate, displayModesCount;
 
         XF86VidModeGetAllModeLines(
             fgDisplay.Display,
@@ -245,29 +243,35 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
             &displayModes
         );
 
-        /* Check every of the modes looking for one that matches our demands */
-        for( i = 0; i < displayModesCount; i++ )
+        /*
+         * Check every of the modes looking for one that matches our demands,
+         * ignoring the refresh rate if no exact match could be found.
+         */
+        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 gone wrong */
-    return GL_FALSE;
+        if( !haveToTest && success ) {
+          XF86VidModeSwitchToMode( fgDisplay.Display, fgDisplay.Screen, displayModes[ i ] );
+        }
+
+        XFree( displayModes );
+    }
 
 #   else
     /*
@@ -279,7 +283,6 @@ static 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;
 
@@ -345,9 +348,9 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
         }
     }
 
-    return success;
-
 #endif
+
+    return success;
 }