From a075038d3e43d44627b9b21981b1c8dc54b9ec42 Mon Sep 17 00:00:00 2001 From: Daniel van Vugt Date: Fri, 5 Mar 2021 18:54:39 +0800 Subject: [PATCH 1/2] renderer-native: Try to choose the first matching EGL config As per regular `eglChooseConfig` semantics, which means choosing the highest color depth. The reason why it was hard-coded to `GBM_FORMAT_XRGB8888` originates from commit 712ec30cd9 to fix https://gitlab.gnome.org/GNOME/mutter/issues/2 However that entire problem was later removed by commit 14c706e51b, so we don't need to limit the GBM format any more. In practice this means most systems should now get a 30-bit color mode set instead of 24-bit. This works on modern Intel systems (the 'iris' Mesa driver) for example. It doesn't work on Raspberry Pi FKMS though, which is one reason why we also need to check the pixel format support of the primary plane here... **Performance considerations** For most drivers we would expect no change in memory bandwidth requirements since both the old and new formats are 4 bytes per pixel. Compositing of native Wayland GL clients is made slightly more efficient using 30-bit because they already default to XR30 or AR30 formats when possible. Only legacy Xwayland clients and most SHM clients still using 24-bit color will see slightly slower compositing. --- src/backends/native/meta-renderer-native.c | 87 ++++++++++++++++++++-- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index f8de8b30398..8fc99777b2a 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -407,6 +407,49 @@ choose_egl_config_from_gbm_format (MetaEgl *egl, return FALSE; } +static gboolean +all_crtcs_support_egl_config (MetaGpu *gpu, + MetaEgl *egl, + EGLDisplay egl_display, + EGLConfig egl_config) +{ + EGLint visual_id; + uint32_t format; + GList *c; + + if (!meta_egl_get_config_attrib (egl, + egl_display, + egl_config, + EGL_NATIVE_VISUAL_ID, + &visual_id, + NULL)) + return FALSE; + + format = (uint32_t) visual_id; + + for (c = meta_gpu_get_crtcs (gpu); c; c = c->next) + { + MetaCrtc *crtc = c->data; + MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); + + if (!meta_crtc_kms_supports_format (crtc_kms, format)) + return FALSE; + } + + return TRUE; +} + +static gboolean +force_8bpc (void) +{ + static GOnce get_once = G_ONCE_INIT; + char *env = g_once (&get_once, + (GThreadFunc) g_getenv, + (gpointer) "MUTTER_FORCE_8BPC"); + + return env ? TRUE : FALSE; +} + static gboolean meta_renderer_native_choose_egl_config (CoglDisplay *cogl_display, EGLint *attributes, @@ -420,6 +463,7 @@ meta_renderer_native_choose_egl_config (CoglDisplay *cogl_display, MetaEgl *egl = meta_backend_get_egl (backend); MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; EGLDisplay egl_display = cogl_renderer_egl->edpy; + MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); switch (renderer_gpu_data->mode) { @@ -431,6 +475,33 @@ meta_renderer_native_choose_egl_config (CoglDisplay *cogl_display, }; int i; + if (!force_8bpc ()) + { + if (meta_egl_choose_first_config (egl, + egl_display, + attributes, + out_config, + error)) + { + MetaGpuKms *gpu_kms = renderer_native->primary_gpu_kms; + + g_warn_if_fail (gpu_kms != NULL); + + if (gpu_kms != NULL && + all_crtcs_support_egl_config (META_GPU (gpu_kms), + egl, + egl_display, + *out_config)) + return TRUE; + } + else + { + g_warning ("Failed to choose first EGL config: %s", + (*error)->message); + g_clear_error (error); + } + } + for (i = 0; i < G_N_ELEMENTS (formats); i++) { g_clear_error (error); @@ -1536,20 +1607,22 @@ create_secondary_egl_config (MetaEgl *egl, { case META_RENDERER_NATIVE_MODE_GBM: case META_RENDERER_NATIVE_MODE_SURFACELESS: - return choose_egl_config_from_gbm_format (egl, - egl_display, - attributes, - GBM_FORMAT_XRGB8888, - egl_config, - error); + if (force_8bpc ()) + return choose_egl_config_from_gbm_format (egl, + egl_display, + attributes, + GBM_FORMAT_XRGB8888, + egl_config, + error); #ifdef HAVE_EGL_DEVICE + G_GNUC_FALLTHROUGH; case META_RENDERER_NATIVE_MODE_EGL_DEVICE: +#endif return meta_egl_choose_first_config (egl, egl_display, attributes, egl_config, error); -#endif } return FALSE; -- GitLab From a9f9cb55d9ce9f02e6fa4cd3d5766f14da1b72a1 Mon Sep 17 00:00:00 2001 From: Daniel van Vugt Date: Fri, 1 Jul 2022 16:13:31 +0800 Subject: [PATCH 2/2] onscreen-native: Check zero-copy buffer format is supported by secondary GPU Otherwise importing a deep color buffer on DisplayLink would succeed but then forever fail to post, because the CRTC doesn't support deep color. We don't have a post-posting fallback path so check for compatibility during the first import attempt. This way we get a clean fallback to `COPY_MODE_PRIMARY`. --- src/backends/native/meta-onscreen-native.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index b3f53b4aaac..3c80b4a2448 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -547,6 +547,8 @@ import_shared_framebuffer (CoglOnscreen *onscreen, MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, MetaDrmBuffer *primary_gpu_fb) { + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); + MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); MetaRenderDevice *render_device; g_autoptr (GError) error = NULL; MetaDrmBuffer *imported_buffer; @@ -571,6 +573,23 @@ import_shared_framebuffer (CoglOnscreen *onscreen, return NULL; } + if (!meta_crtc_kms_supports_format (crtc_kms, + meta_drm_buffer_get_format (imported_buffer))) + { + meta_topic (META_DEBUG_KMS, + "Zero-copy disabled for %s, " + "secondary GPU CRTC doesn't support the buffer format.", + meta_render_device_get_name (render_device)); + + g_warn_if_fail (secondary_gpu_state->import_status == + META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE); + secondary_gpu_state->import_status = + META_SHARED_FRAMEBUFFER_IMPORT_STATUS_FAILED; + + g_clear_object (&imported_buffer); + return NULL; + } + if (secondary_gpu_state->import_status == META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE) { -- GitLab