From ceade3493045898a30f0da1bbb639552447ffcdf Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Thu, 16 Jun 2022 17:39:14 -0500 Subject: 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. --- video/out/x11_common.c | 25 +++++++++++++++++++++++++ video/out/x11_common.h | 2 ++ 2 files changed, 27 insertions(+) (limited to 'video/out') diff --git a/video/out/x11_common.c b/video/out/x11_common.c index d8cda687f8..802af60760 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -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++) { diff --git a/video/out/x11_common.h b/video/out/x11_common.h index acc08f2ee0..e9abf51585 100644 --- a/video/out/x11_common.h +++ b/video/out/x11_common.h @@ -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; -- cgit v1.2.3