diff options
author | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2018-03-17 21:57:08 -0300 |
---|---|---|
committer | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2018-03-21 03:01:54 -0300 |
commit | 67f8a3c52111a78313ae5b68ab8965f94672176f (patch) | |
tree | d5657d66efc3f6b390c498d2b2d0817b3a963ffe | |
parent | 602844ffcc562e45bb3ac9dee8ba6f757b9affeb (diff) | |
download | mutter-gbsneto/wayland-stutter.tar.gz |
gpu-kms: Ignore GPUs with no connectorsgbsneto/wayland-stutter
Mutter recently gained the ability to deal with multiple GPUs
rendering at different displays. These GPUs would have a display
connected to them, and Mutter was adapted in order to be aware
of different GPUs and their outputs.
However, one specific edge case appeared: PRIME systems. PRIME
systems have two GPUs:
* The integrated GPU (iGPU), usually Intel, which has connectors
and deals with the routine load.
* The dedicated GPU (dGPU), usually AMD or NVidia, which has no
connectors at all and are there just to aid heavy loads.
On those systems, the dGPU is aggressively put to sleep by the
kernel to avoid energy waste. Waking it up is a costly operation.
With Mutter's adaptation to deal with multiple GPUs, Mutter began
wakening the dGPU every time some rendering had to be done. This
was causing stuttering every time the dGPU was put to sleep, and
Mutter asked it to wake up again.
To fix this situation, this commit ignores GPUs with no connectors
attached.
Issue: #77
-rw-r--r-- | src/backends/native/meta-gpu-kms.c | 31 | ||||
-rw-r--r-- | src/backends/native/meta-gpu-kms.h | 8 | ||||
-rw-r--r-- | src/backends/native/meta-monitor-manager-kms.c | 7 |
3 files changed, 44 insertions, 2 deletions
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; } |