src/video/x11/SDL_x11framebuffer.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 13 Oct 2011 01:08:30 -0400
changeset 5981 75caa8a7d559
parent 5535 96594ac5fd1a
child 6138 4c64952a58fb
permissions -rw-r--r--
Fixed a whole slew of compiler warnings that -Wall exposed.
slouken@5182
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@5535
     3
  Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
slouken@5182
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@5182
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@5182
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@5182
    20
*/
slouken@5182
    21
#include "SDL_config.h"
slouken@5182
    22
slouken@5481
    23
#if SDL_VIDEO_DRIVER_X11
slouken@5481
    24
slouken@5182
    25
#include "SDL_x11video.h"
slouken@5182
    26
#include "SDL_x11framebuffer.h"
slouken@5182
    27
slouken@5182
    28
slouken@5182
    29
#ifndef NO_SHARED_MEMORY
slouken@5182
    30
slouken@5182
    31
/* Shared memory error handler routine */
slouken@5182
    32
static int shm_error;
slouken@5182
    33
static int (*X_handler)(Display *, XErrorEvent *) = NULL;
slouken@5182
    34
static int shm_errhandler(Display *d, XErrorEvent *e)
slouken@5182
    35
{
slouken@5182
    36
        if ( e->error_code == BadAccess ) {
slouken@5182
    37
            shm_error = True;
slouken@5182
    38
            return(0);
slouken@5182
    39
        } else
slouken@5182
    40
        return(X_handler(d,e));
slouken@5182
    41
}
slouken@5182
    42
slouken@5182
    43
static SDL_bool have_mitshm(void)
slouken@5182
    44
{
slouken@5182
    45
    /* Only use shared memory on local X servers */
slouken@5182
    46
    if ( (SDL_strncmp(XDisplayName(NULL), ":", 1) == 0) ||
slouken@5182
    47
         (SDL_strncmp(XDisplayName(NULL), "unix:", 5) == 0) ) {
slouken@5182
    48
        return SDL_X11_HAVE_SHM;
slouken@5182
    49
    }
slouken@5182
    50
    return SDL_FALSE;
slouken@5182
    51
}
slouken@5182
    52
slouken@5182
    53
#endif /* !NO_SHARED_MEMORY */
slouken@5182
    54
slouken@5182
    55
int
slouken@5182
    56
X11_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format,
slouken@5182
    57
                            void ** pixels, int *pitch)
slouken@5182
    58
{
slouken@5182
    59
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5182
    60
    Display *display = data->videodata->display;
slouken@5182
    61
    XGCValues gcv;
slouken@5182
    62
    XVisualInfo vinfo;
slouken@5182
    63
slouken@5182
    64
    /* Free the old framebuffer surface */
slouken@5182
    65
    X11_DestroyWindowFramebuffer(_this, window);
slouken@5182
    66
slouken@5182
    67
    /* Create the graphics context for drawing */
slouken@5182
    68
    gcv.graphics_exposures = False;
slouken@5182
    69
    data->gc = XCreateGC(display, data->xwindow, GCGraphicsExposures, &gcv);
slouken@5182
    70
    if (!data->gc) {
slouken@5182
    71
        SDL_SetError("Couldn't create graphics context");
slouken@5182
    72
        return -1;
slouken@5182
    73
    }
slouken@5182
    74
slouken@5182
    75
    /* Find out the pixel format and depth */
slouken@5182
    76
    if (X11_GetVisualInfoFromVisual(display, data->visual, &vinfo) < 0) {
slouken@5182
    77
        SDL_SetError("Couldn't get window visual information");
slouken@5182
    78
        return -1;
slouken@5182
    79
    }
slouken@5182
    80
slouken@5182
    81
    *format = X11_GetPixelFormatFromVisualInfo(display, &vinfo);
slouken@5182
    82
    if (*format == SDL_PIXELFORMAT_UNKNOWN) {
slouken@5182
    83
        SDL_SetError("Unknown window pixel format");
slouken@5182
    84
        return -1;
slouken@5182
    85
    }
slouken@5182
    86
slouken@5182
    87
    /* Calculate pitch */
slouken@5182
    88
    *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
slouken@5182
    89
slouken@5182
    90
    /* Create the actual image */
slouken@5182
    91
#ifndef NO_SHARED_MEMORY
slouken@5182
    92
    if (have_mitshm()) {
slouken@5182
    93
        XShmSegmentInfo *shminfo = &data->shminfo;
slouken@5182
    94
slouken@5182
    95
        shminfo->shmid = shmget(IPC_PRIVATE, window->h*(*pitch), IPC_CREAT | 0777);
slouken@5182
    96
        if ( shminfo->shmid >= 0 ) {
slouken@5182
    97
            shminfo->shmaddr = (char *)shmat(shminfo->shmid, 0, 0);
slouken@5182
    98
            shminfo->readOnly = False;
slouken@5182
    99
            if ( shminfo->shmaddr != (char *)-1 ) {
slouken@5182
   100
                shm_error = False;
slouken@5182
   101
                X_handler = XSetErrorHandler(shm_errhandler);
slouken@5182
   102
                XShmAttach(display, shminfo);
slouken@5182
   103
                XSync(display, True);
slouken@5182
   104
                XSetErrorHandler(X_handler);
slouken@5182
   105
                if ( shm_error )
slouken@5182
   106
                    shmdt(shminfo->shmaddr);
slouken@5182
   107
            } else {
slouken@5182
   108
                shm_error = True;
slouken@5182
   109
            }
slouken@5182
   110
            shmctl(shminfo->shmid, IPC_RMID, NULL);
slouken@5182
   111
        } else {
slouken@5182
   112
            shm_error = True;
slouken@5182
   113
        }
slouken@5182
   114
        if (!shm_error) {
slouken@5182
   115
            data->ximage = XShmCreateImage(display, data->visual,
slouken@5182
   116
                             vinfo.depth, ZPixmap,
slouken@5182
   117
                             shminfo->shmaddr, shminfo, 
slouken@5182
   118
                             window->w, window->h);
slouken@5182
   119
            if (!data->ximage) {
slouken@5182
   120
                XShmDetach(display, shminfo);
slouken@5182
   121
                XSync(display, False);
slouken@5182
   122
                shmdt(shminfo->shmaddr);
slouken@5182
   123
            } else {
slouken@5182
   124
                /* Done! */
slouken@5182
   125
                data->use_mitshm = SDL_TRUE;
slouken@5182
   126
                *pixels = shminfo->shmaddr;
slouken@5182
   127
                return 0;
slouken@5182
   128
            }
slouken@5182
   129
        }
slouken@5182
   130
    }
slouken@5182
   131
#endif /* not NO_SHARED_MEMORY */
slouken@5182
   132
slouken@5182
   133
    *pixels = SDL_malloc(window->h*(*pitch));
slouken@5182
   134
    if (*pixels == NULL) {
slouken@5182
   135
        SDL_OutOfMemory();
slouken@5182
   136
        return -1;
slouken@5182
   137
    }
slouken@5182
   138
slouken@5182
   139
    data->ximage = XCreateImage(display, data->visual,
slouken@5182
   140
                      vinfo.depth, ZPixmap, 0, (char *)(*pixels), 
slouken@5182
   141
                      window->w, window->h, 32, 0);
slouken@5182
   142
    if (!data->ximage) {
slouken@5182
   143
        SDL_free(*pixels);
slouken@5182
   144
        SDL_SetError("Couldn't create XImage");
slouken@5182
   145
        return -1;
slouken@5182
   146
    }
slouken@5182
   147
    return 0;
slouken@5182
   148
}
slouken@5182
   149
