From 33529426a921325ecdc49d095ff8bfb9ad84993e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20=C5=81opatka?= Date: Sat, 6 Nov 2021 14:14:25 +0000 Subject: [PATCH] backend: Copy damage rectangles to secondary GPU when available Systems with AMD GPUs do not take advantage of Mutter's zero-copy path when driving DisplayLink screens. This is due to a very slow CPU access to the zero-copy texture. Instead they fall back on primary GPU doing a copy of the texture for fast CPU access. This commit accelerates texture copy by working through damage regions only. Tests on a 4K screen with windowed applications show significant reduction of GPU utilisation. Part-of: --- src/backends/native/meta-onscreen-native.c | 51 +++++++++++++++++----- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 8462d9ee3..1be4d3ca8 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -747,7 +747,9 @@ secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *seconda static gboolean copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) + MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, + const int *rectangles, + int n_rectangles) { CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); @@ -814,14 +816,37 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre error->message); return FALSE; } + /* Limit the number of individual copies to 16 */ +#define MAX_RECTS 16 - if (!cogl_blit_framebuffer (framebuffer, COGL_FRAMEBUFFER (dmabuf_fb), - 0, 0, 0, 0, - width, height, - &error)) + if (n_rectangles == 0 || n_rectangles > MAX_RECTS) { - g_object_unref (dmabuf_fb); - return FALSE; + if (!cogl_blit_framebuffer (framebuffer, COGL_FRAMEBUFFER (dmabuf_fb), + 0, 0, 0, 0, + width, height, + &error)) + { + g_object_unref (dmabuf_fb); + return FALSE; + } + } + else + { + int i; + + for (i = 0; i < n_rectangles; ++i) + { + if (!cogl_blit_framebuffer (framebuffer, COGL_FRAMEBUFFER (dmabuf_fb), + rectangles[i * 4], rectangles[i * 4 + 1], + rectangles[i * 4], rectangles[i * 4 + 1], + rectangles[i * 4 + 2], + rectangles[i * 4 + 3], + &error)) + { + g_object_unref (dmabuf_fb); + return FALSE; + } + } } g_object_unref (dmabuf_fb); @@ -890,7 +915,9 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen, } static void -update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen) +update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; @@ -920,7 +947,9 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen) G_GNUC_FALLTHROUGH; case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: if (!copy_shared_framebuffer_primary_gpu (onscreen, - secondary_gpu_state)) + secondary_gpu_state, + rectangles, + n_rectangles)) { if (!secondary_gpu_state->noted_primary_gpu_copy_failed) { @@ -1041,7 +1070,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, "Onscreen (swap-buffers)"); - update_secondary_gpu_state_pre_swap_buffers (onscreen); + update_secondary_gpu_state_pre_swap_buffers (onscreen, + rectangles, + n_rectangles); parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); parent_class->swap_buffers_with_damage (onscreen,