From ce943021121d1e9bac2bdfec282251ff221a3ebc Mon Sep 17 00:00:00 2001 From: Sav <62543096+dongioia@users.noreply.github.com> Date: Mon, 9 Mar 2026 15:14:16 +0100 Subject: [PATCH] native: Add preferred-primary GPU selection via udev tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On multi-GPU SoCs like RK3588 (Rockchip), the mainline kernel exposes two DRM devices: card0 (rockchip-drm, display-only, no 3D) and card1 (panthor, Mali-G610 GPU with full 3D). Muffin's choose_primary_gpu_unchecked() selects the first platform device with render capability, which picks card0 — a display controller with no OpenGL/Vulkan support. This causes EGL clients to fall back to llvmpipe (software rendering), as the compositor advertises the wrong device via wl_drm. GNOME's Mutter solved this by introducing a udev tag mechanism (mutter-device-preferred-primary) that lets system integrators explicitly mark which GPU should be used as primary. This commit ports that mechanism to Muffin using the tag "muffin-device-preferred-primary". Changes: - meta-udev.c/h: Add meta_is_udev_device_preferred_primary() that checks for the "muffin-device-preferred-primary" udev tag - meta-kms-types.h: Add META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY flag - meta-backend-native.c: Propagate the flag during GPU initialization - meta-gpu-kms.c/h: Add meta_gpu_kms_is_preferred_primary() accessor - meta-renderer-native.c: Check preferred_primary before platform_device and boot_vga in choose_primary_gpu_unchecked() Example udev rule for RK3588 boards: SUBSYSTEM=="drm", KERNEL=="card1", DRIVERS=="panthor", \ TAG+="muffin-device-preferred-primary" Tested on Rock 5B+ (RK3588) running BredOS with kernel 7.0-rc1 and 6.19.1, Cinnamon Wayland session. Verified that Muffin correctly selects panthor (renderD128) as primary GPU with this patch applied. Note: This fixes the compositor-side GPU selection (Part A). Full client-side GPU discovery requires upgrading zwp_linux_dmabuf_v1 from v3 to v4+ with device feedback (Part B, separate work). Ref: Mutter meta-udev.c meta_is_udev_device_preferred_primary() --- src/backends/native/meta-backend-native.c | 3 +++ src/backends/native/meta-gpu-kms.c | 9 +++++++++ src/backends/native/meta-gpu-kms.h | 1 + src/backends/native/meta-kms-types.h | 1 + src/backends/native/meta-renderer-native.c | 11 +++++++++++ src/backends/native/meta-udev.c | 12 ++++++++++++ src/backends/native/meta-udev.h | 2 ++ 7 files changed, 39 insertions(+) diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index 9d8eb4842..398ab589c 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -526,6 +526,9 @@ create_gpu_from_udev_device (MetaBackendNative *native, if (meta_is_udev_device_requires_modifiers (device)) flags |= META_KMS_DEVICE_FLAG_REQUIRES_MODIFIERS; + if (meta_is_udev_device_preferred_primary (device)) + flags |= META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY; + device_path = g_udev_device_get_device_file (device); kms_device = meta_kms_create_device (native->kms, device_path, flags, diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c index 2e2ed3ccf..c89310232 100644 --- a/src/backends/native/meta-gpu-kms.c +++ b/src/backends/native/meta-gpu-kms.c @@ -283,6 +283,15 @@ meta_gpu_kms_requires_modifiers (MetaGpuKms *gpu_kms) return !!(flags & META_KMS_DEVICE_FLAG_REQUIRES_MODIFIERS); } +gboolean +meta_gpu_kms_is_preferred_primary (MetaGpuKms *gpu_kms) +{ + MetaKmsDeviceFlag flags; + + flags = meta_kms_device_get_flags (gpu_kms->kms_device); + return !!(flags & META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY); +} + static int compare_outputs (gconstpointer one, gconstpointer two) diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h index bc2c43665..62d8bb92a 100644 --- a/src/backends/native/meta-gpu-kms.h +++ b/src/backends/native/meta-gpu-kms.h @@ -48,6 +48,7 @@ gboolean meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms, gboolean meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms); gboolean meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms); gboolean meta_gpu_kms_requires_modifiers (MetaGpuKms *gpu_kms); +gboolean meta_gpu_kms_is_preferred_primary (MetaGpuKms *gpu_kms); gboolean meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms, GError **error); diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h index 1fed7e332..1d5902505 100644 --- a/src/backends/native/meta-kms-types.h +++ b/src/backends/native/meta-kms-types.h @@ -57,6 +57,7 @@ typedef enum _MetaKmsDeviceFlag META_KMS_DEVICE_FLAG_BOOT_VGA = 1 << 0, META_KMS_DEVICE_FLAG_PLATFORM_DEVICE = 1 << 1, META_KMS_DEVICE_FLAG_REQUIRES_MODIFIERS = 1 << 2, + META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY = 1 << 3, } MetaKmsDeviceFlag; typedef enum _MetaKmsPlaneType MetaKmsPlaneType; diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index fd2272df3..28d4c0d0a 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -3940,6 +3940,17 @@ choose_primary_gpu_unchecked (MetaBackend *backend, */ for (allow_sw = 0; allow_sw < 2; allow_sw++) { + /* Prefer a device tagged as preferred primary via udev */ + for (l = gpus; l; l = l->next) + { + MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); + + if (meta_gpu_kms_is_preferred_primary (gpu_kms) && + (allow_sw == 1 || + gpu_kms_is_hardware_rendering (renderer_native, gpu_kms))) + return gpu_kms; + } + /* Prefer a platform device */ for (l = gpus; l; l = l->next) { diff --git a/src/backends/native/meta-udev.c b/src/backends/native/meta-udev.c index 1c8851102..836cf25bc 100644 --- a/src/backends/native/meta-udev.c +++ b/src/backends/native/meta-udev.c @@ -74,6 +74,18 @@ meta_is_udev_device_boot_vga (GUdevDevice *device) return g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga") == 1; } +gboolean +meta_is_udev_device_preferred_primary (GUdevDevice *device) +{ + const char * const * tags; + + tags = g_udev_device_get_tags (device); + if (!tags) + return FALSE; + + return g_strv_contains (tags, "muffin-device-preferred-primary"); +} + gboolean meta_is_udev_device_requires_modifiers (GUdevDevice *device) { diff --git a/src/backends/native/meta-udev.h b/src/backends/native/meta-udev.h index eb90abb09..52117d323 100644 --- a/src/backends/native/meta-udev.h +++ b/src/backends/native/meta-udev.h @@ -32,6 +32,8 @@ gboolean meta_is_udev_device_platform_device (GUdevDevice *device); gboolean meta_is_udev_device_boot_vga (GUdevDevice *device); +gboolean meta_is_udev_device_preferred_primary (GUdevDevice *device); + gboolean meta_is_udev_device_requires_modifiers (GUdevDevice *device); gboolean meta_udev_is_drm_device (MetaUdev *udev,