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>
*
@ -33,46 +33,71 @@
#include <linux/memfd.h>
#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]);
}

61
drwl.h
View file

@ -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);
}

26
mew.c
View file

@ -1,4 +1,5 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <ctype.h>
#include <locale.h>
#include <poll.h>
@ -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)