From c377f307659fa95263d8c9c902ca14e3cb7e1059 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 19 Mar 2026 13:31:02 +0100 Subject: [PATCH] render/egl: add support for EGL_EXT_device_type This new EGL extension provides a standard way to fetch the type of a device. References: https://github.com/KhronosGroup/EGL-Registry/pull/220 --- include/render/egl.h | 1 + render/egl.c | 33 +++++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/include/render/egl.h b/include/render/egl.h index 103ab57df..ec5a4be57 100644 --- a/include/render/egl.h +++ b/include/render/egl.h @@ -37,6 +37,7 @@ struct wlr_egl { PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR; PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT; PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT; + PFNEGLQUERYDEVICEATTRIBEXTPROC eglQueryDeviceAttribEXT; PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT; PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR; PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR; diff --git a/render/egl.c b/render/egl.c index 8673acabf..bed4fd2b1 100644 --- a/render/egl.c +++ b/render/egl.c @@ -12,6 +12,13 @@ #include "render/egl.h" #include "util/env.h" +// TODO: drop +#define EGL_DEVICE_TYPE_EXT 0x3590 +#define EGL_DEVICE_TYPE_OTHER_EXT 0x3591 +#define EGL_DEVICE_TYPE_INTEGRATED_GPU_EXT 0x3592 +#define EGL_DEVICE_TYPE_DISCRETE_GPU_EXT 0x3593 +#define EGL_DEVICE_TYPE_CPU_EXT 0x3594 + static enum wlr_log_importance egl_log_importance_to_wlr(EGLint type) { switch (type) { case EGL_DEBUG_MSG_CRITICAL_KHR: return WLR_ERROR; @@ -231,10 +238,9 @@ static struct wlr_egl *egl_create(void) { if (check_egl_ext(client_exts_str, "EGL_EXT_device_base") || check_egl_ext(client_exts_str, "EGL_EXT_device_query")) { egl->exts.EXT_device_query = true; - load_egl_proc(&egl->procs.eglQueryDeviceStringEXT, - "eglQueryDeviceStringEXT"); - load_egl_proc(&egl->procs.eglQueryDisplayAttribEXT, - "eglQueryDisplayAttribEXT"); + load_egl_proc(&egl->procs.eglQueryDeviceStringEXT, "eglQueryDeviceStringEXT"); + load_egl_proc(&egl->procs.eglQueryDeviceAttribEXT, "eglQueryDeviceAttribEXT"); + load_egl_proc(&egl->procs.eglQueryDisplayAttribEXT, "eglQueryDisplayAttribEXT"); } if (check_egl_ext(client_exts_str, "EGL_KHR_debug")) { @@ -260,6 +266,19 @@ static struct wlr_egl *egl_create(void) { return egl; } +static bool device_is_software(struct wlr_egl *egl, EGLDeviceEXT *device, + const char *device_exts_str) { + if (check_egl_ext(device_exts_str, "EGL_EXT_device_type")) { + EGLAttrib device_type; + if (!egl->procs.eglQueryDeviceAttribEXT(egl->device, EGL_DEVICE_TYPE_EXT, &device_type)) { + wlr_log(WLR_ERROR, "eglQueryDeviceAttribEXT(EGL_DEVICE_TYPE_EXT) failed"); + } else { + return device_type == EGL_DEVICE_TYPE_CPU_EXT; + } + } + return check_egl_ext(device_exts_str, "EGL_MESA_device_software"); +} + static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display, bool allow_software) { egl->display = display; @@ -327,7 +346,7 @@ static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display, // The only way a non-DRM device is selected is when the user // explicitly picks software rendering - if (check_egl_ext(device_exts_str, "EGL_MESA_device_software")) { + if (device_is_software(egl, egl->device, device_exts_str)) { if (allow_software || env_parse_bool("WLR_RENDERER_ALLOW_SOFTWARE")) { wlr_log(WLR_INFO, "Using software rendering"); } else { @@ -510,13 +529,11 @@ static EGLDeviceEXT get_egl_device_from_drm_fd(struct wlr_egl *egl, } } - bool is_software = check_egl_ext(device_exts_str, "EGL_MESA_device_software"); - bool found; if (selected_drm_device != NULL) { found = egl_device_name != NULL && device_has_name(selected_drm_device, egl_device_name); } else { - found = is_software; + found = device_is_software(egl, devices[i], device_exts_str); } if (found) { if (egl_device_name != NULL) {