slouken@5182
   150
int
slouken@5297
   151
X11_UpdateWindowFramebuffer(_THIS, SDL_Window * window, SDL_Rect * rects,
slouken@5297
   152
                            int numrects)
slouken@5182
   153
{
slouken@5182
   154
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5182
   155
    Display *display = data->videodata->display;
slouken@5182
   156
    int i;
slouken@5182
   157
    SDL_Rect *rect;
slouken@5182
   158
slouken@5182
   159
#ifndef NO_SHARED_MEMORY
slouken@5182
   160
    if (data->use_mitshm) {
slouken@5182
   161
        for (i = 0; i < numrects; ++i) {
slouken@5182
   162
            rect = &rects[i];
slouken@5182
   163
slouken@5182
   164
            if (rect->w == 0 || rect->h == 0) { /* Clipped? */
slouken@5182
   165
                continue;
slouken@5182
   166
            }
slouken@5182
   167
            XShmPutImage(display, data->xwindow, data->gc, data->ximage,
slouken@5182
   168
                    rect->x, rect->y,
slouken@5182
   169
                    rect->x, rect->y, rect->w, rect->h, False);
slouken@5182
   170
        }
slouken@5182
   171
    }
slouken@5182
   172
    else
slouken@5182
   173
#endif /* !NO_SHARED_MEMORY */
slouken@5182
   174
    {
slouken@5182
   175
        for (i = 0; i < numrects; ++i) {
slouken@5182
   176
            rect = &rects[i];
slouken@5182
   177
slouken@5182
   178
            if (rect->w == 0 || rect->h == 0) { /* Clipped? */
slouken@5182
   179
                continue;
slouken@5182
   180
            }
slouken@5182
   181
            XPutImage(display, data->xwindow, data->gc, data->ximage,
slouken@5182
   182
                  rect->x, rect->y,
slouken@5182
   183
                  rect->x, rect->y, rect->w, rect->h);
slouken@5182
   184
        }
slouken@5182
   185
    }
icculus@5981
   186
slouken@5182
   187
    XSync(display, False);
icculus@5981
   188
icculus@5981
   189
    return 0;
slouken@5182
   190
}
slouken@5182
   191
slouken@5182
   192
void
slouken@5182
   193
X11_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
slouken@5182
   194
{
slouken@5182
   195
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5182
   196
    Display *display = data->videodata->display;
slouken@5182
   197
slouken@5182
   198
    if (data->ximage) {
slouken@5182
   199
        XDestroyImage(data->ximage);
slouken@5182
   200
slouken@5182
   201
#ifndef NO_SHARED_MEMORY
slouken@5182
   202
        if (data->use_mitshm) {
slouken@5182
   203
            XShmDetach(display, &data->shminfo);
slouken@5182
   204
            XSync(display, False);
slouken@5182
   205
            shmdt(data->shminfo.shmaddr);
slouken@5182
   206
            data->use_mitshm = SDL_FALSE;
slouken@5182
   207
        }
slouken@5182
   208
#endif /* !NO_SHARED_MEMORY */
slouken@5182
   209
slouken@5182
   210
        data->ximage = NULL;
slouken@5182
   211
    }
slouken@5182
   212
    if (data->gc) {
slouken@5182
   213
        XFreeGC(display, data->gc);
slouken@5182
   214
        data->gc = NULL;
slouken@5182
   215
    }
slouken@5182
   216
}
slouken@5182
   217
slouken@5481
   218
#endif /* SDL_VIDEO_DRIVER_X11 */
slouken@5481
   219
slouken@5182
   220
/* vi: set ts=4 sw=4 expandtab: */