Fixed bug #80
authorSam Lantinga <slouken@libsdl.org>
Fri, 05 May 2006 05:50:26 +0000
changeset 1768814f9f2c7a33
parent 1767 ae9f6be81810
child 1769 290b5baf2fca
Fixed bug #80

Date: 21 Apr 2003 17:20:20 +0100
From: Alan Swanson <swanson@uklinux.net>
Subject: [SDL] New XFree 4.3 Video Mode Patch


If you look at the unsorted list of modes returned by X, here's mine;

1280 x 1024 @ 85.0 >
1024 x 768 @ 100.3 > USER
800 x 600 @ 125.5 > SET
640 x 480 @ 124.9 >
1280 x 1024 @ 75.0 ]
1280 x 1024 @ 60.0 ]
1280 x 960 @ 85.0 ] X11
1280 x 960 @ 60.0 ] AUTO
1152 x 864 @ 75.0 ]=20
1152 x 768 @ 54.8 ]
960 x 720 @ 120.0 ]
...
640 x 400 @ 85.1 ] 256k
576 x 432 @ 150.0 ] 249k PIXEL
640 x 350 @ 85.1 ] 224k COUNT
576 x 384 @ 109.6 ] 221k
...

The user set modes come first followed by X set modes which are ordered
by decreasing number of pixels and refresh.

The reason why every other library or program not using SDL working is
due to SDL scanning the modes in reverse getting X11 provided modes
modes with the lowest refresh.
src/video/x11/SDL_x11modes.c
     1.1 --- a/src/video/x11/SDL_x11modes.c	Fri May 05 05:09:10 2006 +0000
     1.2 +++ b/src/video/x11/SDL_x11modes.c	Fri May 05 05:50:26 2006 +0000
     1.3 @@ -33,6 +33,8 @@
     1.4  #include "SDL_x11modes_c.h"
     1.5  #include "SDL_x11image_c.h"
     1.6  
     1.7 +/*#define X11MODES_DEBUG*/
     1.8 +
     1.9  #define MAX(a, b)        (a > b ? a : b)
    1.10  
    1.11  #if SDL_VIDEO_DRIVER_X11_XRANDR
    1.12 @@ -103,45 +105,37 @@
    1.13          SDL_NAME(XF86VidModeModeLine) mode;
    1.14          SDL_NAME(XF86VidModeModeInfo) **modes;
    1.15          int i;
    1.16 -        int best_width = 0, best_height = 0;
    1.17          int nmodes;
    1.18 +        int best = -1;
    1.19  
    1.20          if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &i, &mode) &&
    1.21 -             SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes)){
    1.22 -#ifdef X11MODES_DEBUG
    1.23 -            printf("Available modes (unsorted):\n");
    1.24 -            for ( i = 0; i < nmodes; ++i ) {
    1.25 -                printf("Mode %d: %d x %d @ %d\n", i,
    1.26 -                        modes[i]->hdisplay, modes[i]->vdisplay,
    1.27 -                        1000 * modes[i]->dotclock / (modes[i]->htotal *
    1.28 -                        modes[i]->vtotal) );
    1.29 -            }
    1.30 -#endif
    1.31 +             SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes) ) {
    1.32              for ( i = 0; i < nmodes ; i++ ) {
    1.33                  if ( (modes[i]->hdisplay == width) &&
    1.34 -                     (modes[i]->vdisplay == height) )
    1.35 -                    goto match;
    1.36 -            }
    1.37 -            qsort(modes, nmodes, sizeof *modes, cmpmodes);
    1.38 -            for ( i = nmodes-1; i > 0 ; i-- ) {
    1.39 -		if ( ! best_width ) {
    1.40 -                    if ( (modes[i]->hdisplay >= width) &&
    1.41 -                         (modes[i]->vdisplay >= height) ) {
    1.42 -                        best_width = modes[i]->hdisplay;
    1.43 -                        best_height = modes[i]->vdisplay;
    1.44 -                    }
    1.45 -                } else {
    1.46 -                    if ( (modes[i]->hdisplay != best_width) ||
    1.47 -                         (modes[i]->vdisplay != best_height) ) {
    1.48 -                        i++;
    1.49 -                        break;
    1.50 +                     (modes[i]->vdisplay == height) ) {
    1.51 +                    best = i;
    1.52 +                    break;
    1.53 +                }
    1.54 +                if ( modes[i]->hdisplay >= width &&
    1.55 +                     modes[i]->vdisplay >= height ) {
    1.56 +                    if ( best < 0 ||
    1.57 +                         (modes[i]->hdisplay < modes[best]->hdisplay &&
    1.58 +                          modes[i]->vdisplay <= modes[best]->vdisplay) ||
    1.59 +                         (modes[i]->vdisplay < modes[best]->vdisplay &&
    1.60 +                          modes[i]->hdisplay <= modes[best]->hdisplay) ) {
    1.61 +                        best = i;
    1.62                      }
    1.63                  }
    1.64              }
    1.65 -       match:
    1.66 -            if ( (modes[i]->hdisplay != mode.hdisplay) ||
    1.67 -                 (modes[i]->vdisplay != mode.vdisplay) ) {
    1.68 -                SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[i]);
    1.69 +            if ( best >= 0 &&
    1.70 +                 ((modes[best]->hdisplay != mode.hdisplay) ||
    1.71 +                  (modes[best]->vdisplay != mode.vdisplay)) ) {
    1.72 +#ifdef X11MODES_DEBUG
    1.73 +                printf("Best Mode %d: %d x %d @ %d\n", best,
    1.74 +                        modes[best]->hdisplay, modes[best]->vdisplay,
    1.75 +                        (modes[best]->htotal && modes[best]->vtotal) ? (1000 * modes[best]->dotclock / (modes[best]->htotal * modes[best]->vtotal)) : 0 );
    1.76 +#endif
    1.77 +                SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[best]);
    1.78              }
    1.79              XFree(modes);
    1.80          }
    1.81 @@ -150,13 +144,13 @@
    1.82  
    1.83                                  /* XiG */
    1.84  #if SDL_VIDEO_DRIVER_X11_XME
    1.85 -#ifdef X11MODES_DEBUG
    1.86 -    fprintf(stderr, "XME: set_best_resolution(): w = %d, h = %d\n",
    1.87 -            width, height);
    1.88 -#endif
    1.89 -    if ( SDL_modelist ) {
    1.90 +    if ( use_xme && SDL_modelist ) {
    1.91          int i;
    1.92  
    1.93 +#ifdef X11MODES_DEBUG
    1.94 +        fprintf(stderr, "XME: set_best_resolution(): w = %d, h = %d\n",
    1.95 +                width, height);
    1.96 +#endif
    1.97          for ( i=0; SDL_modelist[i]; ++i ) {
    1.98              if ( (SDL_modelist[i]->w >= width) &&
    1.99                   (SDL_modelist[i]->h >= height) ) {
   1.100 @@ -174,8 +168,8 @@
   1.101  #ifdef X11MODES_DEBUG
   1.102                  fprintf(stderr, "XME: set_best_resolution: "
   1.103                          "XiGMiscChangeResolution: %d %d\n",
   1.104 -                        SDL_modelist[s]->w, SDL_modelist[s]->h);
   1.105 -# endif
   1.106 +                        SDL_modelist[i]->w, SDL_modelist[i]->h);
   1.107 +#endif
   1.108                  XiGMiscChangeResolution(SDL_Display, 
   1.109                                          SDL_Screen,
   1.110                                          0, /* view */
   1.111 @@ -189,54 +183,51 @@
   1.112  #endif /* SDL_VIDEO_DRIVER_X11_XME */
   1.113  
   1.114  #if SDL_VIDEO_DRIVER_X11_XRANDR
   1.115 -    if ( use_xrandr ) {
   1.116 +    if ( use_xrandr && SDL_modelist ) {
   1.117  #ifdef X11MODES_DEBUG
   1.118          fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n",
   1.119                  width, height);
   1.120  #endif
   1.121 -        if ( SDL_modelist ) {
   1.122 -            int i, nsizes;
   1.123 -            XRRScreenSize *sizes;
   1.124 +        int i, nsizes;
   1.125 +        XRRScreenSize *sizes;
   1.126  
   1.127 -            /* find the smallest resolution that is at least as big as the user requested */
   1.128 -            sizes = XRRConfigSizes(screen_config, &nsizes);
   1.129 -            for ( i = (nsizes-1); i >= 0; i-- ) {
   1.130 -                if ( (SDL_modelist[i]->w >= width) &&
   1.131 -                     (SDL_modelist[i]->h >= height) ) {
   1.132 -                    break;
   1.133 -                }
   1.134 +        /* find the smallest resolution that is at least as big as the user requested */
   1.135 +        sizes = XRRConfigSizes(screen_config, &nsizes);
   1.136 +        for ( i = (nsizes-1); i >= 0; i-- ) {
   1.137 +            if ( (SDL_modelist[i]->w >= width) &&
   1.138 +                 (SDL_modelist[i]->h >= height) ) {
   1.139 +                break;
   1.140              }
   1.141 +        }
   1.142  
   1.143 -            if ( i >= 0 && SDL_modelist[i] ) { /* found one, lets try it */
   1.144 -                int w, h;
   1.145 +        if ( i >= 0 && SDL_modelist[i] ) { /* found one, lets try it */
   1.146 +            int w, h;
   1.147  
   1.148 -                /* check current mode so we can avoid uneccessary mode changes */
   1.149 -                get_real_resolution(this, &w, &h);
   1.150 +            /* check current mode so we can avoid uneccessary mode changes */
   1.151 +            get_real_resolution(this, &w, &h);
   1.152  
   1.153 -                if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) {
   1.154 -                    int size_id;
   1.155 +            if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) {
   1.156 +                int size_id;
   1.157  
   1.158  #ifdef X11MODES_DEBUG
   1.159 -                    fprintf(stderr, "XRANDR: set_best_resolution: "
   1.160 -                            "XXRSetScreenConfig: %d %d\n",
   1.161 -                            SDL_modelist[i]->w, SDL_modelist[i]->h);
   1.162 +                fprintf(stderr, "XRANDR: set_best_resolution: "
   1.163 +                        "XXRSetScreenConfig: %d %d\n",
   1.164 +                        SDL_modelist[i]->w, SDL_modelist[i]->h);
   1.165  #endif
   1.166  
   1.167 -                    /* find the matching size entry index */
   1.168 -                    for ( size_id = 0; size_id < nsizes; ++size_id ) {
   1.169 -                        if ( (sizes[size_id].width == SDL_modelist[i]->w) &&
   1.170 -                             (sizes[size_id].height == SDL_modelist[i]->h) )
   1.171 -                            break;
   1.172 -                    }
   1.173 +                /* find the matching size entry index */
   1.174 +                for ( size_id = 0; size_id < nsizes; ++size_id ) {
   1.175 +                    if ( (sizes[size_id].width == SDL_modelist[i]->w) &&
   1.176 +                         (sizes[size_id].height == SDL_modelist[i]->h) )
   1.177 +                        break;
   1.178 +                }
   1.179  
   1.180 -                    XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root,
   1.181 -                                       size_id, saved_rotation, CurrentTime);
   1.182 -                }
   1.183 +                XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root,
   1.184 +                                   size_id, saved_rotation, CurrentTime);
   1.185              }
   1.186          }
   1.187      }
   1.188  #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
   1.189 -
   1.190  }
   1.191  
   1.192  static void get_real_resolution(_THIS, int* w, int* h)
   1.193 @@ -643,7 +634,7 @@
   1.194           SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) )
   1.195      {
   1.196  #ifdef X11MODES_DEBUG
   1.197 -        printf("Available modes: (sorted)\n");
   1.198 +        printf("VidMode modes: (unsorted)\n");
   1.199          for ( i = 0; i < nmodes; ++i ) {
   1.200              printf("Mode %d: %d x %d @ %d\n", i,
   1.201                      modes[i]->hdisplay, modes[i]->vdisplay,
   1.202 @@ -838,7 +829,7 @@
   1.203      }
   1.204  
   1.205      if ( use_vidmode ) {
   1.206 -        printf("XFree86 VidMode is enabled\n");
   1.207 +        printf("VidMode is enabled\n");
   1.208      }
   1.209  
   1.210      if ( use_xme ) {