[mutter] cursor-render/native: Realize hw cursor lazilly



commit 516fb524cbabdb543dbde5ed8e87978651cc2ad8
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed May 2 20:32:43 2018 +0200

    cursor-render/native: Realize hw cursor lazilly
    
    Where to realize a hardware cursor depends on where on the screen it
    will be displayed. For example it only needs buffers for the cursor
    plane on a certain GPU if it overlaps with a monitor that is connected
    said GPU.
    
    Previously, we were too eager with uploading the cursor plane buffers,
    which in effect resulted in the secondary GPU always being woken up
    when changing the cursor, even though the cursor plane would actually
    never be set unless the pointer cursor was moved to a monitor connected
    to the secondary GPU. These wake-ups caused noticable stuttering; thus
    by uploading the buffers more lazilly, the stuttering is avoided.
    
    Closes: https://gitlab.gnome.org/GNOME/mutter/issues/77

 src/backends/native/meta-cursor-renderer-native.c | 176 ++++++++++++----------
 1 file changed, 100 insertions(+), 76 deletions(-)
---
diff --git a/src/backends/native/meta-cursor-renderer-native.c 
b/src/backends/native/meta-cursor-renderer-native.c
index 910eb10ec..81df57b1c 100644
--- a/src/backends/native/meta-cursor-renderer-native.c
+++ b/src/backends/native/meta-cursor-renderer-native.c
@@ -121,7 +121,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_nativ
 
 static void
 realize_cursor_sprite (MetaCursorRenderer *renderer,
-                       MetaCursorSprite   *cursor_sprite);
+                       MetaCursorSprite   *cursor_sprite,
+                       GList              *gpus);
 
 static MetaCursorNativeGpuState *
 get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
@@ -575,19 +576,15 @@ can_draw_cursor_unscaled (MetaCursorRenderer *renderer,
 
 static gboolean
 should_have_hw_cursor (MetaCursorRenderer *renderer,
-                       MetaCursorSprite   *cursor_sprite)
+                       MetaCursorSprite   *cursor_sprite,
+                       GList              *gpus)
 {
-  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
-  MetaCursorRendererNativePrivate *priv =
-    meta_cursor_renderer_native_get_instance_private (native);
-  GList *gpus;
   GList *l;
   CoglTexture *texture;
 
   if (!cursor_sprite)
     return FALSE;
 
-  gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
   for (l = gpus; l; l = l->next)
     {
       MetaGpuKms *gpu_kms = l->data;
@@ -670,6 +667,54 @@ maybe_schedule_cursor_sprite_animation_frame (MetaCursorRendererNative *native,
     }
 }
 
+static GList *
+calculate_cursor_sprite_gpus (MetaCursorRenderer *renderer,
+                              MetaCursorSprite   *cursor_sprite)
+{
+  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
+  MetaCursorRendererNativePrivate *priv =
+    meta_cursor_renderer_native_get_instance_private (native);
+  MetaMonitorManager *monitor_manager = priv->monitor_manager;
+  GList *gpus = NULL;
+  GList *logical_monitors;
+  GList *l;
+  ClutterRect cursor_rect;
+
+  cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
+
+  logical_monitors =
+    meta_monitor_manager_get_logical_monitors (monitor_manager);
+  for (l = logical_monitors; l; l = l->next)
+    {
+      MetaLogicalMonitor *logical_monitor = l->data;
+      MetaRectangle logical_monitor_layout;
+      ClutterRect logical_monitor_rect;
+      GList *monitors, *l_mon;
+
+      logical_monitor_layout =
+        meta_logical_monitor_get_layout (logical_monitor);
+      logical_monitor_rect =
+        meta_rectangle_to_clutter_rect (&logical_monitor_layout);
+
+      if (!clutter_rect_intersection (&cursor_rect, &logical_monitor_rect,
+                                      NULL))
+        continue;
+
+      monitors = meta_logical_monitor_get_monitors (logical_monitor);
+      for (l_mon = monitors; l_mon; l_mon = l_mon->next)
+        {
+          MetaMonitor *monitor = l_mon->data;
+          MetaGpu *gpu;
+
+          gpu = meta_monitor_get_gpu (monitor);
+          if (!g_list_find (gpus, gpu))
+            gpus = g_list_prepend (gpus, gpu);
+        }
+    }
+
+  return gpus;
+}
+
 static gboolean
 meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
                                            MetaCursorSprite   *cursor_sprite)
@@ -677,13 +722,18 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
   MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
   MetaCursorRendererNativePrivate *priv =
     meta_cursor_renderer_native_get_instance_private (native);
+  g_autoptr (GList) gpus = NULL;
 
   if (cursor_sprite)
-    realize_cursor_sprite (renderer, cursor_sprite);
+    {
+      meta_cursor_sprite_realize_texture (cursor_sprite);
+      gpus = calculate_cursor_sprite_gpus (renderer, cursor_sprite);
+      realize_cursor_sprite (renderer, cursor_sprite, gpus);
+    }
 
   maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite);
 
-  priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite);
+  priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus);
   update_hw_cursor (native, cursor_sprite);
 
   return (priv->has_hw_cursor ||
@@ -875,8 +925,7 @@ is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite,
 static void
 realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer      *renderer,
                                               MetaGpuKms              *gpu_kms,
-                                              MetaCursorSpriteWayland *sprite_wayland,
-                                              struct wl_resource      *buffer)
+                                              MetaCursorSpriteWayland *sprite_wayland)
 {
   MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
   MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_wayland);
