[mutter] renderer/native: Prefer hardware rendering for primary GPU



commit 22f865122cdab3a7b843c9e29e1da6b0c2f0b567
Author: Pekka Paalanen <pekka paalanen collabora com>
Date:   Mon Dec 10 16:49:58 2018 +0200

    renderer/native: Prefer hardware rendering for primary GPU
    
    Mutter prefers platform devices over anything else as the primary GPU.
    This will not work too well, when a platform device does not actually
    have a rendering GPU but is a display-only device. An example of this
    are DisplayLink devices with the proprietary driver stack, which exposes
    a DRM KMS platform device but without any rendering driver.
    
    Mutter cannot rely on EGL init failing on such devices either, because
    nowadays Mesa supports software renderers on GBM, so the initialization
    may well succeed.
    
    The hardware rendering capability is recognized by matching the GL
    renderer string to the known Mesa software renderers. At this time,
    there is no better alternative to detecting this.
    
    The secondary GPU data is abused for the GL renderer, as the Cogl
    context may not have been created yet.  Also, the Cogl context would
    only be created on the primary GPU, but at this point the primary GPU
    has not been chosen yet. Hence, GPU copy path GL context is used as a
    proxy and predictor of what the Cogl context might be if it was created.
    Mind, that even the GL flavour are not the same between Cogl and
    secondary contexts, so this is stretch but it should be just enough.
    
    The logic to choose the primary GPU is changed to always prefer hardware
    rendering devices while also maintaining the old order of preferring
    platform over boot_vga devices.
    
    Co-authored by: Emilio Pozuelo Monfort <emilio pozuelo collabora co uk>
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/271

 src/backends/native/meta-renderer-native.c | 91 ++++++++++++++++++++++--------
 1 file changed, 69 insertions(+), 22 deletions(-)
---
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index bd63347c8..1b74ae17c 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -112,6 +112,7 @@ typedef struct _MetaRendererNativeGpuData
    */
   struct {
     MetaSharedFramebufferCopyMode copy_mode;
+    gboolean is_hardware_rendering;
 
     /* For GPU blit mode */
     EGLContext egl_context;
@@ -3207,6 +3208,8 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
   EGLConfig egl_config;
   EGLContext egl_context;
   char **missing_gl_extensions;
+  const char *renderer_str;
+  gboolean is_hardware;
 
   if (!create_secondary_egl_config (egl, renderer_gpu_data->mode, egl_display,
                                     &egl_config, error))
@@ -3229,6 +3232,14 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
       return FALSE;
     }
 
+  renderer_str = (const char *) glGetString (GL_RENDERER);
+  if (g_str_has_prefix (renderer_str, "llvmpipe") ||
+      g_str_has_prefix (renderer_str, "softpipe") ||
+      g_str_has_prefix (renderer_str, "swrast"))
+    is_hardware = FALSE;
+  else
+    is_hardware = TRUE;
+
   if (!meta_gles3_has_extensions (renderer_native->gles3,
                                   &missing_gl_extensions,
                                   "GL_OES_EGL_image_external",
@@ -3244,6 +3255,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
       g_free (missing_gl_extensions);
     }
 
+  renderer_gpu_data->secondary.is_hardware_rendering = is_hardware;
   renderer_gpu_data->secondary.egl_context = egl_context;
   renderer_gpu_data->secondary.egl_config = egl_config;
   renderer_gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_GPU;
@@ -3254,6 +3266,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
 static void
 init_secondary_gpu_data_cpu (MetaRendererNativeGpuData *renderer_gpu_data)
 {
+  renderer_gpu_data->secondary.is_hardware_rendering = FALSE;
   renderer_gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_CPU;
 }
 
@@ -3272,6 +3285,16 @@ init_secondary_gpu_data (MetaRendererNativeGpuData *renderer_gpu_data)
   init_secondary_gpu_data_cpu (renderer_gpu_data);
 }
 
+static gboolean
+gpu_kms_is_hardware_rendering (MetaRendererNative *renderer_native,
+                               MetaGpuKms         *gpu_kms)
+{
+  MetaRendererNativeGpuData *data;
+
+  data = meta_renderer_native_get_gpu_data (renderer_native, gpu_kms);
+  return data->secondary.is_hardware_rendering;
+}
+
 static MetaRendererNativeGpuData *
 create_renderer_gpu_data_gbm (MetaRendererNative  *renderer_native,
                               MetaGpuKms          *gpu_kms,
@@ -3619,31 +3642,54 @@ on_gpu_added (MetaMonitorManager *monitor_manager,
 }
 
 static MetaGpuKms *
-choose_primary_gpu (MetaMonitorManager *manager)
+choose_primary_gpu (MetaMonitorManager *manager,
+                    MetaRendererNative *renderer_native)
 {
   GList *gpus = meta_monitor_manager_get_gpus (manager);
   GList *l;
+  int allow_sw;
 
-  /* Prefer a platform device */
-  for (l = gpus; l; l = l->next)
-    {
-      MetaGpuKms *gpu_kms = META_GPU_KMS (l->data);
-
-      if (meta_gpu_kms_is_platform_device (gpu_kms))
-        return gpu_kms;
-    }
-
-  /* Otherwise a device we booted with */
-  for (l = gpus; l; l = l->next)
-    {
-      MetaGpuKms *gpu_kms = META_GPU_KMS (l->data);
-
-      if (meta_gpu_kms_is_boot_vga (gpu_kms))
-        return gpu_kms;
-    }
-
-  /* Lastly, just pick the first device */
-  return META_GPU_KMS (gpus->data);
+  /*
+   * Check first hardware rendering devices, and if none found,
+   * then software rendering devices.
+   */
+  for (allow_sw = 0; allow_sw < 2; allow_sw++)
+  {
+    /* Prefer a platform device */
+    for (l = gpus; l; l = l->next)
+      {
+        MetaGpuKms *gpu_kms = META_GPU_KMS (l->data);
+
+        if (meta_gpu_kms_is_platform_device (gpu_kms) &&
+            (allow_sw == 1 ||
+             gpu_kms_is_hardware_rendering (renderer_native, gpu_kms)))
+          return gpu_kms;
+      }
+
+    /* Otherwise a device we booted with */
+    for (l = gpus; l; l = l->next)
+      {
+        MetaGpuKms *gpu_kms = META_GPU_KMS (l->data);
+
+        if (meta_gpu_kms_is_boot_vga (gpu_kms) &&
+            (allow_sw == 1 ||
+             gpu_kms_is_hardware_rendering (renderer_native, gpu_kms)))
+          return gpu_kms;
+      }
+
+    /* Fall back to any device */
+    for (l = gpus; l; l = l->next)
+      {
+        MetaGpuKms *gpu_kms = META_GPU_KMS (l->data);
+
+        if (allow_sw == 1 ||
+            gpu_kms_is_hardware_rendering (renderer_native, gpu_kms))
+          return gpu_kms;
+      }
+  }
+
+  g_assert_not_reached ();
+  return NULL;
 }
 
 static gboolean
@@ -3668,7 +3714,8 @@ meta_renderer_native_initable_init (GInitable     *initable,
         return FALSE;
     }
 
-  renderer_native->primary_gpu_kms = choose_primary_gpu (monitor_manager);
+  renderer_native->primary_gpu_kms = choose_primary_gpu (monitor_manager,
+                                                         renderer_native);
 
   return TRUE;
 }


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