src/video/x11/SDL_x11modes.c
changeset 9920 183936dd34d5
parent 9834 d3fa6d0d3793
child 9944 88608984f245
equal deleted inserted replaced
9919:ac5490d5aefc 9920:183936dd34d5
   355 
   355 
   356 
   356 
   357 int
   357 int
   358 X11_InitModes_XRandR(_THIS)
   358 X11_InitModes_XRandR(_THIS)
   359 {
   359 {
   360     /* In theory, you _could_ have multiple screens (like DISPLAY=:0.0
       
   361        and DISPLAY=:0.1) but no XRandR system we care about is like this,
       
   362        as all the physical displays would be separate XRandR "outputs" on
       
   363        the one X11 virtual "screen". So we don't use ScreenCount() here. */
       
   364 
       
   365     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   360     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   366     Display *dpy = data->display;
   361     Display *dpy = data->display;
       
   362     const int screencount = ScreenCount(dpy);
       
   363     const int default_screen = DefaultScreen(dpy);
       
   364     RROutput primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, default_screen));
   367     Atom EDID = X11_XInternAtom(dpy, "EDID", False);
   365     Atom EDID = X11_XInternAtom(dpy, "EDID", False);
   368     const int screen = DefaultScreen(dpy);
       
   369     RROutput primary;
       
   370     XRRScreenResources *res = NULL;
   366     XRRScreenResources *res = NULL;
   371     Uint32 pixelformat;
   367     Uint32 pixelformat;
   372     XVisualInfo vinfo;
   368     XVisualInfo vinfo;
   373     XPixmapFormatValues *pixmapformats;
   369     XPixmapFormatValues *pixmapformats;
   374     int looking_for_primary;
   370     int looking_for_primary;
   375     int scanline_pad;
   371     int scanline_pad;
   376     int output;
   372     int output;
   377     int i, n;
   373     int screen, i, n;
   378 
       
   379     if (get_visualinfo(dpy, screen, &vinfo) < 0) {
       
   380         return -1;
       
   381     }
       
   382 
       
   383     pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
       
   384     if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
       
   385         return SDL_SetError("Palettized video modes are no longer supported");
       
   386     }
       
   387 
       
   388     scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
       
   389     pixmapformats = X11_XListPixmapFormats(dpy, &n);
       
   390     if (pixmapformats) {
       
   391         for (i = 0; i < n; ++i) {
       
   392             if (pixmapformats[i].depth == vinfo.depth) {
       
   393                 scanline_pad = pixmapformats[i].scanline_pad;
       
   394                 break;
       
   395             }
       
   396         }
       
   397         X11_XFree(pixmapformats);
       
   398     }
       
   399 
       
   400     res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
       
   401     if (!res) {
       
   402         return -1;
       
   403     }
       
   404 
       
   405     primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, screen));
       
   406 
   374 
   407     for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
   375     for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
   408         for (output = 0; output < res->noutput; output++) {
   376         for (screen = 0; screen < screencount; screen++) {
   409             XRROutputInfo *output_info;
   377 
   410             int display_x, display_y;
   378             /* we want the primary output first, and then skipped later. */
   411             unsigned long display_mm_width, display_mm_height;
   379             if ((looking_for_primary && (screen != default_screen)) ||
   412             SDL_DisplayData *displaydata;
   380                 (!looking_for_primary && (screen == default_screen))) {
   413             char display_name[128];
       
   414             SDL_DisplayMode mode;
       
   415             SDL_DisplayModeData *modedata;
       
   416             SDL_VideoDisplay display;
       
   417             RRMode modeID;
       
   418             RRCrtc output_crtc;
       
   419             XRRCrtcInfo *crtc;
       
   420 
       
   421             /* The primary output _should_ always be sorted first, but just in case... */
       
   422             if ((looking_for_primary && (res->outputs[output] != primary)) ||
       
   423                 (!looking_for_primary && (res->outputs[output] == primary))) {
       
   424                 continue;
   381                 continue;
   425             }
   382             }
   426 
   383 
   427             output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
   384             if (get_visualinfo(dpy, screen, &vinfo) < 0) {
   428             if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
   385                 continue;  /* uh, skip this screen? */
       
   386             }
       
   387 
       
   388             pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
       
   389             if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
       
   390                 continue;  /* Palettized video modes are no longer supported */
       
   391             }
       
   392 
       
   393             scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
       
   394             pixmapformats = X11_XListPixmapFormats(dpy, &n);
       
   395             if (pixmapformats) {
       
   396                 for (i = 0; i < n; ++i) {
       
   397                     if (pixmapformats[i].depth == vinfo.depth) {
       
   398                         scanline_pad = pixmapformats[i].scanline_pad;
       
   399                         break;
       
   400                     }
       
   401                 }
       
   402                 X11_XFree(pixmapformats);
       
   403             }
       
   404 
       
   405             res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
       
   406             if (!res) {
       
   407                 continue;
       
   408             }
       
   409 
       
   410             for (output = 0; output < res->noutput; output++) {
       
   411                 XRROutputInfo *output_info;
       
   412                 int display_x, display_y;
       
   413                 unsigned long display_mm_width, display_mm_height;
       
   414                 SDL_DisplayData *displaydata;
       
   415                 char display_name[128];
       
   416                 SDL_DisplayMode mode;
       
   417                 SDL_DisplayModeData *modedata;
       
   418                 SDL_VideoDisplay display;
       
   419                 RRMode modeID;
       
   420                 RRCrtc output_crtc;
       
   421                 XRRCrtcInfo *crtc;
       
   422 
       
   423                 /* The primary output _should_ always be sorted first, but just in case... */
       
   424                 if ((looking_for_primary && ((screen != default_screen) || (res->outputs[output] != primary))) ||
       
   425                     (!looking_for_primary && (screen == default_screen) && (res->outputs[output] == primary))) {
       
   426                     continue;
       
   427                 }
       
   428 
       
   429                 output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
       
   430                 if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
       
   431                     X11_XRRFreeOutputInfo(output_info);
       
   432                     continue;
       
   433                 }
       
   434 
       
   435                 SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
       
   436                 display_mm_width = output_info->mm_width;
       
   437                 display_mm_height = output_info->mm_height;
       
   438                 output_crtc = output_info->crtc;
   429                 X11_XRRFreeOutputInfo(output_info);
   439                 X11_XRRFreeOutputInfo(output_info);
   430                 continue;
   440 
   431             }
   441                 crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
   432 
   442                 if (!crtc) {
   433             SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
   443                     continue;
   434             display_mm_width = output_info->mm_width;
   444                 }
   435             display_mm_height = output_info->mm_height;
   445 
   436             output_crtc = output_info->crtc;
   446                 SDL_zero(mode);
   437             X11_XRRFreeOutputInfo(output_info);
   447                 modeID = crtc->mode;
   438 
   448                 mode.w = crtc->width;
   439             crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
   449                 mode.h = crtc->height;
   440             if (!crtc) {
   450                 mode.format = pixelformat;
   441                 continue;
   451 
   442             }
   452                 display_x = crtc->x;
   443 
   453                 display_y = crtc->y;
   444             SDL_zero(mode);
   454 
   445             modeID = crtc->mode;
   455                 X11_XRRFreeCrtcInfo(crtc);
   446             mode.w = crtc->width;
   456 
   447             mode.h = crtc->height;
   457                 displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
   448             mode.format = pixelformat;
   458                 if (!displaydata) {
   449 
   459                     return SDL_OutOfMemory();
   450             display_x = crtc->x;
   460                 }
   451             display_y = crtc->y;
   461 
   452 
   462                 modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
   453             X11_XRRFreeCrtcInfo(crtc);
   463                 if (!modedata) {
   454 
   464                     SDL_free(displaydata);
   455             displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
   465                     return SDL_OutOfMemory();
   456             if (!displaydata) {
   466                 }
   457                 return SDL_OutOfMemory();
   467                 modedata->xrandr_mode = modeID;
   458             }
   468                 mode.driverdata = modedata;
   459 
   469 
   460             modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
   470                 displaydata->screen = screen;
   461             if (!modedata) {
   471                 displaydata->visual = vinfo.visual;
   462                 SDL_free(displaydata);
   472                 displaydata->depth = vinfo.depth;
   463                 return SDL_OutOfMemory();
   473                 displaydata->hdpi = ((float) mode.w) * 25.4f / display_mm_width;
   464             }
   474                 displaydata->vdpi = ((float) mode.h) * 25.4f / display_mm_height;
   465             modedata->xrandr_mode = modeID;
   475                 displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
   466             mode.driverdata = modedata;
   476                 displaydata->scanline_pad = scanline_pad;
   467 
   477                 displaydata->x = display_x;
   468             displaydata->screen = screen;
   478                 displaydata->y = display_y;
   469             displaydata->visual = vinfo.visual;
   479                 displaydata->use_xrandr = 1;
   470             displaydata->depth = vinfo.depth;
   480                 displaydata->xrandr_output = res->outputs[output];
   471             displaydata->hdpi = ((float) mode.w) * 25.4f / display_mm_width;
   481 
   472             displaydata->vdpi = ((float) mode.h) * 25.4f / display_mm_height;
   482                 SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
   473             displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
   483                 SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);
   474             displaydata->scanline_pad = scanline_pad;
   484 
   475             displaydata->x = display_x;
   485                 SDL_zero(display);
   476             displaydata->y = display_y;
   486                 if (*display_name) {
   477             displaydata->use_xrandr = 1;
   487                     display.name = display_name;
   478             displaydata->xrandr_output = res->outputs[output];
   488                 }
   479 
   489                 display.desktop_mode = mode;
   480             SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
   490                 display.current_mode = mode;
   481             SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);
   491                 display.driverdata = displaydata;
   482 
   492                 SDL_AddVideoDisplay(&display);
   483             SDL_zero(display);
   493             }
   484             if (*display_name) {
       
   485                 display.name = display_name;
       
   486             }
       
   487             display.desktop_mode = mode;
       
   488             display.current_mode = mode;
       
   489             display.driverdata = displaydata;
       
   490             SDL_AddVideoDisplay(&display);
       
   491         }
   494         }
   492     }
   495     }
   493 
   496 
   494     X11_XRRFreeScreenResources(res);
   497     X11_XRRFreeScreenResources(res);
   495 
   498