aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/backend.c1
-rw-r--r--backend/drm/backend.c4
-rw-r--r--backend/drm/drm.c90
-rw-r--r--backend/drm/renderer.c17
-rw-r--r--backend/headless/backend.c2
-rw-r--r--backend/headless/output.c17
-rw-r--r--backend/libinput/backend.c8
-rw-r--r--backend/meson.build13
-rw-r--r--backend/multi/backend.c5
-rw-r--r--backend/wayland/backend.c8
-rw-r--r--backend/wayland/output.c48
-rw-r--r--backend/wayland/wl_seat.c12
-rw-r--r--backend/x11/backend.c17
13 files changed, 155 insertions, 87 deletions
diff --git a/backend/backend.c b/backend/backend.c
index a71cf6b8..98b94c5c 100644
--- a/backend/backend.c
+++ b/backend/backend.c
@@ -37,7 +37,6 @@ void wlr_backend_destroy(struct wlr_backend *backend) {
return;
}
- wl_signal_emit(&backend->events.destroy, backend);
if (backend->impl && backend->impl->destroy) {
backend->impl->destroy(backend);
} else {
diff --git a/backend/drm/backend.c b/backend/drm/backend.c
index 4ca5718a..3782817c 100644
--- a/backend/drm/backend.c
+++ b/backend/drm/backend.c
@@ -34,6 +34,8 @@ static void wlr_drm_backend_destroy(struct wlr_backend *backend) {
wlr_output_destroy(&conn->output);
}
+ wl_signal_emit(&backend->events.destroy, backend);
+
wl_list_remove(&drm->display_destroy.link);
wl_list_remove(&drm->session_signal.link);
wl_list_remove(&drm->drm_invalidated.link);
@@ -89,6 +91,8 @@ static void session_signal(struct wl_listener *listener, void *data) {
struct wlr_drm_plane *plane = conn->crtc->cursor;
drm->iface->crtc_set_cursor(drm, conn->crtc,
(plane && plane->cursor_enabled) ? plane->cursor_bo : NULL);
+ drm->iface->crtc_move_cursor(drm, conn->crtc, conn->cursor_x,
+ conn->cursor_y);
}
} else {
wlr_log(L_INFO, "DRM fd paused");
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index cf5af355..08ced783 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -184,18 +184,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;
@@ -203,16 +207,20 @@ 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;
- wlr_output_update_enabled(output, 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;
+ wlr_output_update_enabled(output, true);
+ return true;
}
static void wlr_drm_connector_set_gamma(struct wlr_output *output,
@@ -250,7 +258,7 @@ void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) {
wlr_output_update_enabled(&conn->output, true);
} else {
wl_event_source_timer_update(conn->retry_pageflip,
- 1000.0f / conn->output.current_mode->refresh);
+ 1000000.0f / conn->output.current_mode->refresh);
}
}
@@ -531,6 +539,9 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
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;
@@ -577,17 +588,15 @@ 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);
- plane->cursor_hotspot_x = transformed_hotspot.x;
- plane->cursor_hotspot_y = transformed_hotspot.y;
+ wlr_box_transform(&hotspot, transform,
+ plane->surf.width, plane->surf.height, &hotspot);
+ plane->cursor_hotspot_x = hotspot.x;
+ plane->cursor_hotspot_y = hotspot.y;
if (!update_pixels) {
// Only update the cursor hotspot
@@ -606,7 +615,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);
@@ -630,35 +639,52 @@ 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);
+ if (!drm->session->active) {
+ return true;
+ }
+
+ 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 (!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_transformed_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, &box);
if (plane != NULL) {
- transformed_box.x -= plane->cursor_hotspot_x;
- transformed_box.y -= plane->cursor_hotspot_y;
+ box.x -= plane->cursor_hotspot_x;
+ box.y -= plane->cursor_hotspot_y;
+ }
+
+ conn->cursor_x = box.x;
+ conn->cursor_y = box.y;
+
+ if (!drm->session->active) {
+ return true;
}
- return drm->iface->crtc_move_cursor(drm, conn->crtc, transformed_box.x,
- transformed_box.y);
+ bool ok = drm->iface->crtc_move_cursor(drm, conn->crtc, box.x, box.y);
+ if (ok) {
+ wlr_output_update_needs_swap(output);
+ }
+ return ok;
}
static void wlr_drm_connector_destroy(struct wlr_output *output) {
@@ -874,7 +900,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 350bfce4..0310a96a 100644
--- a/backend/drm/renderer.c
+++ b/backend/drm/renderer.c
@@ -128,9 +128,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) {
@@ -138,7 +138,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);
@@ -150,7 +152,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);
@@ -222,8 +224,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/backend.c b/backend/headless/backend.c
index 61409d41..0bf5ec28 100644
--- a/backend/headless/backend.c
+++ b/backend/headless/backend.c
@@ -51,6 +51,8 @@ static void backend_destroy(struct wlr_backend *wlr_backend) {
wlr_input_device_destroy(&input_device->wlr_input_device);
}
+ wl_signal_emit(&wlr_backend->events.destroy, backend);
+
wlr_egl_finish(&backend->egl);
free(backend);
}
diff --git a/backend/headless/output.c b/backend/headless/output.c
index 9fc92e88..aac7cc20 100644
--- a/backend/headless/output.c
+++ b/backend/headless/output.c
@@ -48,25 +48,20 @@ 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) {
struct wlr_headless_output *output =
(struct wlr_headless_output *)wlr_output;
- wl_signal_emit(&output->backend->backend.events.output_remove,
- &output->wlr_output);
wl_list_remove(&output->link);
@@ -88,7 +83,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/libinput/backend.c b/backend/libinput/backend.c
index c9352051..86477947 100644
--- a/backend/libinput/backend.c
+++ b/backend/libinput/backend.c
@@ -95,12 +95,12 @@ static bool wlr_libinput_backend_start(struct wlr_backend *_backend) {
return true;
}
-static void wlr_libinput_backend_destroy(struct wlr_backend *_backend) {
- if (!_backend) {
+static void wlr_libinput_backend_destroy(struct wlr_backend *wlr_backend) {
+ if (!wlr_backend) {
return;
}
struct wlr_libinput_backend *backend =
- (struct wlr_libinput_backend *)_backend;
+ (struct wlr_libinput_backend *)wlr_backend;
for (size_t i = 0; i < backend->wlr_device_lists.length; i++) {
struct wl_list *wlr_devices = backend->wlr_device_lists.items[i];
@@ -112,6 +112,8 @@ static void wlr_libinput_backend_destroy(struct wlr_backend *_backend) {
free(wlr_devices);
}
+ wl_signal_emit(&wlr_backend->events.destroy, wlr_backend);
+
wl_list_remove(&backend->display_destroy.link);
wl_list_remove(&backend->session_signal.link);
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/multi/backend.c b/backend/multi/backend.c
index 1e574475..78f5c63b 100644
--- a/backend/multi/backend.c
+++ b/backend/multi/backend.c
@@ -42,11 +42,16 @@ static void subbackend_state_destroy(struct subbackend_state *sub) {
static void multi_backend_destroy(struct wlr_backend *wlr_backend) {
struct wlr_multi_backend *backend = (struct wlr_multi_backend *)wlr_backend;
+
wl_list_remove(&backend->display_destroy.link);
+
struct subbackend_state *sub, *next;
wl_list_for_each_safe(sub, next, &backend->backends, link) {
wlr_backend_destroy(sub->backend);
}
+
+ // Destroy this backend only after removing all sub-backends
+ wl_signal_emit(&wlr_backend->events.destroy, backend);
free(backend);
}
diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c
index eca79350..458c9dd0 100644
--- a/backend/wayland/backend.c
+++ b/backend/wayland/backend.c
@@ -64,9 +64,9 @@ static bool wlr_wl_backend_start(struct wlr_backend *_backend) {
return true;
}
-static void wlr_wl_backend_destroy(struct wlr_backend *_backend) {
- struct wlr_wl_backend *backend = (struct wlr_wl_backend *)_backend;
- if (!_backend) {
+static void wlr_wl_backend_destroy(struct wlr_backend *wlr_backend) {
+ struct wlr_wl_backend *backend = (struct wlr_wl_backend *)wlr_backend;
+ if (backend == NULL) {
return;
}
@@ -80,6 +80,8 @@ static void wlr_wl_backend_destroy(struct wlr_backend *_backend) {
wlr_input_device_destroy(input_device);
}
+ wl_signal_emit(&wlr_backend->events.destroy, wlr_backend);
+
wl_list_remove(&backend->local_display_destroy.link);
free(backend->seat_name);
diff --git a/backend/wayland/output.c b/backend/wayland/output.c
index 52791679..a9140ff7 100644
--- a/backend/wayland/output.c
+++ b/backend/wayland/output.c
@@ -17,11 +17,14 @@ 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);
wl_callback_destroy(cb);
+ output->frame_callback = NULL;
+
+ wlr_output_send_frame(&output->wlr_output);
}
static struct wl_callback_listener frame_listener = {
@@ -36,22 +39,32 @@ 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;
+
+ if (output->frame_callback != NULL) {
+ wlr_log(L_ERROR, "Skipping buffer swap");
+ return false;
+ }
+
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,
@@ -148,11 +161,12 @@ static bool wlr_wl_output_set_cursor(struct wlr_output *_output,
return true;
}
-static void wlr_wl_output_destroy(struct wlr_output *_output) {
+static void wlr_wl_output_destroy(struct wlr_output *wlr_output) {
struct wlr_wl_backend_output *output =
- (struct wlr_wl_backend_output *)_output;
- wl_signal_emit(&output->backend->backend.events.output_remove,
- &output->wlr_output);
+ (struct wlr_wl_backend_output *)wlr_output;
+ if (output == NULL) {
+ return;
+ }
wl_list_remove(&output->link);
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..44e29be1 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;
}
@@ -259,6 +259,8 @@ static void wlr_x11_backend_destroy(struct wlr_backend *backend) {
xkb_state_unref(x11->keyboard_dev.keyboard->xkb_state);
}
+ wl_signal_emit(&backend->events.destroy, backend);
+
wl_list_remove(&x11->display_destroy.link);
wl_event_source_remove(x11->frame_timer);
@@ -392,22 +394,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 = {