21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_X11
46 get_visualinfo(Display * display,
int screen, XVisualInfo * vinfo)
48 const char *visual_id =
SDL_getenv(
"SDL_VIDEO_X11_VISUALID");
53 XVisualInfo *vi,
template;
58 vi = X11_XGetVisualInfo(display, VisualIDMask, &
template, &nvis);
68 X11_XMatchVisualInfo(display,
screen,
depth, DirectColor, vinfo)) ||
69 X11_XMatchVisualInfo(display,
screen,
depth, TrueColor, vinfo) ||
70 X11_XMatchVisualInfo(display,
screen,
depth, PseudoColor, vinfo) ||
71 X11_XMatchVisualInfo(display,
screen,
depth, StaticColor, vinfo)) {
83 vinfo->visualid = X11_XVisualIDFromVisual(visual);
84 vi = X11_XGetVisualInfo(display, VisualIDMask, vinfo, &nvis);
96 if (vinfo->class == DirectColor || vinfo->class == TrueColor) {
98 Uint32 Rmask, Gmask, Bmask, Amask;
100 Rmask = vinfo->visual->red_mask;
101 Gmask = vinfo->visual->green_mask;
102 Bmask = vinfo->visual->blue_mask;
103 if (vinfo->depth == 32) {
104 Amask = (0xFFFFFFFF & ~(Rmask | Gmask | Bmask));
112 XPixmapFormatValues *
p = X11_XListPixmapFormats(display, &
n);
114 for (
i = 0;
i <
n; ++
i) {
116 bpp =
p[
i].bits_per_pixel;
127 if (vinfo->class == PseudoColor || vinfo->class == StaticColor) {
128 switch (vinfo->depth) {
132 if (BitmapBitOrder(display) == LSBFirst) {
139 if (BitmapBitOrder(display) == LSBFirst) {
151 #if SDL_VIDEO_DRIVER_X11_XINERAMA
153 CheckXinerama(Display * display,
int *major,
int *minor)
163 #ifdef X11MODES_DEBUG
164 printf(
"Xinerama disabled due to hint\n");
169 if (!SDL_X11_HAVE_XINERAMA) {
170 #ifdef X11MODES_DEBUG
171 printf(
"Xinerama support not available\n");
177 if (!X11_XineramaQueryExtension(display, &event_base, &error_base) ||
178 !X11_XineramaQueryVersion(display, major, minor) ||
179 !X11_XineramaIsActive(display)) {
180 #ifdef X11MODES_DEBUG
181 printf(
"Xinerama not active on the display\n");
185 #ifdef X11MODES_DEBUG
186 printf(
"Xinerama available at version %d.%d!\n", *major, *minor);
196 X11_XineramaFailed(Display *
d, XErrorEvent *
e)
198 xinerama_triggered_error =
SDL_TRUE;
199 fprintf(stderr,
"XINERAMA X ERROR: type=%d serial=%lu err=%u req=%u minor=%u\n",
200 e->type,
e->serial, (
unsigned int)
e->error_code,
201 (
unsigned int)
e->request_code, (
unsigned int)
e->minor_code);
207 #if SDL_VIDEO_DRIVER_X11_XRANDR
209 CheckXRandR(Display * display,
int *major,
int *minor)
215 #ifdef XRANDR_DISABLED_BY_DEFAULT
217 #ifdef X11MODES_DEBUG
218 printf(
"XRandR disabled by default due to window manager issues\n");
224 #ifdef X11MODES_DEBUG
225 printf(
"XRandR disabled due to hint\n");
231 if (!SDL_X11_HAVE_XRANDR) {
232 #ifdef X11MODES_DEBUG
233 printf(
"XRandR support not available\n");
239 *major = 1; *minor = 3;
240 if (!X11_XRRQueryVersion(display, major, minor)) {
241 #ifdef X11MODES_DEBUG
242 printf(
"XRandR not active on the display\n");
247 #ifdef X11MODES_DEBUG
248 printf(
"XRandR available at version %d.%d!\n", *major, *minor);
253 #define XRANDR_ROTATION_LEFT (1 << 1)
254 #define XRANDR_ROTATION_RIGHT (1 << 3)
257 CalculateXRandRRefreshRate(
const XRRModeInfo *info)
259 return (info->hTotal && info->vTotal) ?
260 round(((
double)info->dotClock / (
double)(info->hTotal * info->vTotal))) : 0;
264 SetXRandRModeInfo(Display *display, XRRScreenResources *
res, RRCrtc crtc,
268 for (
i = 0;
i <
res->nmode; ++
i) {
269 const XRRModeInfo *info = &
res->modes[
i];
270 if (info->id == modeID) {
271 XRRCrtcInfo *crtcinfo;
272 Rotation rotation = 0;
274 crtcinfo = X11_XRRGetCrtcInfo(display,
res, crtc);
276 rotation = crtcinfo->rotation;
277 X11_XRRFreeCrtcInfo(crtcinfo);
280 if (rotation & (XRANDR_ROTATION_LEFT|XRANDR_ROTATION_RIGHT)) {
281 mode->w = info->height;
282 mode->h = info->width;
284 mode->w = info->width;
285 mode->h = info->height;
287 mode->refresh_rate = CalculateXRandRRefreshRate(info);
289 #ifdef X11MODES_DEBUG
290 printf(
"XRandR mode %d: %dx%d@%dHz\n", (
int) modeID,
mode->w,
mode->h,
mode->refresh_rate);
299 SetXRandRDisplayName(Display *
dpy, Atom EDID,
char *
name,
const size_t namelen, RROutput
output,
const unsigned long widthmm,
const unsigned long heightmm)
307 for (
i = 0;
i < nprop; ++
i) {
310 unsigned long nitems, bytes_after;
315 False, AnyPropertyType, &actual_type,
316 &actual_format, &nitems, &bytes_after,
320 #ifdef X11MODES_DEBUG
321 printf(
"Found EDID data for %s\n",
name);
337 inches = (int)((
SDL_sqrtf(widthmm * widthmm + heightmm * heightmm) / 25.4
f) + 0.5f);
338 if (*
name && inches) {
343 #ifdef X11MODES_DEBUG
344 printf(
"Display name: %s\n",
name);
350 X11_InitModes_XRandR(
_THIS)
354 const int screencount = ScreenCount(
dpy);
355 const int default_screen = DefaultScreen(
dpy);
356 RROutput primary = X11_XRRGetOutputPrimary(
dpy, RootWindow(
dpy, default_screen));
357 Atom EDID = X11_XInternAtom(
dpy,
"EDID", False);
358 XRRScreenResources *
res =
NULL;
361 XPixmapFormatValues *pixmapformats;
362 int looking_for_primary;
367 for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
371 if (looking_for_primary && (
screen != default_screen)) {
375 if (get_visualinfo(
dpy,
screen, &vinfo) < 0) {
385 pixmapformats = X11_XListPixmapFormats(
dpy, &
n);
387 for (
i = 0;
i <
n; ++
i) {
388 if (pixmapformats[
i].
depth == vinfo.depth) {
389 scanline_pad = pixmapformats[
i].scanline_pad;
393 X11_XFree(pixmapformats);
397 if (!
res ||
res->noutput == 0) {
399 X11_XRRFreeScreenResources(
res);
409 XRROutputInfo *output_info;
410 int display_x, display_y;
411 unsigned long display_mm_width, display_mm_height;
413 char display_name[128];
422 if ((looking_for_primary && (
res->outputs[
output] != primary)) ||
423 (!looking_for_primary && (
screen == default_screen) && (
res->outputs[
output] == primary))) {
428 if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
429 X11_XRRFreeOutputInfo(output_info);
433 SDL_strlcpy(display_name, output_info->name,
sizeof(display_name));
434 display_mm_width = output_info->mm_width;
435 display_mm_height = output_info->mm_height;
436 output_crtc = output_info->crtc;
437 X11_XRRFreeOutputInfo(output_info);
439 crtc = X11_XRRGetCrtcInfo(
dpy,
res, output_crtc);
446 mode.w = crtc->width;
447 mode.h = crtc->height;
448 mode.format = pixelformat;
453 X11_XRRFreeCrtcInfo(crtc);
465 modedata->xrandr_mode = modeID;
466 mode.driverdata = modedata;
469 displaydata->
visual = vinfo.visual;
470 displaydata->
depth = vinfo.depth;
471 displaydata->
hdpi = display_mm_width ? (((float)
mode.w) * 25.4f / display_mm_width) : 0.0
f;
472 displaydata->
vdpi = display_mm_height ? (((float)
mode.h) * 25.4f / display_mm_height) : 0.0
f;
475 displaydata->
x = display_x;
476 displaydata->
y = display_y;
478 displaydata->xrandr_output =
res->outputs[
output];
480 SetXRandRModeInfo(
dpy,
res, output_crtc, modeID, &
mode);
481 SetXRandRDisplayName(
dpy, EDID, display_name,
sizeof (display_name),
res->outputs[
output], display_mm_width, display_mm_height);
485 display.
name = display_name;
493 X11_XRRFreeScreenResources(
res);
505 #if SDL_VIDEO_DRIVER_X11_XVIDMODE
507 CheckVidMode(Display * display,
int *major,
int *minor)
509 int vm_event, vm_error = -1;
515 #ifdef X11MODES_DEBUG
516 printf(
"XVidMode disabled due to hint\n");
521 if (!SDL_X11_HAVE_XVIDMODE) {
522 #ifdef X11MODES_DEBUG
523 printf(
"XVidMode support not available\n");
529 if (!X11_XF86VidModeQueryExtension(display, &vm_event, &vm_error)
530 || !X11_XF86VidModeQueryVersion(display, major, minor)) {
531 #ifdef X11MODES_DEBUG
532 printf(
"XVidMode not active on the display\n");
536 #ifdef X11MODES_DEBUG
537 printf(
"XVidMode available at version %d.%d!\n", *major, *minor);
543 Bool XF86VidModeGetModeInfo(Display *
dpy,
int scr,
544 XF86VidModeModeInfo* info)
548 XF86VidModeModeLine
l;
551 retval = X11_XF86VidModeGetModeLine(
dpy, scr, &dotclock, &
l);
552 info->dotclock = dotclock;
553 info->hdisplay =
l.hdisplay;
554 info->hsyncstart =
l.hsyncstart;
555 info->hsyncend =
l.hsyncend;
556 info->htotal =
l.htotal;
557 info->hskew =
l.hskew;
558 info->vdisplay =
l.vdisplay;
559 info->vsyncstart =
l.vsyncstart;
560 info->vsyncend =
l.vsyncend;
561 info->vtotal =
l.vtotal;
562 info->flags =
l.flags;
563 info->privsize =
l.privsize;
564 info->private =
l.private;
569 CalculateXVidModeRefreshRate(
const XF86VidModeModeInfo * info)
572 && info->vtotal) ? (1000 * info->dotclock / (info->htotal *
579 mode->w = info->hdisplay;
580 mode->h = info->vdisplay;
581 mode->refresh_rate = CalculateXVidModeRefreshRate(info);
591 int snum,
screen, screencount = 0;
593 int xinerama_major, xinerama_minor;
594 int use_xinerama = 0;
595 XineramaScreenInfo *xinerama =
NULL;
598 int xrandr_major, xrandr_minor;
601 int vm_major, vm_minor;
609 if (CheckXRandR(
data->display, &xrandr_major, &xrandr_minor) &&
610 (xrandr_major >= 2 || (xrandr_major == 1 && xrandr_minor >= 3))) {
611 if (X11_InitModes_XRandR(
_this) == 0)
623 #if SDL_VIDEO_DRIVER_X11_XRANDR
624 return SDL_SetError(
"XRandR support is required but not available");
626 return SDL_SetError(
"XRandR support is required but not built into SDL!");
631 #if SDL_VIDEO_DRIVER_X11_XINERAMA
636 if (CheckXinerama(
data->display, &xinerama_major, &xinerama_minor)) {
637 int (*handler) (Display *, XErrorEvent *);
638 X11_XSync(
data->display, False);
639 handler = X11_XSetErrorHandler(X11_XineramaFailed);
640 xinerama = X11_XineramaQueryScreens(
data->display, &screencount);
641 X11_XSync(
data->display, False);
642 X11_XSetErrorHandler(handler);
643 if (xinerama_triggered_error) {
647 use_xinerama = xinerama_major * 100 + xinerama_minor;
651 screencount = ScreenCount(
data->display);
654 screencount = ScreenCount(
data->display);
657 #if SDL_VIDEO_DRIVER_X11_XVIDMODE
658 if (CheckVidMode(
data->display, &vm_major, &vm_minor)) {
659 use_vidmode = vm_major * 100 + vm_minor;
663 for (snum = 0; snum < screencount; ++snum) {
669 XPixmapFormatValues *pixmapFormats;
670 char display_name[128];
676 }
else if (snum == DefaultScreen(
data->display)) {
682 #if SDL_VIDEO_DRIVER_X11_XINERAMA
684 if (get_visualinfo(
data->display, 0, &vinfo) < 0) {
688 if (get_visualinfo(
data->display,
screen, &vinfo) < 0) {
693 if (get_visualinfo(
data->display,
screen, &vinfo) < 0) {
702 display_name[0] =
'\0';
710 #if SDL_VIDEO_DRIVER_X11_XINERAMA
722 mode.refresh_rate = 0;
729 mode.driverdata = modedata;
731 #if SDL_VIDEO_DRIVER_X11_XINERAMA
739 displaydata->xinerama_info = xinerama[
screen];
740 displaydata->xinerama_screen =
screen;
746 displaydata->
visual = vinfo.visual;
747 displaydata->
depth = vinfo.depth;
752 displaydata->
hdpi = (float)DisplayWidth(
data->display, displaydata->
screen) * 25.4f /
753 DisplayWidthMM(
data->display, displaydata->
screen);
754 displaydata->
vdpi = (float)DisplayHeight(
data->display, displaydata->
screen) * 25.4f /
755 DisplayHeightMM(
data->display, displaydata->
screen);
757 DisplayHeight(
data->display, displaydata->
screen),
758 (
float)DisplayWidthMM(
data->display, displaydata->
screen) / 25.4f,
759 (
float)DisplayHeightMM(
data->display, displaydata->
screen) / 25.4f);
762 pixmapFormats = X11_XListPixmapFormats(
data->display, &
n);
764 for (
i = 0;
i <
n; ++
i) {
765 if (pixmapFormats[
i].
depth == displaydata->
depth) {
770 X11_XFree(pixmapFormats);
773 #if SDL_VIDEO_DRIVER_X11_XINERAMA
775 displaydata->
x = xinerama[
screen].x_org;
776 displaydata->
y = xinerama[
screen].y_org;
785 #if SDL_VIDEO_DRIVER_X11_XVIDMODE
790 (displaydata->
x == 0 && displaydata->
y == 0)) &&
795 displaydata->vidmode_screen = 0;
797 displaydata->vidmode_screen =
screen;
799 XF86VidModeGetModeInfo(
data->display, displaydata->vidmode_screen, &modedata->vm_mode);
805 display.
name = display_name;
813 #if SDL_VIDEO_DRIVER_X11_XINERAMA
814 if (xinerama) X11_XFree(xinerama);
830 XF86VidModeModeInfo ** modes;
848 screen_w = DisplayWidth(display,
data->screen);
849 screen_h = DisplayHeight(display,
data->screen);
851 if (
data->use_vidmode && !
data->xinerama_info.x_org && !
data->xinerama_info.y_org &&
852 (screen_w >
data->xinerama_info.width || screen_h >
data->xinerama_info.height)) {
859 mode.refresh_rate = 0;
864 mode.driverdata = modedata;
869 else if (!
data->use_xrandr)
874 mode.h =
data->xinerama_info.height;
875 mode.refresh_rate = 0;
880 mode.driverdata = modedata;
889 #if SDL_VIDEO_DRIVER_X11_XRANDR
890 if (
data->use_xrandr) {
891 XRRScreenResources *
res;
893 res = X11_XRRGetScreenResources (display, RootWindow(display,
data->screen));
896 XRROutputInfo *output_info;
899 output_info = X11_XRRGetOutputInfo(display,
res,
data->xrandr_output);
900 if (output_info && output_info->connection != RR_Disconnected) {
901 for (
i = 0;
i < output_info->nmode; ++
i) {
906 mode.driverdata = modedata;
908 if (!SetXRandRModeInfo(display,
res, output_info->crtc, output_info->modes[
i], &
mode) ||
914 X11_XRRFreeOutputInfo(output_info);
915 X11_XRRFreeScreenResources(
res);
921 #if SDL_VIDEO_DRIVER_X11_XVIDMODE
922 if (
data->use_vidmode &&
923 X11_XF86VidModeGetAllModeLines(display,
data->vidmode_screen, &nmodes, &modes)) {
927 #ifdef X11MODES_DEBUG
928 printf(
"VidMode modes: (unsorted)\n");
929 for (
i = 0;
i < nmodes; ++
i) {
930 printf(
"Mode %d: %d x %d @ %d, flags: 0x%x\n",
i,
931 modes[
i]->hdisplay, modes[
i]->vdisplay,
932 CalculateXVidModeRefreshRate(modes[
i]), modes[
i]->
flags);
935 for (
i = 0;
i < nmodes; ++
i) {
940 mode.driverdata = modedata;
951 if (!
data->use_xrandr && !
data->use_vidmode) {
959 mode.driverdata = modedata;
970 Display *display = viddata->
display;
976 #if SDL_VIDEO_DRIVER_X11_XRANDR
977 if (
data->use_xrandr) {
978 XRRScreenResources *
res;
979 XRROutputInfo *output_info;
983 res = X11_XRRGetScreenResources (display, RootWindow(display,
data->screen));
985 return SDL_SetError(
"Couldn't get XRandR screen resources");
988 output_info = X11_XRRGetOutputInfo(display,
res,
data->xrandr_output);
989 if (!output_info || output_info->connection == RR_Disconnected) {
990 X11_XRRFreeScreenResources(
res);
994 crtc = X11_XRRGetCrtcInfo(display,
res, output_info->crtc);
996 X11_XRRFreeOutputInfo(output_info);
997 X11_XRRFreeScreenResources(
res);
1001 status = X11_XRRSetCrtcConfig (display,
res, output_info->crtc, CurrentTime,
1002 crtc->x, crtc->y, modedata->xrandr_mode, crtc->rotation,
1003 &
data->xrandr_output, 1);
1005 X11_XRRFreeCrtcInfo(crtc);
1006 X11_XRRFreeOutputInfo(output_info);
1007 X11_XRRFreeScreenResources(
res);
1009 if (status != Success) {
1015 #if SDL_VIDEO_DRIVER_X11_XVIDMODE
1016 if (
data->use_vidmode) {
1017 X11_XF86VidModeSwitchToMode(display,
data->vidmode_screen, &modedata->vm_mode);
1041 if (
data->use_xinerama) {
1044 XineramaScreenInfo *xinerama = X11_XineramaQueryScreens(display, &screencount);
1046 rect->
x = xinerama[
data->xinerama_screen].x_org;
1047 rect->
y = xinerama[
data->xinerama_screen].y_org;
1048 X11_XFree(xinerama);
1077 Display *display =
data->display;
1079 int status, real_format;
1082 unsigned long items_read = 0, items_left = 0;
1083 unsigned char *propdata =
NULL;
1089 _NET_WORKAREA = X11_XInternAtom(display,
"_NET_WORKAREA", False);
1090 status = X11_XGetWindowProperty(display, DefaultRootWindow(display),
1091 _NET_WORKAREA, 0L, 4L, False, XA_CARDINAL,
1092 &real_type, &real_format, &items_read,
1093 &items_left, &propdata);
1094 if ((status == Success) && (items_read >= 4)) {
1095 const long *
p = (
long*) propdata;
1096 const SDL_Rect usable = { (int)
p[0], (
int)
p[1], (int)
p[2], (
int)
p[3] };
1104 X11_XFree(propdata);