Atlas - SDL_waylandshmbuffer.c
Home / ext / SDL / src / video / wayland Lines: 1 | Size: 4893 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21 22#include "SDL_internal.h" 23 24#ifdef SDL_VIDEO_DRIVER_WAYLAND 25 26#include <errno.h> 27#include <fcntl.h> 28#include <limits.h> 29#include <signal.h> 30#include <sys/mman.h> 31#include <unistd.h> 32 33#include "SDL_waylandshmbuffer.h" 34#include "SDL_waylandvideo.h" 35 36static bool SetTempFileSize(int fd, off_t size) 37{ 38#ifdef HAVE_POSIX_FALLOCATE 39 sigset_t set, old_set; 40 int ret; 41 42 /* SIGALRM can potentially block a large posix_fallocate() operation 43 * from succeeding, so block it. 44 */ 45 sigemptyset(&set); 46 sigaddset(&set, SIGALRM); 47 sigprocmask(SIG_BLOCK, &set, &old_set); 48 49 do { 50 ret = posix_fallocate(fd, 0, size); 51 } while (ret == EINTR); 52 53 sigprocmask(SIG_SETMASK, &old_set, NULL); 54 55 if (ret == 0) { 56 return true; 57 } else if (ret != EINVAL && errno != EOPNOTSUPP) { 58 return false; 59 } 60#endif 61 62 if (ftruncate(fd, size) < 0) { 63 return false; 64 } 65 return true; 66} 67 68static int CreateTempFD(off_t size) 69{ 70 int fd; 71 72#ifdef HAVE_MEMFD_CREATE 73 fd = memfd_create("SDL", MFD_CLOEXEC | MFD_ALLOW_SEALING); 74 if (fd >= 0) { 75 fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL); 76 } else 77#endif 78 { 79 static const char template[] = "/sdl-shared-XXXXXX"; 80 const char *xdg_path; 81 char tmp_path[PATH_MAX]; 82 83 xdg_path = SDL_getenv("XDG_RUNTIME_DIR"); 84 if (!xdg_path) { 85 return -1; 86 } 87 88 SDL_strlcpy(tmp_path, xdg_path, PATH_MAX); 89 SDL_strlcat(tmp_path, template, PATH_MAX); 90 91 fd = mkostemp(tmp_path, O_CLOEXEC); 92 if (fd < 0) { 93 return -1; 94 } 95 96 // Need to manually unlink the temp files, or they can persist after close and fill up the temp storage. 97 unlink(tmp_path); 98 } 99 100 if (!SetTempFileSize(fd, size)) { 101 close(fd); 102 return -1; 103 } 104 105 return fd; 106} 107 108static void buffer_handle_release(void *data, struct wl_buffer *wl_buffer) 109{ 110 // NOP 111} 112 113static struct wl_buffer_listener buffer_listener = { 114 buffer_handle_release 115}; 116 117struct Wayland_SHMPool 118{ 119 struct wl_shm_pool *shm_pool; 120 void *shm_pool_memory; 121 int shm_pool_size; 122 int offset; 123}; 124 125Wayland_SHMPool *Wayland_AllocSHMPool(int size) 126{ 127 SDL_VideoDevice *vd = SDL_GetVideoDevice(); 128 SDL_VideoData *data = vd->internal; 129 130 if (size <= 0) { 131 return NULL; 132 } 133 134 Wayland_SHMPool *shmPool = SDL_calloc(1, sizeof(Wayland_SHMPool)); 135 if (!shmPool) { 136 return NULL; 137 } 138 139 shmPool->shm_pool_size = (size + 15) & (~15); 140 141 const int shm_fd = CreateTempFD(shmPool->shm_pool_size); 142 if (shm_fd < 0) { 143 SDL_free(shmPool); 144 SDL_SetError("Creating SHM buffer failed."); 145 return NULL; 146 } 147 148 shmPool->shm_pool_memory = mmap(NULL, shmPool->shm_pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); 149 if (shmPool->shm_pool_memory == MAP_FAILED) { 150 shmPool->shm_pool_memory = NULL; 151 close(shm_fd); 152 SDL_free(shmPool); 153 SDL_SetError("mmap() failed."); 154 return NULL; 155 } 156 157 shmPool->shm_pool = wl_shm_create_pool(data->shm, shm_fd, shmPool->shm_pool_size); 158 close(shm_fd); 159 160 return shmPool; 161} 162 163struct wl_buffer *Wayland_AllocBufferFromPool(Wayland_SHMPool *shmPool, int width, int height, void **data) 164{ 165 const Uint32 SHM_FMT = WL_SHM_FORMAT_ARGB8888; 166 167 if (!shmPool || !width || !height || !data) { 168 return NULL; 169 } 170 171 *data = (Uint8 *)shmPool->shm_pool_memory + shmPool->offset; 172 struct wl_buffer *buffer = wl_shm_pool_create_buffer(shmPool->shm_pool, shmPool->offset, width, height, width * 4, SHM_FMT); 173 wl_buffer_add_listener(buffer, &buffer_listener, shmPool); 174 175 shmPool->offset += width * height * 4; 176 177 return buffer; 178} 179 180void Wayland_ReleaseSHMPool(Wayland_SHMPool *shmPool) 181{ 182 if (shmPool) { 183 wl_shm_pool_destroy(shmPool->shm_pool); 184 munmap(shmPool->shm_pool_memory, shmPool->shm_pool_size); 185 SDL_free(shmPool); 186 } 187} 188 189#endif 190[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.