diff options
author | marius vlad <marius.vlad@collabora.com> | 2023-04-03 13:21:51 +0300 |
---|---|---|
committer | Marius Vlad <marius.vlad@collabora.com> | 2023-04-12 14:40:38 +0300 |
commit | cd634c34edff74a4349d28dcf0ed56c2fca247d0 (patch) | |
tree | 6e8503057ff1cce943f0fdbd4e0457b007b63e23 | |
parent | 76f689e370c60e40f376d9a121abceaabe2caaa6 (diff) | |
download | weston-cd634c34edff74a4349d28dcf0ed56c2fca247d0.tar.gz |
simple-shm: Use buffers as a list
Rather than having them as an array. This would simplify handling of
maximized and fullscreen and make things easier to reason with.
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
-rw-r--r-- | clients/simple-shm.c | 99 |
1 files changed, 83 insertions, 16 deletions
diff --git a/clients/simple-shm.c b/clients/simple-shm.c index 1c2bea9e..8ecd8c48 100644 --- a/clients/simple-shm.c +++ b/clients/simple-shm.c @@ -41,6 +41,8 @@ #include "xdg-shell-client-protocol.h" #include "fullscreen-shell-unstable-v1-client-protocol.h" +#define MAX_BUFFER_ALLOC 2 + struct display { struct wl_display *display; struct wl_registry *registry; @@ -52,9 +54,13 @@ struct display { }; struct buffer { + struct window *window; struct wl_buffer *buffer; void *shm_data; int busy; + int width, height; + size_t size; /* width * 4 * height */ + struct wl_list buffer_link; /** window::buffer_list */ }; struct window { @@ -63,7 +69,7 @@ struct window { struct wl_surface *surface; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; - struct buffer buffers[2]; + struct wl_list buffer_list; struct buffer *prev_buffer; struct wl_callback *callback; bool wait_for_configure; @@ -74,6 +80,58 @@ static int running = 1; static void redraw(void *data, struct wl_callback *callback, uint32_t time); +static struct buffer * +alloc_buffer(struct window *window, int width, int height) +{ + struct buffer *buffer = calloc(1, sizeof(*buffer)); + + buffer->width = width; + buffer->height = height; + wl_list_insert(&window->buffer_list, &buffer->buffer_link); + + return buffer; +} + +static void +destroy_buffer(struct buffer *buffer) +{ + if (buffer->buffer) + wl_buffer_destroy(buffer->buffer); + + munmap(buffer->shm_data, buffer->size); + wl_list_remove(&buffer->buffer_link); + free(buffer); +} + +static struct buffer * +pick_free_buffer(struct window *window) +{ + struct buffer *b; + struct buffer *buffer = NULL; + + wl_list_for_each(b, &window->buffer_list, buffer_link) { + if (!b->busy) { + buffer = b; + break; + } + } + + return buffer; +} + +static void +prune_old_released_buffers(struct window *window) +{ + struct buffer *b, *b_next; + + wl_list_for_each_safe(b, b_next, + &window->buffer_list, buffer_link) { + if (!b->busy && (b->width != window->width || + b->height != window->height)) + destroy_buffer(b); + } +} + static void buffer_release(void *data, struct wl_buffer *buffer) { @@ -87,15 +145,19 @@ static const struct wl_buffer_listener buffer_listener = { }; static int -create_shm_buffer(struct display *display, struct buffer *buffer, - int width, int height, uint32_t format) +create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format) { struct wl_shm_pool *pool; int fd, size, stride; void *data; + int width, height; + struct display *display; + width = window->width; + height = window->height; stride = width * 4; size = stride * height; + display = window->display; fd = os_create_anonymous_file(size); if (fd < 0) { @@ -119,6 +181,7 @@ create_shm_buffer(struct display *display, struct buffer *buffer, wl_shm_pool_destroy(pool); close(fd); + buffer->size = size; buffer->shm_data = data; return 0; @@ -164,6 +227,7 @@ static struct window * create_window(struct display *display, int width, int height) { struct window *window; + int i; window = zalloc(sizeof *window); if (!window) @@ -174,6 +238,7 @@ create_window(struct display *display, int width, int height) window->width = width; window->height = height; window->surface = wl_compositor_create_surface(display->compositor); + wl_list_init(&window->buffer_list); if (display->wm_base) { window->xdg_surface = @@ -204,19 +269,23 @@ create_window(struct display *display, int width, int height) assert(0); } + for (i = 0; i < MAX_BUFFER_ALLOC; i++) + alloc_buffer(window, window->width, window->height); + return window; } static void destroy_window(struct window *window) { + struct buffer *buffer, *buffer_next; + if (window->callback) wl_callback_destroy(window->callback); - if (window->buffers[0].buffer) - wl_buffer_destroy(window->buffers[0].buffer); - if (window->buffers[1].buffer) - wl_buffer_destroy(window->buffers[1].buffer); + wl_list_for_each_safe(buffer, buffer_next, + &window->buffer_list, buffer_link) + destroy_buffer(buffer); if (window->xdg_toplevel) xdg_toplevel_destroy(window->xdg_toplevel); @@ -229,20 +298,16 @@ destroy_window(struct window *window) static struct buffer * window_next_buffer(struct window *window) { - struct buffer *buffer; + struct buffer *buffer = NULL; int ret = 0; - if (!window->buffers[0].busy) - buffer = &window->buffers[0]; - else if (!window->buffers[1].busy) - buffer = &window->buffers[1]; - else + buffer = pick_free_buffer(window); + + if (!buffer) return NULL; if (!buffer->buffer) { - ret = create_shm_buffer(window->display, buffer, - window->width, window->height, - WL_SHM_FORMAT_XRGB8888); + ret = create_shm_buffer(window, buffer, WL_SHM_FORMAT_XRGB8888); if (ret < 0) return NULL; @@ -309,6 +374,8 @@ redraw(void *data, struct wl_callback *callback, uint32_t time) struct window *window = data; struct buffer *buffer; + prune_old_released_buffers(window); + buffer = window_next_buffer(window); if (!buffer) { fprintf(stderr, |