src/video/x11/SDL_x11modes.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 03 Oct 2012 12:04:30 -0700
changeset 6538 05cf19d1eb53
parent 6537 85cf169db434
child 6548 fc9e6be24ca9
permissions -rw-r--r--
Fixed compile error - had work in progress in there.
slouken@1950
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@1950
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1950
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1950
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1950
    20
*/
slouken@1950
    21
#include "SDL_config.h"
slouken@1950
    22
slouken@5481
    23
#if SDL_VIDEO_DRIVER_X11
slouken@5481
    24
slouken@6472
    25
#include "SDL_hints.h"
slouken@1950
    26
#include "SDL_x11video.h"
slouken@1950
    27
slouken@6538
    28
/*#define X11MODES_DEBUG*/
slouken@1950
    29
slouken@1950
    30
static int
slouken@1950
    31
get_visualinfo(Display * display, int screen, XVisualInfo * vinfo)
slouken@1950
    32
{
slouken@1950
    33
    const char *visual_id = SDL_getenv("SDL_VIDEO_X11_VISUALID");
slouken@1950
    34
    int depth;
slouken@1950
    35
slouken@1950
    36
    /* Look for an exact visual, if requested */
slouken@1950
    37
    if (visual_id) {
slouken@3697
    38
        XVisualInfo *vi, template;
slouken@3697
    39
        int nvis;
slouken@1950
    40
slouken@1950
    41
        SDL_zero(template);
slouken@1950
    42
        template.visualid = SDL_strtol(visual_id, NULL, 0);
slouken@1950
    43
        vi = XGetVisualInfo(display, VisualIDMask, &template, &nvis);
slouken@1950
    44
        if (vi) {
slouken@1950
    45
            *vinfo = *vi;
slouken@1950
    46
            XFree(vi);
slouken@1950
    47
            return 0;
slouken@1950
    48
        }
slouken@1950
    49
    }
slouken@3697
    50
slouken@1950
    51
    depth = DefaultDepth(display, screen);
slouken@5466
    52
    if ((X11_UseDirectColorVisuals() &&
slouken@5466
    53
         XMatchVisualInfo(display, screen, depth, DirectColor, vinfo)) ||
slouken@5466
    54
        XMatchVisualInfo(display, screen, depth, TrueColor, vinfo) ||
slouken@1950
    55
        XMatchVisualInfo(display, screen, depth, PseudoColor, vinfo) ||
slouken@1950
    56
        XMatchVisualInfo(display, screen, depth, StaticColor, vinfo)) {
slouken@1950
    57
        return 0;
slouken@1950
    58
    }
slouken@1950
    59
    return -1;
slouken@1950
    60
}
slouken@1950
    61
slouken@5182
    62
int
slouken@5182
    63
X11_GetVisualInfoFromVisual(Display * display, Visual * visual, XVisualInfo * vinfo)
slouken@5182
    64
{
slouken@5182
    65
    XVisualInfo *vi;
slouken@5182
    66
    int nvis;
slouken@5182
    67
slouken@5182
    68
    vinfo->visualid = XVisualIDFromVisual(visual);
slouken@5182
    69
    vi = XGetVisualInfo(display, VisualIDMask, vinfo, &nvis);
slouken@5182
    70
    if (vi) {
slouken@5182
    71
        *vinfo = *vi;
slouken@5182
    72
        XFree(vi);
slouken@5182
    73
        return 0;
slouken@5182
    74
    }
slouken@5182
    75
    return -1;
slouken@5182
    76
}
slouken@5182
    77
slouken@5182
    78
Uint32
slouken@2874
    79
X11_GetPixelFormatFromVisualInfo(Display * display, XVisualInfo * vinfo)
slouken@2870
    80
{
slouken@2870
    81
    if (vinfo->class == DirectColor || vinfo->class == TrueColor) {
slouken@2870
    82
        int bpp;
slouken@2870
    83
        Uint32 Rmask, Gmask, Bmask, Amask;
slouken@2870
    84
slouken@2870
    85
        Rmask = vinfo->visual->red_mask;
slouken@2870
    86
        Gmask = vinfo->visual->green_mask;
slouken@2870
    87
        Bmask = vinfo->visual->blue_mask;
slouken@2870
    88
        if (vinfo->depth == 32) {
slouken@2870
    89
            Amask = (0xFFFFFFFF & ~(Rmask | Gmask | Bmask));
slouken@2870
    90
        } else {
slouken@2870
    91
            Amask = 0;
slouken@2870
    92
        }
slouken@2870
    93
slouken@2870
    94
        bpp = vinfo->depth;
slouken@2870
    95
        if (bpp == 24) {
slouken@2870
    96
            int i, n;
slouken@2870
    97
            XPixmapFormatValues *p = XListPixmapFormats(display, &n);
slouken@2870
    98
            if (p) {
slouken@2870
    99
                for (i = 0; i < n; ++i) {
slouken@2870
   100
                    if (p[i].depth == 24) {
slouken@2870
   101
                        bpp = p[i].bits_per_pixel;
slouken@2870
   102
                        break;
slouken@2870
   103
                    }
slouken@2870
   104
                }
slouken@2870
   105
                XFree(p);
slouken@2870
   106
            }
slouken@2870
   107
        }
slouken@2870
   108
slouken@2870
   109
        return SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
slouken@2870
   110
    }
slouken@2870
   111
slouken@2870
   112
    if (vinfo->class == PseudoColor || vinfo->class == StaticColor) {
slouken@2870
   113
        switch (vinfo->depth) {
slouken@2870
   114
        case 8:
slouken@2870
   115
            return SDL_PIXELTYPE_INDEX8;
slouken@2870
   116
        case 4:
slouken@2870
   117
            if (BitmapBitOrder(display) == LSBFirst) {
slouken@2870
   118
                return SDL_PIXELFORMAT_INDEX4LSB;
slouken@2870
   119
            } else {
slouken@2870
   120
                return SDL_PIXELFORMAT_INDEX4MSB;
slouken@2870
   121
            }
slouken@2870
   122
            break;
slouken@2870
   123
        case 1:
slouken@2870
   124
            if (BitmapBitOrder(display) == LSBFirst) {
slouken@2870
   125
                return SDL_PIXELFORMAT_INDEX1LSB;
slouken@2870
   126
            } else {
slouken@2870
   127
                return SDL_PIXELFORMAT_INDEX1MSB;
slouken@2870
   128
            }
slouken@2870
   129
            break;
slouken@2870
   130
        }
slouken@2870
   131
    }
slouken@2870
   132
slouken@2870
   133
    return SDL_PIXELFORMAT_UNKNOWN;
slouken@2870
   134
}
gabomdq@6331
   135
