update drwl

This commit is contained in:
sewn 2024-09-05 20:25:21 +03:00
parent 02c3ac09a6
commit 7956a271dc
No known key found for this signature in database
3 changed files with 122 additions and 74 deletions

View file

@ -1,5 +1,5 @@
/* /*
* poolbuf - https://codeberg.org/sewn/drwl * bufpool - https://codeberg.org/sewn/drwl
* *
* Copyright (c) 2023-2024 sewn <sewn@disroot.org> * Copyright (c) 2023-2024 sewn <sewn@disroot.org>
* *
@ -33,46 +33,71 @@
#include <linux/memfd.h> #include <linux/memfd.h>
#endif #endif
#include "drwl.h"
typedef struct { typedef struct {
struct wl_buffer *wl_buf; struct wl_buffer *wl_buf;
int32_t stride; int32_t size;
int32_t size; int busy;
void *data; void *mmapped;
} PoolBuf; Img *image;
} DrwBuf;
typedef struct {
DrwBuf bufs[2];
} BufPool;
static void static void
poolbuf_destroy(PoolBuf *buf) drwbuf_cleanup(DrwBuf *buf)
{ {
wl_buffer_destroy(buf->wl_buf); if (buf->wl_buf)
munmap(buf->data, buf->size); wl_buffer_destroy(buf->wl_buf);
free(buf); if (buf->mmapped)
munmap(buf->mmapped, buf->size);
if (buf->image)
drwl_image_destroy(buf->image);
*buf = (DrwBuf){0};
} }
static void 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; DrwBuf *buf = data;
poolbuf_destroy(buf); buf->busy = 0;
} }
static struct wl_buffer_listener poolbuf_buffer_listener = { static struct wl_buffer_listener drwbuf_buffer_listener = {
.release = poolbuf_buffer_release, .release = drwbuf_handle_release,
}; };
static PoolBuf * static DrwBuf *
poolbuf_create(struct wl_shm *shm, bufpool_getbuf(BufPool *pool, struct wl_shm *shm,
int32_t width, int32_t height, int32_t stride, int norelease) int32_t width, int32_t height)
{ {
int i;
int fd; int fd;
void *data; void *mmapped;
struct wl_shm_pool *shm_pool; struct wl_shm_pool *shm_pool;
struct wl_buffer *wl_buf; struct wl_buffer *wl_buf;
int32_t size = stride * height; int32_t size = width * 4 * height;
PoolBuf *buf; 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__) || \ #if defined(__linux__) || \
((defined(__FreeBSD__) && (__FreeBSD_version >= 1300048))) ((defined(__FreeBSD__) && (__FreeBSD_version >= 1300048)))
fd = memfd_create("poolbuf-shm-buffer-pool", fd = memfd_create("drwbuf-shm-buffer-pool",
MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_CLOEXEC | MFD_ALLOW_SEALING |
#if defined(MFD_NOEXEC_SEAL) #if defined(MFD_NOEXEC_SEAL)
MFD_NOEXEC_SEAL MFD_NOEXEC_SEAL
@ -81,40 +106,58 @@ poolbuf_create(struct wl_shm *shm,
#endif #endif
); );
#else #else
char template[] = "/tmp/poolbuf-XXXXXX"; char template[] = "/tmp/drwbuf-XXXXXX";
#if defined(__OpenBSD__) #if defined(__OpenBSD__)
fd = shm_mkstemp(template); fd = shm_mkstemp(template);
#else #else
fd = mkostemp(template, O_CLOEXEC); fd = mkostemp(template, O_CLOEXEC);
#endif #endif
if (fd < 0)
return NULL;
#if defined(__OpenBSD__)
shm_unlink(template);
#else
unlink(template); unlink(template);
#endif #endif
if (fd < 0) #endif
return NULL;
if ((ftruncate(fd, size)) < 0) { if ((ftruncate(fd, size)) < 0) {
close(fd); close(fd);
return NULL; return NULL;
} }
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); mmapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED) { if (mmapped == MAP_FAILED) {
close(fd); close(fd);
return NULL; 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); shm_pool = wl_shm_create_pool(shm, fd, size);
wl_buf = wl_shm_pool_create_buffer(shm_pool, 0, 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); wl_shm_pool_destroy(shm_pool);
close(fd); close(fd);
buf = calloc(1, sizeof(PoolBuf));
buf->wl_buf = wl_buf; buf->wl_buf = wl_buf;
buf->stride = stride;
buf->size = size; buf->size = size;
buf->data = data; buf->mmapped = mmapped;
if (!norelease) buf->busy = 1;
wl_buffer_add_listener(wl_buf, &poolbuf_buffer_listener, buf); 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; return buf;
} }
static void
bufpool_cleanup(BufPool *pool)
{
int i;
for (i = 0; i < 2; i++)
drwbuf_cleanup(&pool->bufs[i]);
}

61
drwl.h
View file

@ -36,9 +36,10 @@
enum { ColFg, ColBg }; /* colorscheme index */ enum { ColFg, ColBg }; /* colorscheme index */
typedef struct fcft_font Fnt; typedef struct fcft_font Fnt;
typedef pixman_image_t Img;
typedef struct { typedef struct {
pixman_image_t *pix; Img *image;
Fnt *font; Fnt *font;
uint32_t *scheme; uint32_t *scheme;
} Drwl; } Drwl;
@ -102,6 +103,13 @@ drwl_setfont(Drwl *drwl, Fnt *font)
drwl->font = font; drwl->font = font;
} }
static void
drwl_setimage(Drwl *drwl, Img *image)
{
if (drwl)
drwl->image = image;
}
static Fnt * static Fnt *
drwl_font_create(Drwl *drwl, size_t count, drwl_font_create(Drwl *drwl, size_t count,
const char *names[static count], const char *attributes) const char *names[static count], const char *attributes)
@ -136,26 +144,23 @@ drwl_setscheme(Drwl *drwl, uint32_t *scm)
drwl->scheme = scm; drwl->scheme = scm;
} }
static inline int static Img *
drwl_stride(unsigned int width) drwl_image_create(Drwl *drwl, unsigned int w, unsigned int h, uint32_t *bits)
{
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)
{ {
Img *image;
pixman_region32_t clip; pixman_region32_t clip;
if (!drwl) image = pixman_image_create_bits_no_clear(
return; PIXMAN_a8r8g8b8, w, h, bits, w * 4);
if (!image)
drwl->pix = pixman_image_create_bits_no_clear( return NULL;
PIXMAN_a8r8g8b8, w, h, bits, stride);
pixman_region32_init_rect(&clip, 0, 0, w, h); 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); pixman_region32_fini(&clip);
if (drwl)
drwl_setimage(drwl, image);
return image;
} }
static void static void
@ -164,15 +169,15 @@ drwl_rect(Drwl *drwl,
int filled, int invert) int filled, int invert)
{ {
pixman_color_t clr; pixman_color_t clr;
if (!drwl || !drwl->scheme || !drwl->pix) if (!drwl || !drwl->scheme || !drwl->image)
return; return;
clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]);
if (filled) 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}); &(pixman_rectangle16_t){x, y, w, h});
else 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]){ (pixman_rectangle16_t[4]){
{ x, y, w, 1 }, { x, y, w, 1 },
{ x, y + h - 1, w, 1 }, { x, y + h - 1, w, 1 },
@ -195,7 +200,7 @@ drwl_text(Drwl *drwl,
const struct fcft_glyph *glyph, *eg = NULL; const struct fcft_glyph *glyph, *eg = NULL;
int fcft_subpixel_mode = FCFT_SUBPIXEL_DEFAULT; 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; return 0;
if (!render) { if (!render) {
@ -245,7 +250,7 @@ drwl_text(Drwl *drwl,
} else { } else {
w -= eg->advance.x; w -= eg->advance.x;
pixman_image_composite32( 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); 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) if (render && pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8)
/* pre-rendered glyphs (eg. emoji) */ /* pre-rendered glyphs (eg. emoji) */
pixman_image_composite32( 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); x + glyph->x, ty - glyph->y, glyph->width, glyph->height);
else if (render) else if (render)
pixman_image_composite32( 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->x, ty - glyph->y, glyph->width, glyph->height);
x += glyph->advance.x; x += glyph->advance.x;
@ -293,13 +298,9 @@ drwl_font_getwidth_clamp(Drwl *drwl, const char *text, unsigned int n)
} }
static void static void
drwl_finish_drawing(Drwl *drwl) drwl_image_destroy(Img *image)
{ {
if (!drwl) pixman_image_unref(image);
return;
if (drwl->pix)
pixman_image_unref(drwl->pix);
drwl->pix = NULL;
} }
static void static void
@ -307,6 +308,8 @@ drwl_destroy(Drwl *drwl)
{ {
if (drwl->font) if (drwl->font)
drwl_font_destroy(drwl->font); drwl_font_destroy(drwl->font);
if (drwl->image)
drwl_image_destroy(drwl->image);
free(drwl); free(drwl);
} }

26
mew.c
View file

@ -1,4 +1,5 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <ctype.h> #include <ctype.h>
#include <locale.h> #include <locale.h>
#include <poll.h> #include <poll.h>
@ -17,7 +18,7 @@
#define LENGTH(X) (sizeof (X) / sizeof (X)[0]) #define LENGTH(X) (sizeof (X) / sizeof (X)[0])
#include "drwl.h" #include "drwl.h"
#include "poolbuf.h" #include "bufpool.h"
#include "xdg-activation-v1-protocol.h" #include "xdg-activation-v1-protocol.h"
#include "wlr-layer-shell-unstable-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_surface *surface;
static struct wl_registry *registry; static struct wl_registry *registry;
static Drwl *drw; static Drwl *drw;
static BufPool pool;
static struct wl_callback *frame_callback; static struct wl_callback *frame_callback;
/* default output supplied by compositor */ /* default output supplied by compositor */
static struct wl_output *output = NULL; static struct wl_output *output = NULL;
@ -224,6 +226,8 @@ cleanup(void)
free(items[i].text); free(items[i].text);
free(items); free(items);
bufpool_cleanup(&pool);
drwl_setimage(drw, NULL);
drwl_destroy(drw); drwl_destroy(drw);
drwl_fini(); drwl_fini();
@ -272,14 +276,13 @@ drawmenu(void)
{ {
unsigned int curpos; unsigned int curpos;
struct item *item; struct item *item;
int x = 0, y = 0, w, stride; int x = 0, y = 0, w;
PoolBuf *buf; DrwBuf *buf;
stride = drwl_stride(mw); errno = 0;
if (!(buf = poolbuf_create(shm, mw, mh, stride, 0))) if (!(buf = bufpool_getbuf(&pool, shm, mw, mh)))
die("poolbuf_create:"); die("failed to find available buffer");
drwl_setimage(drw, buf->image);
drwl_prepare_drawing(drw, mw, mh, buf->data, buf->stride);
drwl_setscheme(drw, colors[SchemeNorm]); drwl_setscheme(drw, colors[SchemeNorm]);
drwl_rect(drw, 0, 0, mw, mh, 1, 1); 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_set_buffer_scale(surface, scale);
wl_surface_attach(surface, buf->wl_buf, 0, 0); wl_surface_attach(surface, buf->wl_buf, 0, 0);
wl_surface_damage_buffer(surface, 0, 0, mw, mh); wl_surface_damage_buffer(surface, 0, 0, mw, mh);
@ -728,13 +731,13 @@ static const struct wl_keyboard_listener keyboard_listener = {
}; };
static void 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) uint32_t serial, uint32_t width, uint32_t height)
{ {
mw = width * scale; mw = width * scale;
mh = height * scale; mh = height * scale;
inputw = mw / 3; /* input width: ~33% of output width */ 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(); drawmenu();
} }
@ -882,7 +885,6 @@ run(void)
}; };
match(); match();
drawmenu();
while (running) { while (running) {
if (wl_display_prepare_read(display) < 0) if (wl_display_prepare_read(display) < 0)