[mutter/gbsneto/wayland-stutter: 7/7] gpu-kms: Ignore GPUs with no connectors



commit 3832c6b607f92ae7043db60d9e69f5652fd97d70
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Sat Mar 17 21:57:08 2018 -0300

    gpu-kms: Ignore GPUs with no connectors
    
    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

 src/backends/native/meta-gpu-kms.c             | 31 ++++++++++++++++++++++++++
 src/backends/native/meta-gpu-kms.h             |  8 +++++++
 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;
         }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]