mew

fork with password patch and nord colorscheme
git clone https://git.awy.one/mew.git
Log | Files | Refs | README | LICENSE

bufpool.h (3983B)


      1 /*
      2  * bufpool - https://codeberg.org/sewn/drwl
      3  *
      4  * Copyright (c) 2023-2024 sewn <sewn@disroot.org>
      5  * 
      6  * Permission is hereby granted, free of charge, to any person obtaining
      7  * a copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sublicense, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  * 
     14  * The above copyright notice and this permission notice shall be
     15  * included in all copies or substantial portions of the Software.
     16  * 
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  */
     25 #include <stdlib.h>
     26 #include <stddef.h>
     27 #include <stdint.h>
     28 #include <sys/mman.h>
     29 #include <fcntl.h>
     30 #include <unistd.h>
     31 #include <wayland-client.h>
     32 #ifdef __linux__
     33 #include <linux/memfd.h>
     34 #endif
     35 
     36 #include "drwl.h"
     37 
     38 typedef struct {
     39 	struct wl_buffer *wl_buf;
     40 	int32_t size;
     41 	int busy;
     42 	void *mmapped;
     43 	Img *image;
     44 } DrwBuf;
     45 
     46 typedef struct {
     47 	DrwBuf bufs[2];
     48 } BufPool;
     49 
     50 static void
     51 drwbuf_cleanup(DrwBuf *buf)
     52 {
     53 	if (buf->wl_buf)
     54 		wl_buffer_destroy(buf->wl_buf);
     55 	if (buf->mmapped)
     56 		munmap(buf->mmapped, buf->size);
     57 	if (buf->image)
     58 		drwl_image_destroy(buf->image);
     59 	*buf = (DrwBuf){0};
     60 }
     61 
     62 static void
     63 drwbuf_handle_release(void *data, struct wl_buffer *wl_buffer)
     64 {
     65 	DrwBuf *buf = data;
     66 	buf->busy = 0;
     67 }
     68 
     69 static struct wl_buffer_listener drwbuf_buffer_listener = {
     70 	.release = drwbuf_handle_release,
     71 };
     72 
     73 static DrwBuf *
     74 bufpool_getbuf(BufPool *pool, struct wl_shm *shm,
     75 		int32_t width, int32_t height)
     76 {
     77 	int i;
     78 	int fd;
     79 	void *mmapped;
     80 	struct wl_shm_pool *shm_pool;
     81 	struct wl_buffer *wl_buf;
     82 	int32_t size = width * 4 * height;
     83 	Img *image;
     84 	DrwBuf *buf = NULL;
     85 
     86 	for (i = 0; i < 2; i++) {
     87 		if (pool->bufs[i].busy)
     88 			continue;
     89 		if (pool->bufs[i].wl_buf && pool->bufs[i].size != size)
     90 			drwbuf_cleanup(&pool->bufs[i]);
     91 		buf = &pool->bufs[i];
     92 	}
     93 	if (!buf)
     94 		return NULL;
     95 	if (buf->wl_buf && buf->size == size)
     96 		return buf;
     97 
     98 #if defined(__linux__) || \
     99 	((defined(__FreeBSD__) && (__FreeBSD_version >= 1300048)))
    100 	fd = memfd_create("drwbuf-shm-buffer-pool",
    101 		MFD_CLOEXEC | MFD_ALLOW_SEALING |
    102 #if defined(MFD_NOEXEC_SEAL)
    103 		MFD_NOEXEC_SEAL
    104 #else
    105 		0
    106 #endif
    107 	);
    108 #else
    109 	char template[] = "/tmp/drwbuf-XXXXXX";
    110 #if defined(__OpenBSD__)
    111 	fd = shm_mkstemp(template);
    112 #else
    113 	fd = mkostemp(template, O_CLOEXEC);
    114 #endif
    115 	if (fd < 0)
    116 		return NULL;
    117 #if defined(__OpenBSD__)
    118     shm_unlink(template);
    119 #else
    120 	unlink(template);
    121 #endif
    122 #endif
    123 
    124 	if ((ftruncate(fd, size)) < 0) {
    125 		close(fd);
    126 		return NULL;
    127 	}
    128 
    129 	mmapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    130 	if (mmapped == MAP_FAILED) {
    131 		close(fd);
    132 		return NULL;
    133 	}
    134 
    135 #if defined(__linux__) || \
    136 	((defined(__FreeBSD__) && (__FreeBSD_version >= 1300048)))
    137 	fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL);
    138 #endif
    139 
    140 	shm_pool = wl_shm_create_pool(shm, fd, size);
    141 	wl_buf = wl_shm_pool_create_buffer(shm_pool, 0,
    142 		width, height, width * 4, WL_SHM_FORMAT_ARGB8888);
    143 	wl_shm_pool_destroy(shm_pool);
    144 	close(fd);
    145 
    146 	buf->wl_buf = wl_buf;
    147 	buf->size = size;
    148 	buf->mmapped = mmapped;
    149 	buf->busy = 1;
    150 	if (!(image = drwl_image_create(NULL, width, height, buf->mmapped)))
    151 		drwbuf_cleanup(buf);
    152 	buf->image = image;
    153 	wl_buffer_add_listener(wl_buf, &drwbuf_buffer_listener, buf);
    154 	return buf;
    155 }
    156 
    157 static void
    158 bufpool_cleanup(BufPool *pool)
    159 {
    160 	int i;
    161 	for (i = 0; i < 2; i++)
    162 		drwbuf_cleanup(&pool->bufs[i]);
    163 }