From a951fbb2645105f8d34e76a2ef5d579bec205d52 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 7 Mar 2018 10:22:39 +0100 Subject: [PATCH 1/3] output: don't move hidden cursors When using the DRM backend and multiple outputs, that reduces the number of commits. --- types/wlr_output.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/types/wlr_output.c b/types/wlr_output.c index 96c9d324..15bb3577 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -846,12 +846,18 @@ bool wlr_output_cursor_move(struct wlr_output_cursor *cursor, output_cursor_damage_whole(cursor); } + bool was_visible = cursor->visible; x *= cursor->output->scale; y *= cursor->output->scale; cursor->x = x; cursor->y = y; output_cursor_update_visible(cursor); + if (!was_visible && !cursor->visible) { + // Cursor is still hidden, do nothing + return true; + } + if (cursor->output->hardware_cursor != cursor) { output_cursor_damage_whole(cursor); return true; From 8e3d294d6a84ca71b4dfac6b9041b01f228a6a15 Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 11 Mar 2018 11:21:40 +0100 Subject: [PATCH 2/3] output: fix trailing cursor at (0, 0) on startup --- types/wlr_output.c | 52 ++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/types/wlr_output.c b/types/wlr_output.c index 15bb3577..7f19d1fe 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -669,6 +669,31 @@ static void output_cursor_reset(struct wlr_output_cursor *cursor) { } } +static void output_cursor_update_visible(struct wlr_output_cursor *cursor) { + struct wlr_box output_box; + output_box.x = output_box.y = 0; + wlr_output_transformed_resolution(cursor->output, &output_box.width, + &output_box.height); + + struct wlr_box cursor_box; + output_cursor_get_box(cursor, &cursor_box); + + struct wlr_box intersection; + bool visible = + wlr_box_intersection(&output_box, &cursor_box, &intersection); + + if (cursor->surface != NULL) { + if (cursor->visible && !visible) { + wlr_surface_send_leave(cursor->surface, cursor->output); + } + if (!cursor->visible && visible) { + wlr_surface_send_enter(cursor->surface, cursor->output); + } + } + + cursor->visible = visible; +} + bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y) { @@ -682,6 +707,7 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, cursor->height = height; cursor->hotspot_x = hotspot_x; cursor->hotspot_y = hotspot_y; + output_cursor_update_visible(cursor); struct wlr_output_cursor *hwcur = cursor->output->hardware_cursor; if (cursor->output->impl->set_cursor && (hwcur == NULL || hwcur == cursor)) { @@ -716,31 +742,6 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, stride, width, height, pixels); } -static void output_cursor_update_visible(struct wlr_output_cursor *cursor) { - struct wlr_box output_box; - output_box.x = output_box.y = 0; - wlr_output_transformed_resolution(cursor->output, &output_box.width, - &output_box.height); - - struct wlr_box cursor_box; - output_cursor_get_box(cursor, &cursor_box); - - struct wlr_box intersection; - bool visible = - wlr_box_intersection(&output_box, &cursor_box, &intersection); - - if (cursor->surface != NULL) { - if (cursor->visible && !visible) { - wlr_surface_send_leave(cursor->surface, cursor->output); - } - if (!cursor->visible && visible) { - wlr_surface_send_enter(cursor->surface, cursor->output); - } - } - - cursor->visible = visible; -} - static void output_cursor_commit(struct wlr_output_cursor *cursor) { if (cursor->output->hardware_cursor != cursor) { output_cursor_damage_whole(cursor); @@ -882,6 +883,7 @@ struct wlr_output_cursor *wlr_output_cursor_create(struct wlr_output *output) { wl_list_init(&cursor->surface_destroy.link); cursor->surface_destroy.notify = output_cursor_handle_destroy; wl_list_insert(&output->cursors, &cursor->link); + cursor->visible = true; // default position is at (0, 0) return cursor; } From 92ca4ad474b16ff213d2ac7a7113816c38cf4325 Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 11 Mar 2018 11:40:03 +0100 Subject: [PATCH 3/3] backend/drm: refactor wlr_drm_connector_set_cursor --- backend/drm/drm.c | 94 ++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 3b714300..fcadeb09 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -544,10 +544,10 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, if (!crtc) { return false; } - struct wlr_drm_plane *plane = crtc->cursor; - // We don't have a real cursor plane, so we make a fake one + struct wlr_drm_plane *plane = crtc->cursor; if (!plane) { + // We don't have a real cursor plane, so we make a fake one plane = calloc(1, sizeof(*plane)); if (!plane) { wlr_log_errno(L_ERROR, "Allocation failed"); @@ -556,16 +556,6 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, crtc->cursor = plane; } - if (!buf && update_pixels) { - // Hide the cursor - plane->cursor_enabled = false; - if (!drm->session->active) { - return true; - } - return drm->iface->crtc_set_cursor(drm, crtc, NULL); - } - plane->cursor_enabled = true; - if (!plane->surf.gbm) { int ret; uint64_t w, h; @@ -607,10 +597,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, } } - struct wlr_box hotspot = { - .x = hotspot_x, - .y = hotspot_y, - }; + struct wlr_box hotspot = { .x = hotspot_x, .y = hotspot_y }; enum wl_output_transform transform = wlr_output_transform_invert(output->transform); wlr_box_transform(&hotspot, transform, @@ -620,49 +607,54 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, if (!update_pixels) { // Only update the cursor hotspot + wlr_output_update_needs_swap(output); return true; } - struct gbm_bo *bo = plane->cursor_bo; - uint32_t bo_width = gbm_bo_get_width(bo); - uint32_t bo_height = gbm_bo_get_height(bo); - uint32_t bo_stride; - void *bo_data; + plane->cursor_enabled = buf != NULL; - if (!gbm_bo_map(bo, 0, 0, bo_width, bo_height, - GBM_BO_TRANSFER_WRITE, &bo_stride, &bo_data)) { - wlr_log_errno(L_ERROR, "Unable to map buffer"); - return false; + if (buf != NULL) { + uint32_t bo_width = gbm_bo_get_width(plane->cursor_bo); + uint32_t bo_height = gbm_bo_get_height(plane->cursor_bo); + + uint32_t bo_stride; + void *bo_data; + if (!gbm_bo_map(plane->cursor_bo, 0, 0, bo_width, bo_height, + GBM_BO_TRANSFER_WRITE, &bo_stride, &bo_data)) { + wlr_log_errno(L_ERROR, "Unable to map buffer"); + return false; + } + + wlr_drm_surface_make_current(&plane->surf, NULL); + + wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888, + stride, width, height, buf); + + glViewport(0, 0, plane->surf.width, plane->surf.height); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + float matrix[16]; + wlr_texture_get_matrix(plane->wlr_tex, &matrix, &plane->matrix, 0, 0); + wlr_render_with_matrix(plane->surf.renderer->wlr_rend, plane->wlr_tex, + &matrix, 1.0f); + + glFinish(); + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, bo_stride); + glReadPixels(0, 0, plane->surf.width, plane->surf.height, GL_BGRA_EXT, + GL_UNSIGNED_BYTE, bo_data); + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); + + wlr_drm_surface_swap_buffers(&plane->surf, NULL); + + gbm_bo_unmap(plane->cursor_bo, bo_data); } - wlr_drm_surface_make_current(&plane->surf, NULL); - - wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888, - stride, width, height, buf); - - glViewport(0, 0, plane->surf.width, plane->surf.height); - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - float matrix[16]; - wlr_texture_get_matrix(plane->wlr_tex, &matrix, &plane->matrix, 0, 0); - wlr_render_with_matrix(plane->surf.renderer->wlr_rend, plane->wlr_tex, - &matrix, 1.0f); - - glFinish(); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, bo_stride); - glReadPixels(0, 0, plane->surf.width, plane->surf.height, GL_BGRA_EXT, - GL_UNSIGNED_BYTE, bo_data); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - - wlr_drm_surface_swap_buffers(&plane->surf, NULL); - - gbm_bo_unmap(bo, bo_data); - if (!drm->session->active) { - return true; + return true; // will be committed when session is resumed } + struct gbm_bo *bo = plane->cursor_enabled ? plane->cursor_bo : NULL; bool ok = drm->iface->crtc_set_cursor(drm, crtc, bo); if (ok) { wlr_output_update_needs_swap(output); @@ -697,7 +689,7 @@ static bool wlr_drm_connector_move_cursor(struct wlr_output *output, conn->cursor_y = box.y; if (!drm->session->active) { - return true; + return true; // will be committed when session is resumed } bool ok = drm->iface->crtc_move_cursor(drm, conn->crtc, box.x, box.y);