update drwl
This commit is contained in:
parent
02c3ac09a6
commit
7956a271dc
3 changed files with 122 additions and 74 deletions
|
@ -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
61
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);
|
||||
}
|
||||
|
||||
|
|
26
mew.c
26
mew.c
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue