diff options
Diffstat (limited to 'backend')
-rw-r--r-- | backend/drm/drm.c | 91 | ||||
-rw-r--r-- | backend/wayland/output.c | 27 |
2 files changed, 68 insertions, 50 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c index c6e29b86..618274a6 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -92,13 +92,13 @@ static uint32_t get_fb_for_bo(int fd, struct gbm_bo *bo) { return *id; } -static void wlr_drm_output_begin(struct wlr_output_state *output) { +static void wlr_drm_output_make_current(struct wlr_output_state *output) { struct wlr_drm_renderer *renderer = output->renderer; eglMakeCurrent(renderer->egl.display, output->egl, output->egl, renderer->egl.context); } -static void wlr_drm_output_end(struct wlr_output_state *output) { +static void wlr_drm_output_swap_buffers(struct wlr_output_state *output) { struct wlr_drm_renderer *renderer = output->renderer; if (!eglSwapBuffers(renderer->egl.display, output->egl)) { @@ -207,10 +207,10 @@ static void wlr_drm_output_enable(struct wlr_output_state *output, bool enable) DRM_MODE_DPMS_ON); // Start rendering loop again by drawing a black frame - wlr_drm_output_begin(output); + wlr_drm_output_make_current(output); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); - wlr_drm_output_end(output); + wlr_drm_output_swap_buffers(output); } else { drmModeConnectorSetProperty(state->fd, output->connector, output->props.dpms, DRM_MODE_DPMS_STANDBY); @@ -296,54 +296,65 @@ 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 (max %dx%d)", (int)bo_width, (int)bo_height); + 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; } - return !drmModeSetCursor(state->fd, output->crtc, - gbm_bo_get_handle(bo).s32, 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; + } + + return true; } static bool wlr_drm_output_move_cursor(struct wlr_output_state *output, @@ -365,6 +376,8 @@ static struct wlr_output_impl output_impl = { .set_cursor = wlr_drm_output_set_cursor, .move_cursor = wlr_drm_output_move_cursor, .destroy = wlr_drm_output_destroy, + .make_current = wlr_drm_output_make_current, + .swap_buffers = wlr_drm_output_swap_buffers, }; static int32_t calculate_refresh_rate(drmModeModeInfo *mode) { @@ -625,9 +638,7 @@ static void page_flip_handler(int fd, unsigned seq, output->pageflip_pending = false; if (output->state == DRM_OUTPUT_CONNECTED && state->session->active) { - wlr_drm_output_begin(output); wl_signal_emit(&output->wlr_output->events.frame, output->wlr_output); - wlr_drm_output_end(output); } } diff --git a/backend/wayland/output.c b/backend/wayland/output.c index babca2e1..bf3c32eb 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -15,29 +15,34 @@ static void surface_frame_callback(void *data, struct wl_callback *cb, uint32_t struct wlr_output_state *output = data; assert(output); + wlr_log(L_DEBUG, "frame_callback"); + struct wlr_output *wlr_output = output->wlr_output; + wl_signal_emit(&wlr_output->events.frame, wlr_output); + wl_callback_destroy(cb); +} + +static struct wl_callback_listener frame_listener = { + .done = surface_frame_callback +}; + +static void wlr_wl_output_make_current(struct wlr_output_state *output) { + wlr_log(L_DEBUG, "make_current"); if (!eglMakeCurrent(output->backend->egl.display, output->egl_surface, output->egl_surface, output->backend->egl.context)) { wlr_log(L_ERROR, "eglMakeCurrent failed: %s", egl_error()); - return; } +} - struct wlr_output *wlr_output = output->wlr_output; - wl_signal_emit(&wlr_output->events.frame, wlr_output); +static void wlr_wl_output_swap_buffers(struct wlr_output_state *output) { + wlr_log(L_DEBUG, "swap_buffers"); output->frame_callback = wl_surface_frame(output->surface); wl_callback_add_listener(output->frame_callback, &frame_listener, output); - wl_callback_destroy(cb); - if (!eglSwapBuffers(output->backend->egl.display, output->egl_surface)) { wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error()); - return; } } -static struct wl_callback_listener frame_listener = { - .done = surface_frame_callback -}; - static void wlr_wl_output_transform(struct wlr_output_state *output, enum wl_output_transform transform) { output->wlr_output->transform = transform; @@ -55,6 +60,8 @@ static void wlr_wl_output_destroy(struct wlr_output_state *output) { static struct wlr_output_impl output_impl = { .transform = wlr_wl_output_transform, .destroy = wlr_wl_output_destroy, + .make_current = wlr_wl_output_make_current, + .swap_buffers = wlr_wl_output_swap_buffers, }; void handle_ping(void* data, struct wl_shell_surface* ssurface, uint32_t serial) { |