#if SDL_VIDEO_DRIVER_X11_XINERAMA
gabomdq@6331
   136
static SDL_bool CheckXinerama(Display * display, int *major, int *minor);
gabomdq@6331
   137
#endif
slouken@2870
   138
slouken@3521
   139
int
slouken@1950
   140
X11_InitModes(_THIS)
slouken@1950
   141
{
slouken@1950
   142
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
gabomdq@6331
   143
    int screen, screencount;
slouken@1950
   144
gabomdq@6331
   145
#if SDL_VIDEO_DRIVER_X11_XINERAMA
gabomdq@6331
   146
    int xinerama_major, xinerama_minor;
gabomdq@6331
   147
    XineramaScreenInfo * xinerama = NULL;
gabomdq@6331
   148
    /* Query Xinerama extention
gabomdq@6331
   149
     * NOTE: This works with Nvidia Twinview correctly, but you need version 302.17 (released on June 2012)
gabomdq@6331
   150
     *       or newer of the Nvidia binary drivers
gabomdq@6331
   151
     */
gabomdq@6331
   152
    if (CheckXinerama(data->display, &xinerama_major, &xinerama_minor)) {
gabomdq@6331
   153
        xinerama = XineramaQueryScreens(data->display, &screencount);
gabomdq@6331
   154
    }
slouken@6475
   155
    if (!xinerama) {
gabomdq@6331
   156
        screencount = ScreenCount(data->display);
gabomdq@6331
   157
    }
gabomdq@6331
   158
#else
gabomdq@6331
   159
    screencount = ScreenCount(data->display);
gabomdq@6331
   160
#endif
gabomdq@6331
   161
gabomdq@6331
   162
    for (screen = 0; screen < screencount; ++screen) {
slouken@1950
   163
        XVisualInfo vinfo;
slouken@1950
   164
        SDL_VideoDisplay display;
slouken@1950
   165
        SDL_DisplayData *displaydata;
slouken@1950
   166
        SDL_DisplayMode mode;
slouken@2916
   167
        XPixmapFormatValues *pixmapFormats;
slouken@2916
   168
        int i, n;
gabomdq@6331
   169
#if SDL_VIDEO_DRIVER_X11_XINERAMA
gabomdq@6331
   170
        if (xinerama) {
gabomdq@6331
   171
            if (get_visualinfo(data->display, 0, &vinfo) < 0) {
gabomdq@6331
   172
                continue;
gabomdq@6331
   173
            }
gabomdq@6331
   174
        }
gabomdq@6331
   175
        else {
gabomdq@6331
   176
            if (get_visualinfo(data->display, screen, &vinfo) < 0) {
gabomdq@6331
   177
                continue;
gabomdq@6331
   178
            }
gabomdq@6331
   179
        }
gabomdq@6331
   180
#else
slouken@1950
   181
        if (get_visualinfo(data->display, screen, &vinfo) < 0) {
slouken@1950
   182
            continue;
slouken@1950
   183
        }
gabomdq@6331
   184
#endif
slouken@1950
   185
slouken@2870
   186
        mode.format = X11_GetPixelFormatFromVisualInfo(data->display, &vinfo);
slouken@5149
   187
        if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
slouken@5149
   188
            /* We don't support palettized modes now */
slouken@5149
   189
            continue;
slouken@5149
   190
        }
gabomdq@6331
   191
#if SDL_VIDEO_DRIVER_X11_XINERAMA
gabomdq@6331
   192
        if (xinerama) {
gabomdq@6331
   193
            mode.w = xinerama[screen].width;
gabomdq@6331
   194
            mode.h = xinerama[screen].height;
gabomdq@6331
   195
        }
gabomdq@6331
   196
        else {
gabomdq@6331
   197
            mode.w = DisplayWidth(data->display, screen);
gabomdq@6331
   198
            mode.h = DisplayHeight(data->display, screen);
gabomdq@6331
   199
        }
gabomdq@6331
   200
#else
slouken@1950
   201
        mode.w = DisplayWidth(data->display, screen);
slouken@1950
   202
        mode.h = DisplayHeight(data->display, screen);
gabomdq@6331
   203
#endif
slouken@1950
   204
        mode.refresh_rate = 0;
slouken@1950
   205
        mode.driverdata = NULL;
slouken@1950
   206
slouken@6468
   207
        displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
slouken@1950
   208
        if (!displaydata) {
slouken@1950
   209
            continue;
slouken@1950
   210
        }
gabomdq@6331
   211
#if SDL_VIDEO_DRIVER_X11_XINERAMA
gabomdq@6331
   212
        /* Most of SDL's calls to X11 are unwaware of Xinerama, and to X11 standard calls, when Xinerama is active,
gabomdq@6331
   213
         * there's only one screen available. So we force the screen number to zero and
gabomdq@6331
   214
         * let Xinerama specific code handle specific functionality using displaydata->xinerama_info
gabomdq@6331
   215
         */
gabomdq@6331
   216
        if (xinerama) {
gabomdq@6331
   217
            displaydata->screen = 0;
gabomdq@6331
   218
            displaydata->use_xinerama = xinerama_major * 100 + xinerama_minor;
gabomdq@6331
   219
            displaydata->xinerama_info = xinerama[screen];
slouken@6506
   220
            displaydata->xinerama_screen = screen;
gabomdq@6331
   221
        }
gabomdq@6331
   222
        else displaydata->screen = screen;
gabomdq@6331
   223
#else
slouken@1950
   224
        displaydata->screen = screen;
gabomdq@6331
   225
#endif
slouken@1950
   226
        displaydata->visual = vinfo.visual;
slouken@1951
   227
        displaydata->depth = vinfo.depth;
slouken@1950
   228
slouken@2920
   229
        displaydata->scanline_pad = SDL_BYTESPERPIXEL(mode.format) * 8;
slouken@2916
   230
        pixmapFormats = XListPixmapFormats(data->display, &n);
slouken@2916
   231
        if (pixmapFormats) {
slouken@2916
   232
            for (i = 0; i < n; ++i) {
slouken@2916
   233
                if (pixmapFormats[i].depth == displaydata->depth) {
slouken@2916
   234
                    displaydata->scanline_pad = pixmapFormats[i].scanline_pad;
slouken@2916
   235
                    break;
slouken@2916
   236
                }
slouken@2916
   237
            }
slouken@2916
   238
            XFree(pixmapFormats);
slouken@2916
   239
        }
slouken@2916
   240
slouken@1950
   241
        SDL_zero(display);
slouken@1950
   242
        display.desktop_mode = mode;
slouken@1950
   243
        display.current_mode = mode;
slouken@1950
   244
        display.driverdata = displaydata;
slouken@1950
   245
        SDL_AddVideoDisplay(&display);
slouken@1950
   246
    }
