diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c index 11951f557..b33389de6 100644 --- a/src/backends/native/meta-gpu-kms.c +++ b/src/backends/native/meta-gpu-kms.c @@ -64,6 +64,7 @@ struct _MetaGpuKms gboolean page_flips_not_supported; }; +G_DEFINE_QUARK (MetaGpuKmsError, meta_gpu_kms_error) G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU) static gboolean @@ -751,6 +752,8 @@ meta_gpu_kms_read_current (MetaGpu *gpu, are freed by the platform-independent layer. */ free_resources (gpu_kms); + g_assert (resources.resources->count_connectors > 0); + init_connectors (gpu_kms, resources.resources); init_modes (gpu_kms, resources.resources); init_crtcs (gpu_kms, &resources); @@ -774,12 +777,40 @@ meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms, GSource *source; MetaKmsSource *kms_source; MetaGpuKms *gpu_kms; + drmModeRes *drm_resources; + guint n_connectors; int kms_fd; kms_fd = meta_launcher_open_restricted (launcher, kms_file_path, error); if (kms_fd == -1) return NULL; + /* Some GPUs might have no connectors, for example dedicated GPUs on PRIME (hybrid) laptops. + * These GPUs cannot render anything on separate screens, and they are aggressively switched + * off by the kernel. + * + * If we add these PRIME GPUs to the GPU list anyway, Mutter keeps awakening the secondary GPU, + * and doing this causes a considerable stuttering. These GPUs are usually put to sleep again + * after ~2s without a workload. + * + * For now, to avoid this situation, only create the MetaGpuKms when the GPU has any connectors. + */ + drm_resources = drmModeGetResources (kms_fd); + + n_connectors = drm_resources->count_connectors; + + drmModeFreeResources (drm_resources); + + if (n_connectors == 0) + { + g_set_error (error, + META_GPU_KMS_ERROR, + META_GPU_KMS_ERROR_NO_CONNECTORS, + "No connectors available in this GPU. This is probably a dedicated GPU in a hybrid setup."); + meta_launcher_close_restricted (launcher, kms_fd); + return NULL; + } + gpu_kms = g_object_new (META_TYPE_GPU_KMS, "monitor-manager", monitor_manager_kms, NULL); diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h index 6c7d5a312..3d0f5f65e 100644 --- a/src/backends/native/meta-gpu-kms.h +++ b/src/backends/native/meta-gpu-kms.h @@ -29,6 +29,14 @@ #include "backends/meta-gpu.h" #include "backends/native/meta-monitor-manager-kms.h" +typedef enum +{ + META_GPU_KMS_ERROR_NO_CONNECTORS, +} MetaGpuKmsError; + +#define META_GPU_KMS_ERROR (meta_gpu_kms_error_quark ()) +GQuark meta_gpu_kms_error_quark (void); + #define META_TYPE_GPU_KMS (meta_gpu_kms_get_type ()) G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu) diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c index 3cee754d1..1a2eaec56 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c @@ -681,8 +681,11 @@ meta_monitor_manager_kms_initable_init (GInitable *initable, gpu_kms = meta_gpu_kms_new (manager_kms, gpu_path, &secondary_error); if (!gpu_kms) { - g_warning ("Failed to open secondary gpu '%s': %s", - gpu_path, secondary_error->message); + if (g_error_matches (secondary_error, META_GPU_KMS_ERROR, META_GPU_KMS_ERROR_NO_CONNECTORS)) + g_message ("Ignoring GPU %s due to the lack of connectors", gpu_path); + else + g_warning ("Failed to open secondary gpu '%s': %s", gpu_path, secondary_error->message); + continue; }