From 7ab21e72ae59f984655bb3578250fe2a589a0e1c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 22 Oct 2023 10:58:01 +0200 Subject: [PATCH] xf86drm: add drmDevicesQueryAffinity Add a function to check whether two DRM devices have an "affinity", ie. whether it makes sense to use them together by default. This is used for split render/display SoCs: the list of devices here is the same as renderonly/kmsro in Mesa. Signed-off-by: Simon Ser --- core-symbols.txt | 1 + xf86drm.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ xf86drm.h | 1 + 3 files changed, 91 insertions(+) diff --git a/core-symbols.txt b/core-symbols.txt index 0d3464e9..6343f49c 100644 --- a/core-symbols.txt +++ b/core-symbols.txt @@ -38,6 +38,7 @@ drmDelContextTag drmDestroyContext drmDestroyDrawable drmDevicesEqual +drmDevicesQueryAffinity drmDMA drmDropMaster drmError diff --git a/xf86drm.c b/xf86drm.c index ebc60956..39286b50 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -3809,6 +3809,95 @@ drm_public int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b) return 0; } +static bool drmIsDisplayOnly(const char *driver) +{ + return strcmp(driver, "armada-drm") == 0 + || strcmp(driver, "exynos") == 0 + || strcmp(driver, "hdlcd") == 0 + || strcmp(driver, "hx8357d") == 0 + || strcmp(driver, "ili9225") == 0 + || strcmp(driver, "ili9341") == 0 + || strcmp(driver, "imx-drm") == 0 + || strcmp(driver, "imx-dcss") == 0 + || strcmp(driver, "imx-lcdif") == 0 + || strcmp(driver, "ingenic-dr") == 0 + || strcmp(driver, "kirin") == 0 + || strcmp(driver, "komeda") == 0 + || strcmp(driver, "mali-dp") == 0 + || strcmp(driver, "mcde") == 0 + || strcmp(driver, "mediatek") == 0 + || strcmp(driver, "meson") == 0 + || strcmp(driver, "mi0283qt") == 0 + || strcmp(driver, "mxsfb-drm") == 0 + || strcmp(driver, "pl111") == 0 + || strcmp(driver, "rcar-du") == 0 + || strcmp(driver, "repaper") == 0 + || strcmp(driver, "rockchip") == 0 + || strcmp(driver, "st7586") == 0 + || strcmp(driver, "st7735r") == 0 + || strcmp(driver, "stm") == 0 + || strcmp(driver, "sun4i-drm") == 0; +} + +static bool drmIsRenderOnly(const char *driver) +{ + return strcmp(driver, "etnaviv") == 0 + || strcmp(driver, "lima") == 0 + || strcmp(driver, "v3d") == 0 + || strcmp(driver, "vc4") == 0 + || strcmp(driver, "freedreno") == 0 + || strcmp(driver, "panfrost") == 0 + || strcmp(driver, "asahi") == 0; +} + +static drmVersion *drmGetVersionFromPath(const char *path) +{ + int fd; + drmVersion *version; + + fd = open(path, O_RDWR | O_CLOEXEC); + if (fd < 0) + return NULL; + version = drmGetVersion(fd); + close(fd); + + return version; +} + +drm_public int drmDevicesQueryAffinity(drmDevice *a, drmDevice *b) +{ + drmDevice *render_device, *display_device; + drmVersion *render_version, *display_version; + bool is_render_only, is_display_only; + + if (drmDevicesEqual(a, b)) + return 1; + + if (a->bustype != b->bustype) + return 0; + if (a->bustype != DRM_BUS_PLATFORM) + return 0; + + if (a->available_nodes & (1 << DRM_NODE_RENDER)) { + render_device = a; + display_device = b; + } else if (b->available_nodes & (1 << DRM_NODE_RENDER)) { + render_device = b; + display_device = a; + } else { + return 0; + } + + render_version = drmGetVersionFromPath(render_device->nodes[DRM_NODE_RENDER]); + display_version = drmGetVersionFromPath(display_device->nodes[DRM_NODE_PRIMARY]); + is_render_only = drmIsRenderOnly(render_version->name); + is_display_only = drmIsDisplayOnly(display_version->name); + drmFreeVersion(render_version); + drmFreeVersion(display_version); + + return is_render_only && is_display_only; +} + static int drmGetNodeType(const char *name) { if (strncmp(name, DRM_RENDER_MINOR_NAME, diff --git a/xf86drm.h b/xf86drm.h index d20df47d..81ec6898 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -920,6 +920,7 @@ extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_device extern int drmGetDeviceFromDevId(dev_t dev_id, uint32_t flags, drmDevicePtr *device); extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b); +extern int drmDevicesQueryAffinity(drmDevice *a, drmDevice *b); extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle); extern int drmSyncobjDestroy(int fd, uint32_t handle);