gabomdq@6331
   247
gabomdq@6331
   248
#if SDL_VIDEO_DRIVER_X11_XINERAMA
gabomdq@6331
   249
    if (xinerama) XFree(xinerama);
gabomdq@6331
   250
#endif
gabomdq@6331
   251
slouken@3521
   252
    if (_this->num_displays == 0) {
slouken@3521
   253
        SDL_SetError("No available displays");
slouken@3521
   254
        return -1;
slouken@3521
   255
    }
slouken@3521
   256
    return 0;
slouken@1950
   257
}
slouken@1950
   258
slouken@2873
   259
/* Global for the error handler */
slouken@2873
   260
int vm_event, vm_error = -1;
slouken@2873
   261
slouken@2873
   262
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@2873
   263
static SDL_bool
slouken@2874
   264
CheckXinerama(Display * display, int *major, int *minor)
slouken@2873
   265
{
icculus@6027
   266
    int event_base = 0;
icculus@6027
   267
    int error_base = 0;
slouken@2873
   268
    const char *env;
slouken@2873
   269
slouken@2873
   270
    /* Default the extension not available */
slouken@2873
   271
    *major = *minor = 0;
slouken@2873
   272
slouken@2873
   273
    /* Allow environment override */
slouken@6472
   274
    env = SDL_GetHint(SDL_HINT_VIDEO_X11_XINERAMA);
slouken@2873
   275
    if (env && !SDL_atoi(env)) {
slouken@6468
   276
#ifdef X11MODES_DEBUG
slouken@6472
   277
        printf("Xinerama disabled due to hint\n");
slouken@6468
   278
#endif
slouken@2873
   279
        return SDL_FALSE;
slouken@2873
   280
    }
slouken@2873
   281
slouken@5408
   282
    if (!SDL_X11_HAVE_XINERAMA) {
slouken@6468
   283
#ifdef X11MODES_DEBUG
slouken@6468
   284
        printf("Xinerama support not available\n");
slouken@6468
   285
#endif
slouken@5408
   286
        return SDL_FALSE;
slouken@5408
   287
    }
slouken@5408
   288
slouken@2873
   289
    /* Query the extension version */
icculus@6027
   290
    if (!XineramaQueryExtension(display, &event_base, &error_base) ||
icculus@6027
   291
        !XineramaQueryVersion(display, major, minor) ||
slouken@5408
   292
        !XineramaIsActive(display)) {
slouken@6468
   293
#ifdef X11MODES_DEBUG
slouken@6468
   294
        printf("Xinerama not active on the display\n");
slouken@6468
   295
#endif
slouken@2873
   296
        return SDL_FALSE;
slouken@2873
   297
    }
slouken@6468
   298
#ifdef X11MODES_DEBUG
slouken@6468
   299
    printf("Xinerama available!\n");
slouken@6468
   300
#endif
slouken@2873
   301
    return SDL_TRUE;
slouken@2873
   302
}
slouken@2873
   303
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
slouken@2873
   304
slouken@2873
   305
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@2873
   306
static SDL_bool
slouken@2874
   307
CheckXRandR(Display * display, int *major, int *minor)
slouken@2873
   308
{
slouken@2873
   309
    const char *env;
slouken@2873
   310
slouken@2873
   311
    /* Default the extension not available */
slouken@2873
   312
    *major = *minor = 0;
slouken@2873
   313
slouken@2873
   314
    /* Allow environment override */
slouken@6472
   315
    env = SDL_GetHint(SDL_HINT_VIDEO_X11_XRANDR);
slouken@2873
   316
    if (env && !SDL_atoi(env)) {
slouken@6468
   317
#ifdef X11MODES_DEBUG
slouken@6472
   318
        printf("XRandR disabled due to hint\n");
slouken@6468
   319
#endif
slouken@2873
   320
        return SDL_FALSE;
slouken@2873
   321
    }
slouken@2873
   322
slouken@2873
   323
    if (!SDL_X11_HAVE_XRANDR) {
slouken@6468
   324
#ifdef X11MODES_DEBUG
slouken@6468
   325
        printf("XRandR support not available\n");
slouken@6468
   326
#endif
slouken@2873
   327
        return SDL_FALSE;
slouken@2873
   328
    }
slouken@2873
   329
slouken@2873
   330
    /* Query the extension version */
slouken@2873
   331
    if (!XRRQueryVersion(display, major, minor)) {
slouken@6468
   332
#ifdef X11MODES_DEBUG
slouken@6468
   333
        printf("XRandR not active on the display\n");
slouken@6468
   334
#endif
slouken@2873
   335
        return SDL_FALSE;
slouken@2873
   336
    }
slouken@6468
   337
#ifdef X11MODES_DEBUG
slouken@6468
   338
    printf("XRandR available!\n");
slouken@6468
   339
#endif
slouken@2873
   340
    return SDL_TRUE;
slouken@2873
   341
}
slouken@6537
   342
slouken@6537
   343
#define XRANDR_ROTATION_LEFT    (1 << 1)
slouken@6537
   344
#define XRANDR_ROTATION_RIGHT   (1 << 3)
slouken@6537
   345
slouken@6537
   346
static void
slouken@6537
   347
get_xrandr_mode_size(XRRModeInfo *mode, Rotation rotation, int *w, int *h)
slouken@6537
   348
{
slouken@6537
   349
    if (rotation & (XRANDR_ROTATION_LEFT|XRANDR_ROTATION_RIGHT)) {
slouken@6537
   350
        *w = mode->height;
slouken@6537
   351
        *h = mode->width;
slouken@6537
   352
    } else {
slouken@6537
   353
        *w = mode->width;
slouken@6537
   354
        *h = mode->height;
slouken@6537
   355
    }
slouken@6537
   356
}
slouken@2873
   357
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
slouken@2873
   358
slouken@5408
   359
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@2873
   360
static SDL_bool
slouken@2874
   361
