mirror of
https://codeberg.org/dnkl/yambar.git
synced 2025-04-24 04:45:41 +02:00
bar/wayland: much improved error handling
Most asserts() have now been replaced with error messages. Cleanup() no longer tries to free/destroy NULL resources.
This commit is contained in:
parent
e48d90ae12
commit
76655bc944
1 changed files with 145 additions and 40 deletions
185
bar/wayland.c
185
bar/wayland.c
|
@ -431,50 +431,115 @@ get_buffer(struct wayland_backend *backend)
|
|||
{
|
||||
tll_foreach(backend->buffers, it) {
|
||||
if (!it->item.busy) {
|
||||
//printf("re-using non-busy buffer\n");
|
||||
it->item.busy = true;
|
||||
return &it->item;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("allocating a new buffer\n");
|
||||
/*
|
||||
* No existing buffer available. Create a new one by:
|
||||
*
|
||||
* 1. open a memory backed "file" with memfd_create()
|
||||
* 2. mmap() the memory file, to be used by the cairo surface
|
||||
* 3. create a wayland shm buffer for the same memory file
|
||||
*
|
||||
* The cairo surface and the wayland buffer are now sharing
|
||||
* memory.
|
||||
*/
|
||||
|
||||
struct buffer buffer;
|
||||
int pool_fd = -1;
|
||||
void *mmapped = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
struct wl_shm_pool *pool = NULL;
|
||||
struct wl_buffer *buf = NULL;
|
||||
|
||||
cairo_surface_t *cairo_surface = NULL;
|
||||
cairo_t *cairo = NULL;
|
||||
|
||||
/* Backing memory for SHM */
|
||||
int pool_fd = memfd_create("wayland-test-buffer-pool", MFD_CLOEXEC);
|
||||
assert(pool_fd != -1);
|
||||
pool_fd = memfd_create("wayland-test-buffer-pool", MFD_CLOEXEC);
|
||||
if (pool_fd == -1) {
|
||||
LOG_ERRNO("failed to create SHM backing memory file");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Allocate memory for our single buffer */
|
||||
/* Total size */
|
||||
uint32_t stride = backend->width * 4;
|
||||
buffer.size = stride * backend->height;
|
||||
ftruncate(pool_fd, buffer.size);
|
||||
size = stride * backend->height;
|
||||
ftruncate(pool_fd, size);
|
||||
|
||||
buffer.mmapped = mmap(
|
||||
NULL, buffer.size, PROT_READ | PROT_WRITE, MAP_SHARED, pool_fd, 0);
|
||||
assert(buffer.mmapped != MAP_FAILED);
|
||||
mmapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, pool_fd, 0);
|
||||
if (mmapped == MAP_FAILED) {
|
||||
LOG_ERR("failed to mmap SHM backing memory file");
|
||||
goto err;
|
||||
}
|
||||
|
||||
struct wl_shm_pool *pool = wl_shm_create_pool(backend->shm, pool_fd, buffer.size);
|
||||
assert(pool != NULL);
|
||||
pool = wl_shm_create_pool(backend->shm, pool_fd, size);
|
||||
if (pool == NULL) {
|
||||
LOG_ERR("failed to create SHM pool");
|
||||
goto err;
|
||||
}
|
||||
|
||||
buffer.wl_buf = wl_shm_pool_create_buffer(
|
||||
buf = wl_shm_pool_create_buffer(
|
||||
pool, 0, backend->width, backend->height, stride, WL_SHM_FORMAT_ARGB8888);
|
||||
assert(buffer.wl_buf != NULL);
|
||||
buffer.busy = true;
|
||||
if (buf == NULL) {
|
||||
LOG_ERR("failed to create SHM buffer");
|
||||
goto err;
|
||||
}
|
||||
|
||||
wl_shm_pool_destroy(pool);
|
||||
close(pool_fd);
|
||||
/* We use the entire pool for our single buffer */
|
||||
wl_shm_pool_destroy(pool); pool = NULL;
|
||||
close(pool_fd); pool_fd = -1;
|
||||
|
||||
buffer.cairo_surface = cairo_image_surface_create_for_data(
|
||||
buffer.mmapped, CAIRO_FORMAT_ARGB32, backend->width, backend->height, stride);
|
||||
buffer.cairo = cairo_create(buffer.cairo_surface);
|
||||
assert(cairo_status(buffer.cairo) == CAIRO_STATUS_SUCCESS);
|
||||
/* Create a cairo surface around the mmapped memory */
|
||||
cairo_surface = cairo_image_surface_create_for_data(
|
||||
mmapped, CAIRO_FORMAT_ARGB32, backend->width, backend->height, stride);
|
||||
if (cairo_surface_status(cairo_surface) != CAIRO_STATUS_SUCCESS) {
|
||||
LOG_ERR("failed to create cairo surface: %s",
|
||||
cairo_status_to_string(cairo_surface_status(cairo_surface)));
|
||||
goto err;
|
||||
}
|
||||
|
||||
tll_push_back(backend->buffers, buffer);
|
||||
cairo = cairo_create(cairo_surface);
|
||||
if (cairo_status(cairo) != CAIRO_STATUS_SUCCESS) {
|
||||
LOG_ERR("failed to create cairo context: %s",
|
||||
cairo_status_to_string(cairo_status(cairo)));
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Push to list of available buffers, but marked as 'busy' */
|
||||
tll_push_back(
|
||||
backend->buffers,
|
||||
((struct buffer){
|
||||
.busy = true,
|
||||
.size = size,
|
||||
.mmapped = mmapped,
|
||||
.wl_buf = buf,
|
||||
.cairo_surface = cairo_surface,
|
||||
.cairo = cairo}
|
||||
)
|
||||
);
|
||||
|
||||
struct buffer *ret = &tll_back(backend->buffers);
|
||||
wl_buffer_add_listener(buffer.wl_buf, &buffer_listener, ret);
|
||||
wl_buffer_add_listener(ret->wl_buf, &buffer_listener, ret);
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (cairo != NULL)
|
||||
cairo_destroy(cairo);
|
||||
if (cairo_surface != NULL)
|
||||
cairo_surface_destroy(cairo_surface);
|
||||
if (buf != NULL)
|
||||
wl_buffer_destroy(buf);
|
||||
if (pool != NULL)
|
||||
wl_shm_pool_destroy(pool);
|
||||
if (pool_fd != -1)
|
||||
close(pool_fd);
|
||||
if (mmapped != NULL)
|
||||
munmap(mmapped, size);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -486,17 +551,37 @@ setup(struct bar *_bar)
|
|||
backend->bar = _bar;
|
||||
|
||||
backend->display = wl_display_connect(NULL);
|
||||
assert(backend->display != NULL);
|
||||
if (backend->display == NULL) {
|
||||
LOG_ERR("failed to connect to wayland; no compistor running?");
|
||||
return false;
|
||||
}
|
||||
|
||||
backend->registry = wl_display_get_registry(backend->display);
|
||||
assert(backend->registry != NULL);
|
||||
if (backend->registry == NULL) {
|
||||
LOG_ERR("failed to get wayland registry");
|
||||
return false;
|
||||
}
|
||||
|
||||
wl_registry_add_listener(backend->registry, ®istry_listener, backend);
|
||||
|
||||
wl_display_roundtrip(backend->display);
|
||||
assert(backend->compositor != NULL &&
|
||||
backend->layer_shell != NULL &&
|
||||
backend->shm != NULL);
|
||||
|
||||
if (backend->compositor == NULL) {
|
||||
LOG_ERR("no compositor");
|
||||
return false;
|
||||
}
|
||||
if (backend->layer_shell == NULL) {
|
||||
LOG_ERR("no layer shell interface");
|
||||
return false;
|
||||
}
|
||||
if (backend->shm == NULL) {
|
||||
LOG_ERR("no shared memory buffers interface");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tll_length(backend->monitors) == 0) {
|
||||
LOG_ERR("no monitors");
|
||||
return false;
|
||||
}
|
||||
|
||||
tll_foreach(backend->monitors, it) {
|
||||
const struct monitor *mon = &it->item;
|
||||
|
@ -512,18 +597,30 @@ setup(struct bar *_bar)
|
|||
}
|
||||
|
||||
backend->surface = wl_compositor_create_surface(backend->compositor);
|
||||
assert(backend->surface != NULL);
|
||||
if (backend->surface == NULL) {
|
||||
LOG_ERR("failed to create panel surface");
|
||||
return false;
|
||||
}
|
||||
|
||||
backend->pointer.surface = wl_compositor_create_surface(backend->compositor);
|
||||
assert(backend->pointer.surface != NULL);
|
||||
if (backend->pointer.surface == NULL) {
|
||||
LOG_ERR("failed to create cursor surface");
|
||||
return false;
|
||||
}
|
||||
|
||||
backend->pointer.theme = wl_cursor_theme_load(NULL, 24, backend->shm);
|
||||
assert(backend->pointer.theme != NULL);
|
||||
if (backend->pointer.theme == NULL) {
|
||||
LOG_ERR("failed to load cursor theme");
|
||||
return false;
|
||||
}
|
||||
|
||||
backend->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
|
||||
backend->layer_shell, backend->surface, backend->monitor->output,
|
||||
ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "f00bar");
|
||||
assert(backend->layer_surface != NULL);
|
||||
if (backend->layer_surface == NULL) {
|
||||
LOG_ERR("failed to create layer shell surface");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Aligned to top, maximum width */
|
||||
enum zwlr_layer_surface_v1_anchor top_or_bottom = bar->location == BAR_TOP
|
||||
|
@ -543,8 +640,7 @@ setup(struct bar *_bar)
|
|||
|
||||
//zwlr_layer_surface_v1_set_margin(
|
||||
// layer_surface, margin_top, margin_right, margin_bottom, margin_left);
|
||||
//zwlr_layer_surface_v1_set_keyboard_interactivity(
|
||||
// layer_surface, keyboard_interactive);
|
||||
zwlr_layer_surface_v1_set_keyboard_interactivity(backend->layer_surface, 1);
|
||||
|
||||
zwlr_layer_surface_v1_add_listener(
|
||||
backend->layer_surface, &layer_surface_listener, backend);
|
||||
|
@ -553,7 +649,11 @@ setup(struct bar *_bar)
|
|||
wl_surface_commit(backend->surface);
|
||||
wl_display_roundtrip(backend->display);
|
||||
|
||||
assert(backend->width != -1 && backend->height == bar->height_with_border);
|
||||
if (backend->width == -1 || backend->height != bar->height_with_border) {
|
||||
LOG_ERR("failed to get panel width");
|
||||
return false;
|
||||
}
|
||||
|
||||
bar->width = backend->width;
|
||||
bar->x = backend->monitor->x;
|
||||
bar->y = backend->monitor->y;
|
||||
|
@ -561,12 +661,17 @@ setup(struct bar *_bar)
|
|||
? 0
|
||||
: backend->monitor->height_px - bar->height_with_border;
|
||||
|
||||
pipe(backend->pipe_fds);
|
||||
if (pipe(backend->pipe_fds) == -1) {
|
||||
LOG_ERRNO("failed to create pipe");
|
||||
return false;
|
||||
}
|
||||
|
||||
backend->render_scheduled = false;
|
||||
|
||||
wl_surface_commit(backend->surface);
|
||||
wl_display_roundtrip(backend->display);
|
||||
//wl_surface_commit(backend->surface);
|
||||
//wl_display_roundtrip(backend->display);
|
||||
|
||||
/* Prepare a buffer + cairo context for bar to draw to */
|
||||
backend->next_buffer = get_buffer(backend);
|
||||
assert(backend->next_buffer != NULL && backend->next_buffer->busy);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue