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:
Dudemanguy 2022-06-16 17:39:14 -05:00
parent 7ce26dd324
commit ceade34930
2 changed files with 27 additions and 0 deletions

View File

@ -381,6 +381,7 @@ static void xrandr_read(struct vo_x11_state *x11)
talloc_free(x11->displays[i].name);
x11->num_displays = 0;
bool randr_14 = false;
if (x11->xrandr_event < 0) {
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");
return;
}
int major, minor;
XRRQueryVersion(x11->display, &major, &minor);
if (major >= 2 || minor >= 4)
randr_14 = true;
x11->xrandr_event = event_base + RRNotify;
XRRSelectInput(x11->display, x11->rootwin, RRScreenChangeNotifyMask |
RRCrtcChangeNotifyMask | RROutputChangeNotifyMask);
@ -399,6 +404,26 @@ static void xrandr_read(struct vo_x11_state *x11)
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;
RROutput primary = XRRGetOutputPrimary(x11->display, x11->rootwin);
for (int o = 0; o < r->noutput; o++) {

View File

@ -68,6 +68,8 @@ struct vo_x11_state {
int current_icc_screen;
int xrandr_event;
bool has_mesa;
bool has_nvidia;
bool screensaver_enabled;
bool dpms_touched;