Atlas - SDL_x11framebuffer.c
Home / ext / SDL / src / video / x11 Lines: 1 | Size: 7981 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#include "SDL_internal.h" 22 23#ifdef SDL_VIDEO_DRIVER_X11 24 25#include "SDL_x11video.h" 26#include "SDL_x11framebuffer.h" 27#include "SDL_x11xsync.h" 28 29#ifndef NO_SHARED_MEMORY 30 31// Shared memory error handler routine 32static int shm_error; 33static int (*X_handler)(Display *, XErrorEvent *) = NULL; 34static int shm_errhandler(Display *d, XErrorEvent *e) 35{ 36 if (e->error_code == BadAccess || e->error_code == BadRequest) { 37 shm_error = True; 38 return 0; 39 } 40 return X_handler(d, e); 41} 42 43static bool have_mitshm(Display *dpy) 44{ 45 // Only use shared memory on local X servers 46 return X11_XShmQueryExtension(dpy) ? SDL_X11_HAVE_SHM : false; 47} 48 49#endif // !NO_SHARED_MEMORY 50 51bool X11_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, SDL_PixelFormat *format, 52 void **pixels, int *pitch) 53{ 54 SDL_WindowData *data = window->internal; 55 Display *display = data->videodata->display; 56 XGCValues gcv; 57 XVisualInfo vinfo; 58 int w, h; 59 60 SDL_GetWindowSizeInPixels(window, &w, &h); 61 62 // Free the old framebuffer surface 63 X11_DestroyWindowFramebuffer(_this, window); 64 65 // Create the graphics context for drawing 66 gcv.graphics_exposures = False; 67 data->gc = X11_XCreateGC(display, data->xwindow, GCGraphicsExposures, &gcv); 68 if (!data->gc) { 69 return SDL_SetError("Couldn't create graphics context"); 70 } 71 72 // Find out the pixel format and depth 73 if (!X11_GetVisualInfoFromVisual(display, data->visual, &vinfo)) { 74 return SDL_SetError("Couldn't get window visual information"); 75 } 76 77 *format = X11_GetPixelFormatFromVisualInfo(display, &vinfo); 78 if (*format == SDL_PIXELFORMAT_UNKNOWN) { 79 return SDL_SetError("Unknown window pixel format"); 80 } 81 82 // Calculate pitch 83 *pitch = (((w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3); 84 85 // Create the actual image 86#ifndef NO_SHARED_MEMORY 87 if (have_mitshm(display)) { 88 XShmSegmentInfo *shminfo = &data->shminfo; 89 90 shminfo->shmid = shmget(IPC_PRIVATE, (size_t)h * (*pitch), IPC_CREAT | 0777); 91 if (shminfo->shmid >= 0) { 92 shminfo->shmaddr = (char *)shmat(shminfo->shmid, NULL, 0); 93 shminfo->readOnly = False; 94 if (shminfo->shmaddr != (char *)-1) { 95 shm_error = False; 96 X_handler = X11_XSetErrorHandler(shm_errhandler); 97 X11_XShmAttach(display, shminfo); 98 X11_XSync(display, False); 99 X11_XSetErrorHandler(X_handler); 100 if (shm_error) { 101 shmdt(shminfo->shmaddr); 102 } 103 } else { 104 shm_error = True; 105 } 106 shmctl(shminfo->shmid, IPC_RMID, NULL); 107 } else { 108 shm_error = True; 109 } 110 if (!shm_error) { 111 data->ximage = X11_XShmCreateImage(display, data->visual, 112 vinfo.depth, ZPixmap, 113 shminfo->shmaddr, shminfo, 114 w, h); 115 if (!data->ximage) { 116 X11_XShmDetach(display, shminfo); 117 X11_XSync(display, False); 118 shmdt(shminfo->shmaddr); 119 } else { 120 // Done! 121 data->ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? MSBFirst : LSBFirst; 122 data->use_mitshm = true; 123 *pixels = shminfo->shmaddr; 124 return true; 125 } 126 } 127 } 128#endif // not NO_SHARED_MEMORY 129 130 *pixels = SDL_malloc((size_t)h * (*pitch)); 131 if (!*pixels) { 132 return false; 133 } 134 135 data->ximage = X11_XCreateImage(display, data->visual, 136 vinfo.depth, ZPixmap, 0, (char *)(*pixels), 137 w, h, 32, 0); 138 if (!data->ximage) { 139 SDL_free(*pixels); 140 return SDL_SetError("Couldn't create XImage"); 141 } 142 data->ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? MSBFirst : LSBFirst; 143 return true; 144} 145 146bool X11_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, 147 int numrects) 148{ 149 SDL_WindowData *data = window->internal; 150 Display *display = data->videodata->display; 151 int i; 152 int x, y, w, h; 153 int window_w, window_h; 154 155 SDL_GetWindowSizeInPixels(window, &window_w, &window_h); 156 157#ifndef NO_SHARED_MEMORY 158 if (data->use_mitshm) { 159 for (i = 0; i < numrects; ++i) { 160 x = rects[i].x; 161 y = rects[i].y; 162 w = rects[i].w; 163 h = rects[i].h; 164 165 if (w <= 0 || h <= 0 || (x + w) <= 0 || (y + h) <= 0) { 166 // Clipped? 167 continue; 168 } 169 if (x < 0) { 170 x += w; 171 w += rects[i].x; 172 } 173 if (y < 0) { 174 y += h; 175 h += rects[i].y; 176 } 177 if (x + w > window_w) { 178 w = window_w - x; 179 } 180 if (y + h > window_h) { 181 h = window_h - y; 182 } 183 184 X11_XShmPutImage(display, data->xwindow, data->gc, data->ximage, 185 x, y, x, y, w, h, False); 186 } 187 } else 188#endif // !NO_SHARED_MEMORY 189 { 190 for (i = 0; i < numrects; ++i) { 191 x = rects[i].x; 192 y = rects[i].y; 193 w = rects[i].w; 194 h = rects[i].h; 195 196 if (w <= 0 || h <= 0 || (x + w) <= 0 || (y + h) <= 0) { 197 // Clipped? 198 continue; 199 } 200 if (x < 0) { 201 x += w; 202 w += rects[i].x; 203 } 204 if (y < 0) { 205 y += h; 206 h += rects[i].y; 207 } 208 if (x + w > window_w) { 209 w = window_w - x; 210 } 211 if (y + h > window_h) { 212 h = window_h - y; 213 } 214 215 X11_XPutImage(display, data->xwindow, data->gc, data->ximage, 216 x, y, x, y, w, h); 217 } 218 } 219 220#ifdef SDL_VIDEO_DRIVER_X11_XSYNC 221 X11_HandlePresent(data->window); 222#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ 223 224 X11_XSync(display, False); 225 226 return true; 227} 228 229void X11_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window) 230{ 231 SDL_WindowData *data = window->internal; 232 Display *display; 233 234 if (!data) { 235 // The window wasn't fully initialized 236 return; 237 } 238 239 display = data->videodata->display; 240 241 if (data->ximage) { 242 XDestroyImage(data->ximage); 243 244#ifndef NO_SHARED_MEMORY 245 if (data->use_mitshm) { 246 X11_XShmDetach(display, &data->shminfo); 247 X11_XSync(display, False); 248 shmdt(data->shminfo.shmaddr); 249 data->use_mitshm = false; 250 } 251#endif // !NO_SHARED_MEMORY 252 253 data->ximage = NULL; 254 } 255 if (data->gc) { 256 X11_XFreeGC(display, data->gc); 257 data->gc = NULL; 258 } 259} 260 261#endif // SDL_VIDEO_DRIVER_X11 262[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.