CheckVidMode(Display * display, int *major, int *minor)
slouken@2873
   362
{
slouken@2873
   363
    const char *env;
slouken@2873
   364
slouken@2873
   365
    /* Default the extension not available */
slouken@2873
   366
    *major = *minor = 0;
slouken@2873
   367
slouken@2873
   368
    /* Allow environment override */
slouken@6472
   369
    env = SDL_GetHint(SDL_HINT_VIDEO_X11_XVIDMODE);
slouken@2873
   370
    if (env && !SDL_atoi(env)) {
slouken@6468
   371
#ifdef X11MODES_DEBUG
slouken@6472
   372
        printf("XVidMode disabled due to hint\n");
slouken@6468
   373
#endif
slouken@2873
   374
        return SDL_FALSE;
slouken@2873
   375
    }
slouken@2874
   376
slouken@5408
   377
    if (!SDL_X11_HAVE_XVIDMODE) {
slouken@6468
   378
#ifdef X11MODES_DEBUG
slouken@6468
   379
        printf("XVidMode support not available\n");
slouken@6468
   380
#endif
slouken@5408
   381
        return SDL_FALSE;
slouken@5408
   382
    }
slouken@5408
   383
slouken@2873
   384
    /* Query the extension version */
slouken@2873
   385
    vm_error = -1;
slouken@5408
   386
    if (!XF86VidModeQueryExtension(display, &vm_event, &vm_error)
slouken@5408
   387
        || !XF86VidModeQueryVersion(display, major, minor)) {
slouken@6468
   388
#ifdef X11MODES_DEBUG
slouken@6468
   389
        printf("XVidMode not active on the display\n");
slouken@6468
   390
#endif
slouken@2873
   391
        return SDL_FALSE;
slouken@2873
   392
    }
slouken@6468
   393
#ifdef X11MODES_DEBUG
slouken@6468
   394
    printf("XVidMode available!\n");
slouken@6468
   395
#endif
slouken@2873
   396
    return SDL_TRUE;
slouken@2873
   397
}
slouken@2873
   398
slouken@4518
   399
static
slouken@5408
   400
Bool XF86VidModeGetModeInfo(Display * dpy, int scr,
slouken@5408
   401
                                       XF86VidModeModeInfo* info)
slouken@2873
   402
{
slouken@2873
   403
    Bool retval;
slouken@2873
   404
    int dotclock;
slouken@5408
   405
    XF86VidModeModeLine l;
slouken@2873
   406
    SDL_zerop(info);
slouken@2873
   407
    SDL_zero(l);
slouken@5408
   408
    retval = XF86VidModeGetModeLine(dpy, scr, &dotclock, &l);
slouken@2873
   409
    info->dotclock = dotclock;
slouken@2873
   410
    info->hdisplay = l.hdisplay;
slouken@2873
   411
    info->hsyncstart = l.hsyncstart;
slouken@2873
   412
    info->hsyncend = l.hsyncend;
slouken@2873
   413
    info->htotal = l.htotal;
slouken@2873
   414
    info->hskew = l.hskew;
slouken@2873
   415
    info->vdisplay = l.vdisplay;
slouken@2873
   416
    info->vsyncstart = l.vsyncstart;
slouken@2873
   417
    info->vsyncend = l.vsyncend;
slouken@2873
   418
    info->vtotal = l.vtotal;
slouken@2873
   419
    info->flags = l.flags;
slouken@2873
   420
    info->privsize = l.privsize;
slouken@2873
   421
    info->private = l.private;
slouken@2873
   422
    return retval;
slouken@2873
   423
}
slouken@2873
   424
slouken@2873
   425
static int
slouken@5408
   426
calculate_rate(XF86VidModeModeInfo * info)
slouken@2873
   427
{
slouken@2874
   428
    return (info->htotal
slouken@2874
   429
            && info->vtotal) ? (1000 * info->dotclock / (info->htotal *
slouken@2874
   430
                                                         info->vtotal)) : 0;
slouken@2873
   431
}
slouken@2873
   432
slouken@2873
   433
static void
slouken@2874
   434
save_mode(Display * display, SDL_DisplayData * data)
slouken@2873
   435
{
slouken@5408
   436
    XF86VidModeGetModeInfo(display, data->screen,
slouken@5408
   437
                                    &data->saved_mode);
slouken@5408
   438
    XF86VidModeGetViewPort(display, data->screen,
slouken@5408
   439
                                    &data->saved_view.x,
slouken@5408
   440
                                    &data->saved_view.y);
slouken@2873
   441
}
slouken@2873
   442
slouken@4518
   443
/*
slouken@2873
   444
static void
slouken@2874
   445
restore_mode(Display * display, SDL_DisplayData * data)
slouken@2873
   446
{
slouken@5408
   447
    XF86VidModeModeInfo mode;
slouken@2873
   448
slouken@5408
   449
    if (XF86VidModeGetModeInfo(display, data->screen, &mode)) {
slouken@2873
   450
        if (SDL_memcmp(&mode, &data->saved_mode, sizeof(mode)) != 0) {
slouken@5408
   451
            XF86VidModeSwitchToMode(display, data->screen, &data->saved_mode);
slouken@2873
   452
        }
slouken@2873
   453
    }
slouken@2873
   454
    if ((data->saved_view.x != 0) || (data->saved_view.y != 0)) {
slouken@5408
   455
        XF86VidModeSetViewPort(display, data->screen,
slouken@5408
   456
                                        data->saved_view.x,
slouken@5408
   457
                                        data->saved_view.y);
slouken@2873
   458
    }
slouken@2873
   459
}
slouken@4518
   460
*/
slouken@5408
   461
#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
slouken@2873
   462
slouken@1950
   463
void
slouken@3500
   464
