diff options
author | Jonas Ådahl <jadahl@gmail.com> | 2018-05-02 20:32:43 +0200 |
---|---|---|
committer | Jonas Ådahl <jadahl@gmail.com> | 2018-06-15 19:09:56 +0000 |
commit | 516fb524cbabdb543dbde5ed8e87978651cc2ad8 (patch) | |
tree | 09b4ba182c40f17d3b91384687f7ac99ef3d6fa5 /src/backends/native/meta-cursor-renderer-native.c | |
parent | 596b30096d86961506705dda134e9ee2330370fa (diff) | |
download | mutter-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.c | 176 |
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); |