@@ -885,6 +934,9 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer      *renderer,
   uint64_t cursor_width, cursor_height;
   CoglTexture *texture;
   uint width, height;
+  MetaWaylandBuffer *buffer;
+  struct wl_resource *buffer_resource;
+  struct wl_shm_buffer *shm_buffer;
 
   cursor_renderer_gpu_data =
     meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
@@ -898,7 +950,15 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer      *renderer,
   width = cogl_texture_get_width (texture);
   height = cogl_texture_get_height (texture);
 
-  struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
+  buffer = meta_cursor_sprite_wayland_get_buffer (sprite_wayland);
+  if (!buffer)
+    return;
+
+  buffer_resource = meta_wayland_buffer_get_resource (buffer);
+  if (!buffer_resource)
+    return;
+
+  shm_buffer = wl_shm_buffer_get (buffer_resource);
   if (shm_buffer)
     {
       int rowstride = wl_shm_buffer_get_stride (shm_buffer);
@@ -972,49 +1032,17 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer      *renderer,
       set_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms, bo);
     }
 }
-
-static void
-realize_cursor_sprite_from_wl_buffer (MetaCursorRenderer      *renderer,
-                                      MetaCursorSpriteWayland *sprite_wayland)
-{
-  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
-  MetaCursorRendererNativePrivate *priv =
-    meta_cursor_renderer_native_get_instance_private (native);
-  MetaWaylandBuffer *buffer;
-  struct wl_resource *buffer_resource;
-  GList *gpus;
-  GList *l;
-
-  buffer = meta_cursor_sprite_wayland_get_buffer (sprite_wayland);
-  if (!buffer)
-    return;
-
-  buffer_resource = meta_wayland_buffer_get_resource (buffer);
-  if (!buffer_resource)
-    return;
-
-  gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
-  for (l = gpus; l; l = l->next)
-    {
-      MetaGpuKms *gpu_kms = l->data;
-
-      realize_cursor_sprite_from_wl_buffer_for_gpu (renderer,
-                                                    gpu_kms,
-                                                    sprite_wayland,
-                                                    buffer_resource);
-    }
-}
 #endif
 
 static void
 realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer      *renderer,
                                             MetaGpuKms              *gpu_kms,
-                                            MetaCursorSpriteXcursor *sprite_xcursor,
-                                            XcursorImage            *xc_image)
+                                            MetaCursorSpriteXcursor *sprite_xcursor)
 {
   MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
   MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
   MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor);
+  XcursorImage *xc_image;
 
   cursor_renderer_gpu_data =
     meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
@@ -1024,6 +1052,8 @@ realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer      *renderer,
   if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms))
     return;
 
+  xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor);
+
   load_cursor_sprite_gbm_buffer_for_gpu (native,
                                          gpu_kms,
                                          cursor_sprite,
@@ -1035,41 +1065,18 @@ realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer      *renderer,
 }
 
 static void
-realize_cursor_sprite_from_xcursor (MetaCursorRenderer      *renderer,
-                                    MetaCursorSpriteXcursor *sprite_xcursor)
-{
-  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
-  MetaCursorRendererNativePrivate *priv =
-    meta_cursor_renderer_native_get_instance_private (native);
-  XcursorImage *xc_image;
-  GList *gpus;
-  GList *l;
-
-  xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor);
-  gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
-  for (l = gpus; l; l = l->next)
-    {
-      MetaGpuKms *gpu_kms = l->data;
-
-      realize_cursor_sprite_from_xcursor_for_gpu (renderer,
-                                                  gpu_kms,
-                                                  sprite_xcursor,
-                                                  xc_image);
-    }
-}
-
-static void
-realize_cursor_sprite (MetaCursorRenderer *renderer,
-                       MetaCursorSprite   *cursor_sprite)
+realize_cursor_sprite_for_gpu (MetaCursorRenderer *renderer,
+                               MetaGpuKms         *gpu_kms,
+                               MetaCursorSprite   *cursor_sprite)
 {
-  meta_cursor_sprite_realize_texture (cursor_sprite);
-
   if (META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite))
     {
       MetaCursorSpriteXcursor *sprite_xcursor =
         META_CURSOR_SPRITE_XCURSOR (cursor_sprite);
 
-      realize_cursor_sprite_from_xcursor (renderer, sprite_xcursor);
+      realize_cursor_sprite_from_xcursor_for_gpu (renderer,
+                                                  gpu_kms,
+                                                  sprite_xcursor);
     }
 #ifdef HAVE_WAYLAND
   else if (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite))
@@ -1077,11 +1084,28 @@ realize_cursor_sprite (MetaCursorRenderer *renderer,
       MetaCursorSpriteWayland *sprite_wayland =
         META_CURSOR_SPRITE_WAYLAND (cursor_sprite);
 
-      realize_cursor_sprite_from_wl_buffer (renderer, sprite_wayland);
+      realize_cursor_sprite_from_wl_buffer_for_gpu (renderer,
+                                                    gpu_kms,
+                                                    sprite_wayland);
     }
 #endif
 }
 
+static void
+realize_cursor_sprite (MetaCursorRenderer *renderer,
+                       MetaCursorSprite   *cursor_sprite,
+                       GList              *gpus)
+{
+  GList *l;
+
+  for (l = gpus; l; l = l->next)
+    {
+      MetaGpuKms *gpu_kms = l->data;
+
+      realize_cursor_sprite_for_gpu (renderer, gpu_kms, cursor_sprite);
+    }
+}
+
 static void
 meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
 {


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