# HG changeset patch # User Ryan C. Gordon # Date 1143026038 0 # Node ID 34cca785be57e99b2dc338d9a08a8e2a2a25b1e8 # Parent e20dcef5647cc4543df8a0a78a29f8781f254c11 Xrandr support in the X11 target. Fixes Bugzilla #109, and as a bonus, Bugzilla #145, too! diff -r e20dcef5647c -r 34cca785be57 configure.in --- a/configure.in Wed Mar 22 09:18:10 2006 +0000 +++ b/configure.in Wed Mar 22 11:13:58 2006 +0000 @@ -789,9 +789,11 @@ , enable_x11_shared=yes) case "$host" in - *-*-darwin*) + *-*-darwin*) # Latest Mac OS X actually ships with Xrandr/Xrender libs... x11_lib='/usr/X11R6/lib/libX11.6.dylib' x11ext_lib='/usr/X11R6/lib/libXext.6.dylib' + xrandr_lib='/usr/X11R6/lib/libXrandr.2.dylib' + xrender_lib='/usr/X11R6/lib/libXrender.1.dylib' ;; *-*-osf*) x11_lib='libX11.so' @@ -810,6 +812,12 @@ if test "x$x11ext_lib" = "x"; then x11ext_lib=[`ls $path/libXext.so.[0-9] 2>/dev/null | sort -r | sed 's/.*\/\(.*\)/\1/; q'`] fi + if test "x$xrender_lib" = "x"; then + xrender_lib=[`ls $path/libXrender.so.[0-9] 2>/dev/null | sort -r | sed 's/.*\/\(.*\)/\1/; q'`] + fi + if test "x$xrandr_lib" = "x"; then + xrandr_lib=[`ls $path/libXrandr.so.[0-9] 2>/dev/null | sort -r | sed 's/.*\/\(.*\)/\1/; q'`] + fi done ;; esac @@ -833,6 +841,7 @@ AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC, "$x11_lib") AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT, "$x11ext_lib") else + enable_x11_shared=no EXTRA_LDFLAGS="$EXTRA_LDFLAGS $X_LIBS -lX11 -lXext" fi have_video=yes @@ -884,6 +893,37 @@ AC_DEFINE(SDL_VIDEO_DRIVER_X11_XME) SOURCES="$SOURCES $srcdir/src/video/Xext/XME/*.c" fi + AC_ARG_ENABLE(video-x11-xrandr, +AC_HELP_STRING([--enable-video-x11-xrandr], [enable X11 Xrandr extension for fullscreen [default=yes]]), + , enable_video_x11_xrandr=yes) + if test x$enable_video_x11_xrandr = xyes; then + definitely_enable_video_x11_xrandr=no + AC_CHECK_HEADER(X11/extensions/Xrandr.h, + have_xrandr_h_hdr=yes, + have_xrandr_h_hdr=no, + [#include + ]) + if test x$have_xrandr_h_hdr = xyes; then + if test x$enable_x11_shared = xyes && test x$xrandr_lib != x ; then + echo "-- dynamic libXrender -> $xrender_lib" + echo "-- dynamic libXrandr -> $xrandr_lib" + AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER, "$xrender_lib") + AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR, "$xrandr_lib") + definitely_enable_video_x11_xrandr=yes + else + AC_CHECK_LIB(Xrender, XRenderQueryExtension, have_xrender_lib=yes) + AC_CHECK_LIB(Xrandr, XRRQueryExtension, have_xrandr_lib=yes) + if test x$have_xrender_lib = xyes && test x$have_xrandr_lib = xyes ; then + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXrandr -lXrender" + definitely_enable_video_x11_xrandr=yes + fi + fi + fi + fi + + if test x$definitely_enable_video_x11_xrandr = xyes; then + AC_DEFINE(SDL_VIDEO_DRIVER_X11_XRANDR) + fi fi fi } diff -r e20dcef5647c -r 34cca785be57 docs/html/sdlenvvars.html --- a/docs/html/sdlenvvars.html Wed Mar 22 09:18:10 2006 +0000 +++ b/docs/html/sdlenvvars.html Wed Mar 22 11:13:58 2006 +0000 @@ -576,6 +576,18 @@ >
SDL_VIDEO_X11_NO_XRANDR

If set, don't attempt to use the Xrandr extension for resolution mode +switching. Normally Xrandr takes precedence over the XF86VidMode +extension, so setting this environment variable will cause the +XF86VidMode extension to be used if it is available.

