mirror of https://github.com/mpv-player/mpv
x11: use xrandr providers for driver detection
Unfortunately there's a certain company that makes graphics drivers that are harder to deal with. The next commit aims to implement presentation, but some empirical testing from users show that it's actually broken. Give up and just tap into Xrandr so we can figure what drivers (or well, providers by the extension terminology) are driving the screen. Basically if we find intel, amd, or radeon, assume it's a Mesa driver. If we find nvidia, then it must be nvidia. This detection requires randr 1.4 (which means using presentation in mpv secretly depends on randr 1.4), but this protocol version is nearly a decade old anyway so probably 99.9% of users are fine. Do the version query check and all that anyway just to be on the safe side.
This commit is contained in:
parent
7ce26dd324
commit
ceade34930
|
@ -381,6 +381,7 @@ static void xrandr_read(struct vo_x11_state *x11)
|
||||||
talloc_free(x11->displays[i].name);
|
talloc_free(x11->displays[i].name);
|
||||||
|
|
||||||
x11->num_displays = 0;
|
x11->num_displays = 0;
|
||||||
|
bool randr_14 = false;
|
||||||
|
|
||||||
if (x11->xrandr_event < 0) {
|
if (x11->xrandr_event < 0) {
|
||||||
int event_base, error_base;
|
int event_base, error_base;
|
||||||
|
@ -388,6 +389,10 @@ static void xrandr_read(struct vo_x11_state *x11)
|
||||||
MP_VERBOSE(x11, "Couldn't init Xrandr.\n");
|
MP_VERBOSE(x11, "Couldn't init Xrandr.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int major, minor;
|
||||||
|
XRRQueryVersion(x11->display, &major, &minor);
|
||||||
|
if (major >= 2 || minor >= 4)
|
||||||
|
randr_14 = true;
|
||||||
x11->xrandr_event = event_base + RRNotify;
|
x11->xrandr_event = event_base + RRNotify;
|
||||||
XRRSelectInput(x11->display, x11->rootwin, RRScreenChangeNotifyMask |
|
XRRSelectInput(x11->display, x11->rootwin, RRScreenChangeNotifyMask |
|
||||||
RRCrtcChangeNotifyMask | RROutputChangeNotifyMask);
|
RRCrtcChangeNotifyMask | RROutputChangeNotifyMask);
|
||||||
|
@ -399,6 +404,26 @@ static void xrandr_read(struct vo_x11_state *x11)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Look at the available providers on the current screen and try to determine
|
||||||
|
* the driver. If amd/intel/radeon, assume this is mesa. If nvidia is found,
|
||||||
|
* assume nvidia. Because the same screen can have multiple providers (e.g.
|
||||||
|
* a laptop with switchable graphics), we need to know both of these things.
|
||||||
|
* In practice, this is used for determining whether or not to use XPresent
|
||||||
|
* (i.e. needs to be Mesa and not Nvidia). Requires Randr 1.4. */
|
||||||
|
if (randr_14) {
|
||||||
|
XRRProviderResources *pr = XRRGetProviderResources(x11->display, x11->rootwin);
|
||||||
|
for (int i = 0; i < pr->nproviders; i++) {
|
||||||
|
XRRProviderInfo *info = XRRGetProviderInfo(x11->display, r, pr->providers[i]);
|
||||||
|
char *amd = strcasestr(info->name, "amd");
|
||||||
|
char *intel = strcasestr(info->name, "intel");
|
||||||
|
char *nvidia = strcasestr(info->name, "nvidia");
|
||||||
|
char *radeon = strcasestr(info->name, "radeon");
|
||||||
|
x11->has_mesa = (amd || intel || radeon) ? true : false;
|
||||||
|
x11->has_nvidia = nvidia ? true : false;
|
||||||
|
}
|
||||||
|
XRRFreeProviderResources(pr);
|
||||||
|
}
|
||||||
|
|
||||||
int primary_id = -1;
|
int primary_id = -1;
|
||||||
RROutput primary = XRRGetOutputPrimary(x11->display, x11->rootwin);
|
RROutput primary = XRRGetOutputPrimary(x11->display, x11->rootwin);
|
||||||
for (int o = 0; o < r->noutput; o++) {
|
for (int o = 0; o < r->noutput; o++) {
|
||||||
|
|
|
@ -68,6 +68,8 @@ struct vo_x11_state {
|
||||||
int current_icc_screen;
|
int current_icc_screen;
|
||||||
|
|
||||||
int xrandr_event;
|
int xrandr_event;
|
||||||
|
bool has_mesa;
|
||||||
|
bool has_nvidia;
|
||||||
|
|
||||||
bool screensaver_enabled;
|
bool screensaver_enabled;
|
||||||
bool dpms_touched;
|
bool dpms_touched;
|
||||||
|
|
Loading…
Reference in New Issue