From 82322d81a7cb685ed8ddbb23507129724ebf3c58 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 26 Jun 2017 19:32:36 +1200 Subject: [PATCH] Hardware cursor improvements. --- backend/drm/drm.c | 72 +++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 2f64066e..d5779c2c 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -296,54 +296,60 @@ static void wlr_drm_output_transform(struct wlr_output_state *output, output->wlr_output->transform = transform; } -static void wlr_drm_cursor_bo_update(struct wlr_output_state *output, - uint32_t width, uint32_t height) { - if (output->cursor_width == width && output->cursor_height == height) { - return; - } - wlr_log(L_DEBUG, "Allocating new cursor bos"); - struct wlr_backend_state *state = - wl_container_of(output->renderer, state, renderer); - for (size_t i = 0; i < 2; ++i) { - output->cursor_bo[i] = gbm_bo_create(state->renderer.gbm, - width, height, GBM_FORMAT_ARGB8888, - GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); - if (!output->cursor_bo[i]) { - wlr_log(L_ERROR, "Failed to create cursor bo"); - return; - } - if (!get_fb_for_bo(state->fd, output->cursor_bo[i])) { - wlr_log(L_ERROR, "Failed to create cursor fb"); - return; - } - } -} - static bool wlr_drm_output_set_cursor(struct wlr_output_state *output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) { - struct wlr_backend_state *state = - wl_container_of(output->renderer, state, renderer); + struct wlr_backend_state *state = wl_container_of(output->renderer, state, renderer); if (!buf) { drmModeSetCursor(state->fd, output->crtc, 0, 0, 0); return true; } - wlr_drm_cursor_bo_update(output, width, height); + + uint64_t bo_width, bo_height; + int ret; + + ret = drmGetCap(state->fd, DRM_CAP_CURSOR_WIDTH, &bo_width); + bo_width = ret ? 64 : bo_width; + ret = drmGetCap(state->fd, DRM_CAP_CURSOR_HEIGHT, &bo_height); + bo_height = ret ? 64 : bo_height; + + if (width > bo_width || height > bo_width) { + wlr_log(L_INFO, "Cursor too large"); + return false; + } + + for (int i = 0; i < 2; ++i) { + if (output->cursor_bo[i]) { + continue; + } + + output->cursor_bo[i] = gbm_bo_create(state->renderer.gbm, bo_width, bo_height, + GBM_FORMAT_RGBA8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); + + if (!output->cursor_bo[i]) { + wlr_log(L_ERROR, "Failed to create cursor bo"); + return false; + } + } + struct gbm_bo *bo; output->current_cursor ^= 1; bo = output->cursor_bo[output->current_cursor]; - uint32_t _buf[width * height]; - memset(_buf, 0, sizeof(_buf)); + + uint32_t bo_stride = gbm_bo_get_stride(bo); + uint8_t tmp[bo_stride * height]; + memset(tmp, 0, sizeof(tmp)); + for (size_t i = 0; i < height; ++i) { - memcpy(_buf + i * width, - buf + i * stride, - width * 4); + memcpy(tmp + i * bo_stride, buf + i * stride * 4, width * 4); } - if (gbm_bo_write(bo, _buf, sizeof(_buf)) < 0) { + + if (gbm_bo_write(bo, tmp, sizeof(tmp)) < 0) { wlr_log(L_ERROR, "Failed to write cursor to bo"); return false; } - if (drmModeSetCursor(state->fd, output->crtc, gbm_bo_get_handle(bo).u32, width, height)) { + uint32_t bo_handle = gbm_bo_get_handle(bo).u32; + if (drmModeSetCursor(state->fd, output->crtc, bo_handle, bo_width, bo_height)) { wlr_log_errno(L_INFO, "Failed to set hardware cursor"); return false; }