SDL_VIDEO_YUV_DIRECT
\ No newline at end of file +> diff -r e20dcef5647c -r 34cca785be57 include/SDL_config.h.in --- a/include/SDL_config.h.in Wed Mar 22 09:18:10 2006 +0000 +++ b/include/SDL_config.h.in Wed Mar 22 11:13:58 2006 +0000 @@ -278,9 +278,12 @@ #undef SDL_VIDEO_DRIVER_X11_DGAMOUSE #undef SDL_VIDEO_DRIVER_X11_DYNAMIC #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER #undef SDL_VIDEO_DRIVER_X11_VIDMODE #undef SDL_VIDEO_DRIVER_X11_XINERAMA #undef SDL_VIDEO_DRIVER_X11_XME +#undef SDL_VIDEO_DRIVER_X11_XRANDR #undef SDL_VIDEO_DRIVER_X11_XV #undef SDL_VIDEO_DRIVER_XBIOS diff -r e20dcef5647c -r 34cca785be57 src/video/x11/SDL_x11dyn.c --- a/src/video/x11/SDL_x11dyn.c Wed Mar 22 09:18:10 2006 +0000 +++ b/src/video/x11/SDL_x11dyn.c Wed Mar 22 11:13:58 2006 +0000 @@ -21,13 +21,11 @@ */ #include "SDL_config.h" -#if 0 -#define DEBUG_DYNAMIC_X11 1 -#endif +#define DEBUG_DYNAMIC_X11 0 #include "SDL_x11dyn.h" -#ifdef DEBUG_DYNAMIC_X11 +#if DEBUG_DYNAMIC_X11 #include #endif @@ -39,6 +37,10 @@ static void *x11_handle = NULL; static const char *x11ext_library = SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT; static void *x11ext_handle = NULL; +static const char *xrender_library = SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER; +static void *xrender_handle = NULL; +static const char *xrandr_library = SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR; +static void *xrandr_handle = NULL; typedef struct { @@ -54,6 +56,8 @@ { { x11_handle, "libX11" }, { x11ext_handle, "libX11ext" }, + { xrender_handle, "libXrender" }, + { xrandr_handle, "libXrandr" }, }; for (i = 0; i < (sizeof (libs) / sizeof (libs[0])); i++) @@ -130,6 +134,14 @@ SDL_UnloadObject(x11ext_handle); x11ext_handle = NULL; } + if (xrender_handle != NULL) { + SDL_UnloadObject(xrender_handle); + xrender_handle = NULL; + } + if (xrandr_handle != NULL) { + SDL_UnloadObject(xrandr_handle); + xrandr_handle = NULL; + } } } #endif @@ -146,6 +158,8 @@ int *thismod = NULL; x11_handle = SDL_LoadObject(x11_library); x11ext_handle = SDL_LoadObject(x11ext_library); + xrender_handle = SDL_LoadObject(xrender_library); + xrandr_handle = SDL_LoadObject(xrandr_library); #define SDL_X11_MODULE(modname) thismod = &SDL_X11_HAVE_##modname; #define SDL_X11_SYM(a,fn,x,y,z) p##fn = X11_GetSym(#fn,thismod); #include "SDL_x11sym.h" diff -r e20dcef5647c -r 34cca785be57 src/video/x11/SDL_x11dyn.h --- a/src/video/x11/SDL_x11dyn.h Wed Mar 22 09:18:10 2006 +0000 +++ b/src/video/x11/SDL_x11dyn.h Wed Mar 22 11:13:58 2006 +0000 @@ -38,6 +38,10 @@ #include #endif +#if SDL_VIDEO_DRIVER_X11_XRANDR +#include +#endif + /* * When using the "dynamic X11" functionality, we duplicate all the Xlib * symbols that would be referenced by SDL inside of SDL itself. diff -r e20dcef5647c -r 34cca785be57 src/video/x11/SDL_x11modes.c --- a/src/video/x11/SDL_x11modes.c Wed Mar 22 09:18:10 2006 +0000 +++ b/src/video/x11/SDL_x11modes.c Wed Mar 22 11:13:58 2006 +0000 @@ -86,6 +86,18 @@ } #endif +#if SDL_VIDEO_DRIVER_X11_XRANDR +static int cmpmodelist(const void *va, const void *vb) +{ + const SDL_Rect *a = *(const SDL_Rect **)va; + const SDL_Rect *b = *(const SDL_Rect **)vb; + if ( a->w == b->w ) + return b->h - a->h; + else + return b->w - a->w; +} +#endif + static void get_real_resolution(_THIS, int* w, int* h); static void set_best_resolution(_THIS, int width, int height) @@ -180,6 +192,55 @@ } #endif /* SDL_VIDEO_DRIVER_X11_XME */ +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr ) { +#ifdef XRANDR_DEBUG + fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n", + width, height); +#endif + if ( SDL_modelist ) { + int i, nsizes; + XRRScreenSize *sizes; + + /* find the smallest resolution that is at least as big as the user requested */ + sizes = XRRConfigSizes(screen_config, &nsizes); + for ( i = (nsizes-1); i >= 0; i-- ) { + if ( (SDL_modelist[i]->w >= width) && + (SDL_modelist[i]->h >= height) ) { + break; + } + } + + if ( i >= 0 && SDL_modelist[i] ) { /* found one, lets try it */ + int w, h; + + /* check current mode so we can avoid uneccessary mode changes */ + get_real_resolution(this, &w, &h); + + if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) { + int size_id; + +#ifdef XRANDR_DEBUG + fprintf(stderr, "XRANDR: set_best_resolution: " + "XXRSetScreenConfig: %d %d\n", + SDL_modelist[i]->w, SDL_modelist[i]->h); +#endif + + /* find the matching size entry index */ + for ( size_id = 0; size_id < nsizes; ++size_id ) { + if ( (sizes[size_id].width == SDL_modelist[i]->w) && + (sizes[size_id].height == SDL_modelist[i]->h) ) + break; + } + + XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, + size_id, saved_rotation, CurrentTime); + } + } + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + } static void get_real_resolution(_THIS, int* w, int* h) @@ -195,7 +256,7 @@ return; } } -#endif +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ #if SDL_VIDEO_DRIVER_X11_XME if ( use_xme ) { @@ -213,7 +274,30 @@ XFree(modelist); return; } -#endif /* XIG_XME */ +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr ) { + int nsizes; + XRRScreenSize* sizes; + + sizes = XRRConfigSizes(screen_config, &nsizes); + if ( nsizes > 0 ) { + int cur_size; + Rotation cur_rotation; + + cur_size = XRRConfigCurrentConfiguration(screen_config, &cur_rotation); + if ( cur_size >= 0 && cur_size < nsizes ) { + *w = sizes[cur_size].width; + *h = sizes[cur_size].height; + } +#ifdef XRANDR_DEBUG + fprintf(stderr, "XRANDR: get_real_resolution: w = %d h = %d\n", *w, *h); +#endif + return; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ *w = DisplayWidth(SDL_Display, SDL_Screen); *h = DisplayHeight(SDL_Display, SDL_Screen); @@ -289,15 +373,69 @@ int ractive, nummodes; XiGMiscResolutionInfo *modelist; #endif +#if SDL_VIDEO_DRIVER_X11_XRANDR + int xrandr_major, xrandr_minor; + int nsizes; + XRRScreenSize *sizes; +#endif int i, n; int screen_w; int screen_h; vm_error = -1; use_vidmode = 0; + use_xrandr = 0; screen_w = DisplayWidth(SDL_Display, SDL_Screen); screen_h = DisplayHeight(SDL_Display, SDL_Screen); + /* XRandR */ +#if SDL_VIDEO_DRIVER_X11_XRANDR + /* require at least XRandR v1.0 (arbitrary) */ + if ( ( SDL_X11_HAVE_XRANDR ) && + ( getenv("SDL_VIDEO_X11_NO_XRANDR") == NULL ) && + ( XRRQueryVersion(SDL_Display, &xrandr_major, &xrandr_minor) ) && + ( xrandr_major >= 1 ) ) { + +#ifdef XRANDR_DEBUG + fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n", + xrandr_major, xrandr_minor); +#endif + + /* save the screen configuration since we must reference it + each time we toggle modes. + */ + screen_config = XRRGetScreenInfo(SDL_Display, SDL_Root); + + /* retrieve the list of resolution */ + sizes = XRRConfigSizes(screen_config, &nsizes); + if (nsizes > 0) { + SDL_modelist = (SDL_Rect **)malloc((nsizes+1)*sizeof(SDL_Rect *)); + if (SDL_modelist) { + for ( i=0; i < nsizes; i++ ) { + if ((SDL_modelist[i] = + (SDL_Rect *)malloc(sizeof(SDL_Rect))) == NULL) + break; +#ifdef XRANDR_DEBUG + fprintf(stderr, "XRANDR: mode = %4d, w = %4d, h = %4d\n", + i, sizes[i].width, sizes[i].height); +#endif + + SDL_modelist[i]->x = 0; + SDL_modelist[i]->y = 0; + SDL_modelist[i]->w = sizes[i].width; + SDL_modelist[i]->h = sizes[i].height; + + } + /* sort the mode list descending as SDL expects */ + qsort(SDL_modelist, nsizes, sizeof *SDL_modelist, cmpmodelist); + SDL_modelist[i] = NULL; /* terminator */ + } + use_xrandr = xrandr_major * 100 + xrandr_minor; + saved_size_id = XRRConfigCurrentConfiguration(screen_config, &saved_rotation); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + #if SDL_VIDEO_DRIVER_X11_VIDMODE /* Metro-X 4.3.0 and earlier has a broken implementation of XF86VidModeGetAllModeLines() - it hangs the client. @@ -345,7 +483,7 @@ buggy_X11 = 1; } } - if ( ! buggy_X11 && + if ( ! buggy_X11 && ! use_xrandr && SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) { #ifdef XFREE86_DEBUG @@ -426,7 +564,7 @@ */ fprintf(stderr, "XME: If you are using Xi Graphics CDE and a Summit server, you need to\n" -"XME: get the libXext update from our ftp site before fullscreen switching\n" +"XME: get the libXext update from Xi's ftp site before fullscreen switching\n" "XME: will work. Fullscreen switching is only supported on Summit Servers\n"); } } else { @@ -635,6 +773,14 @@ SDL_free(SDL_modelist); SDL_modelist = NULL; } + +#if SDL_VIDEO_DRIVER_X11_XRANDR + /* Free the Xrandr screen configuration */ + if ( screen_config ) { + XRRFreeScreenConfigInfo(screen_config); + screen_config = NULL; + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ } int X11_ResizeFullScreen(_THIS) @@ -804,6 +950,13 @@ } #endif +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr ) { + XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, + saved_size_id, saved_rotation, CurrentTime); + } +#endif + XUnmapWindow(SDL_Display, FSwindow); X11_WaitUnmapped(this, FSwindow); XSync(SDL_Display, True); /* Flush spurious mode change events */ diff -r e20dcef5647c -r 34cca785be57 src/video/x11/SDL_x11sym.h --- a/src/video/x11/SDL_x11sym.h Wed Mar 22 09:18:10 2006 +0000 +++ b/src/video/x11/SDL_x11sym.h Wed Mar 22 11:13:58 2006 +0000 @@ -176,5 +176,16 @@ SDL_X11_SYM(int,ipUnallocateAndSendData,(ChannelPtr a, IPCard b),(a,b),return) #endif +/* Xrandr support. */ +#if SDL_VIDEO_DRIVER_X11_XRANDR +SDL_X11_MODULE(XRANDR) +SDL_X11_SYM(Status,XRRQueryVersion,(Display *dpy,int *major_versionp,int *minor_versionp),(dpy,major_versionp,minor_versionp),return) +SDL_X11_SYM(XRRScreenConfiguration *,XRRGetScreenInfo,(Display *dpy,Drawable draw),(dpy,draw),return) +SDL_X11_SYM(SizeID,XRRConfigCurrentConfiguration,(XRRScreenConfiguration *config,Rotation *rotation),(config,rotation),return) +SDL_X11_SYM(XRRScreenSize *,XRRConfigSizes,(XRRScreenConfiguration *config, int *nsizes),(config,nsizes),return) +SDL_X11_SYM(Status,XRRSetScreenConfig,(Display *dpy, XRRScreenConfiguration *config, Drawable draw, int size_index, Rotation rotation, Time timestamp),(dpy,config,draw,size_index,rotation,timestamp),return) +SDL_X11_SYM(void,XRRFreeScreenConfigInfo,(XRRScreenConfiguration *config),(config),) +#endif + /* end of SDL_x11sym.h ... */ diff -r e20dcef5647c -r 34cca785be57 src/video/x11/SDL_x11video.h --- a/src/video/x11/SDL_x11video.h Wed Mar 22 09:18:10 2006 +0000 +++ b/src/video/x11/SDL_x11video.h Wed Mar 22 11:13:58 2006 +0000 @@ -40,6 +40,9 @@ #if SDL_VIDEO_DRIVER_X11_XME #include "../Xext/extensions/xme.h" #endif +#if SDL_VIDEO_DRIVER_X11_XRANDR +#include +#endif #include "SDL_x11dyn.h" @@ -116,10 +119,16 @@ int use_xme; XiGMiscResolutionInfo saved_res; #endif +#if SDL_VIDEO_DRIVER_X11_XRANDR + XRRScreenConfiguration* screen_config; + int saved_size_id; + Rotation saved_rotation; +#endif int xinerama_x; int xinerama_y; int use_vidmode; + int use_xrandr; int currently_fullscreen; /* Automatic mode switching support (entering/leaving fullscreen) */ @@ -169,6 +178,10 @@ #define saved_view (this->hidden->saved_view) #define use_xme (this->hidden->use_xme) #define saved_res (this->hidden->saved_res) +#define use_xrandr (this->hidden->use_xrandr) +#define screen_config (this->hidden->screen_config) +#define saved_size_id (this->hidden->saved_size_id) +#define saved_rotation (this->hidden->saved_rotation) #define xinerama_x (this->hidden->xinerama_x) #define xinerama_y (this->hidden->xinerama_y) #define use_vidmode (this->hidden->use_vidmode)