[mutter] backend: Copy damage rectangles to secondary GPU when available



commit 33529426a921325ecdc49d095ff8bfb9ad84993e
Author: Piotr Łopatka <piotr lopatka gmail com>
Date:   Sat Nov 6 14:14:25 2021 +0000

    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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2033>

 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 8462d9ee35..1be4d3ca83 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,


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