diff options
Diffstat (limited to 'backend')
-rw-r--r-- | backend/drm/drm.c | 70 | ||||
-rw-r--r-- | backend/drm/renderer.c | 17 | ||||
-rw-r--r-- | backend/headless/output.c | 15 | ||||
-rw-r--r-- | backend/meson.build | 13 | ||||
-rw-r--r-- | backend/wayland/output.c | 33 | ||||
-rw-r--r-- | backend/wayland/wl_seat.c | 12 | ||||
-rw-r--r-- | backend/x11/backend.c | 15 |
7 files changed, 109 insertions, 66 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 63a6e2da..a1227d15 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -183,18 +183,22 @@ void wlr_drm_resources_free(struct wlr_drm_backend *drm) { free(drm->planes); } -static void wlr_drm_connector_make_current(struct wlr_output *output) { +static bool wlr_drm_connector_make_current(struct wlr_output *output, + int *buffer_age) { struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; - wlr_drm_surface_make_current(&conn->crtc->primary->surf); + return wlr_drm_surface_make_current(&conn->crtc->primary->surf, buffer_age); } -static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { +static bool wlr_drm_connector_swap_buffers(struct wlr_output *output) { struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend; + if (!drm->session->active) { + return false; + } struct wlr_drm_crtc *crtc = conn->crtc; if (!crtc) { - return; + return false; } struct wlr_drm_plane *plane = crtc->primary; @@ -202,15 +206,19 @@ static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { if (drm->parent) { bo = wlr_drm_surface_mgpu_copy(&plane->mgpu_surf, bo); } - uint32_t fb_id = get_fb_for_bo(bo); - if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { - conn->pageflip_pending = true; - } else { - wl_event_source_timer_update(conn->retry_pageflip, - 1000.0f / conn->output.current_mode->refresh); + if (conn->pageflip_pending) { + wlr_log(L_ERROR, "Skipping pageflip"); + return false; + } + + if (!drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { + return false; } + + conn->pageflip_pending = true; + return true; } static void wlr_drm_connector_set_gamma(struct wlr_output *output, @@ -247,7 +255,7 @@ void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { conn->pageflip_pending = true; } else { wl_event_source_timer_update(conn->retry_pageflip, - 1000.0f / conn->output.current_mode->refresh); + 1000000.0f / conn->output.current_mode->refresh); } } @@ -509,6 +517,10 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend; struct wlr_drm_renderer *renderer = &drm->renderer; + if (!drm->session->active) { + return false; + } + struct wlr_drm_crtc *crtc = conn->crtc; if (!crtc) { return false; @@ -574,15 +586,14 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, } struct wlr_box hotspot = { - .width = plane->surf.width, - .height = plane->surf.height, .x = hotspot_x, .y = hotspot_y, }; enum wl_output_transform transform = wlr_output_transform_invert(output->transform); struct wlr_box transformed_hotspot; - wlr_box_transform(&hotspot, transform, &transformed_hotspot); + wlr_box_transform(&hotspot, transform, + plane->surf.width, plane->surf.height, &transformed_hotspot); plane->cursor_hotspot_x = transformed_hotspot.x; plane->cursor_hotspot_y = transformed_hotspot.y; @@ -603,7 +614,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, return false; } - wlr_drm_surface_make_current(&plane->surf); + wlr_drm_surface_make_current(&plane->surf, NULL); wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888, stride, width, height, buf); @@ -627,35 +638,46 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, gbm_bo_unmap(bo, bo_data); - return drm->iface->crtc_set_cursor(drm, crtc, bo); + bool ok = drm->iface->crtc_set_cursor(drm, crtc, bo); + if (ok) { + wlr_output_update_needs_swap(output); + } + return ok; } static bool wlr_drm_connector_move_cursor(struct wlr_output *output, int x, int y) { struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend; - if (!conn || !conn->crtc) { + if (!drm->session->active) { + return false; + } + if (!conn->crtc) { return false; } struct wlr_drm_plane *plane = conn->crtc->cursor; - struct wlr_box box; - box.x = x; - box.y = y; - wlr_output_effective_resolution(output, &box.width, &box.height); + struct wlr_box box = { .x = x, .y = y }; + + int width, height; + wlr_output_effective_resolution(output, &width, &height); enum wl_output_transform transform = wlr_output_transform_invert(output->transform); struct wlr_box transformed_box; - wlr_box_transform(&box, transform, &transformed_box); + wlr_box_transform(&box, transform, width, height, &transformed_box); if (plane != NULL) { transformed_box.x -= plane->cursor_hotspot_x; transformed_box.y -= plane->cursor_hotspot_y; } - return drm->iface->crtc_move_cursor(drm, conn->crtc, transformed_box.x, + bool ok = drm->iface->crtc_move_cursor(drm, conn->crtc, transformed_box.x, transformed_box.y); + if (ok) { + wlr_output_update_needs_swap(output); + } + return ok; } static void wlr_drm_connector_destroy(struct wlr_output *output) { @@ -867,7 +889,7 @@ static void page_flip_handler(int fd, unsigned seq, } if (drm->session->active) { - wl_signal_emit(&conn->output.events.frame, &conn->output); + wlr_output_send_frame(&conn->output); } } diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 00182c59..e2891057 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -113,9 +113,9 @@ void wlr_drm_surface_finish(struct wlr_drm_surface *surf) { memset(surf, 0, sizeof(*surf)); } -void wlr_drm_surface_make_current(struct wlr_drm_surface *surf) { - eglMakeCurrent(surf->renderer->egl.display, surf->egl, surf->egl, - surf->renderer->egl.context); +bool wlr_drm_surface_make_current(struct wlr_drm_surface *surf, + int *buffer_damage) { + return wlr_egl_make_current(&surf->renderer->egl, surf->egl, buffer_damage); } struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf) { @@ -123,7 +123,9 @@ struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf) { gbm_surface_release_buffer(surf->gbm, surf->front); } - eglSwapBuffers(surf->renderer->egl.display, surf->egl); + if (!eglSwapBuffers(surf->renderer->egl.display, surf->egl)) { + wlr_log(L_ERROR, "eglSwapBuffers failed"); + } surf->front = surf->back; surf->back = gbm_surface_lock_front_buffer(surf->gbm); @@ -135,7 +137,7 @@ struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf) { return surf->front; } - wlr_drm_surface_make_current(surf); + wlr_drm_surface_make_current(surf, NULL); glViewport(0, 0, surf->width, surf->height); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); @@ -207,8 +209,9 @@ static struct wlr_texture *get_tex_for_bo(struct wlr_drm_renderer *renderer, str return tex->tex; } -struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest, struct gbm_bo *src) { - wlr_drm_surface_make_current(dest); +struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest, + struct gbm_bo *src) { + wlr_drm_surface_make_current(dest, NULL); struct wlr_texture *tex = get_tex_for_bo(dest->renderer, src); diff --git a/backend/headless/output.c b/backend/headless/output.c index 9fc92e88..46f9d212 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -48,18 +48,15 @@ static void output_transform(struct wlr_output *wlr_output, output->wlr_output.transform = transform; } -static void output_make_current(struct wlr_output *wlr_output) { +static bool output_make_current(struct wlr_output *wlr_output, int *buffer_age) { struct wlr_headless_output *output = (struct wlr_headless_output *)wlr_output; - 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 wlr_egl_make_current(&output->backend->egl, output->egl_surface, + buffer_age); } -static void output_swap_buffers(struct wlr_output *wlr_output) { - // No-op +static bool output_swap_buffers(struct wlr_output *wlr_output) { + return true; // No-op } static void output_destroy(struct wlr_output *wlr_output) { @@ -88,7 +85,7 @@ bool wlr_output_is_headless(struct wlr_output *wlr_output) { static int signal_frame(void *data) { struct wlr_headless_output *output = data; - wl_signal_emit(&output->wlr_output.events.frame, &output->wlr_output); + wlr_output_send_frame(&output->wlr_output); wl_event_source_timer_update(output->frame_timer, output->frame_delay); return 0; } diff --git a/backend/meson.build b/backend/meson.build index 173b65f6..9c8f5852 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -45,5 +45,16 @@ lib_wlr_backend = static_library( 'wlr_backend', backend_files, include_directories: wlr_inc, - dependencies: [wayland_server, egl, gbm, libinput, systemd, elogind, wlr_render, wlr_protos, drm], + dependencies: [ + wayland_server, + egl, + gbm, + libinput, + systemd, + elogind, + wlr_render, + wlr_protos, + drm, + pixman, + ], ) diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 52791679..4fec1955 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -17,11 +17,13 @@ int os_create_anonymous_file(off_t size); static struct wl_callback_listener frame_listener; -static void surface_frame_callback(void *data, struct wl_callback *cb, uint32_t time) { - struct wlr_output *wlr_output = data; - assert(wlr_output); - wl_signal_emit(&wlr_output->events.frame, wlr_output); +static void surface_frame_callback(void *data, struct wl_callback *cb, + uint32_t time) { + struct wlr_wl_backend_output *output = data; + assert(output); + wlr_output_send_frame(&output->wlr_output); wl_callback_destroy(cb); + output->frame_callback = NULL; } static struct wl_callback_listener frame_listener = { @@ -36,22 +38,27 @@ static bool wlr_wl_output_set_custom_mode(struct wlr_output *_output, return true; } -static void wlr_wl_output_make_current(struct wlr_output *_output) { - struct wlr_wl_backend_output *output = (struct wlr_wl_backend_output *)_output; - 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()); - } +static bool wlr_wl_output_make_current(struct wlr_output *wlr_output, + int *buffer_age) { + struct wlr_wl_backend_output *output = + (struct wlr_wl_backend_output *)wlr_output; + return wlr_egl_make_current(&output->backend->egl, output->egl_surface, + buffer_age); } -static void wlr_wl_output_swap_buffers(struct wlr_output *_output) { - struct wlr_wl_backend_output *output = (struct wlr_wl_backend_output *)_output; +static bool wlr_wl_output_swap_buffers(struct wlr_output *wlr_output) { + struct wlr_wl_backend_output *output = + (struct wlr_wl_backend_output *)wlr_output; + output->frame_callback = wl_surface_frame(output->surface); wl_callback_add_listener(output->frame_callback, &frame_listener, output); + if (!eglSwapBuffers(output->backend->egl.display, output->egl_surface)) { wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error()); + return false; } + + return true; } static void wlr_wl_output_transform(struct wlr_output *_output, diff --git a/backend/wayland/wl_seat.c b/backend/wayland/wl_seat.c index 90f7d44c..37489678 100644 --- a/backend/wayland/wl_seat.c +++ b/backend/wayland/wl_seat.c @@ -54,14 +54,16 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, struct wlr_output *wlr_output = &wlr_wl_pointer->current_output->wlr_output; - struct wlr_box box; + int width, height; wl_egl_window_get_attached_size(wlr_wl_pointer->current_output->egl_window, - &box.width, &box.height); - box.x = wl_fixed_to_int(surface_x); - box.y = wl_fixed_to_int(surface_y); + &width, &height); + struct wlr_box box = { + .x = wl_fixed_to_int(surface_x), + .y = wl_fixed_to_int(surface_y), + }; struct wlr_box transformed; - wlr_box_transform(&box, wlr_output->transform, &transformed); + wlr_box_transform(&box, wlr_output->transform, width, height, &transformed); transformed.x /= wlr_output->scale; transformed.y /= wlr_output->scale; diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 3e450dbd..3bad8d61 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -45,7 +45,7 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e switch (event->response_type) { case XCB_EXPOSE: { - wl_signal_emit(&output->wlr_output.events.frame, output); + wlr_output_send_frame(&output->wlr_output); break; } case XCB_KEY_PRESS: @@ -175,7 +175,7 @@ static int x11_event(int fd, uint32_t mask, void *data) { static int signal_frame(void *data) { struct wlr_x11_backend *x11 = data; - wl_signal_emit(&x11->output.wlr_output.events.frame, &x11->output); + wlr_output_send_frame(&x11->output.wlr_output); wl_event_source_timer_update(x11->frame_timer, 16); return 0; } @@ -392,22 +392,23 @@ static void output_destroy(struct wlr_output *wlr_output) { // output has been allocated on the stack, do not free it } -static void output_make_current(struct wlr_output *wlr_output) { +static bool output_make_current(struct wlr_output *wlr_output, int *buffer_age) { struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; struct wlr_x11_backend *x11 = output->x11; - if (!eglMakeCurrent(x11->egl.display, output->surf, output->surf, x11->egl.context)) { - wlr_log(L_ERROR, "eglMakeCurrent failed: %s", egl_error()); - } + return wlr_egl_make_current(&x11->egl, output->surf, buffer_age); } -static void output_swap_buffers(struct wlr_output *wlr_output) { +static bool output_swap_buffers(struct wlr_output *wlr_output) { struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; struct wlr_x11_backend *x11 = output->x11; if (!eglSwapBuffers(x11->egl.display, output->surf)) { wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error()); + return false; } + + return true; } static struct wlr_output_impl output_impl = { |