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
This commit is contained in:
parent
596b30096d
commit
516fb524cb
@ -121,7 +121,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_nativ
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
realize_cursor_sprite (MetaCursorRenderer *renderer,
|
realize_cursor_sprite (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite);
|
MetaCursorSprite *cursor_sprite,
|
||||||
|
GList *gpus);
|
||||||
|
|
||||||
static MetaCursorNativeGpuState *
|
static MetaCursorNativeGpuState *
|
||||||
get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
|
get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
|
||||||
@ -575,19 +576,15 @@ can_draw_cursor_unscaled (MetaCursorRenderer *renderer,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
should_have_hw_cursor (MetaCursorRenderer *renderer,
|
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;
|
GList *l;
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
|
|
||||||
if (!cursor_sprite)
|
if (!cursor_sprite)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
|
|
||||||
for (l = gpus; l; l = l->next)
|
for (l = gpus; l; l = l->next)
|
||||||
{
|
{
|
||||||
MetaGpuKms *gpu_kms = l->data;
|
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
|
static gboolean
|
||||||
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
|
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite)
|
MetaCursorSprite *cursor_sprite)
|
||||||
@ -677,13 +722,18 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
|
|||||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||||
MetaCursorRendererNativePrivate *priv =
|
MetaCursorRendererNativePrivate *priv =
|
||||||
meta_cursor_renderer_native_get_instance_private (native);
|
meta_cursor_renderer_native_get_instance_private (native);
|
||||||
|
g_autoptr (GList) gpus = NULL;
|
||||||
|
|
||||||
if (cursor_sprite)
|
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);
|
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);
|
update_hw_cursor (native, cursor_sprite);
|
||||||
|
|
||||||
return (priv->has_hw_cursor ||
|
return (priv->has_hw_cursor ||
|
||||||
@ -875,8 +925,7 @@ is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite,
|
|||||||
static void
|
static void
|
||||||
realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
|
realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
|
||||||
MetaGpuKms *gpu_kms,
|
MetaGpuKms *gpu_kms,
|
||||||
MetaCursorSpriteWayland *sprite_wayland,
|
MetaCursorSpriteWayland *sprite_wayland)
|
||||||
struct wl_resource *buffer)
|
|
||||||
{
|
{
|
||||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||||
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_wayland);
|
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;
|
uint64_t cursor_width, cursor_height;
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
uint width, height;
|
uint width, height;
|
||||||
|
MetaWaylandBuffer *buffer;
|
||||||
|
struct wl_resource *buffer_resource;
|
||||||
|
struct wl_shm_buffer *shm_buffer;
|
||||||
|
|
||||||
cursor_renderer_gpu_data =
|
cursor_renderer_gpu_data =
|
||||||
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
|
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);
|
width = cogl_texture_get_width (texture);
|
||||||
height = cogl_texture_get_height (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)
|
if (shm_buffer)
|
||||||
{
|
{
|
||||||
int rowstride = wl_shm_buffer_get_stride (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);
|
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
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer,
|
realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer,
|
||||||
MetaGpuKms *gpu_kms,
|
MetaGpuKms *gpu_kms,
|
||||||
MetaCursorSpriteXcursor *sprite_xcursor,
|
MetaCursorSpriteXcursor *sprite_xcursor)
|
||||||
XcursorImage *xc_image)
|
|
||||||
{
|
{
|
||||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||||
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
||||||
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor);
|
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor);
|
||||||
|
XcursorImage *xc_image;
|
||||||
|
|
||||||
cursor_renderer_gpu_data =
|
cursor_renderer_gpu_data =
|
||||||
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
|
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))
|
if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor);
|
||||||
|
|
||||||
load_cursor_sprite_gbm_buffer_for_gpu (native,
|
load_cursor_sprite_gbm_buffer_for_gpu (native,
|
||||||
gpu_kms,
|
gpu_kms,
|
||||||
cursor_sprite,
|
cursor_sprite,
|
||||||
@ -1035,41 +1065,18 @@ realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
realize_cursor_sprite_from_xcursor (MetaCursorRenderer *renderer,
|
realize_cursor_sprite_for_gpu (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSpriteXcursor *sprite_xcursor)
|
MetaGpuKms *gpu_kms,
|
||||||
|
MetaCursorSprite *cursor_sprite)
|
||||||
{
|
{
|
||||||
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)
|
|
||||||
{
|
|
||||||
meta_cursor_sprite_realize_texture (cursor_sprite);
|
|
||||||
|
|
||||||
if (META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite))
|
if (META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite))
|
||||||
{
|
{
|
||||||
MetaCursorSpriteXcursor *sprite_xcursor =
|
MetaCursorSpriteXcursor *sprite_xcursor =
|
||||||
META_CURSOR_SPRITE_XCURSOR (cursor_sprite);
|
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
|
#ifdef HAVE_WAYLAND
|
||||||
else if (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite))
|
else if (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite))
|
||||||
@ -1077,11 +1084,28 @@ realize_cursor_sprite (MetaCursorRenderer *renderer,
|
|||||||
MetaCursorSpriteWayland *sprite_wayland =
|
MetaCursorSpriteWayland *sprite_wayland =
|
||||||
META_CURSOR_SPRITE_WAYLAND (cursor_sprite);
|
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
|
#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
|
static void
|
||||||
meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
|
meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user