X11_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display)
slouken@1950
   465
{
slouken@2870
   466
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@3500
   467
    SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
slouken@2873
   468
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@2873
   469
    int xrandr_major, xrandr_minor;
slouken@2873
   470
    int nsizes, nrates;
slouken@2873
   471
    XRRScreenSize *sizes;
slouken@2873
   472
    short *rates;
slouken@2873
   473
#endif
slouken@5408
   474
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@2873
   475
    int vm_major, vm_minor;
slouken@2873
   476
    int nmodes;
slouken@5408
   477
    XF86VidModeModeInfo ** modes;
slouken@2873
   478
#endif
slouken@2873
   479
    int screen_w;
slouken@2873
   480
    int screen_h;
slouken@1950
   481
    SDL_DisplayMode mode;
slouken@2870
   482
slouken@2873
   483
    /* Unfortunately X11 requires the window to be created with the correct
slouken@2873
   484
     * visual and depth ahead of time, but the SDL API allows you to create
slouken@2873
   485
     * a window before setting the fullscreen display mode.  This means that
slouken@2873
   486
     * we have to use the same format for all windows and all display modes.
slouken@2873
   487
     * (or support recreating the window with a new visual behind the scenes)
slouken@2873
   488
     */
slouken@3500
   489
    mode.format = sdl_display->current_mode.format;
slouken@2873
   490
    mode.driverdata = NULL;
slouken@2873
   491
slouken@2873
   492
    screen_w = DisplayWidth(display, data->screen);
slouken@2873
   493
    screen_h = DisplayHeight(display, data->screen);
slouken@2873
   494
slouken@2873
   495
#if SDL_VIDEO_DRIVER_X11_XINERAMA
gabomdq@6331
   496
    if (data->use_xinerama) {
gabomdq@6331
   497
        /* Add the full (both screens combined) xinerama mode only on the display that starts at 0,0 */
gabomdq@6331
   498
        if (!data->xinerama_info.x_org && !data->xinerama_info.y_org &&
gabomdq@6331
   499
           (screen_w > data->xinerama_info.width || screen_h > data->xinerama_info.height)) {
gabomdq@6331
   500
            mode.w = screen_w;
gabomdq@6331
   501
            mode.h = screen_h;
slouken@2873
   502
            mode.refresh_rate = 0;
slouken@3500
   503
            SDL_AddDisplayMode(sdl_display, &mode);
slouken@2873
   504
        }
gabomdq@6331
   505
gabomdq@6331
   506
        /* Add the head xinerama mode */
gabomdq@6331
   507
        mode.w = data->xinerama_info.width;
gabomdq@6331
   508
        mode.h = data->xinerama_info.height;
gabomdq@6331
   509
        mode.refresh_rate = 0;
gabomdq@6331
   510
        SDL_AddDisplayMode(sdl_display, &mode);
slouken@2873
   511
    }
slouken@2873
   512
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
slouken@2873
   513
slouken@2873
   514
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@2873
   515
    /* XRandR */
slouken@2873
   516
    /* require at least XRandR v1.0 (arbitrary) */
slouken@2874
   517
    if (CheckXRandR(display, &xrandr_major, &xrandr_minor)
slouken@2874
   518
        && xrandr_major >= 1) {
slouken@2873
   519
#ifdef X11MODES_DEBUG
slouken@2873
   520
        fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n",
slouken@2873
   521
                xrandr_major, xrandr_minor);
slouken@2873
   522
#endif
slouken@2873
   523
slouken@2873
   524
        /* save the screen configuration since we must reference it
slouken@2873
   525
           each time we toggle modes.
slouken@2874
   526
         */
slouken@2874
   527
        data->screen_config =
slouken@2874
   528
            XRRGetScreenInfo(display, RootWindow(display, data->screen));
slouken@2873
   529
slouken@2873
   530
        /* retrieve the list of resolution */
slouken@2873
   531
        sizes = XRRConfigSizes(data->screen_config, &nsizes);
slouken@2873
   532
        if (nsizes > 0) {
slouken@2873
   533
            int i, j;
slouken@2874
   534
            for (i = 0; i < nsizes; i++) {
slouken@2873
   535
                mode.w = sizes[i].width;
slouken@2873
   536
                mode.h = sizes[i].height;
slouken@2873
   537
slouken@2873
   538
                rates = XRRConfigRates(data->screen_config, i, &nrates);
slouken@2873
   539
                for (j = 0; j < nrates; ++j) {
slouken@2873
   540
                    mode.refresh_rate = rates[j];
slouken@2873
   541
#ifdef X11MODES_DEBUG
slouken@2874
   542
                    fprintf(stderr,
slouken@2874
   543
                            "XRANDR: mode = %4d[%d], w = %4d, h = %4d, rate = %4d\n",
slouken@2873
   544
                            i, j, mode.w, mode.h, mode.refresh_rate);
slouken@2873
   545
#endif
slouken@3500
   546
                    SDL_AddDisplayMode(sdl_display, &mode);
slouken@2873
   547
                }
slouken@2873
   548
            }
slouken@2873
   549
slouken@2873
   550
            data->use_xrandr = xrandr_major * 100 + xrandr_minor;
slouken@2874
   551
            data->saved_size =
slouken@2874
   552
                XRRConfigCurrentConfiguration(data->screen_config,
slouken@2874
   553
                                              &data->saved_rotation);
slouken@2873
   554
            data->saved_rate = XRRConfigCurrentRate(data->screen_config);
slouken@2873
   555
        }
slouken@2873
   556
    }
slouken@2873
   557
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
slouken@2873
   558
slouken@5408
   559
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@2873
   560
    /* XVidMode */
slouken@2873
   561
    if (!data->use_xrandr &&
slouken@2873
   562
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@2873
   563
        (!data->use_xinerama || data->xinerama_info.screen_number == 0) &&
slouken@2873
   564
#endif
slouken@2873
   565
        CheckVidMode(display, &vm_major, &vm_minor) &&
slouken@5408
   566
        XF86VidModeGetAllModeLines(display, data->screen, &nmodes, &modes)) {
slouken@2873
   567
        int i;
slouken@2873
   568
slouken@2873
   569
#ifdef X11MODES_DEBUG
slouken@2873
   570
        printf("VidMode modes: (unsorted)\n");
slouken@2873
   571
        for (i = 0; i < nmodes; ++i) {
slouken@2873
   572
            printf("Mode %d: %d x %d @ %d\n", i,
slouken@2874
   573
                   modes[i]->hdisplay, modes[i]->vdisplay,
slouken@2874
   574
                   calculate_rate(modes[i]));
slouken@2873
   575
        }
slouken@2873
   576
#endif
slouken@2873
   577
        for (i = 0; i < nmodes; ++i) {
slouken@2873
   578
            mode.w = modes[i]->hdisplay;
slouken@2873
   579
            mode.h = modes[i]->vdisplay;
slouken@2873
   580
            mode.refresh_rate = calculate_rate(modes[i]);
slouken@3500
   581
            SDL_AddDisplayMode(sdl_display, &mode);
slouken@2873
   582
        }
slouken@2873
   583
        XFree(modes);
slouken@2873
   584
slouken@2873
   585
        data->use_vidmode = vm_major * 100 + vm_minor;
slouken@2873
   586
        save_mode(display, data);
slouken@2873
   587
    }
slouken@5408
   588
#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
slouken@2873
   589
slouken@2873
   590
    if (!data->use_xrandr && !data->use_vidmode) {
slouken@2873
   591
        mode.w = screen_w;
slouken@2873
   592
        mode.h = screen_h;
slouken@2873
   593
        mode.refresh_rate = 0;
slouken@3500
   594
        SDL_AddDisplayMode(sdl_display, &mode);
slouken@2874
   595
    }
slouken@2873
   596
#ifdef X11MODES_DEBUG
slouken@2873
   597
    if (data->use_xinerama) {
slouken@2873
   598
        printf("Xinerama is enabled\n");
slouken@2873
   599
    }
slouken@2873
   600
slouken@2873
   601
    if (data->use_xrandr) {
slouken@2873
   602
        printf("XRandR is enabled\n");
slouken@2873
   603
    }
slouken@2873
   604
slouken@2873
   605
    if (data->use_vidmode) {
slouken@2873
   606
        printf("VidMode is enabled\n");
slouken@2873
   607
    }
slouken@2873
   608
#endif /* X11MODES_DEBUG */
slouken@2873
   609
}
slouken@2873
   610
slouken@2873
   611
static void
slouken@2874
   612
get_real_resolution(Display * display, SDL_DisplayData * data, int *w, int *h,
slouken@2874
   613
                    int *rate)
slouken@2873
   614
{
slouken@2873
   615
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@2873
   616
    if (data->use_xrandr) {
slouken@2873
   617
        int nsizes;
slouken@2873
   618
        XRRScreenSize *sizes;
slouken@2874
   619
slouken@2873
   620
        sizes = XRRConfigSizes(data->screen_config, &nsizes);
slouken@2873
   621
        if (nsizes > 0) {
slouken@2873
   622
            int cur_size;
slouken@2873
   623
            Rotation cur_rotation;
slouken@2873
   624
slouken@2874
   625
            cur_size =
slouken@2874
   626
                XRRConfigCurrentConfiguration(data->screen_config,
slouken@2874
   627
                                              &cur_rotation);
slouken@2873
   628
            *w = sizes[cur_size].width;
slouken@2873
   629
            *h = sizes[cur_size].height;
slouken@2873
   630
            *rate = XRRConfigCurrentRate(data->screen_config);
slouken@2873
   631
#ifdef X11MODES_DEBUG
slouken@2874
   632
            fprintf(stderr,
slouken@2874
   633
                    "XRANDR: get_real_resolution: w = %d, h = %d, rate = %d\n",
slouken@2874
   634
                    *w, *h, *rate);
slouken@2873
   635
#endif
slouken@2873
   636
            return;
slouken@2873
   637
        }
slouken@2873
   638
    }
slouken@2873
   639
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
slouken@2873
   640
slouken@5408
   641
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@2873
   642
    if (data->use_vidmode) {
slouken@5408
   643
        XF86VidModeModeInfo mode;
slouken@2873
   644
slouken@5408
   645
        if (XF86VidModeGetModeInfo(display, data->screen, &mode)) {
slouken@2873
   646
            *w = mode.hdisplay;
slouken@2873
   647
            *h = mode.vdisplay;
slouken@2873
   648
            *rate = calculate_rate(&mode);
slouken@2873
   649
            return;
slouken@2873
   650
        }
slouken@2873
   651
    }
slouken@5408
   652
#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
slouken@2873
   653
slouken@6482
   654
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6482
   655
    if (data->use_xinerama) {
slouken@6502
   656
        int screencount;
slouken@6502
   657
        XineramaScreenInfo *xinerama;
slouken@6502
   658
slouken@6502
   659
        /* Update the current screen layout information */
slouken@6502
   660
        xinerama = XineramaQueryScreens(display, &screencount);
slouken@6506
   661
        if (xinerama && data->xinerama_screen < screencount) {
slouken@6506
   662
            data->xinerama_info = xinerama[data->xinerama_screen];
slouken@6502
   663
        }
slouken@6502
   664
        if (xinerama) XFree(xinerama);
slouken@6502
   665
slouken@6482
   666
        *w = data->xinerama_info.width;
slouken@6482
   667
        *h = data->xinerama_info.height;
slouken@6482
   668
        *rate = 0;
slouken@6482
   669
        return;
slouken@6482
   670
    }
slouken@6482
   671
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
slouken@6482
   672
slouken@2873
   673
    *w = DisplayWidth(display, data->screen);
slouken@2873
   674
    *h = DisplayHeight(display, data->screen);
slouken@2873
   675
    *rate = 0;
slouken@2873
   676
}
slouken@2873
   677
slouken@2873
   678
static void
slouken@2874
   679
set_best_resolution(Display * display, SDL_DisplayData * data, int w, int h,
slouken@2874
   680
                    int rate)
slouken@2873
   681
{
slouken@2873
   682
    int real_w, real_h, real_rate;
slouken@2873
   683
slouken@2873
   684
    /* check current mode so we can avoid uneccessary mode changes */
slouken@2873
   685
    get_real_resolution(display, data, &real_w, &real_h, &real_rate);
gabomdq@6331
   686
slouken@6482
   687
    if (w == real_w && h == real_h && (!rate || !real_rate || rate == real_rate)) {
gabomdq@6331
   688
        return;
gabomdq@6331
   689
    }
gabomdq@6331
   690
slouken@2873
   691
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@2873
   692
    if (data->use_xrandr) {
slouken@2873
   693
#ifdef X11MODES_DEBUG
slouken@2873
   694
        fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n",
slouken@2873
   695
                w, h);
slouken@2873
   696
#endif
slouken@2873
   697
        int i, nsizes, nrates;
slouken@2873
   698
        int best;
slouken@2873
   699
        int best_rate;
slouken@2873
   700
        XRRScreenSize *sizes;
slouken@2873
   701
        short *rates;
slouken@2873
   702
slouken@6537
   703
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6537
   704
        if (data->use_xrandr >= 102 && data->use_xinerama) {
slouken@6537
   705
            /* See http://cgit.freedesktop.org/xorg/app/xrandr/tree/xrandr.c for the rationale behind this */
slouken@6537
   706
            /* Note by Gabriel: the refresh rate is ignored in this code, and seeing that both xrandr
slouken@6537
   707
             * and nvidia-settings don't provide a way to set it when Xinerama is enabled, it may not be possible to set it */
slouken@6537
   708
            int screencount;
slouken@6537
   709
            XineramaScreenInfo * xinerama = NULL;
slouken@6537
   710
            XRRScreenResources  *res;
slouken@6537
   711
slouken@6537
   712
            /* Update the current screen layout information */
slouken@6537
   713
            xinerama = XineramaQueryScreens(display, &screencount);
slouken@6537
   714
            if (xinerama && data->xinerama_screen < screencount) {
slouken@6537
   715
                data->xinerama_info = xinerama[data->xinerama_screen];
slouken@2873
   716
            }
slouken@6537
   717
            if (xinerama) XFree(xinerama);
slouken@6537
   718
slouken@6537
   719
            res = XRRGetScreenResources (display, RootWindow(display, data->screen));
slouken@6537
   720
            if (res) {
slouken@6537
   721
                XRROutputInfo *output_info = NULL;
slouken@6537
   722
                XRRCrtcInfo *crtc = NULL;
slouken@6537
   723
                XRRModeInfo *mode_info, *best_mode_info = NULL;
slouken@6537
   724
                int mode_index = 0, output_mode_index = 0, output;
slouken@6537
   725
                int mode_w, mode_h, best_w = 0, best_h = 0;
slouken@6537
   726
slouken@6537
   727
                for ( output = 0; output < res->noutput; output++) {
slouken@6537
   728
                    output_info = XRRGetOutputInfo (display, res, res->outputs[output]);
slouken@6537
   729
                    if (!output_info || !output_info->crtc) {
slouken@6537
   730
                        XRRFreeOutputInfo(output_info);
slouken@6537
   731
                        continue;
slouken@6537
   732
                    }
slouken@6537
   733
slouken@6537
   734
                    crtc = XRRGetCrtcInfo (display, res, output_info->crtc);
slouken@6537
   735
                    if (!crtc || data->xinerama_info.x_org != crtc->x || data->xinerama_info.y_org != crtc->y) {
slouken@6537
   736
                        XRRFreeCrtcInfo(crtc);
slouken@6537
   737
                        continue;
slouken@6537
   738
                    }
slouken@6537
   739
slouken@6537
   740
                    /* The CRT offset matches the Xinerama mode, let's hope it's the right one! */
slouken@6537
   741
#ifdef X11MODES_DEBUG
slouken@6538
   742
                    fprintf(stderr, "XRANDR: set_best_resolution, matched Xinerama screen %d to CRT %ld at %d,%d\n",
slouken@6537
   743
                        data->xinerama_info.screen_number, output_info->crtc, crtc->x, crtc->y);
slouken@6537
   744
#endif
slouken@6537
   745
                    /* Find out the best mode we can use */
slouken@6537
   746
                    for (mode_index = 0; mode_index < res->nmode; mode_index++) {
slouken@6537
   747
                        mode_info = &res->modes[mode_index];
slouken@6537
   748
                        get_xrandr_mode_size(mode_info, crtc->rotation, &mode_w, &mode_h);
slouken@6537
   749
                        if (mode_w >= w && mode_h >= h) {
slouken@6537
   750
                            /* This may be a useful mode, check out if it belongs to the correct output */
slouken@6537
   751
#ifdef X11MODES_DEBUG
slouken@6537
   752
                            fprintf(stderr, "Evaluating valid mode %d, w: %d, h: %d\n", mode_index, mode_info->width, mode_info->height);
slouken@6537
   753
#endif
slouken@6537
   754
                            for ( output_mode_index = 0; output_mode_index < output_info->nmode; output_mode_index++) {
slouken@6537
   755
                                if (output_info->modes[output_mode_index] == mode_info->id) {
slouken@6537
   756
                                    break;
slouken@6537
   757
                                }
slouken@6537
   758
                            }
slouken@6537
   759
                            if (output_mode_index < output_info->nmode) {
slouken@6537
   760
#ifdef X11MODES_DEBUG
slouken@6537
   761
                                fprintf(stderr, "Mode belongs to the desired output %d w: %d, h: %d, rotation: %x\n", mode_index, mode_info->width, mode_info->height, crtc->rotation);
slouken@6537
   762
#endif
slouken@6537
   763
                                /* We have a mode that belongs to the right output and that can contain the w,h required, see if it's smaller than the current one */
slouken@6537
   764
                                if ( !best_mode_info || mode_w < best_w || (mode_w == best_w && mode_h < best_h) ) {
slouken@6537
   765
                                    best_mode_info = mode_info;
slouken@6537
   766
                                    best_w = mode_w;
slouken@6537
   767
                                    best_h = mode_h;
slouken@6537
   768
                                }
slouken@6537
   769
                            }
slouken@6537
   770
#ifdef X11MODES_DEBUG
slouken@6537
   771
                            else {
slouken@6537
   772
                                fprintf(stderr, "Discarding mode because it does not belong to the desired output %d, w: %d, h: %d, rotation: %d\n", mode_index, mode_info->width, mode_info->height, crtc->rotation);
slouken@6537
   773
                            }
slouken@6537
   774
#endif
slouken@6537
   775
                        }
slouken@6537
   776
                    }
slouken@6537
   777
slouken@6537
   778
                    if (best_mode_info) {
slouken@6537
   779
#ifdef X11MODES_DEBUG
slouken@6537
   780
                            fprintf(stderr, "XRANDR: set_best_resolution, setting mode w = %d, h = %d on output: %d, CRT with offsets: %d,%d for Xinerama screen: %d\n",
slouken@6537
   781
                                    best_mode_info->width, best_mode_info->height, output, crtc->x, crtc->y, data->xinerama_info.screen_number);
slouken@6537
   782
#endif
slouken@6537
   783
                        XGrabServer (display);
slouken@6537
   784
                        XRRSetCrtcConfig (display, res, output_info->crtc, CurrentTime,
slouken@6537
   785
                          crtc->x, crtc->y, best_mode_info->id, crtc->rotation,
slouken@6537
   786
                          &res->outputs[output], 1);
slouken@6537
   787
                        /* TODO: Handle screen rotations, should we call XRRSetCrtcTransform if Xrandr >=1.3 ? */
slouken@6537
   788
                        XUngrabServer (display);
slouken@6537
   789
                    } else {
slouken@6537
   790
                        /* If we reach here, we have found the right screen but no valid best mode */
slouken@6537
   791
                        SDL_SetError("The selected screen can't support a resolution of the size desired");
slouken@6537
   792
                    }
slouken@6537
   793
                    XRRFreeCrtcInfo(crtc);
slouken@6537
   794
                    XRRFreeOutputInfo(output_info);
slouken@6537
   795
                    break;
slouken@6537
   796
                }
slouken@6537
   797
                XRRFreeScreenResources(res);
slouken@2873
   798
            }
slouken@2873
   799
        }
slouken@6537
   800
        else
slouken@6537
   801
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
slouken@6537
   802
        {
slouken@6537
   803
            /* Use older xrandr functions that don't play along very nicely with multi monitors setups */
slouken@6537
   804
            /* find the smallest resolution that is at least as big as the user requested */
slouken@6537
   805
            best = -1;
slouken@6537
   806
            sizes = XRRConfigSizes(data->screen_config, &nsizes);
slouken@6537
   807
            for (i = 0; i < nsizes; ++i) {
slouken@6537
   808
                if (sizes[i].width < w || sizes[i].height < h) {
slouken@6537
   809
                    continue;
slouken@6537
   810
                }
slouken@6537
   811
                if (sizes[i].width == w && sizes[i].height == h) {
slouken@6537
   812
                    best = i;
slouken@2873
   813
                    break;
slouken@2873
   814
                }
slouken@6537
   815
                if (best == -1 ||
slouken@6537
   816
                    (sizes[i].width < sizes[best].width) ||
slouken@6537
   817
                    (sizes[i].width == sizes[best].width
slouken@6537
   818
                     && sizes[i].height < sizes[best].height)) {
slouken@6537
   819
                    best = i;
slouken@6537
   820
                }
slouken@6537
   821
            }
slouken@6537
   822
slouken@6537
   823
            if (best >= 0) {
slouken@6537
   824
                best_rate = 0;
slouken@6537
   825
                rates = XRRConfigRates(data->screen_config, best, &nrates);
slouken@6537
   826
                for (i = 0; i < nrates; ++i) {
slouken@6537
   827
                    if (rates[i] == rate) {
slouken@6537
   828
                        best_rate = rate;
slouken@6537
   829
                        break;
slouken@2873
   830
                    }
slouken@6537
   831
                    if (!rate) {
slouken@6537
   832
                        /* Higher is better, right? */
slouken@6537
   833
                        if (rates[i] > best_rate) {
slouken@6537
   834
                            best_rate = rates[i];
slouken@6537
   835
                        }
slouken@6537
   836
                    } else {
slouken@6537
   837
                        if (SDL_abs(rates[i] - rate) < SDL_abs(best_rate - rate)) {
slouken@6537
   838
                            best_rate = rates[i];
slouken@6537
   839
                        }
slouken@2873
   840
                    }
slouken@2873
   841
                }
slouken@6537
   842
                XRRSetScreenConfigAndRate(display, data->screen_config,
slouken@6537
   843
                                          RootWindow(display, data->screen), best,
slouken@6537
   844
                                          data->saved_rotation, best_rate,
slouken@6537
   845
                                          CurrentTime);
slouken@2873
   846
            }
slouken@2873
   847
        }
slouken@2873
   848
        return;
slouken@2873
   849
    }
