Fixes #1522, improved Xinerama / Twinview support
authorGabriel Jacobo <gabomdq@gmail.com>
Tue, 19 Jun 2012 14:19:05 -0300
changeset 63315732e1a80bde
parent 6330 0fa55ca2efdd
child 6332 019660f4cc2b
Fixes #1522, improved Xinerama / Twinview support
src/video/x11/SDL_x11modes.c
src/video/x11/SDL_x11modes.h
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11window.c
     1.1 --- a/src/video/x11/SDL_x11modes.c	Tue Jun 19 13:57:42 2012 -0300
     1.2 +++ b/src/video/x11/SDL_x11modes.c	Tue Jun 19 14:19:05 2012 -0300
     1.3 @@ -131,32 +131,76 @@
     1.4  
     1.5      return SDL_PIXELFORMAT_UNKNOWN;
     1.6  }
     1.7 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
     1.8 +static SDL_bool CheckXinerama(Display * display, int *major, int *minor);
     1.9 +#endif
    1.10  
    1.11  int
    1.12  X11_InitModes(_THIS)
    1.13  {
    1.14      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    1.15 -    int screen;
    1.16 +    int screen, screencount;
    1.17  
    1.18 -    for (screen = 0; screen < ScreenCount(data->display); ++screen) {
    1.19 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
    1.20 +    int xinerama_major, xinerama_minor;
    1.21 +    XineramaScreenInfo * xinerama = NULL;
    1.22 +    /* Query Xinerama extention
    1.23 +     * NOTE: This works with Nvidia Twinview correctly, but you need version 302.17 (released on June 2012)
    1.24 +     *       or newer of the Nvidia binary drivers
    1.25 +     */
    1.26 +    if (CheckXinerama(data->display, &xinerama_major, &xinerama_minor)) {
    1.27 +        xinerama = XineramaQueryScreens(data->display, &screencount);
    1.28 +        if (!xinerama) screencount = ScreenCount(data->display);
    1.29 +    }
    1.30 +    else {
    1.31 +        screencount = ScreenCount(data->display);
    1.32 +    }
    1.33 +#else
    1.34 +    screencount = ScreenCount(data->display);
    1.35 +#endif
    1.36 +
    1.37 +    for (screen = 0; screen < screencount; ++screen) {
    1.38          XVisualInfo vinfo;
    1.39          SDL_VideoDisplay display;
    1.40          SDL_DisplayData *displaydata;
    1.41          SDL_DisplayMode mode;
    1.42          XPixmapFormatValues *pixmapFormats;
    1.43          int i, n;
    1.44 -
    1.45 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
    1.46 +        if (xinerama) {
    1.47 +            if (get_visualinfo(data->display, 0, &vinfo) < 0) {
    1.48 +                continue;
    1.49 +            }
    1.50 +        }
    1.51 +        else {
    1.52 +            if (get_visualinfo(data->display, screen, &vinfo) < 0) {
    1.53 +                continue;
    1.54 +            }
    1.55 +        }
    1.56 +#else
    1.57          if (get_visualinfo(data->display, screen, &vinfo) < 0) {
    1.58              continue;
    1.59          }
    1.60 +#endif
    1.61  
    1.62          mode.format = X11_GetPixelFormatFromVisualInfo(data->display, &vinfo);
    1.63          if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
    1.64              /* We don't support palettized modes now */
    1.65              continue;
    1.66          }
    1.67 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
    1.68 +        if (xinerama) {
    1.69 +            mode.w = xinerama[screen].width;
    1.70 +            mode.h = xinerama[screen].height;
    1.71 +        }
    1.72 +        else {
    1.73 +            mode.w = DisplayWidth(data->display, screen);
    1.74 +            mode.h = DisplayHeight(data->display, screen);
    1.75 +        }
    1.76 +#else
    1.77          mode.w = DisplayWidth(data->display, screen);
    1.78          mode.h = DisplayHeight(data->display, screen);
    1.79 +#endif
    1.80          mode.refresh_rate = 0;
    1.81          mode.driverdata = NULL;
    1.82  
    1.83 @@ -164,7 +208,20 @@
    1.84          if (!displaydata) {
    1.85              continue;
    1.86          }
    1.87 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
    1.88 +        /* Most of SDL's calls to X11 are unwaware of Xinerama, and to X11 standard calls, when Xinerama is active,
    1.89 +         * there's only one screen available. So we force the screen number to zero and
    1.90 +         * let Xinerama specific code handle specific functionality using displaydata->xinerama_info
    1.91 +         */
    1.92 +        if (xinerama) {
    1.93 +            displaydata->screen = 0;
    1.94 +            displaydata->use_xinerama = xinerama_major * 100 + xinerama_minor;
    1.95 +            displaydata->xinerama_info = xinerama[screen];
    1.96 +        }
    1.97 +        else displaydata->screen = screen;
    1.98 +#else
    1.99          displaydata->screen = screen;
   1.100 +#endif
   1.101          displaydata->visual = vinfo.visual;
   1.102          displaydata->depth = vinfo.depth;
   1.103  
   1.104 @@ -186,6 +243,11 @@
   1.105          display.driverdata = displaydata;
   1.106          SDL_AddVideoDisplay(&display);
   1.107      }
   1.108 +
   1.109 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.110 +    if (xinerama) XFree(xinerama);
   1.111 +#endif
   1.112 +
   1.113      if (_this->num_displays == 0) {
   1.114          SDL_SetError("No available displays");
   1.115          return -1;
   1.116 @@ -351,11 +413,6 @@
   1.117  {
   1.118      Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   1.119      SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
   1.120 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.121 -    int xinerama_major, xinerama_minor;
   1.122 -    int screens;
   1.123 -    XineramaScreenInfo * xinerama;
   1.124 -#endif
   1.125  #if SDL_VIDEO_DRIVER_X11_XRANDR
   1.126      int xrandr_major, xrandr_minor;
   1.127      int nsizes, nrates;
   1.128 @@ -380,53 +437,27 @@
   1.129      mode.format = sdl_display->current_mode.format;
   1.130      mode.driverdata = NULL;
   1.131  
   1.132 -    data->use_xinerama = 0;
   1.133      data->use_xrandr = 0;
   1.134      data->use_vidmode = 0;
   1.135      screen_w = DisplayWidth(display, data->screen);
   1.136      screen_h = DisplayHeight(display, data->screen);
   1.137  
   1.138  #if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.139 -    /* Query Xinerama extention */
   1.140 -    if (CheckXinerama(display, &xinerama_major, &xinerama_minor)) {
   1.141 -#ifdef X11MODES_DEBUG
   1.142 -        printf("X11 detected Xinerama:\n");
   1.143 -#endif
   1.144 -        xinerama = XineramaQueryScreens(display, &screens);
   1.145 -        if (xinerama) {
   1.146 -            int i;
   1.147 -            for (i = 0; i < screens; i++) {
   1.148 -#ifdef X11MODES_DEBUG
   1.149 -                printf("xinerama %d: %dx%d+%d+%d\n",
   1.150 -                       xinerama[i].screen_number,
   1.151 -                       xinerama[i].width, xinerama[i].height,
   1.152 -                       xinerama[i].x_org, xinerama[i].y_org);
   1.153 -#endif
   1.154 -                if (xinerama[i].screen_number == data->screen) {
   1.155 -                    data->use_xinerama =
   1.156 -                        xinerama_major * 100 + xinerama_minor;
   1.157 -                    data->xinerama_info = xinerama[i];
   1.158 -                }
   1.159 -            }
   1.160 -            XFree(xinerama);
   1.161 -        }
   1.162 -
   1.163 -        if (data->use_xinerama) {
   1.164 -            /* Add the full xinerama mode */
   1.165 -            if (screen_w > data->xinerama_info.width ||
   1.166 -                screen_h > data->xinerama_info.height) {
   1.167 -                mode.w = screen_w;
   1.168 -                mode.h = screen_h;
   1.169 -                mode.refresh_rate = 0;
   1.170 -                SDL_AddDisplayMode(sdl_display, &mode);
   1.171 -            }
   1.172 -
   1.173 -            /* Add the head xinerama mode */
   1.174 -            mode.w = data->xinerama_info.width;
   1.175 -            mode.h = data->xinerama_info.height;
   1.176 +    if (data->use_xinerama) {
   1.177 +        /* Add the full (both screens combined) xinerama mode only on the display that starts at 0,0 */
   1.178 +        if (!data->xinerama_info.x_org && !data->xinerama_info.y_org &&
   1.179 +           (screen_w > data->xinerama_info.width || screen_h > data->xinerama_info.height)) {
   1.180 +            mode.w = screen_w;
   1.181 +            mode.h = screen_h;
   1.182              mode.refresh_rate = 0;
   1.183              SDL_AddDisplayMode(sdl_display, &mode);
   1.184          }
   1.185 +
   1.186 +        /* Add the head xinerama mode */
   1.187 +        mode.w = data->xinerama_info.width;
   1.188 +        mode.h = data->xinerama_info.height;
   1.189 +        mode.refresh_rate = 0;
   1.190 +        SDL_AddDisplayMode(sdl_display, &mode);
   1.191      }
   1.192  #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
   1.193  
   1.194 @@ -531,6 +562,15 @@
   1.195  get_real_resolution(Display * display, SDL_DisplayData * data, int *w, int *h,
   1.196                      int *rate)
   1.197  {
   1.198 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.199 +    if (data->use_xinerama) {
   1.200 +        *w = data->xinerama_info.width;
   1.201 +        *h = data->xinerama_info.height;
   1.202 +        *rate = 0;
   1.203 +        return;
   1.204 +    }
   1.205 +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
   1.206 +
   1.207  #if SDL_VIDEO_DRIVER_X11_XRANDR
   1.208      if (data->use_xrandr) {
   1.209          int nsizes;
   1.210 @@ -570,15 +610,6 @@
   1.211      }
   1.212  #endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
   1.213  
   1.214 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.215 -    if (data->use_xinerama) {
   1.216 -        *w = data->xinerama_info.width;
   1.217 -        *h = data->xinerama_info.height;
   1.218 -        *rate = 0;
   1.219 -        return;
   1.220 -    }
   1.221 -#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
   1.222 -
   1.223      *w = DisplayWidth(display, data->screen);
   1.224      *h = DisplayHeight(display, data->screen);
   1.225      *rate = 0;
   1.226 @@ -592,9 +623,17 @@
   1.227  
   1.228      /* check current mode so we can avoid uneccessary mode changes */
   1.229      get_real_resolution(display, data, &real_w, &real_h, &real_rate);
   1.230 +
   1.231 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.232 +    if (w == real_w && h == real_h && (data->use_xinerama || !rate || rate == real_rate)) {
   1.233 +        return;
   1.234 +    }
   1.235 +#else
   1.236      if (w == real_w && h == real_h && (!rate || rate == real_rate)) {
   1.237          return;
   1.238      }
   1.239 +#endif
   1.240 +
   1.241  #if SDL_VIDEO_DRIVER_X11_XRANDR
   1.242      if (data->use_xrandr) {
   1.243  #ifdef X11MODES_DEBUG
   1.244 @@ -719,6 +758,30 @@
   1.245  {
   1.246  }
   1.247  
   1.248 +int
   1.249 +X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect)
   1.250 +{
   1.251 +    SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
   1.252 +
   1.253 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.254 +    if (data && data->use_xinerama) {
   1.255 +        rect->x = data->xinerama_info.x_org;
   1.256 +        rect->y = data->xinerama_info.y_org;
   1.257 +        rect->w = data->xinerama_info.width;
   1.258 +        rect->h = data->xinerama_info.height;
   1.259 +        return 0;
   1.260 +    }
   1.261 +#endif
   1.262 +    if (_this->windows) {
   1.263 +        rect->x = 0;
   1.264 +        rect->y = 0;
   1.265 +        rect->w = _this->windows->w;
   1.266 +        rect->h = _this->windows->h;
   1.267 +        return 0;
   1.268 +    }
   1.269 +    return -1;
   1.270 +}
   1.271 +
   1.272  #endif /* SDL_VIDEO_DRIVER_X11 */
   1.273  
   1.274  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/video/x11/SDL_x11modes.h	Tue Jun 19 13:57:42 2012 -0300
     2.2 +++ b/src/video/x11/SDL_x11modes.h	Tue Jun 19 14:19:05 2012 -0300
     2.3 @@ -63,6 +63,7 @@
     2.4                                         XVisualInfo * vinfo);
     2.5  extern Uint32 X11_GetPixelFormatFromVisualInfo(Display * display,
     2.6                                                 XVisualInfo * vinfo);
     2.7 +extern int X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect);
     2.8  
     2.9  #endif /* _SDL_x11modes_h */
    2.10  
     3.1 --- a/src/video/x11/SDL_x11video.c	Tue Jun 19 13:57:42 2012 -0300
     3.2 +++ b/src/video/x11/SDL_x11video.c	Tue Jun 19 14:19:05 2012 -0300
     3.3 @@ -187,6 +187,7 @@
     3.4      device->VideoInit = X11_VideoInit;
     3.5      device->VideoQuit = X11_VideoQuit;
     3.6      device->GetDisplayModes = X11_GetDisplayModes;
     3.7 +    device->GetDisplayBounds = X11_GetDisplayBounds;
     3.8      device->SetDisplayMode = X11_SetDisplayMode;
     3.9      device->SuspendScreenSaver = X11_SuspendScreenSaver;
    3.10      device->PumpEvents = X11_PumpEvents;
     4.1 --- a/src/video/x11/SDL_x11window.c	Tue Jun 19 13:57:42 2012 -0300
     4.2 +++ b/src/video/x11/SDL_x11window.c	Tue Jun 19 14:19:05 2012 -0300
     4.3 @@ -269,14 +269,6 @@
     4.4      Atom wmstate_atoms[3];
     4.5      Uint32 fevent = 0;
     4.6  
     4.7 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
     4.8 -/* FIXME
     4.9 -    if ( use_xinerama ) {
    4.10 -        x = xinerama_info.x_org;
    4.11 -        y = xinerama_info.y_org;
    4.12 -    }
    4.13 -*/
    4.14 -#endif
    4.15  #if SDL_VIDEO_OPENGL_GLX
    4.16      if (window->flags & SDL_WINDOW_OPENGL) {
    4.17          XVisualInfo *vinfo;