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
This commit is contained in:
parent
60ac2838b5
commit
22f865122c
@ -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,17 +3642,27 @@ 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;
|
||||
|
||||
/*
|
||||
* 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))
|
||||
if (meta_gpu_kms_is_platform_device (gpu_kms) &&
|
||||
(allow_sw == 1 ||
|
||||
gpu_kms_is_hardware_rendering (renderer_native, gpu_kms)))
|
||||
return gpu_kms;
|
||||
}
|
||||
|
||||
@ -3638,12 +3671,25 @@ choose_primary_gpu (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaGpuKms *gpu_kms = META_GPU_KMS (l->data);
|
||||
|
||||
if (meta_gpu_kms_is_boot_vga (gpu_kms))
|
||||
if (meta_gpu_kms_is_boot_vga (gpu_kms) &&
|
||||
(allow_sw == 1 ||
|
||||
gpu_kms_is_hardware_rendering (renderer_native, gpu_kms)))
|
||||
return gpu_kms;
|
||||
}
|
||||
|
||||
/* Lastly, just pick the first device */
|
||||
return META_GPU_KMS (gpus->data);
|
||||
/* 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user