From d6dbdd97e90882569899e458f6bbc44bdc6d0a8a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 12 Dec 2020 13:12:06 +0100 Subject: [PATCH] backend/x11: re-use pixmaps Instead of re-importing a buffer each time we submit a frame, re-use the pixmaps if possible. --- backend/x11/output.c | 44 +++++++++++++++++++++++++++++++++---------- include/backend/x11.h | 1 + 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/backend/x11/output.c b/backend/x11/output.c index cba9f600..a5d834fc 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -132,7 +132,24 @@ static bool output_test(struct wlr_output *wlr_output) { return true; } -static struct wlr_x11_buffer *import_x11_buffer(struct wlr_x11_output *output, +static void destroy_x11_buffer(struct wlr_x11_buffer *buffer) { + if (!buffer) { + return; + } + wl_list_remove(&buffer->buffer_destroy.link); + wl_list_remove(&buffer->link); + xcb_free_pixmap(buffer->x11->xcb, buffer->pixmap); + free(buffer); +} + +static void buffer_handle_buffer_destroy(struct wl_listener *listener, + void *data) { + struct wlr_x11_buffer *buffer = + wl_container_of(listener, buffer, buffer_destroy); + destroy_x11_buffer(buffer); +} + +static struct wlr_x11_buffer *create_x11_buffer(struct wlr_x11_output *output, struct wlr_buffer *wlr_buffer) { struct wlr_x11_backend *x11 = output->x11; @@ -170,17 +187,24 @@ static struct wlr_x11_buffer *import_x11_buffer(struct wlr_x11_output *output, buffer->pixmap = pixmap; buffer->x11 = x11; wl_list_insert(&output->buffers, &buffer->link); + + buffer->buffer_destroy.notify = buffer_handle_buffer_destroy; + wl_signal_add(&wlr_buffer->events.destroy, &buffer->buffer_destroy); + return buffer; } -static void destroy_x11_buffer(struct wlr_x11_buffer *buffer) { - if (!buffer) { - return; +static struct wlr_x11_buffer *get_or_create_x11_buffer( + struct wlr_x11_output *output, struct wlr_buffer *wlr_buffer) { + struct wlr_x11_buffer *buffer; + wl_list_for_each(buffer, &output->buffers, link) { + if (buffer->buffer == wlr_buffer) { + wlr_buffer_lock(buffer->buffer); + return buffer; + } } - wl_list_remove(&buffer->link); - xcb_free_pixmap(buffer->x11->xcb, buffer->pixmap); - wlr_buffer_unlock(buffer->buffer); - free(buffer); + + return create_x11_buffer(output, wlr_buffer); } static bool output_commit_buffer(struct wlr_x11_output *output) { @@ -192,7 +216,7 @@ static bool output_commit_buffer(struct wlr_x11_output *output) { wlr_egl_unset_current(&x11->egl); struct wlr_x11_buffer *x11_buffer = - import_x11_buffer(output, output->back_buffer); + get_or_create_x11_buffer(output, output->back_buffer); if (!x11_buffer) { goto error; } @@ -502,7 +526,7 @@ void handle_x11_present_event(struct wlr_x11_backend *x11, return; } - destroy_x11_buffer(buffer); + wlr_buffer_unlock(buffer->buffer); // may destroy buffer break; case XCB_PRESENT_COMPLETE_NOTIFY:; xcb_present_complete_notify_event_t *complete_notify = diff --git a/include/backend/x11.h b/include/backend/x11.h index b872385d..7ffcf465 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -115,6 +115,7 @@ struct wlr_x11_buffer { struct wlr_buffer *buffer; xcb_pixmap_t pixmap; struct wl_list link; // wlr_x11_output::buffers + struct wl_listener buffer_destroy; }; struct wlr_x11_format {