Skip to content
Permalink
Browse files
X11: Let XRandR respect multiple screens (DISPLAY=:0.0 vs :0.1, etc).
  • Loading branch information
icculus committed Nov 17, 2015
1 parent 11f2a9f commit 5224dfcc9aaa00452ee2516ccde009071ed9bffd
Showing with 105 additions and 102 deletions.
  1. +105 −102 src/video/x11/SDL_x11modes.c
@@ -357,137 +357,140 @@ SetXRandRDisplayName(Display *dpy, Atom EDID, char *name, const size_t namelen,
int
X11_InitModes_XRandR(_THIS)
{
/* In theory, you _could_ have multiple screens (like DISPLAY=:0.0
and DISPLAY=:0.1) but no XRandR system we care about is like this,
as all the physical displays would be separate XRandR "outputs" on
the one X11 virtual "screen". So we don't use ScreenCount() here. */

SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
Display *dpy = data->display;
const int screencount = ScreenCount(dpy);
const int default_screen = DefaultScreen(dpy);
RROutput primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, default_screen));
Atom EDID = X11_XInternAtom(dpy, "EDID", False);
const int screen = DefaultScreen(dpy);
RROutput primary;
XRRScreenResources *res = NULL;
Uint32 pixelformat;
XVisualInfo vinfo;
XPixmapFormatValues *pixmapformats;
int looking_for_primary;
int scanline_pad;
int output;
int i, n;

if (get_visualinfo(dpy, screen, &vinfo) < 0) {
return -1;
}
int screen, i, n;

pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
return SDL_SetError("Palettized video modes are no longer supported");
}
for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
for (screen = 0; screen < screencount; screen++) {

scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
pixmapformats = X11_XListPixmapFormats(dpy, &n);
if (pixmapformats) {
for (i = 0; i < n; ++i) {
if (pixmapformats[i].depth == vinfo.depth) {
scanline_pad = pixmapformats[i].scanline_pad;
break;
/* we want the primary output first, and then skipped later. */
if ((looking_for_primary && (screen != default_screen)) ||
(!looking_for_primary && (screen == default_screen))) {
continue;
}
}
X11_XFree(pixmapformats);
}

res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
if (!res) {
return -1;
}
if (get_visualinfo(dpy, screen, &vinfo) < 0) {
continue; /* uh, skip this screen? */
}

primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, screen));
pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
continue; /* Palettized video modes are no longer supported */
}

for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
for (output = 0; output < res->noutput; output++) {
XRROutputInfo *output_info;
int display_x, display_y;
unsigned long display_mm_width, display_mm_height;
SDL_DisplayData *displaydata;
char display_name[128];
SDL_DisplayMode mode;
SDL_DisplayModeData *modedata;
SDL_VideoDisplay display;
RRMode modeID;
RRCrtc output_crtc;
XRRCrtcInfo *crtc;

/* The primary output _should_ always be sorted first, but just in case... */
if ((looking_for_primary && (res->outputs[output] != primary)) ||
(!looking_for_primary && (res->outputs[output] == primary))) {
continue;
scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
pixmapformats = X11_XListPixmapFormats(dpy, &n);
if (pixmapformats) {
for (i = 0; i < n; ++i) {
if (pixmapformats[i].depth == vinfo.depth) {
scanline_pad = pixmapformats[i].scanline_pad;
break;
}
}
X11_XFree(pixmapformats);
}

output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
X11_XRRFreeOutputInfo(output_info);
res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
if (!res) {
continue;
}

SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
display_mm_width = output_info->mm_width;
display_mm_height = output_info->mm_height;
output_crtc = output_info->crtc;
X11_XRRFreeOutputInfo(output_info);
for (output = 0; output < res->noutput; output++) {
XRROutputInfo *output_info;
int display_x, display_y;
unsigned long display_mm_width, display_mm_height;
SDL_DisplayData *displaydata;
char display_name[128];
SDL_DisplayMode mode;
SDL_DisplayModeData *modedata;
SDL_VideoDisplay display;
RRMode modeID;
RRCrtc output_crtc;
XRRCrtcInfo *crtc;

/* The primary output _should_ always be sorted first, but just in case... */
if ((looking_for_primary && ((screen != default_screen) || (res->outputs[output] != primary))) ||
(!looking_for_primary && (screen == default_screen) && (res->outputs[output] == primary))) {
continue;
}

crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
if (!crtc) {
continue;
}
output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
X11_XRRFreeOutputInfo(output_info);
continue;
}

SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
display_mm_width = output_info->mm_width;
display_mm_height = output_info->mm_height;
output_crtc = output_info->crtc;
X11_XRRFreeOutputInfo(output_info);

SDL_zero(mode);
modeID = crtc->mode;
mode.w = crtc->width;
mode.h = crtc->height;
mode.format = pixelformat;
crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
if (!crtc) {
continue;
}

display_x = crtc->x;
display_y = crtc->y;
SDL_zero(mode);
modeID = crtc->mode;
mode.w = crtc->width;
mode.h = crtc->height;
mode.format = pixelformat;

X11_XRRFreeCrtcInfo(crtc);
display_x = crtc->x;
display_y = crtc->y;

displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
if (!displaydata) {
return SDL_OutOfMemory();
}
X11_XRRFreeCrtcInfo(crtc);

modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
if (!modedata) {
SDL_free(displaydata);
return SDL_OutOfMemory();
}
modedata->xrandr_mode = modeID;
mode.driverdata = modedata;
displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
if (!displaydata) {
return SDL_OutOfMemory();
}

displaydata->screen = screen;
displaydata->visual = vinfo.visual;
displaydata->depth = vinfo.depth;
displaydata->hdpi = ((float) mode.w) * 25.4f / display_mm_width;
displaydata->vdpi = ((float) mode.h) * 25.4f / display_mm_height;
displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
displaydata->scanline_pad = scanline_pad;
displaydata->x = display_x;
displaydata->y = display_y;
displaydata->use_xrandr = 1;
displaydata->xrandr_output = res->outputs[output];

SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);

SDL_zero(display);
if (*display_name) {
display.name = display_name;
modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
if (!modedata) {
SDL_free(displaydata);
return SDL_OutOfMemory();
}
modedata->xrandr_mode = modeID;
mode.driverdata = modedata;

displaydata->screen = screen;
displaydata->visual = vinfo.visual;
displaydata->depth = vinfo.depth;
displaydata->hdpi = ((float) mode.w) * 25.4f / display_mm_width;
displaydata->vdpi = ((float) mode.h) * 25.4f / display_mm_height;
displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
displaydata->scanline_pad = scanline_pad;
displaydata->x = display_x;
displaydata->y = display_y;
displaydata->use_xrandr = 1;
displaydata->xrandr_output = res->outputs[output];

SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);

SDL_zero(display);
if (*display_name) {
display.name = display_name;
}
display.desktop_mode = mode;
display.current_mode = mode;
display.driverdata = displaydata;
SDL_AddVideoDisplay(&display);
}
display.desktop_mode = mode;
display.current_mode = mode;
display.driverdata = displaydata;
SDL_AddVideoDisplay(&display);
}
}

0 comments on commit 5224dfc

Please sign in to comment.