2006-07-26 06:34:54 +00:00
/*
2011-04-08 13:03:26 -07:00
Simple DirectMedia Layer
2011-12-31 09:28:07 -05:00
Copyright ( C ) 1997 - 2012 Sam Lantinga < slouken @ libsdl . org >
2011-04-08 13:03:26 -07:00
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
2006-07-26 06:34:54 +00:00
*/
# include "SDL_config.h"
2011-03-12 13:21:57 -08:00
# if SDL_VIDEO_DRIVER_X11
2012-09-27 11:29:13 -07:00
# include "SDL_hints.h"
2006-07-26 06:34:54 +00:00
# include "SDL_x11video.h"
2012-10-03 12:04:30 -07:00
/*#define X11MODES_DEBUG*/
2006-07-26 06:34:54 +00:00
static int
get_visualinfo ( Display * display , int screen , XVisualInfo * vinfo )
{
const char * visual_id = SDL_getenv ( " SDL_VIDEO_X11_VISUALID " ) ;
int depth ;
/* Look for an exact visual, if requested */
if ( visual_id ) {
XVisualInfo * vi , template ;
int nvis ;
SDL_zero ( template ) ;
template . visualid = SDL_strtol ( visual_id , NULL , 0 ) ;
vi = XGetVisualInfo ( display , VisualIDMask , & template , & nvis ) ;
if ( vi ) {
* vinfo = * vi ;
XFree ( vi ) ;
return 0 ;
}
}
depth = DefaultDepth ( display , screen ) ;
2011-03-11 08:49:20 -08:00
if ( ( X11_UseDirectColorVisuals ( ) & &
XMatchVisualInfo ( display , screen , depth , DirectColor , vinfo ) ) | |
XMatchVisualInfo ( display , screen , depth , TrueColor , vinfo ) | |
2006-07-26 06:34:54 +00:00
XMatchVisualInfo ( display , screen , depth , PseudoColor , vinfo ) | |
XMatchVisualInfo ( display , screen , depth , StaticColor , vinfo ) ) {
return 0 ;
}
return - 1 ;
}
2011-02-04 18:05:20 -08:00
int
X11_GetVisualInfoFromVisual ( Display * display , Visual * visual , XVisualInfo * vinfo )
{
XVisualInfo * vi ;
int nvis ;
vinfo - > visualid = XVisualIDFromVisual ( visual ) ;
vi = XGetVisualInfo ( display , VisualIDMask , vinfo , & nvis ) ;
if ( vi ) {
* vinfo = * vi ;
XFree ( vi ) ;
return 0 ;
}
return - 1 ;
}
Uint32
2008-12-16 17:44:10 +00:00
X11_GetPixelFormatFromVisualInfo ( Display * display , XVisualInfo * vinfo )
2008-12-14 04:36:32 +00:00
{
if ( vinfo - > class = = DirectColor | | vinfo - > class = = TrueColor ) {
int bpp ;
Uint32 Rmask , Gmask , Bmask , Amask ;
Rmask = vinfo - > visual - > red_mask ;
Gmask = vinfo - > visual - > green_mask ;
Bmask = vinfo - > visual - > blue_mask ;
if ( vinfo - > depth = = 32 ) {
Amask = ( 0xFFFFFFFF & ~ ( Rmask | Gmask | Bmask ) ) ;
} else {
Amask = 0 ;
}
bpp = vinfo - > depth ;
if ( bpp = = 24 ) {
int i , n ;
XPixmapFormatValues * p = XListPixmapFormats ( display , & n ) ;
if ( p ) {
for ( i = 0 ; i < n ; + + i ) {
if ( p [ i ] . depth = = 24 ) {
bpp = p [ i ] . bits_per_pixel ;
break ;
}
}
XFree ( p ) ;
}
}
return SDL_MasksToPixelFormatEnum ( bpp , Rmask , Gmask , Bmask , Amask ) ;
}
if ( vinfo - > class = = PseudoColor | | vinfo - > class = = StaticColor ) {
switch ( vinfo - > depth ) {
case 8 :
return SDL_PIXELTYPE_INDEX8 ;
case 4 :
if ( BitmapBitOrder ( display ) = = LSBFirst ) {
return SDL_PIXELFORMAT_INDEX4LSB ;
} else {
return SDL_PIXELFORMAT_INDEX4MSB ;
}
break ;
case 1 :
if ( BitmapBitOrder ( display ) = = LSBFirst ) {
return SDL_PIXELFORMAT_INDEX1LSB ;
} else {
return SDL_PIXELFORMAT_INDEX1MSB ;
}
break ;
}
}
return SDL_PIXELFORMAT_UNKNOWN ;
}
2012-06-19 14:19:05 -03:00
# if SDL_VIDEO_DRIVER_X11_XINERAMA
static SDL_bool CheckXinerama ( Display * display , int * major , int * minor ) ;
# endif
2008-12-14 04:36:32 +00:00
2009-12-04 09:01:48 +00:00
int
2006-07-26 06:34:54 +00:00
X11_InitModes ( _THIS )
{
SDL_VideoData * data = ( SDL_VideoData * ) _this - > driverdata ;
2012-06-19 14:19:05 -03:00
int screen , screencount ;
2006-07-26 06:34:54 +00:00
2012-06-19 14:19:05 -03:00
# if SDL_VIDEO_DRIVER_X11_XINERAMA
int xinerama_major , xinerama_minor ;
XineramaScreenInfo * xinerama = NULL ;
/* Query Xinerama extention
* NOTE : This works with Nvidia Twinview correctly , but you need version 302.17 ( released on June 2012 )
* or newer of the Nvidia binary drivers
*/
if ( CheckXinerama ( data - > display , & xinerama_major , & xinerama_minor ) ) {
xinerama = XineramaQueryScreens ( data - > display , & screencount ) ;
}
2012-09-27 13:23:34 -07:00
if ( ! xinerama ) {
2012-06-19 14:19:05 -03:00
screencount = ScreenCount ( data - > display ) ;
}
# else
screencount = ScreenCount ( data - > display ) ;
# endif
for ( screen = 0 ; screen < screencount ; + + screen ) {
2006-07-26 06:34:54 +00:00
XVisualInfo vinfo ;
SDL_VideoDisplay display ;
SDL_DisplayData * displaydata ;
SDL_DisplayMode mode ;
2008-12-25 04:42:28 +00:00
XPixmapFormatValues * pixmapFormats ;
int i , n ;
2012-06-19 14:19:05 -03:00
# if SDL_VIDEO_DRIVER_X11_XINERAMA
if ( xinerama ) {
if ( get_visualinfo ( data - > display , 0 , & vinfo ) < 0 ) {
continue ;
}
}
else {
if ( get_visualinfo ( data - > display , screen , & vinfo ) < 0 ) {
continue ;
}
}
# else
2006-07-26 06:34:54 +00:00
if ( get_visualinfo ( data - > display , screen , & vinfo ) < 0 ) {
continue ;
}
2012-06-19 14:19:05 -03:00
# endif
2006-07-26 06:34:54 +00:00
2008-12-14 04:36:32 +00:00
mode . format = X11_GetPixelFormatFromVisualInfo ( data - > display , & vinfo ) ;
2011-02-01 21:23:43 -08:00
if ( SDL_ISPIXELFORMAT_INDEXED ( mode . format ) ) {
/* We don't support palettized modes now */
continue ;
}
2012-06-19 14:19:05 -03:00
# if SDL_VIDEO_DRIVER_X11_XINERAMA
if ( xinerama ) {
mode . w = xinerama [ screen ] . width ;
mode . h = xinerama [ screen ] . height ;
}
else {
mode . w = DisplayWidth ( data - > display , screen ) ;
mode . h = DisplayHeight ( data - > display , screen ) ;
}
# else
2006-07-26 06:34:54 +00:00
mode . w = DisplayWidth ( data - > display , screen ) ;
mode . h = DisplayHeight ( data - > display , screen ) ;
2012-06-19 14:19:05 -03:00
# endif
2006-07-26 06:34:54 +00:00
mode . refresh_rate = 0 ;
mode . driverdata = NULL ;
2012-09-27 10:41:16 -07:00
displaydata = ( SDL_DisplayData * ) SDL_calloc ( 1 , sizeof ( * displaydata ) ) ;
2006-07-26 06:34:54 +00:00
if ( ! displaydata ) {
continue ;
}
2012-06-19 14:19:05 -03:00
# if SDL_VIDEO_DRIVER_X11_XINERAMA
/* Most of SDL's calls to X11 are unwaware of Xinerama, and to X11 standard calls, when Xinerama is active,
* there ' s only one screen available . So we force the screen number to zero and
* let Xinerama specific code handle specific functionality using displaydata - > xinerama_info
*/
if ( xinerama ) {
displaydata - > screen = 0 ;
displaydata - > use_xinerama = xinerama_major * 100 + xinerama_minor ;
displaydata - > xinerama_info = xinerama [ screen ] ;
2012-09-28 14:22:18 -07:00
displaydata - > xinerama_screen = screen ;
2012-06-19 14:19:05 -03:00
}
else displaydata - > screen = screen ;
# else
2006-07-26 06:34:54 +00:00
displaydata - > screen = screen ;
2012-06-19 14:19:05 -03:00
# endif
2006-07-26 06:34:54 +00:00
displaydata - > visual = vinfo . visual ;
2006-07-27 06:53:23 +00:00
displaydata - > depth = vinfo . depth ;
2006-07-26 06:34:54 +00:00
2008-12-25 05:26:29 +00:00
displaydata - > scanline_pad = SDL_BYTESPERPIXEL ( mode . format ) * 8 ;
2008-12-25 04:42:28 +00:00
pixmapFormats = XListPixmapFormats ( data - > display , & n ) ;
if ( pixmapFormats ) {
for ( i = 0 ; i < n ; + + i ) {
if ( pixmapFormats [ i ] . depth = = displaydata - > depth ) {
displaydata - > scanline_pad = pixmapFormats [ i ] . scanline_pad ;
break ;
}
}
XFree ( pixmapFormats ) ;
}
2006-07-26 06:34:54 +00:00
SDL_zero ( display ) ;
display . desktop_mode = mode ;
display . current_mode = mode ;
display . driverdata = displaydata ;
SDL_AddVideoDisplay ( & display ) ;
}
2012-06-19 14:19:05 -03:00
# if SDL_VIDEO_DRIVER_X11_XINERAMA
if ( xinerama ) XFree ( xinerama ) ;
# endif
2009-12-04 09:01:48 +00:00
if ( _this - > num_displays = = 0 ) {
SDL_SetError ( " No available displays " ) ;
return - 1 ;
}
return 0 ;
2006-07-26 06:34:54 +00:00
}
2008-12-16 17:41:03 +00:00
/* Global for the error handler */
int vm_event , vm_error = - 1 ;
# if SDL_VIDEO_DRIVER_X11_XINERAMA
static SDL_bool
2008-12-16 17:44:10 +00:00
CheckXinerama ( Display * display , int * major , int * minor )
2008-12-16 17:41:03 +00:00
{
2011-10-24 15:33:58 -04:00
int event_base = 0 ;
int error_base = 0 ;
2008-12-16 17:41:03 +00:00
const char * env ;
/* Default the extension not available */
* major = * minor = 0 ;
/* Allow environment override */
2012-09-27 11:29:13 -07:00
env = SDL_GetHint ( SDL_HINT_VIDEO_X11_XINERAMA ) ;
2008-12-16 17:41:03 +00:00
if ( env & & ! SDL_atoi ( env ) ) {
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
2012-09-27 11:29:13 -07:00
printf ( " Xinerama disabled due to hint \n " ) ;
2012-09-27 10:41:16 -07:00
# endif
2008-12-16 17:41:03 +00:00
return SDL_FALSE ;
}
2011-02-28 09:01:53 -08:00
if ( ! SDL_X11_HAVE_XINERAMA ) {
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
printf ( " Xinerama support not available \n " ) ;
# endif
2011-02-28 09:01:53 -08:00
return SDL_FALSE ;
}
2008-12-16 17:41:03 +00:00
/* Query the extension version */
2011-10-24 15:33:58 -04:00
if ( ! XineramaQueryExtension ( display , & event_base , & error_base ) | |
! XineramaQueryVersion ( display , major , minor ) | |
2011-02-28 09:01:53 -08:00
! XineramaIsActive ( display ) ) {
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
printf ( " Xinerama not active on the display \n " ) ;
# endif
2008-12-16 17:41:03 +00:00
return SDL_FALSE ;
}
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
printf ( " Xinerama available! \n " ) ;
# endif
2008-12-16 17:41:03 +00:00
return SDL_TRUE ;
}
# endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
# if SDL_VIDEO_DRIVER_X11_XRANDR
static SDL_bool
2008-12-16 17:44:10 +00:00
CheckXRandR ( Display * display , int * major , int * minor )
2008-12-16 17:41:03 +00:00
{
const char * env ;
/* Default the extension not available */
* major = * minor = 0 ;
/* Allow environment override */
2012-09-27 11:29:13 -07:00
env = SDL_GetHint ( SDL_HINT_VIDEO_X11_XRANDR ) ;
2008-12-16 17:41:03 +00:00
if ( env & & ! SDL_atoi ( env ) ) {
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
2012-09-27 11:29:13 -07:00
printf ( " XRandR disabled due to hint \n " ) ;
2012-09-27 10:41:16 -07:00
# endif
2008-12-16 17:41:03 +00:00
return SDL_FALSE ;
}
if ( ! SDL_X11_HAVE_XRANDR ) {
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
printf ( " XRandR support not available \n " ) ;
# endif
2008-12-16 17:41:03 +00:00
return SDL_FALSE ;
}
/* Query the extension version */
if ( ! XRRQueryVersion ( display , major , minor ) ) {
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
printf ( " XRandR not active on the display \n " ) ;
# endif
2008-12-16 17:41:03 +00:00
return SDL_FALSE ;
}
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
printf ( " XRandR available! \n " ) ;
# endif
2008-12-16 17:41:03 +00:00
return SDL_TRUE ;
}
2012-10-03 11:33:09 -07:00
# define XRANDR_ROTATION_LEFT (1 << 1)
# define XRANDR_ROTATION_RIGHT (1 << 3)
static void
get_xrandr_mode_size ( XRRModeInfo * mode , Rotation rotation , int * w , int * h )
{
if ( rotation & ( XRANDR_ROTATION_LEFT | XRANDR_ROTATION_RIGHT ) ) {
* w = mode - > height ;
* h = mode - > width ;
} else {
* w = mode - > width ;
* h = mode - > height ;
}
}
2008-12-16 17:41:03 +00:00
# endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
2011-02-28 09:01:53 -08:00
# if SDL_VIDEO_DRIVER_X11_XVIDMODE
2008-12-16 17:41:03 +00:00
static SDL_bool
2008-12-16 17:44:10 +00:00
CheckVidMode ( Display * display , int * major , int * minor )
2008-12-16 17:41:03 +00:00
{
const char * env ;
/* Default the extension not available */
* major = * minor = 0 ;
/* Allow environment override */
2012-09-27 11:29:13 -07:00
env = SDL_GetHint ( SDL_HINT_VIDEO_X11_XVIDMODE ) ;
2008-12-16 17:41:03 +00:00
if ( env & & ! SDL_atoi ( env ) ) {
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
2012-09-27 11:29:13 -07:00
printf ( " XVidMode disabled due to hint \n " ) ;
2012-09-27 10:41:16 -07:00
# endif
2008-12-16 17:41:03 +00:00
return SDL_FALSE ;
}
2008-12-16 17:44:10 +00:00
2011-02-28 09:01:53 -08:00
if ( ! SDL_X11_HAVE_XVIDMODE ) {
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
printf ( " XVidMode support not available \n " ) ;
# endif
2011-02-28 09:01:53 -08:00
return SDL_FALSE ;
}
2008-12-16 17:41:03 +00:00
/* Query the extension version */
vm_error = - 1 ;
2011-02-28 09:01:53 -08:00
if ( ! XF86VidModeQueryExtension ( display , & vm_event , & vm_error )
| | ! XF86VidModeQueryVersion ( display , major , minor ) ) {
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
printf ( " XVidMode not active on the display \n " ) ;
# endif
2008-12-16 17:41:03 +00:00
return SDL_FALSE ;
}
2012-09-27 10:41:16 -07:00
# ifdef X11MODES_DEBUG
printf ( " XVidMode available! \n " ) ;
# endif
2008-12-16 17:41:03 +00:00
return SDL_TRUE ;
}
2010-07-13 23:11:10 -07:00
static
2011-02-28 09:01:53 -08:00
Bool XF86VidModeGetModeInfo ( Display * dpy , int scr ,
XF86VidModeModeInfo * info )
2008-12-16 17:41:03 +00:00
{
Bool retval ;
int dotclock ;
2011-02-28 09:01:53 -08:00
XF86VidModeModeLine l ;
2008-12-16 17:41:03 +00:00
SDL_zerop ( info ) ;
SDL_zero ( l ) ;
2011-02-28 09:01:53 -08:00
retval = XF86VidModeGetModeLine ( dpy , scr , & dotclock , & l ) ;
2008-12-16 17:41:03 +00:00
info - > dotclock = dotclock ;
info - > hdisplay = l . hdisplay ;
info - > hsyncstart = l . hsyncstart ;
info - > hsyncend = l . hsyncend ;
info - > htotal = l . htotal ;
info - > hskew = l . hskew ;
info - > vdisplay = l . vdisplay ;
info - > vsyncstart = l . vsyncstart ;
info - > vsyncend = l . vsyncend ;
info - > vtotal = l . vtotal ;
info - > flags = l . flags ;
info - > privsize = l . privsize ;
info - > private = l . private ;
return retval ;
}
static int
2011-02-28 09:01:53 -08:00
calculate_rate ( XF86VidModeModeInfo * info )
2008-12-16 17:41:03 +00:00
{
2008-12-16 17:44:10 +00:00
return ( info - > htotal
& & info - > vtotal ) ? ( 1000 * info - > dotclock / ( info - > htotal *
info - > vtotal ) ) : 0 ;
2008-12-16 17:41:03 +00:00
}
static void
2008-12-16 17:44:10 +00:00
save_mode ( Display * display , SDL_DisplayData * data )
2008-12-16 17:41:03 +00:00
{
2011-02-28 09:01:53 -08:00
XF86VidModeGetModeInfo ( display , data - > screen ,
& data - > saved_mode ) ;
XF86VidModeGetViewPort ( display , data - > screen ,
& data - > saved_view . x ,
& data - > saved_view . y ) ;
2008-12-16 17:41:03 +00:00
}
2010-07-13 23:11:10 -07:00
/*
2008-12-16 17:41:03 +00:00
static void
2008-12-16 17:44:10 +00:00
restore_mode ( Display * display , SDL_DisplayData * data )
2008-12-16 17:41:03 +00:00
{
2011-02-28 09:01:53 -08:00
XF86VidModeModeInfo mode ;
2008-12-16 17:41:03 +00:00
2011-02-28 09:01:53 -08:00
if ( XF86VidModeGetModeInfo ( display , data - > screen , & mode ) ) {
2008-12-16 17:41:03 +00:00
if ( SDL_memcmp ( & mode , & data - > saved_mode , sizeof ( mode ) ) ! = 0 ) {
2011-02-28 09:01:53 -08:00
XF86VidModeSwitchToMode ( display , data - > screen , & data - > saved_mode ) ;
2008-12-16 17:41:03 +00:00
}
}
if ( ( data - > saved_view . x ! = 0 ) | | ( data - > saved_view . y ! = 0 ) ) {
2011-02-28 09:01:53 -08:00
XF86VidModeSetViewPort ( display , data - > screen ,
data - > saved_view . x ,
data - > saved_view . y ) ;
2008-12-16 17:41:03 +00:00
}
}
2010-07-13 23:11:10 -07:00
*/
2011-02-28 09:01:53 -08:00
# endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
2008-12-16 17:41:03 +00:00
2006-07-26 06:34:54 +00:00
void
2009-12-01 05:57:15 +00:00
X11_GetDisplayModes ( _THIS , SDL_VideoDisplay * sdl_display )
2006-07-26 06:34:54 +00:00
{
2008-12-14 04:36:32 +00:00
Display * display = ( ( SDL_VideoData * ) _this - > driverdata ) - > display ;
2009-12-01 05:57:15 +00:00
SDL_DisplayData * data = ( SDL_DisplayData * ) sdl_display - > driverdata ;
2008-12-16 17:41:03 +00:00
# if SDL_VIDEO_DRIVER_X11_XRANDR
int xrandr_major , xrandr_minor ;
int nsizes , nrates ;
XRRScreenSize * sizes ;
short * rates ;
# endif
2011-02-28 09:01:53 -08:00
# if SDL_VIDEO_DRIVER_X11_XVIDMODE
2008-12-16 17:41:03 +00:00
int vm_major , vm_minor ;
int nmodes ;
2011-02-28 09:01:53 -08:00
XF86VidModeModeInfo * * modes ;
2008-12-16 17:41:03 +00:00
# endif
int screen_w ;
int screen_h ;
2006-07-26 06:34:54 +00:00
SDL_DisplayMode mode ;
2008-12-14 04:36:32 +00:00
2008-12-16 17:41:03 +00:00
/* Unfortunately X11 requires the window to be created with the correct
* visual and depth ahead of time , but the SDL API allows you to create
* a window before setting the fullscreen display mode . This means that
* we have to use the same format for all windows and all display modes .
* ( or support recreating the window with a new visual behind the scenes )
*/
2009-12-01 05:57:15 +00:00
mode . format = sdl_display - > current_mode . format ;
2008-12-16 17:41:03 +00:00
mode . driverdata = NULL ;
screen_w = DisplayWidth ( display , data - > screen ) ;
screen_h = DisplayHeight ( display , data - > screen ) ;
# if SDL_VIDEO_DRIVER_X11_XINERAMA
2012-06-19 14:19:05 -03:00
if ( data - > use_xinerama ) {
/* Add the full (both screens combined) xinerama mode only on the display that starts at 0,0 */
if ( ! data - > xinerama_info . x_org & & ! data - > xinerama_info . y_org & &
( screen_w > data - > xinerama_info . width | | screen_h > data - > xinerama_info . height ) ) {
mode . w = screen_w ;
mode . h = screen_h ;
2008-12-16 17:41:03 +00:00
mode . refresh_rate = 0 ;
2009-12-01 05:57:15 +00:00
SDL_AddDisplayMode ( sdl_display , & mode ) ;
2008-12-16 17:41:03 +00:00
}
2012-06-19 14:19:05 -03:00
/* Add the head xinerama mode */
mode . w = data - > xinerama_info . width ;
mode . h = data - > xinerama_info . height ;
mode . refresh_rate = 0 ;
SDL_AddDisplayMode ( sdl_display , & mode ) ;
2008-12-16 17:41:03 +00:00
}
# endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
# if SDL_VIDEO_DRIVER_X11_XRANDR
/* XRandR */
/* require at least XRandR v1.0 (arbitrary) */
2008-12-16 17:44:10 +00:00
if ( CheckXRandR ( display , & xrandr_major , & xrandr_minor )
& & xrandr_major > = 1 ) {
2008-12-16 17:41:03 +00:00
# ifdef X11MODES_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 .
2008-12-16 17:44:10 +00:00
*/
data - > screen_config =
XRRGetScreenInfo ( display , RootWindow ( display , data - > screen ) ) ;
2008-12-16 17:41:03 +00:00
/* retrieve the list of resolution */
sizes = XRRConfigSizes ( data - > screen_config , & nsizes ) ;
if ( nsizes > 0 ) {
int i , j ;
2008-12-16 17:44:10 +00:00
for ( i = 0 ; i < nsizes ; i + + ) {
2008-12-16 17:41:03 +00:00
mode . w = sizes [ i ] . width ;
mode . h = sizes [ i ] . height ;
rates = XRRConfigRates ( data - > screen_config , i , & nrates ) ;
for ( j = 0 ; j < nrates ; + + j ) {
mode . refresh_rate = rates [ j ] ;
# ifdef X11MODES_DEBUG
2008-12-16 17:44:10 +00:00
fprintf ( stderr ,
" XRANDR: mode = %4d[%d], w = %4d, h = %4d, rate = %4d \n " ,
2008-12-16 17:41:03 +00:00
i , j , mode . w , mode . h , mode . refresh_rate ) ;
# endif
2009-12-01 05:57:15 +00:00
SDL_AddDisplayMode ( sdl_display , & mode ) ;
2008-12-16 17:41:03 +00:00
}
}
data - > use_xrandr = xrandr_major * 100 + xrandr_minor ;
2008-12-16 17:44:10 +00:00
data - > saved_size =
XRRConfigCurrentConfiguration ( data - > screen_config ,
& data - > saved_rotation ) ;
2008-12-16 17:41:03 +00:00
data - > saved_rate = XRRConfigCurrentRate ( data - > screen_config ) ;
}
}
# endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
2011-02-28 09:01:53 -08:00
# if SDL_VIDEO_DRIVER_X11_XVIDMODE
2008-12-16 17:41:03 +00:00
/* XVidMode */
if ( ! data - > use_xrandr & &
# if SDL_VIDEO_DRIVER_X11_XINERAMA
( ! data - > use_xinerama | | data - > xinerama_info . screen_number = = 0 ) & &
# endif
CheckVidMode ( display , & vm_major , & vm_minor ) & &
2011-02-28 09:01:53 -08:00
XF86VidModeGetAllModeLines ( display , data - > screen , & nmodes , & modes ) ) {
2008-12-16 17:41:03 +00:00
int i ;
# ifdef X11MODES_DEBUG
printf ( " VidMode modes: (unsorted) \n " ) ;
for ( i = 0 ; i < nmodes ; + + i ) {
printf ( " Mode %d: %d x %d @ %d \n " , i ,
2008-12-16 17:44:10 +00:00
modes [ i ] - > hdisplay , modes [ i ] - > vdisplay ,
calculate_rate ( modes [ i ] ) ) ;
2008-12-16 17:41:03 +00:00
}
# endif
for ( i = 0 ; i < nmodes ; + + i ) {
mode . w = modes [ i ] - > hdisplay ;
mode . h = modes [ i ] - > vdisplay ;
mode . refresh_rate = calculate_rate ( modes [ i ] ) ;
2009-12-01 05:57:15 +00:00
SDL_AddDisplayMode ( sdl_display , & mode ) ;
2008-12-16 17:41:03 +00:00
}
XFree ( modes ) ;
data - > use_vidmode = vm_major * 100 + vm_minor ;
save_mode ( display , data ) ;
}
2011-02-28 09:01:53 -08:00
# endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
2008-12-16 17:41:03 +00:00
if ( ! data - > use_xrandr & & ! data - > use_vidmode ) {
mode . w = screen_w ;
mode . h = screen_h ;
mode . refresh_rate = 0 ;
2009-12-01 05:57:15 +00:00
SDL_AddDisplayMode ( sdl_display , & mode ) ;
2008-12-16 17:44:10 +00:00
}
2008-12-16 17:41:03 +00:00
# ifdef X11MODES_DEBUG
if ( data - > use_xinerama ) {
printf ( " Xinerama is enabled \n " ) ;
}
if ( data - > use_xrandr ) {
printf ( " XRandR is enabled \n " ) ;
}
if ( data - > use_vidmode ) {
printf ( " VidMode is enabled \n " ) ;
}
# endif /* X11MODES_DEBUG */
}
static void
2008-12-16 17:44:10 +00:00
get_real_resolution ( Display * display , SDL_DisplayData * data , int * w , int * h ,
int * rate )
2008-12-16 17:41:03 +00:00
{
# if SDL_VIDEO_DRIVER_X11_XRANDR
if ( data - > use_xrandr ) {
int nsizes ;
XRRScreenSize * sizes ;
2008-12-16 17:44:10 +00:00
2008-12-16 17:41:03 +00:00
sizes = XRRConfigSizes ( data - > screen_config , & nsizes ) ;
if ( nsizes > 0 ) {
int cur_size ;
Rotation cur_rotation ;
2008-12-16 17:44:10 +00:00
cur_size =
XRRConfigCurrentConfiguration ( data - > screen_config ,
& cur_rotation ) ;
2008-12-16 17:41:03 +00:00
* w = sizes [ cur_size ] . width ;
* h = sizes [ cur_size ] . height ;
* rate = XRRConfigCurrentRate ( data - > screen_config ) ;
# ifdef X11MODES_DEBUG
2008-12-16 17:44:10 +00:00
fprintf ( stderr ,
" XRANDR: get_real_resolution: w = %d, h = %d, rate = %d \n " ,
* w , * h , * rate ) ;
2008-12-16 17:41:03 +00:00
# endif
return ;
}
}
# endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
2011-02-28 09:01:53 -08:00
# if SDL_VIDEO_DRIVER_X11_XVIDMODE
2008-12-16 17:41:03 +00:00
if ( data - > use_vidmode ) {
2011-02-28 09:01:53 -08:00
XF86VidModeModeInfo mode ;
2008-12-16 17:41:03 +00:00
2011-02-28 09:01:53 -08:00
if ( XF86VidModeGetModeInfo ( display , data - > screen , & mode ) ) {
2008-12-16 17:41:03 +00:00
* w = mode . hdisplay ;
* h = mode . vdisplay ;
* rate = calculate_rate ( & mode ) ;
return ;
}
}
2011-02-28 09:01:53 -08:00
# endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
2008-12-16 17:41:03 +00:00
2012-09-28 00:40:47 -07:00
# if SDL_VIDEO_DRIVER_X11_XINERAMA
if ( data - > use_xinerama ) {
2012-09-28 11:51:16 -07:00
int screencount ;
XineramaScreenInfo * xinerama ;
/* Update the current screen layout information */
xinerama = XineramaQueryScreens ( display , & screencount ) ;
2012-09-28 14:22:18 -07:00
if ( xinerama & & data - > xinerama_screen < screencount ) {
data - > xinerama_info = xinerama [ data - > xinerama_screen ] ;
2012-09-28 11:51:16 -07:00
}
if ( xinerama ) XFree ( xinerama ) ;
2012-09-28 00:40:47 -07:00
* w = data - > xinerama_info . width ;
* h = data - > xinerama_info . height ;
* rate = 0 ;
return ;
}
# endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
2008-12-16 17:41:03 +00:00
* w = DisplayWidth ( display , data - > screen ) ;
* h = DisplayHeight ( display , data - > screen ) ;
* rate = 0 ;
}
static void
2008-12-16 17:44:10 +00:00
set_best_resolution ( Display * display , SDL_DisplayData * data , int w , int h ,
int rate )
2008-12-16 17:41:03 +00:00
{
int real_w , real_h , real_rate ;
/* check current mode so we can avoid uneccessary mode changes */
get_real_resolution ( display , data , & real_w , & real_h , & real_rate ) ;
2012-06-19 14:19:05 -03:00
2012-09-28 00:40:47 -07:00
if ( w = = real_w & & h = = real_h & & ( ! rate | | ! real_rate | | rate = = real_rate ) ) {
2012-06-19 14:19:05 -03:00
return ;
}
2008-12-16 17:41:03 +00:00
# if SDL_VIDEO_DRIVER_X11_XRANDR
if ( data - > use_xrandr ) {
# ifdef X11MODES_DEBUG
fprintf ( stderr , " XRANDR: set_best_resolution(): w = %d, h = %d \n " ,
w , h ) ;
# endif
int i , nsizes , nrates ;
int best ;
int best_rate ;
XRRScreenSize * sizes ;
short * rates ;
2012-10-03 11:33:09 -07:00
# if SDL_VIDEO_DRIVER_X11_XINERAMA
if ( data - > use_xrandr > = 102 & & data - > use_xinerama ) {
/* See http://cgit.freedesktop.org/xorg/app/xrandr/tree/xrandr.c for the rationale behind this */
/* Note by Gabriel: the refresh rate is ignored in this code, and seeing that both xrandr
* and nvidia - settings don ' t provide a way to set it when Xinerama is enabled , it may not be possible to set it */
int screencount ;
XineramaScreenInfo * xinerama = NULL ;
XRRScreenResources * res ;
/* Update the current screen layout information */
xinerama = XineramaQueryScreens ( display , & screencount ) ;
if ( xinerama & & data - > xinerama_screen < screencount ) {
data - > xinerama_info = xinerama [ data - > xinerama_screen ] ;
2008-12-16 17:41:03 +00:00
}
2012-10-03 11:33:09 -07:00
if ( xinerama ) XFree ( xinerama ) ;
res = XRRGetScreenResources ( display , RootWindow ( display , data - > screen ) ) ;
if ( res ) {
XRROutputInfo * output_info = NULL ;
XRRCrtcInfo * crtc = NULL ;
XRRModeInfo * mode_info , * best_mode_info = NULL ;
int mode_index = 0 , output_mode_index = 0 , output ;
int mode_w , mode_h , best_w = 0 , best_h = 0 ;
for ( output = 0 ; output < res - > noutput ; output + + ) {
output_info = XRRGetOutputInfo ( display , res , res - > outputs [ output ] ) ;
if ( ! output_info | | ! output_info - > crtc ) {
XRRFreeOutputInfo ( output_info ) ;
continue ;
}
crtc = XRRGetCrtcInfo ( display , res , output_info - > crtc ) ;
if ( ! crtc | | data - > xinerama_info . x_org ! = crtc - > x | | data - > xinerama_info . y_org ! = crtc - > y ) {
XRRFreeCrtcInfo ( crtc ) ;
continue ;
}
/* The CRT offset matches the Xinerama mode, let's hope it's the right one! */
# ifdef X11MODES_DEBUG
2012-10-03 12:04:30 -07:00
fprintf ( stderr , " XRANDR: set_best_resolution, matched Xinerama screen %d to CRT %ld at %d,%d \n " ,
2012-10-03 11:33:09 -07:00
data - > xinerama_info . screen_number , output_info - > crtc , crtc - > x , crtc - > y ) ;
# endif
/* Find out the best mode we can use */
for ( mode_index = 0 ; mode_index < res - > nmode ; mode_index + + ) {
mode_info = & res - > modes [ mode_index ] ;
get_xrandr_mode_size ( mode_info , crtc - > rotation , & mode_w , & mode_h ) ;
if ( mode_w > = w & & mode_h > = h ) {
/* This may be a useful mode, check out if it belongs to the correct output */
# ifdef X11MODES_DEBUG
fprintf ( stderr , " Evaluating valid mode %d, w: %d, h: %d \n " , mode_index , mode_info - > width , mode_info - > height ) ;
# endif
for ( output_mode_index = 0 ; output_mode_index < output_info - > nmode ; output_mode_index + + ) {
if ( output_info - > modes [ output_mode_index ] = = mode_info - > id ) {
break ;
}
}
if ( output_mode_index < output_info - > nmode ) {
# ifdef X11MODES_DEBUG
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 ) ;
# endif
/* 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 */
if ( ! best_mode_info | | mode_w < best_w | | ( mode_w = = best_w & & mode_h < best_h ) ) {
best_mode_info = mode_info ;
best_w = mode_w ;
best_h = mode_h ;
}
}
# ifdef X11MODES_DEBUG
else {
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 ) ;
}
# endif
}
}
if ( best_mode_info ) {
# ifdef X11MODES_DEBUG
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 " ,
best_mode_info - > width , best_mode_info - > height , output , crtc - > x , crtc - > y , data - > xinerama_info . screen_number ) ;
# endif
XGrabServer ( display ) ;
XRRSetCrtcConfig ( display , res , output_info - > crtc , CurrentTime ,
crtc - > x , crtc - > y , best_mode_info - > id , crtc - > rotation ,
& res - > outputs [ output ] , 1 ) ;
/* TODO: Handle screen rotations, should we call XRRSetCrtcTransform if Xrandr >=1.3 ? */
XUngrabServer ( display ) ;
} else {
/* If we reach here, we have found the right screen but no valid best mode */
SDL_SetError ( " The selected screen can't support a resolution of the size desired " ) ;
}
XRRFreeCrtcInfo ( crtc ) ;
XRRFreeOutputInfo ( output_info ) ;
break ;
}
XRRFreeScreenResources ( res ) ;
2008-12-16 17:41:03 +00:00
}
}
2012-10-03 11:33:09 -07:00
else
# endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
{
/* Use older xrandr functions that don't play along very nicely with multi monitors setups */
/* find the smallest resolution that is at least as big as the user requested */
best = - 1 ;
sizes = XRRConfigSizes ( data - > screen_config , & nsizes ) ;
for ( i = 0 ; i < nsizes ; + + i ) {
if ( sizes [ i ] . width < w | | sizes [ i ] . height < h ) {
continue ;
}
if ( sizes [ i ] . width = = w & & sizes [ i ] . height = = h ) {
best = i ;
2008-12-16 17:41:03 +00:00
break ;
}
2012-10-03 11:33:09 -07:00
if ( best = = - 1 | |
( sizes [ i ] . width < sizes [ best ] . width ) | |
( sizes [ i ] . width = = sizes [ best ] . width
& & sizes [ i ] . height < sizes [ best ] . height ) ) {
best = i ;
}
}
if ( best > = 0 ) {
best_rate = 0 ;
rates = XRRConfigRates ( data - > screen_config , best , & nrates ) ;
for ( i = 0 ; i < nrates ; + + i ) {
if ( rates [ i ] = = rate ) {
best_rate = rate ;
break ;
2008-12-16 17:41:03 +00:00
}
2012-10-03 11:33:09 -07:00
if ( ! rate ) {
/* Higher is better, right? */
if ( rates [ i ] > best_rate ) {
best_rate = rates [ i ] ;
}
} else {
if ( SDL_abs ( rates [ i ] - rate ) < SDL_abs ( best_rate - rate ) ) {
best_rate = rates [ i ] ;
}
2008-12-16 17:41:03 +00:00
}
}
2012-10-03 11:33:09 -07:00
XRRSetScreenConfigAndRate ( display , data - > screen_config ,
RootWindow ( display , data - > screen ) , best ,
data - > saved_rotation , best_rate ,
CurrentTime ) ;
2008-12-16 17:41:03 +00:00
}
}
return ;
}
# endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
2011-02-28 09:01:53 -08:00
# if SDL_VIDEO_DRIVER_X11_XVIDMODE
2008-12-16 17:41:03 +00:00
if ( data - > use_vidmode ) {
2011-02-28 09:01:53 -08:00
XF86VidModeModeInfo * * modes ;
2008-12-16 17:41:03 +00:00
int i , nmodes ;
int best ;
2011-02-28 09:01:53 -08:00
if ( XF86VidModeGetAllModeLines ( display , data - > screen , & nmodes , & modes ) ) {
2008-12-16 17:41:03 +00:00
best = - 1 ;
for ( i = 0 ; i < nmodes ; + + i ) {
if ( modes [ i ] - > hdisplay < w | | modes [ i ] - > vdisplay < h ) {
continue ;
}
if ( best = = - 1 | |
( modes [ i ] - > hdisplay < modes [ best ] - > hdisplay ) | |
2008-12-16 17:44:10 +00:00
( modes [ i ] - > hdisplay = = modes [ best ] - > hdisplay
& & modes [ i ] - > vdisplay < modes [ best ] - > vdisplay ) ) {
2008-12-16 17:41:03 +00:00
best = i ;
continue ;
}
if ( ( modes [ i ] - > hdisplay = = modes [ best ] - > hdisplay ) & &
( modes [ i ] - > vdisplay = = modes [ best ] - > vdisplay ) ) {
if ( ! rate ) {
/* Higher is better, right? */
2008-12-16 17:44:10 +00:00
if ( calculate_rate ( modes [ i ] ) >
calculate_rate ( modes [ best ] ) ) {
2008-12-16 17:41:03 +00:00
best = i ;
}
} else {
2008-12-16 17:44:10 +00:00
if ( SDL_abs ( calculate_rate ( modes [ i ] ) - rate ) <
SDL_abs ( calculate_rate ( modes [ best ] ) - rate ) ) {
2008-12-16 17:41:03 +00:00
best = i ;
}
}
}
}
if ( best > = 0 ) {
# ifdef X11MODES_DEBUG
printf ( " Best Mode %d: %d x %d @ %d \n " , best ,
2008-12-16 17:44:10 +00:00
modes [ best ] - > hdisplay , modes [ best ] - > vdisplay ,
calculate_rate ( modes [ best ] ) ) ;
2008-12-16 17:41:03 +00:00
# endif
2011-02-28 09:01:53 -08:00
XF86VidModeSwitchToMode ( display , data - > screen , modes [ best ] ) ;
2008-12-16 17:41:03 +00:00
}
XFree ( modes ) ;
}
return ;
}
2011-02-28 09:01:53 -08:00
# endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
2006-07-26 06:34:54 +00:00
}
int
2009-12-01 05:57:15 +00:00
X11_SetDisplayMode ( _THIS , SDL_VideoDisplay * sdl_display , SDL_DisplayMode * mode )
2006-07-26 06:34:54 +00:00
{
2008-12-16 17:41:03 +00:00
Display * display = ( ( SDL_VideoData * ) _this - > driverdata ) - > display ;
2009-12-01 05:57:15 +00:00
SDL_DisplayData * data = ( SDL_DisplayData * ) sdl_display - > driverdata ;
2008-12-16 17:41:03 +00:00
set_best_resolution ( display , data , mode - > w , mode - > h , mode - > refresh_rate ) ;
return 0 ;
2006-07-26 06:34:54 +00:00
}
void
X11_QuitModes ( _THIS )
{
}
2012-06-19 14:19:05 -03:00
int
X11_GetDisplayBounds ( _THIS , SDL_VideoDisplay * sdl_display , SDL_Rect * rect )
{
2012-09-28 11:51:16 -07:00
Display * display = ( ( SDL_VideoData * ) _this - > driverdata ) - > display ;
2012-06-19 14:19:05 -03:00
SDL_DisplayData * data = ( SDL_DisplayData * ) sdl_display - > driverdata ;
2012-09-28 11:51:16 -07:00
int real_rate ;
rect - > x = 0 ;
rect - > y = 0 ;
get_real_resolution ( display , data , & rect - > w , & rect - > h , & real_rate ) ;
2012-06-19 14:19:05 -03:00
# if SDL_VIDEO_DRIVER_X11_XINERAMA
2012-09-28 11:51:16 -07:00
if ( data - > use_xinerama ) {
2012-06-19 14:19:05 -03:00
rect - > x = data - > xinerama_info . x_org ;
rect - > y = data - > xinerama_info . y_org ;
}
# endif
2012-09-27 13:23:34 -07:00
return 0 ;
2012-06-19 14:19:05 -03:00
}
2011-03-12 13:21:57 -08:00
# endif /* SDL_VIDEO_DRIVER_X11 */
2006-07-26 06:34:54 +00:00
/* vi: set ts=4 sw=4 expandtab: */