slouken@2873
   850
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
slouken@2873
   851
slouken@5408
   852
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@2873
   853
    if (data->use_vidmode) {
slouken@5408
   854
        XF86VidModeModeInfo ** modes;
slouken@2873
   855
        int i, nmodes;
slouken@2873
   856
        int best;
slouken@2873
   857
slouken@5408
   858
        if (XF86VidModeGetAllModeLines(display, data->screen, &nmodes, &modes)) {
slouken@2873
   859
            best = -1;
slouken@2873
   860
            for (i = 0; i < nmodes; ++i) {
slouken@2873
   861
                if (modes[i]->hdisplay < w || modes[i]->vdisplay < h) {
slouken@2873
   862
                    continue;
slouken@2873
   863
                }
slouken@2873
   864
                if (best == -1 ||
slouken@2873
   865
                    (modes[i]->hdisplay < modes[best]->hdisplay) ||
slouken@2874
   866
                    (modes[i]->hdisplay == modes[best]->hdisplay
slouken@2874
   867
                     && modes[i]->vdisplay < modes[best]->vdisplay)) {
slouken@2873
   868
                    best = i;
slouken@2873
   869
                    continue;
slouken@2873
   870
                }
slouken@2873
   871
                if ((modes[i]->hdisplay == modes[best]->hdisplay) &&
slouken@2873
   872
                    (modes[i]->vdisplay == modes[best]->vdisplay)) {
slouken@2873
   873
                    if (!rate) {
slouken@2873
   874
                        /* Higher is better, right? */
slouken@2874
   875
                        if (calculate_rate(modes[i]) >
slouken@2874
   876
                            calculate_rate(modes[best])) {
slouken@2873
   877
                            best = i;
slouken@2873
   878
                        }
slouken@2873
   879
                    } else {
slouken@2874
   880
                        if (SDL_abs(calculate_rate(modes[i]) - rate) <
slouken@2874
   881
                            SDL_abs(calculate_rate(modes[best]) - rate)) {
slouken@2873
   882
                            best = i;
slouken@2873
   883
                        }
slouken@2873
   884
                    }
slouken@2873
   885
                }
slouken@2873
   886
            }
slouken@2873
   887
            if (best >= 0) {
slouken@2873
   888
#ifdef X11MODES_DEBUG
slouken@2873
   889
                printf("Best Mode %d: %d x %d @ %d\n", best,
slouken@2874
   890
                       modes[best]->hdisplay, modes[best]->vdisplay,
slouken@2874
   891
                       calculate_rate(modes[best]));
slouken@2873
   892
#endif
slouken@5408
   893
                XF86VidModeSwitchToMode(display, data->screen, modes[best]);
slouken@2873
   894
            }
slouken@2873
   895
            XFree(modes);
slouken@2873
   896
        }
slouken@2873
   897
        return;
slouken@2873
   898
    }
slouken@5408
   899
#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
slouken@1950
   900
}
slouken@1950
   901
slouken@1950
   902
int
slouken@3500
   903
X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode)
slouken@1950
   904
{
slouken@2873
   905
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@3500
   906
    SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
slouken@2873
   907
slouken@2873
   908
    set_best_resolution(display, data, mode->w, mode->h, mode->refresh_rate);
slouken@2873
   909
    return 0;
slouken@1950
   910
}
slouken@1950
   911
slouken@1950
   912
void
slouken@1950
   913
X11_QuitModes(_THIS)
slouken@1950
   914
{
slouken@1950
   915
}
slouken@1950
   916
gabomdq@6331
   917
int
gabomdq@6331
   918
X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect)
gabomdq@6331
   919
{
slouken@6502
   920
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
gabomdq@6331
   921
    SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
slouken@6502
   922
    int real_rate;
slouken@6502
   923
slouken@6502
   924
    rect->x = 0;
slouken@6502
   925
    rect->y = 0;
slouken@6502
   926
    get_real_resolution(display, data, &rect->w, &rect->h, &real_rate);
gabomdq@6331
   927
gabomdq@6331
   928
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6502
   929
    if (data->use_xinerama) {
gabomdq@6331
   930
        rect->x = data->xinerama_info.x_org;
gabomdq@6331
   931
        rect->y = data->xinerama_info.y_org;
gabomdq@6331
   932
    }
gabomdq@6331
   933
#endif
slouken@6475
   934
    return 0;
gabomdq@6331
   935
}
gabomdq@6331
   936
slouken@5481
   937
#endif /* SDL_VIDEO_DRIVER_X11 */
slouken@5481
   938
slouken@1950
   939
/* vi: set ts=4 sw=4 expandtab: */