vnc: Fix cursor updates
Now that overlapping outputs are a thing, we have a problem with vnc cursors. The surface->damage used to update the vnc cursor might actually be flushed by a previous output's repaint cycle, leading to a missing cursor update to the vnc client. Instead we should use the damage accumulated on the cursor plane to choose when to update the cursor. This damage is in output coordinates, so let's be lazy and just use the presence of damage as an indicator that the cursor needs an update. Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
parent
0def955a48
commit
bbaba601c8
@ -534,14 +534,57 @@ vnc_output_update_cursor(struct vnc_output *output)
|
|||||||
struct vnc_backend *backend = output->backend;
|
struct vnc_backend *backend = output->backend;
|
||||||
struct weston_pointer *pointer;
|
struct weston_pointer *pointer;
|
||||||
struct weston_paint_node *pointer_pnode = NULL;
|
struct weston_paint_node *pointer_pnode = NULL;
|
||||||
struct weston_view *view;
|
bool update_cursor;
|
||||||
|
pixman_region32_t damage;
|
||||||
struct weston_buffer *buffer;
|
struct weston_buffer *buffer;
|
||||||
|
struct weston_surface *cursor_surface;
|
||||||
struct nvnc_fb *fb;
|
struct nvnc_fb *fb;
|
||||||
int32_t stride;
|
int32_t stride;
|
||||||
uint32_t format;
|
|
||||||
uint8_t *src, *dst;
|
uint8_t *src, *dst;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
pointer = vnc_output_get_pointer(output, &pointer_pnode);
|
||||||
|
|
||||||
|
pixman_region32_init(&damage);
|
||||||
|
weston_output_flush_damage_for_plane(&output->base, &output->cursor_plane, &damage);
|
||||||
|
update_cursor = pixman_region32_not_empty(&damage);
|
||||||
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
|
if (!update_cursor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cursor_surface = output->cursor_surface;
|
||||||
|
buffer = cursor_surface->buffer_ref.buffer;
|
||||||
|
|
||||||
|
stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
|
||||||
|
|
||||||
|
fb = nvnc_fb_new(buffer->width, buffer->height, DRM_FORMAT_ARGB8888,
|
||||||
|
buffer->width);
|
||||||
|
assert(fb);
|
||||||
|
|
||||||
|
src = wl_shm_buffer_get_data(buffer->shm_buffer);
|
||||||
|
dst = nvnc_fb_get_addr(fb);
|
||||||
|
|
||||||
|
wl_shm_buffer_begin_access(buffer->shm_buffer);
|
||||||
|
for (i = 0; i < buffer->height; i++)
|
||||||
|
memcpy(dst + i * 4 * buffer->width, src + i * stride,
|
||||||
|
4 * buffer->width);
|
||||||
|
wl_shm_buffer_end_access(buffer->shm_buffer);
|
||||||
|
|
||||||
|
nvnc_set_cursor(backend->server, fb, buffer->width, buffer->height,
|
||||||
|
pointer->hotspot.c.x, pointer->hotspot.c.y, true);
|
||||||
|
nvnc_fb_unref(fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vnc_output_assign_cursor_plane(struct vnc_output *output)
|
||||||
|
{
|
||||||
|
struct weston_pointer *pointer;
|
||||||
|
struct weston_paint_node *pointer_pnode = NULL;
|
||||||
|
struct weston_view *view;
|
||||||
|
struct weston_buffer *buffer;
|
||||||
|
uint32_t format;
|
||||||
|
|
||||||
pointer = vnc_output_get_pointer(output, &pointer_pnode);
|
pointer = vnc_output_get_pointer(output, &pointer_pnode);
|
||||||
if (!pointer)
|
if (!pointer)
|
||||||
return;
|
return;
|
||||||
@ -562,30 +605,7 @@ vnc_output_update_cursor(struct vnc_output *output)
|
|||||||
|
|
||||||
weston_paint_node_move_to_plane(pointer_pnode, &output->cursor_plane);
|
weston_paint_node_move_to_plane(pointer_pnode, &output->cursor_plane);
|
||||||
|
|
||||||
if (view->surface == output->cursor_surface &&
|
|
||||||
!pixman_region32_not_empty(&view->surface->damage))
|
|
||||||
return;
|
|
||||||
|
|
||||||
output->cursor_surface = view->surface;
|
output->cursor_surface = view->surface;
|
||||||
|
|
||||||
stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
|
|
||||||
|
|
||||||
fb = nvnc_fb_new(buffer->width, buffer->height, DRM_FORMAT_ARGB8888,
|
|
||||||
buffer->width);
|
|
||||||
assert(fb);
|
|
||||||
|
|
||||||
src = wl_shm_buffer_get_data(buffer->shm_buffer);
|
|
||||||
dst = nvnc_fb_get_addr(fb);
|
|
||||||
|
|
||||||
wl_shm_buffer_begin_access(buffer->shm_buffer);
|
|
||||||
for (i = 0; i < buffer->height; i++)
|
|
||||||
memcpy(dst + i * 4 * buffer->width, src + i * stride,
|
|
||||||
4 * buffer->width);
|
|
||||||
wl_shm_buffer_end_access(buffer->shm_buffer);
|
|
||||||
|
|
||||||
nvnc_set_cursor(backend->server, fb, buffer->width, buffer->height,
|
|
||||||
pointer->hotspot.c.x, pointer->hotspot.c.y, true);
|
|
||||||
nvnc_fb_unref(fb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -994,6 +1014,8 @@ vnc_output_repaint(struct weston_output *base, pixman_region32_t *damage)
|
|||||||
if (wl_list_empty(&output->peers))
|
if (wl_list_empty(&output->peers))
|
||||||
weston_output_power_off(base);
|
weston_output_power_off(base);
|
||||||
|
|
||||||
|
vnc_output_update_cursor(output);
|
||||||
|
|
||||||
if (pixman_region32_not_empty(damage)) {
|
if (pixman_region32_not_empty(damage)) {
|
||||||
vnc_update_buffer(output->display, damage);
|
vnc_update_buffer(output->display, damage);
|
||||||
}
|
}
|
||||||
@ -1036,7 +1058,7 @@ vnc_output_assign_planes(struct weston_output *base)
|
|||||||
|
|
||||||
/* Update VNC cursor and move cursor view to plane */
|
/* Update VNC cursor and move cursor view to plane */
|
||||||
if (vnc_clients_support_cursor(output))
|
if (vnc_clients_support_cursor(output))
|
||||||
vnc_output_update_cursor(output);
|
vnc_output_assign_cursor_plane(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -322,4 +322,9 @@ void
|
|||||||
notify_tablet_tool_frame(struct weston_tablet_tool *tool,
|
notify_tablet_tool_frame(struct weston_tablet_tool *tool,
|
||||||
const struct timespec *time);
|
const struct timespec *time);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_output_flush_damage_for_plane(struct weston_output *output,
|
||||||
|
struct weston_plane *plane,
|
||||||
|
pixman_region32_t *damage);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3364,7 +3364,7 @@ weston_output_take_feedback_list(struct weston_output *output,
|
|||||||
wl_list_init(&surface->feedback_list);
|
wl_list_init(&surface->feedback_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
WL_EXPORT bool
|
||||||
weston_output_flush_damage_for_plane(struct weston_output *output,
|
weston_output_flush_damage_for_plane(struct weston_output *output,
|
||||||
struct weston_plane *plane,
|
struct weston_plane *plane,
|
||||||
pixman_region32_t *damage)
|
pixman_region32_t *damage)
|
||||||
|
Loading…
Reference in New Issue
Block a user