summaryrefslogtreecommitdiff
path: root/src/backends/native/meta-cursor-renderer-native.c
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2018-05-02 20:32:43 +0200
committerJonas Ådahl <jadahl@gmail.com>2018-06-15 19:09:56 +0000
commit516fb524cbabdb543dbde5ed8e87978651cc2ad8 (patch)
tree09b4ba182c40f17d3b91384687f7ac99ef3d6fa5 /src/backends/native/meta-cursor-renderer-native.c
parent596b30096d86961506705dda134e9ee2330370fa (diff)
downloadmutter-516fb524cbabdb543dbde5ed8e87978651cc2ad8.tar.gz
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
Diffstat (limited to 'src/backends/native/meta-cursor-renderer-native.c')
-rw-r--r--src/backends/native/meta-cursor-renderer-native.c176
1 files 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,12 +1084,29 @@ 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)
{
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);