summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarius vlad <marius.vlad@collabora.com>2023-04-03 13:21:51 +0300
committerMarius Vlad <marius.vlad@collabora.com>2023-04-12 14:40:38 +0300
commitcd634c34edff74a4349d28dcf0ed56c2fca247d0 (patch)
tree6e8503057ff1cce943f0fdbd4e0457b007b63e23
parent76f689e370c60e40f376d9a121abceaabe2caaa6 (diff)
downloadweston-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.c99
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,