From 7956a271dc8cc8285f05034b747e0fd3171806ba Mon Sep 17 00:00:00 2001 From: sewn Date: Thu, 5 Sep 2024 20:25:21 +0300 Subject: [PATCH] update drwl --- poolbuf.h => bufpool.h | 109 ++++++++++++++++++++++++++++------------- drwl.h | 61 ++++++++++++----------- mew.c | 26 +++++----- 3 files changed, 122 insertions(+), 74 deletions(-) rename poolbuf.h => bufpool.h (52%) diff --git a/poolbuf.h b/bufpool.h similarity index 52% rename from poolbuf.h rename to bufpool.h index 4cf3807..af672c4 100644 --- a/poolbuf.h +++ b/bufpool.h @@ -1,5 +1,5 @@ /* - * poolbuf - https://codeberg.org/sewn/drwl + * bufpool - https://codeberg.org/sewn/drwl * * Copyright (c) 2023-2024 sewn * @@ -33,46 +33,71 @@ #include #endif +#include "drwl.h" + typedef struct { - struct wl_buffer *wl_buf; - int32_t stride; - int32_t size; - void *data; -} PoolBuf; + struct wl_buffer *wl_buf; + int32_t size; + int busy; + void *mmapped; + Img *image; +} DrwBuf; + +typedef struct { + DrwBuf bufs[2]; +} BufPool; static void -poolbuf_destroy(PoolBuf *buf) +drwbuf_cleanup(DrwBuf *buf) { - wl_buffer_destroy(buf->wl_buf); - munmap(buf->data, buf->size); - free(buf); + if (buf->wl_buf) + wl_buffer_destroy(buf->wl_buf); + if (buf->mmapped) + munmap(buf->mmapped, buf->size); + if (buf->image) + drwl_image_destroy(buf->image); + *buf = (DrwBuf){0}; } static void -poolbuf_buffer_release(void *data, struct wl_buffer *wl_buffer) +drwbuf_handle_release(void *data, struct wl_buffer *wl_buffer) { - PoolBuf *buf = data; - poolbuf_destroy(buf); + DrwBuf *buf = data; + buf->busy = 0; } -static struct wl_buffer_listener poolbuf_buffer_listener = { - .release = poolbuf_buffer_release, +static struct wl_buffer_listener drwbuf_buffer_listener = { + .release = drwbuf_handle_release, }; -static PoolBuf * -poolbuf_create(struct wl_shm *shm, - int32_t width, int32_t height, int32_t stride, int norelease) +static DrwBuf * +bufpool_getbuf(BufPool *pool, struct wl_shm *shm, + int32_t width, int32_t height) { + int i; int fd; - void *data; + void *mmapped; struct wl_shm_pool *shm_pool; struct wl_buffer *wl_buf; - int32_t size = stride * height; - PoolBuf *buf; + int32_t size = width * 4 * height; + Img *image; + DrwBuf *buf = NULL; + + for (i = 0; i < 2; i++) { + if (pool->bufs[i].busy) + continue; + if (pool->bufs[i].wl_buf && pool->bufs[i].size != size) + drwbuf_cleanup(&pool->bufs[i]); + buf = &pool->bufs[i]; + } + if (!buf) + return NULL; + if (buf->wl_buf && buf->size == size) + return buf; #if defined(__linux__) || \ ((defined(__FreeBSD__) && (__FreeBSD_version >= 1300048))) - fd = memfd_create("poolbuf-shm-buffer-pool", + fd = memfd_create("drwbuf-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING | #if defined(MFD_NOEXEC_SEAL) MFD_NOEXEC_SEAL @@ -81,40 +106,58 @@ poolbuf_create(struct wl_shm *shm, #endif ); #else - char template[] = "/tmp/poolbuf-XXXXXX"; + char template[] = "/tmp/drwbuf-XXXXXX"; #if defined(__OpenBSD__) fd = shm_mkstemp(template); #else fd = mkostemp(template, O_CLOEXEC); #endif + if (fd < 0) + return NULL; +#if defined(__OpenBSD__) + shm_unlink(template); +#else unlink(template); #endif - if (fd < 0) - return NULL; +#endif if ((ftruncate(fd, size)) < 0) { close(fd); return NULL; } - data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) { + mmapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mmapped == MAP_FAILED) { close(fd); return NULL; } +#if defined(__linux__) || \ + ((defined(__FreeBSD__) && (__FreeBSD_version >= 1300048))) + fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL); +#endif + shm_pool = wl_shm_create_pool(shm, fd, size); wl_buf = wl_shm_pool_create_buffer(shm_pool, 0, - width, height, stride, WL_SHM_FORMAT_ARGB8888); + width, height, width * 4, WL_SHM_FORMAT_ARGB8888); wl_shm_pool_destroy(shm_pool); close(fd); - buf = calloc(1, sizeof(PoolBuf)); buf->wl_buf = wl_buf; - buf->stride = stride; buf->size = size; - buf->data = data; - if (!norelease) - wl_buffer_add_listener(wl_buf, &poolbuf_buffer_listener, buf); + buf->mmapped = mmapped; + buf->busy = 1; + if (!(image = drwl_image_create(NULL, width, height, buf->mmapped))) + drwbuf_cleanup(buf); + buf->image = image; + wl_buffer_add_listener(wl_buf, &drwbuf_buffer_listener, buf); return buf; } + +static void +bufpool_cleanup(BufPool *pool) +{ + int i; + for (i = 0; i < 2; i++) + drwbuf_cleanup(&pool->bufs[i]); +} diff --git a/drwl.h b/drwl.h index 92a3fbb..a506247 100644 --- a/drwl.h +++ b/drwl.h @@ -36,9 +36,10 @@ enum { ColFg, ColBg }; /* colorscheme index */ typedef struct fcft_font Fnt; +typedef pixman_image_t Img; typedef struct { - pixman_image_t *pix; + Img *image; Fnt *font; uint32_t *scheme; } Drwl; @@ -102,6 +103,13 @@ drwl_setfont(Drwl *drwl, Fnt *font) drwl->font = font; } +static void +drwl_setimage(Drwl *drwl, Img *image) +{ + if (drwl) + drwl->image = image; +} + static Fnt * drwl_font_create(Drwl *drwl, size_t count, const char *names[static count], const char *attributes) @@ -136,26 +144,23 @@ drwl_setscheme(Drwl *drwl, uint32_t *scm) drwl->scheme = scm; } -static inline int -drwl_stride(unsigned int width) -{ - return (((PIXMAN_FORMAT_BPP(PIXMAN_a8r8g8b8) * width + 7) / 8 + 4 - 1) & -4); -} - -static void -drwl_prepare_drawing(Drwl *drwl, unsigned int w, unsigned int h, - uint32_t *bits, int stride) +static Img * +drwl_image_create(Drwl *drwl, unsigned int w, unsigned int h, uint32_t *bits) { + Img *image; pixman_region32_t clip; - if (!drwl) - return; - - drwl->pix = pixman_image_create_bits_no_clear( - PIXMAN_a8r8g8b8, w, h, bits, stride); + image = pixman_image_create_bits_no_clear( + PIXMAN_a8r8g8b8, w, h, bits, w * 4); + if (!image) + return NULL; pixman_region32_init_rect(&clip, 0, 0, w, h); - pixman_image_set_clip_region32(drwl->pix, &clip); + pixman_image_set_clip_region32(image, &clip); pixman_region32_fini(&clip); + + if (drwl) + drwl_setimage(drwl, image); + return image; } static void @@ -164,15 +169,15 @@ drwl_rect(Drwl *drwl, int filled, int invert) { pixman_color_t clr; - if (!drwl || !drwl->scheme || !drwl->pix) + if (!drwl || !drwl->scheme || !drwl->image) return; clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); if (filled) - pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->pix, &clr, 1, + pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 1, &(pixman_rectangle16_t){x, y, w, h}); else - pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->pix, &clr, 4, + pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 4, (pixman_rectangle16_t[4]){ { x, y, w, 1 }, { x, y + h - 1, w, 1 }, @@ -195,7 +200,7 @@ drwl_text(Drwl *drwl, const struct fcft_glyph *glyph, *eg = NULL; int fcft_subpixel_mode = FCFT_SUBPIXEL_DEFAULT; - if (!drwl || (render && (!drwl->scheme || !w || !drwl->pix)) || !text || !drwl->font) + if (!drwl || (render && (!drwl->scheme || !w || !drwl->image)) || !text || !drwl->font) return 0; if (!render) { @@ -245,7 +250,7 @@ drwl_text(Drwl *drwl, } else { w -= eg->advance.x; pixman_image_composite32( - PIXMAN_OP_OVER, fg_pix, eg->pix, drwl->pix, 0, 0, 0, 0, + PIXMAN_OP_OVER, fg_pix, eg->pix, drwl->image, 0, 0, 0, 0, x + eg->x, ty - eg->y, eg->width, eg->height); } } @@ -258,11 +263,11 @@ drwl_text(Drwl *drwl, if (render && pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) /* pre-rendered glyphs (eg. emoji) */ pixman_image_composite32( - PIXMAN_OP_OVER, glyph->pix, NULL, drwl->pix, 0, 0, 0, 0, + PIXMAN_OP_OVER, glyph->pix, NULL, drwl->image, 0, 0, 0, 0, x + glyph->x, ty - glyph->y, glyph->width, glyph->height); else if (render) pixman_image_composite32( - PIXMAN_OP_OVER, fg_pix, glyph->pix, drwl->pix, 0, 0, 0, 0, + PIXMAN_OP_OVER, fg_pix, glyph->pix, drwl->image, 0, 0, 0, 0, x + glyph->x, ty - glyph->y, glyph->width, glyph->height); x += glyph->advance.x; @@ -293,13 +298,9 @@ drwl_font_getwidth_clamp(Drwl *drwl, const char *text, unsigned int n) } static void -drwl_finish_drawing(Drwl *drwl) +drwl_image_destroy(Img *image) { - if (!drwl) - return; - if (drwl->pix) - pixman_image_unref(drwl->pix); - drwl->pix = NULL; + pixman_image_unref(image); } static void @@ -307,6 +308,8 @@ drwl_destroy(Drwl *drwl) { if (drwl->font) drwl_font_destroy(drwl->font); + if (drwl->image) + drwl_image_destroy(drwl->image); free(drwl); } diff --git a/mew.c b/mew.c index dd9f593..44b1525 100644 --- a/mew.c +++ b/mew.c @@ -1,4 +1,5 @@ /* See LICENSE file for copyright and license details. */ +#include #include #include #include @@ -17,7 +18,7 @@ #define LENGTH(X) (sizeof (X) / sizeof (X)[0]) #include "drwl.h" -#include "poolbuf.h" +#include "bufpool.h" #include "xdg-activation-v1-protocol.h" #include "wlr-layer-shell-unstable-v1-protocol.h" @@ -71,6 +72,7 @@ static struct xdg_activation_v1 *activation; static struct wl_surface *surface; static struct wl_registry *registry; static Drwl *drw; +static BufPool pool; static struct wl_callback *frame_callback; /* default output supplied by compositor */ static struct wl_output *output = NULL; @@ -224,6 +226,8 @@ cleanup(void) free(items[i].text); free(items); + bufpool_cleanup(&pool); + drwl_setimage(drw, NULL); drwl_destroy(drw); drwl_fini(); @@ -272,14 +276,13 @@ drawmenu(void) { unsigned int curpos; struct item *item; - int x = 0, y = 0, w, stride; - PoolBuf *buf; + int x = 0, y = 0, w; + DrwBuf *buf; - stride = drwl_stride(mw); - if (!(buf = poolbuf_create(shm, mw, mh, stride, 0))) - die("poolbuf_create:"); - - drwl_prepare_drawing(drw, mw, mh, buf->data, buf->stride); + errno = 0; + if (!(buf = bufpool_getbuf(&pool, shm, mw, mh))) + die("failed to find available buffer"); + drwl_setimage(drw, buf->image); drwl_setscheme(drw, colors[SchemeNorm]); drwl_rect(drw, 0, 0, mw, mh, 1, 1); @@ -322,7 +325,7 @@ drawmenu(void) } } - drwl_finish_drawing(drw); + drwl_setimage(drw, NULL); wl_surface_set_buffer_scale(surface, scale); wl_surface_attach(surface, buf->wl_buf, 0, 0); wl_surface_damage_buffer(surface, 0, 0, mw, mh); @@ -728,13 +731,13 @@ static const struct wl_keyboard_listener keyboard_listener = { }; static void -layer_surface_handle_configure(void *data, struct zwlr_layer_surface_v1 *surface, +layer_surface_handle_configure(void *data, struct zwlr_layer_surface_v1 *layer_surface, uint32_t serial, uint32_t width, uint32_t height) { mw = width * scale; mh = height * scale; inputw = mw / 3; /* input width: ~33% of output width */ - zwlr_layer_surface_v1_ack_configure(surface, serial); + zwlr_layer_surface_v1_ack_configure(layer_surface, serial); drawmenu(); } @@ -882,7 +885,6 @@ run(void) }; match(); - drawmenu(); while (running) { if (wl_display_prepare_read(display) < 0)