Date: Wed, 9 Apr 2003 18:21:33 -0230
authorSam Lantinga <slouken@libsdl.org>
Sun, 20 Apr 2003 05:36:52 +0000
changeset 6140b4c3f5ff63d
parent 613 9c6717a1c66f
child 615 7ec821f3cbd0
Date: Wed, 9 Apr 2003 18:21:33 -0230
From: Stephen Anthony <stephena@roadrunner.nf.net>
Subject: [SDL] First patch concerning 4.3 and refresh rates

OK, here's my first draft of the patch for the above subject.

A short explanation:

X 4.3 introduces many more modelines than older versions. This would be
fine, except it introduces many modes with the *same* resolution but
different refresh rates. And SDL won't necessarily pick the one with the
highest refresh rate.

So this patch restores SDL to X 4.2 functionality. That is, there is only
ever one refresh rate *per* resolution, and it is the highest possible.
This functionality can be totally disabled by using the environment
variable 'SDL_VIDEO_X11_USE_ALL_MODES' set equal to 1.
src/video/x11/SDL_x11modes.c
     1.1 --- a/src/video/x11/SDL_x11modes.c	Tue Apr 15 16:33:56 2003 +0000
     1.2 +++ b/src/video/x11/SDL_x11modes.c	Sun Apr 20 05:36:52 2003 +0000
     1.3 @@ -44,6 +44,8 @@
     1.4  #endif 
     1.5  
     1.6  #define MAX(a, b)        (a > b ? a : b)
     1.7 +#define V_INTERLACE      0x010
     1.8 +#define V_DBLSCAN        0x020
     1.9  
    1.10  #ifdef XFREE86_VM
    1.11  Bool SDL_NAME(XF86VidModeGetModeInfo)(Display *dpy, int scr, SDL_NAME(XF86VidModeModeInfo) *info)
    1.12 @@ -91,6 +93,82 @@
    1.13  }
    1.14  #endif
    1.15  
    1.16 +#ifdef XFREE86_VM
    1.17 +static int get_vidmode_filter(SDL_NAME(XF86VidModeModeInfo) **modes, int nmodes, char **bitmap)
    1.18 +{
    1.19 +    int i, result = 0;
    1.20 +    int use_all_modes, use_specific_mode;
    1.21 +    const char *variable;
    1.22 +    char *temp;
    1.23 +
    1.24 +    if (!nmodes)
    1.25 +        return 0;
    1.26 +
    1.27 +    temp = (char *)malloc((nmodes)*sizeof(char));
    1.28 +    if (!temp)
    1.29 +        return 0;
    1.30 +
    1.31 +    for ( i = 0; i < nmodes; ++i )
    1.32 +        temp[i] = 0;
    1.33 +
    1.34 +    variable = getenv("SDL_VIDEO_X11_USE_ALL_MODES");
    1.35 +    use_all_modes = variable ? atoi(variable) : 0;
    1.36 +    variable = getenv("SDL_VIDEO_X11_USE_SPECIFIC_MODE");
    1.37 +    use_specific_mode = variable ? atoi(variable) : 0;
    1.38 +
    1.39 +    qsort(modes, nmodes, sizeof *modes, cmpmodes);
    1.40 +
    1.41 +    if ( use_all_modes ) {
    1.42 +        for ( i = 0; i < nmodes; ++i )
    1.43 +            temp[i] = 1;
    1.44 +        result  = 1;
    1.45 +/*    } else if ( use_specific_mode ) { ... */
    1.46 +    } else {
    1.47 +        int previous_refresh, current_refresh;
    1.48 +        SDL_NAME(XF86VidModeModeInfo) *previous, *current;
    1.49 +
    1.50 +        previous = modes[0];
    1.51 +        previous_refresh = (int)(previous->dotclock * 1000.0 /
    1.52 +          (previous->htotal * previous->vtotal));
    1.53 +        if ( previous->flags & V_INTERLACE ) previous_refresh *= 2;
    1.54 +        else if ( previous->flags & V_DBLSCAN ) previous_refresh /= 2;
    1.55 +
    1.56 +        temp[0] = 1;
    1.57 +        for ( i = 1; i < nmodes; ++i ) {
    1.58 +            current = modes[i];
    1.59 +            current_refresh = (int)(current->dotclock * 1000.0 /
    1.60 +              (current->htotal * current->vtotal));
    1.61 +            if ( current->flags & V_INTERLACE ) current_refresh *= 2;
    1.62 +            else if ( current->flags & V_DBLSCAN ) current_refresh /= 2;
    1.63 +
    1.64 +            /* Compare this mode to the previous one */
    1.65 +            if ( current->hdisplay == previous->hdisplay &&
    1.66 +                 current->vdisplay == previous->vdisplay ) {
    1.67 +#ifdef XFREE86_DEBUG
    1.68 +		printf("Comparing %dx%d at %d Hz and %d Hz\n",
    1.69 +			current->hdisplay, current->vdisplay,
    1.70 +			current_refresh, previous_refresh);
    1.71 +#endif
    1.72 +                if ( current_refresh > previous_refresh ) {
    1.73 +                    temp[i-1] = 0;
    1.74 +                    temp[i]   = 1;
    1.75 +                }
    1.76 +                else
    1.77 +                    temp[i] = 0;
    1.78 +            }
    1.79 +            else
    1.80 +                temp[i] = 1;
    1.81 +
    1.82 +            previous = current;
    1.83 +            previous_refresh = current_refresh;
    1.84 +        }
    1.85 +        result = 1;
    1.86 +    }
    1.87 +    *bitmap = temp;
    1.88 +    return result;
    1.89 +}
    1.90 +#endif
    1.91 +
    1.92  static void get_real_resolution(_THIS, int* w, int* h);
    1.93  
    1.94  static void set_best_resolution(_THIS, int width, int height)
    1.95 @@ -101,10 +179,11 @@
    1.96          SDL_NAME(XF86VidModeModeInfo) **modes;
    1.97          int i;
    1.98          int nmodes;
    1.99 +        char *bitmap;
   1.100  
   1.101          if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &i, &mode) &&
   1.102 -             SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes)){
   1.103 -            qsort(modes, nmodes, sizeof *modes, cmpmodes);
   1.104 +             SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes) &&
   1.105 +             get_vidmode_filter(modes, nmodes, &bitmap) ) {
   1.106  #ifdef XFREE86_DEBUG
   1.107              printf("Available modes:\n");
   1.108              for ( i = 0; i < nmodes; ++i ) {
   1.109 @@ -114,12 +193,14 @@
   1.110  #endif
   1.111              for ( i = nmodes-1; i > 0 ; --i ) {
   1.112                  if ( (modes[i]->hdisplay == width) &&
   1.113 -                     (modes[i]->vdisplay == height) )
   1.114 +                     (modes[i]->vdisplay == height) &&
   1.115 +                     (bitmap[i] == 1) )
   1.116                      goto match;
   1.117              }
   1.118              for ( i = nmodes-1; i > 0 ; --i ) {
   1.119                  if ( (modes[i]->hdisplay >= width) &&
   1.120 -                     (modes[i]->vdisplay >= height) )
   1.121 +                     (modes[i]->vdisplay >= height) &&
   1.122 +                     (bitmap[i] == 1) )
   1.123                      break;
   1.124              }
   1.125         match:
   1.126 @@ -128,6 +209,7 @@
   1.127                  SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[i]);
   1.128              }
   1.129              XFree(modes);
   1.130 +            if (bitmap) free(bitmap);
   1.131          }
   1.132      }
   1.133  #endif /* XFREE86_VM */
   1.134 @@ -275,6 +357,7 @@
   1.135      int vm_major, vm_minor;
   1.136      int nmodes;
   1.137      SDL_NAME(XF86VidModeModeInfo) **modes;
   1.138 +    char *bitmap = (char*)0;
   1.139  #endif
   1.140  #ifdef HAVE_XIGXME
   1.141      int xme_major, xme_minor;
   1.142 @@ -336,15 +419,18 @@
   1.143          }
   1.144      }
   1.145      if ( ! buggy_X11 &&
   1.146 -         SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) {
   1.147 +         SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) &&
   1.148 +         get_vidmode_filter(modes, nmodes, &bitmap) ) {
   1.149  
   1.150 -        qsort(modes, nmodes, sizeof *modes, cmpmodes);
   1.151          SDL_modelist = (SDL_Rect **)malloc((nmodes+2)*sizeof(SDL_Rect *));
   1.152          if ( SDL_modelist ) {
   1.153              n = 0;
   1.154              for ( i=0; i<nmodes; ++i ) {
   1.155                  int w, h;
   1.156  
   1.157 +                /* Exclude those vidmodes that have been filtered out */
   1.158 +                if (!bitmap[i]) continue;
   1.159 +
   1.160                  /* Check to see if we should add the screen size (Xinerama) */
   1.161                  w = modes[i]->hdisplay;
   1.162                  h = modes[i]->vdisplay;
   1.163 @@ -377,6 +463,7 @@
   1.164              SDL_modelist[n] = NULL;
   1.165          }
   1.166          XFree(modes);
   1.167 +        if (bitmap) free(bitmap);
   1.168  
   1.169          use_vidmode = vm_major * 100 + vm_minor;
   1.170          save_mode(this);