diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 95f7ec3d09d6fff177e14bb120f5e181f386b877..68254d9ad2e16a3d42f4cef9eba11bf4e2c695f3 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -1290,7 +1290,15 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen, /* prepare fallback */ G_GNUC_FALLTHROUGH; case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - if (!renderer_gpu_data->secondary.copy_mode_primary_force_cpu) + /* + * Only recover from a failed zero-copy using the primary GPU if we + * DIDN'T initialise to fall back to the secondary GPU. So our + * first recovery frame will be a CPU copy if required and then + * the second and subsequent frames will be secondary GPU copies. + */ + if (renderer_gpu_data->secondary.fallback_copy_mode != + META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU && + !renderer_gpu_data->secondary.copy_mode_primary_force_cpu) { copy = copy_shared_framebuffer_primary_gpu (onscreen, secondary_gpu_state, @@ -1360,7 +1368,13 @@ acquire_front_buffer (CoglOnscreen *onscreen, * in secondary_gpu_fb. */ renderer_gpu_data->secondary.copy_mode = - META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; + renderer_gpu_data->secondary.fallback_copy_mode; + /* + * Yes we fall through to primary copy mode to recover from a failed + * zero-copy even if the fallback mode is secondary. Because only + * primary can recover from a zero copy failure. On the next frame + * we will start using the fallback_copy_mode proper. + */ G_GNUC_FALLTHROUGH; case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: if (secondary_gpu_fb == NULL) @@ -2852,10 +2866,15 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_nat drm_format, width, height); - secondary_gpu_state = g_new0 (MetaOnscreenNativeSecondaryGpuState, 1); - secondary_gpu_state->renderer_gpu_data = renderer_gpu_data; - secondary_gpu_state->gpu_kms = gpu_kms; - secondary_gpu_state->egl_surface = EGL_NO_SURFACE; + secondary_gpu_state = onscreen_native->secondary_gpu_state; + /* Coexist with init_secondary_gpu_state_gpu_copy_mode if it was used... */ + if (!secondary_gpu_state) + { + secondary_gpu_state = g_new0 (MetaOnscreenNativeSecondaryGpuState, 1); + secondary_gpu_state->renderer_gpu_data = renderer_gpu_data; + secondary_gpu_state->gpu_kms = gpu_kms; + secondary_gpu_state->egl_surface = EGL_NO_SURFACE; + } for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++) { @@ -2899,41 +2918,21 @@ init_secondary_gpu_state (MetaRendererNative *renderer_native, renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, META_GPU_KMS (gpu)); - switch (renderer_gpu_data->secondary.copy_mode) + if ((renderer_gpu_data->secondary.fallback_copy_mode == + META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU) && + !init_secondary_gpu_state_gpu_copy_mode (renderer_native, + onscreen, + renderer_gpu_data, + &local_error)) { - case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU: - if (init_secondary_gpu_state_gpu_copy_mode (renderer_native, - onscreen, - renderer_gpu_data, - &local_error)) - return TRUE; - - g_warning ("Secondary GPU initialization failed (%s). " - "Falling back to GPU-less mode instead, so the " - "secondary monitor may be slow to update.", - local_error->message); - - renderer_gpu_data->secondary.copy_mode = - META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO; - - G_GNUC_FALLTHROUGH; - case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO: - /* - * Initialize also the primary copy mode, so that if zero-copy - * path fails, which is quite likely, we can simply continue - * with the primary copy path on the very first frame. - */ - G_GNUC_FALLTHROUGH; - case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - if (!init_secondary_gpu_state_cpu_copy_mode (renderer_native, - onscreen, - renderer_gpu_data, - error)) - return FALSE; - break; + renderer_gpu_data->secondary.fallback_copy_mode = + META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; } - return TRUE; + return init_secondary_gpu_state_cpu_copy_mode (renderer_native, + onscreen, + renderer_gpu_data, + error); } void diff --git a/src/backends/native/meta-renderer-native-private.h b/src/backends/native/meta-renderer-native-private.h index 9c7887a1efcd009bf86f119e7c6af0f57a30b1da..86793e0ffa80db3f531f7bb56d18b20bf58f8242 100644 --- a/src/backends/native/meta-renderer-native-private.h +++ b/src/backends/native/meta-renderer-native-private.h @@ -60,6 +60,7 @@ typedef struct _MetaRendererNativeGpuData struct { MetaSharedFramebufferCopyMode copy_mode; gboolean copy_mode_primary_force_cpu; + MetaSharedFramebufferCopyMode fallback_copy_mode; gboolean has_EGL_EXT_image_dma_buf_import_modifiers; gboolean needs_explicit_sync; diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 8af326121820a7744005512a4c55445a4d882f72..42c325ac922452ffbb7d5ebc61c44287ca6a33a0 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -1919,7 +1919,7 @@ set_default_secondary_gpu_copy_mode (MetaRendererNativeGpuData *gpu_data) { const char *copy_mode; - gpu_data->secondary.copy_mode = + gpu_data->secondary.fallback_copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU; copy_mode = getenv ("MUTTER_DEBUG_MULTI_GPU_FORCE_COPY_MODE"); @@ -1928,16 +1928,16 @@ set_default_secondary_gpu_copy_mode (MetaRendererNativeGpuData *gpu_data) if (strcmp (copy_mode, "primary-gpu-gpu") == 0) { - gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; + gpu_data->secondary.fallback_copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; } else if (strcmp (copy_mode, "primary-gpu-cpu") == 0) { - gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; + gpu_data->secondary.fallback_copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; gpu_data->secondary.copy_mode_primary_force_cpu = TRUE; } else if (strcmp (copy_mode, "zero-copy") == 0) { - gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO; + gpu_data->secondary.fallback_copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO; } } @@ -2039,27 +2039,22 @@ out: return ret; } -static void -init_secondary_gpu_data_cpu (MetaRendererNativeGpuData *renderer_gpu_data) -{ - /* First try ZERO, it automatically falls back to PRIMARY as needed */ - renderer_gpu_data->secondary.copy_mode = - META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO; -} - static void init_secondary_gpu_data (MetaRendererNativeGpuData *renderer_gpu_data) { GError *error = NULL; + renderer_gpu_data->secondary.copy_mode = + META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO; + renderer_gpu_data->secondary.fallback_copy_mode = + META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; + if (init_secondary_gpu_data_gpu (renderer_gpu_data, &error)) return; g_message ("Failed to initialize accelerated iGPU/dGPU framebuffer sharing: %s", error->message); g_error_free (error); - - init_secondary_gpu_data_cpu (renderer_gpu_data); } static gboolean