cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_x11framebuffer.c (7630B)


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