src/video/x11/SDL_x11render.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 02 Aug 2009 18:39:57 +0000
changeset 3227 458e53d8662c
parent 3066 8cbf68bdf81b
child 3239 ab5aebd50add
permissions -rw-r--r--
Clarified API documentation
slouken@2810
     1
/*
slouken@2810
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@2810
     4
slouken@2810
     5
    This library is free software; you can redistribute it and/or
slouken@2810
     6
    modify it under the terms of the GNU Lesser General Public
slouken@2810
     7
    License as published by the Free Software Foundation; either
slouken@2810
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@2810
     9
slouken@2810
    10
    This library is distributed in the hope that it will be useful,
slouken@2810
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@2810
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@2810
    13
    Lesser General Public License for more details.
slouken@2810
    14
slouken@2810
    15
    You should have received a copy of the GNU Lesser General Public
slouken@2810
    16
    License along with this library; if not, write to the Free Software
slouken@2810
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@2810
    18
slouken@2810
    19
    Sam Lantinga
slouken@2810
    20
    slouken@libsdl.org
slouken@2810
    21
*/
slouken@2810
    22
#include "SDL_config.h"
slouken@2810
    23
slouken@2810
    24
#if SDL_VIDEO_RENDER_X11
slouken@2810
    25
slouken@2810
    26
#include "SDL_x11video.h"
slouken@2810
    27
#include "../SDL_rect_c.h"
slouken@2810
    28
#include "../SDL_pixels_c.h"
slouken@2810
    29
#include "../SDL_yuv_sw_c.h"
slouken@2810
    30
slouken@2810
    31
/* X11 renderer implementation */
slouken@2810
    32
slouken@2810
    33
static SDL_Renderer *X11_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@2810
    34
static int X11_DisplayModeChanged(SDL_Renderer * renderer);
slouken@2810
    35
static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@2810
    36
static int X11_QueryTexturePixels(SDL_Renderer * renderer,
slouken@2810
    37
                                  SDL_Texture * texture, void **pixels,
slouken@2810
    38
                                  int *pitch);
slouken@2810
    39
static int X11_SetTextureBlendMode(SDL_Renderer * renderer,
slouken@2810
    40
                                   SDL_Texture * texture);
slouken@2810
    41
static int X11_SetTextureScaleMode(SDL_Renderer * renderer,
slouken@2810
    42
                                   SDL_Texture * texture);
slouken@2810
    43
static int X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
    44
                             const SDL_Rect * rect, const void *pixels,
slouken@2810
    45
                             int pitch);
slouken@2810
    46
static int X11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
    47
                           const SDL_Rect * rect, int markDirty,
slouken@2810
    48
                           void **pixels, int *pitch);
slouken@2810
    49
static void X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@2884
    50
static int X11_SetDrawBlendMode(SDL_Renderer * renderer);
slouken@2901
    51
static int X11_RenderPoint(SDL_Renderer * renderer, int x, int y);
slouken@2884
    52
static int X11_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
slouken@2884
    53
                          int y2);
slouken@2884
    54
static int X11_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
slouken@2810
    55
static int X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
    56
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@2810
    57
static void X11_RenderPresent(SDL_Renderer * renderer);
slouken@2810
    58
static void X11_DestroyTexture(SDL_Renderer * renderer,
slouken@2810
    59
                               SDL_Texture * texture);
slouken@2810
    60
static void X11_DestroyRenderer(SDL_Renderer * renderer);
slouken@2810
    61
slouken@2810
    62
slouken@2810
    63
SDL_RenderDriver X11_RenderDriver = {
slouken@2810
    64
    X11_CreateRenderer,
slouken@2810
    65
    {
slouken@2810
    66
     "x11",
slouken@2810
    67
     (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
slouken@2810
    68
      SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
slouken@2810
    69
      SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED),
slouken@2810
    70
     SDL_TEXTUREMODULATE_NONE,
slouken@2884
    71
     SDL_BLENDMODE_NONE,
slouken@2810
    72
     SDL_TEXTURESCALEMODE_NONE,
slouken@2810
    73
     0,
slouken@2810
    74
     {0},
slouken@2810
    75
     0,
slouken@2810
    76
     0}
slouken@2810
    77
};
slouken@2810
    78
slouken@2810
    79
typedef struct
slouken@2810
    80
{
slouken@2810
    81
    Display *display;
slouken@2810
    82
    int screen;
slouken@2870
    83
    Visual *visual;
slouken@2870
    84
    int depth;
slouken@2916
    85
    int scanline_pad;
slouken@2810
    86
    Window window;
slouken@2810
    87
    Pixmap pixmaps[3];
slouken@2810
    88
    int current_pixmap;
slouken@2810
    89
    Drawable drawable;
slouken@2967
    90
    SDL_PixelFormat format;
slouken@2810
    91
    GC gc;
slouken@2810
    92
    SDL_DirtyRectList dirty;
slouken@2810
    93
    SDL_bool makedirty;
slouken@2810
    94
} X11_RenderData;
slouken@2810
    95
slouken@2810
    96
typedef struct
slouken@2810
    97
{
slouken@2810
    98
    SDL_SW_YUVTexture *yuv;
slouken@2810
    99
    Uint32 format;
slouken@2810
   100
    Pixmap pixmap;
slouken@2810
   101
    XImage *image;
slouken@2810
   102
#ifndef NO_SHARED_MEMORY
slouken@2810
   103
    /* MIT shared memory extension information */
slouken@2810
   104
    XShmSegmentInfo shminfo;
slouken@2810
   105
#endif
slouken@2828
   106
    XImage *scaling_image;
slouken@2810
   107
    void *pixels;
slouken@2810
   108
    int pitch;
slouken@2810
   109
} X11_TextureData;
slouken@2810
   110
slouken@2810
   111
#ifndef NO_SHARED_MEMORY
slouken@2810
   112
/* Shared memory error handler routine */
slouken@2810
   113
static int shm_error;
slouken@2814
   114
static int (*X_handler) (Display *, XErrorEvent *) = NULL;
slouken@2814
   115
static int
slouken@2814
   116
shm_errhandler(Display * d, XErrorEvent * e)
slouken@2810
   117
{
slouken@2814
   118
    if (e->error_code == BadAccess) {
slouken@2814
   119
        shm_error = True;
slouken@2814
   120
        return (0);
slouken@2814
   121
    } else {
slouken@2814
   122
        return (X_handler(d, e));
slouken@2814
   123
    }
slouken@2810
   124
}
slouken@2810
   125
#endif /* ! NO_SHARED_MEMORY */
slouken@2810
   126
slouken@2810
   127
static void
slouken@2810
   128
UpdateYUVTextureData(SDL_Texture * texture)
slouken@2810
   129
{
slouken@2810
   130
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   131
    SDL_Rect rect;
slouken@2810
   132
slouken@2810
   133
    rect.x = 0;
slouken@2810
   134
    rect.y = 0;
slouken@2810
   135
    rect.w = texture->w;
slouken@2810
   136
    rect.h = texture->h;
slouken@2810
   137
    SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
slouken@2810
   138
                        texture->h, data->pixels, data->pitch);
slouken@2810
   139
}
slouken@2810
   140
slouken@2810
   141
void
slouken@2810
   142
X11_AddRenderDriver(_THIS)
slouken@2810
   143
{
slouken@2810
   144
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@2810
   145
    SDL_RendererInfo *info = &X11_RenderDriver.info;
slouken@2870
   146
    SDL_DisplayMode *mode = &SDL_CurrentDisplay.desktop_mode;
slouken@2810
   147
slouken@2870
   148
    info->texture_formats[info->num_texture_formats++] = mode->format;
slouken@2870
   149
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YV12;
slouken@2870
   150
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
slouken@2870
   151
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2;
slouken@2870
   152
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
slouken@2870
   153
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU;
slouken@2810
   154
slouken@2810
   155
    SDL_AddRenderDriver(0, &X11_RenderDriver);
slouken@2810
   156
}
slouken@2810
   157
slouken@2810
   158
SDL_Renderer *
slouken@2810
   159
X11_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@2810
   160
{
slouken@2870
   161
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@2870
   162
    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
slouken@2810
   163
    SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
slouken@2810
   164
    SDL_Renderer *renderer;
slouken@2810
   165
    SDL_RendererInfo *info;
slouken@2810
   166
    X11_RenderData *data;
slouken@2810
   167
    XGCValues gcv;
slouken@2810
   168
    int i, n;
slouken@2810
   169
    int bpp;
slouken@2810
   170
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@2810
   171
slouken@2810
   172
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@2810
   173
    if (!renderer) {
slouken@2810
   174
        SDL_OutOfMemory();
slouken@2810
   175
        return NULL;
slouken@2810
   176
    }
slouken@2810
   177
slouken@2810
   178
    data = (X11_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@2810
   179
    if (!data) {
slouken@2810
   180
        X11_DestroyRenderer(renderer);
slouken@2810
   181
        SDL_OutOfMemory();
slouken@2810
   182
        return NULL;
slouken@2810
   183
    }
slouken@2810
   184
    data->display = windowdata->videodata->display;
slouken@2810
   185
    data->screen = displaydata->screen;
slouken@2870
   186
    data->visual = displaydata->visual;
slouken@2870
   187
    data->depth = displaydata->depth;
slouken@2916
   188
    data->scanline_pad = displaydata->scanline_pad;
slouken@2810
   189
    data->window = windowdata->window;
slouken@2810
   190
slouken@2810
   191
    renderer->DisplayModeChanged = X11_DisplayModeChanged;
slouken@2810
   192
    renderer->CreateTexture = X11_CreateTexture;
slouken@2810
   193
    renderer->QueryTexturePixels = X11_QueryTexturePixels;
slouken@2810
   194
    renderer->SetTextureBlendMode = X11_SetTextureBlendMode;
slouken@2810
   195
    renderer->SetTextureScaleMode = X11_SetTextureScaleMode;
slouken@2810
   196
    renderer->UpdateTexture = X11_UpdateTexture;
slouken@2810
   197
    renderer->LockTexture = X11_LockTexture;
slouken@2810
   198
    renderer->UnlockTexture = X11_UnlockTexture;
slouken@2884
   199
    renderer->SetDrawBlendMode = X11_SetDrawBlendMode;
slouken@2901
   200
    renderer->RenderPoint = X11_RenderPoint;
slouken@2884
   201
    renderer->RenderLine = X11_RenderLine;
slouken@2810
   202
    renderer->RenderFill = X11_RenderFill;
slouken@2810
   203
    renderer->RenderCopy = X11_RenderCopy;
slouken@2810
   204
    renderer->RenderPresent = X11_RenderPresent;
slouken@2810
   205
    renderer->DestroyTexture = X11_DestroyTexture;
slouken@2810
   206
    renderer->DestroyRenderer = X11_DestroyRenderer;
slouken@2810
   207
    renderer->info = X11_RenderDriver.info;
slouken@2810
   208
    renderer->window = window->id;
slouken@2810
   209
    renderer->driverdata = data;
slouken@2810
   210
slouken@2810
   211
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
slouken@2810
   212
slouken@2810
   213
    if (flags & SDL_RENDERER_SINGLEBUFFER) {
slouken@2810
   214
        renderer->info.flags |=
slouken@2810
   215
            (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY);
slouken@2810
   216
        n = 0;
slouken@2810
   217
    } else if (flags & SDL_RENDERER_PRESENTFLIP2) {
slouken@2810
   218
        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
slouken@2810
   219
        n = 2;
slouken@2810
   220
    } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
slouken@2810
   221
        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
slouken@2810
   222
        n = 3;
slouken@2810
   223
    } else {
slouken@2810
   224
        renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
slouken@2810
   225
        n = 1;
slouken@2810
   226
    }
slouken@2810
   227
    for (i = 0; i < n; ++i) {
slouken@2814
   228
        data->pixmaps[i] =
slouken@2814
   229
            XCreatePixmap(data->display, data->window, window->w, window->h,
slouken@2870
   230
                          displaydata->depth);
slouken@2810
   231
        if (data->pixmaps[i] == None) {
slouken@2810
   232
            X11_DestroyRenderer(renderer);
slouken@2810
   233
            SDL_SetError("XCreatePixmap() failed");
slouken@2810
   234
            return NULL;
slouken@2810
   235
        }
slouken@2810
   236
    }
slouken@2810
   237
    if (n > 0) {
slouken@2810
   238
        data->drawable = data->pixmaps[0];
slouken@2810
   239
        data->makedirty = SDL_TRUE;
slouken@2810
   240
    } else {
slouken@2810
   241
        data->drawable = data->window;
slouken@2810
   242
        data->makedirty = SDL_FALSE;
slouken@2810
   243
    }
slouken@2810
   244
    data->current_pixmap = 0;
slouken@2810
   245
slouken@2810
   246
    /* Get the format of the window */
slouken@2874
   247
    if (!SDL_PixelFormatEnumToMasks
slouken@2874
   248
        (display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask,
slouken@2874
   249
         &Amask)) {
slouken@2870
   250
        SDL_SetError("Unknown display format");
slouken@2870
   251
        X11_DestroyRenderer(renderer);
slouken@2870
   252
        return NULL;
slouken@2810
   253
    }
slouken@2967
   254
    SDL_InitFormat(&data->format, bpp, Rmask, Gmask, Bmask, Amask);
slouken@2810
   255
slouken@2810
   256
    /* Create the drawing context */
slouken@2810
   257
    gcv.graphics_exposures = False;
slouken@2814
   258
    data->gc =
slouken@2814
   259
        XCreateGC(data->display, data->window, GCGraphicsExposures, &gcv);
slouken@2810
   260
    if (!data->gc) {
slouken@2810
   261
        X11_DestroyRenderer(renderer);
slouken@2810
   262
        SDL_SetError("XCreateGC() failed");
slouken@2810
   263
        return NULL;
slouken@2810
   264
    }
slouken@2810
   265
slouken@2810
   266
    return renderer;
slouken@2810
   267
}
slouken@2810
   268
slouken@2810
   269
static int
slouken@2810
   270
X11_DisplayModeChanged(SDL_Renderer * renderer)
slouken@2810
   271
{
slouken@2810
   272
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2810
   273
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@2810
   274
    int i, n;
slouken@2810
   275
slouken@2810
   276
    if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) {
slouken@2810
   277
        n = 0;
slouken@2810
   278
    } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
slouken@2810
   279
        n = 2;
slouken@2810
   280
    } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
slouken@2810
   281
        n = 3;
slouken@2810
   282
    } else {
slouken@2810
   283
        n = 1;
slouken@2810
   284
    }
slouken@2810
   285
    for (i = 0; i < n; ++i) {
slouken@2810
   286
        if (data->pixmaps[i] != None) {
slouken@2810
   287
            XFreePixmap(data->display, data->pixmaps[i]);
slouken@2810
   288
            data->pixmaps[i] = None;
slouken@2810
   289
        }
slouken@2810
   290
    }
slouken@2810
   291
    for (i = 0; i < n; ++i) {
slouken@2814
   292
        data->pixmaps[i] =
slouken@2814
   293
            XCreatePixmap(data->display, data->window, window->w, window->h,
slouken@2870
   294
                          data->depth);
slouken@2810
   295
        if (data->pixmaps[i] == None) {
slouken@2810
   296
            SDL_SetError("XCreatePixmap() failed");
slouken@2810
   297
            return -1;
slouken@2810
   298
        }
slouken@2810
   299
    }
slouken@2810
   300
    if (n > 0) {
slouken@2810
   301
        data->drawable = data->pixmaps[0];
slouken@2810
   302
    }
slouken@2810
   303
    data->current_pixmap = 0;
slouken@2810
   304
slouken@2810
   305
    return 0;
slouken@2810
   306
}
slouken@2810
   307
slouken@2810
   308
static int
slouken@2810
   309
X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
   310
{
slouken@2810
   311
    X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
slouken@2810
   312
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@2810
   313
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@2810
   314
    X11_TextureData *data;
slouken@2916
   315
    int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1);
slouken@2810
   316
slouken@2810
   317
    data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
slouken@2810
   318
    if (!data) {
slouken@2810
   319
        SDL_OutOfMemory();
slouken@2810
   320
        return -1;
slouken@2810
   321
    }
slouken@2810
   322
slouken@2810
   323
    texture->driverdata = data;
slouken@2810
   324
slouken@2810
   325
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@2810
   326
        data->yuv =
slouken@2810
   327
            SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
slouken@2810
   328
        if (!data->yuv) {
slouken@2810
   329
            return -1;
slouken@2810
   330
        }
slouken@2810
   331
        data->format = display->current_mode.format;
slouken@2810
   332
    } else {
slouken@2870
   333
        /* The image/pixmap depth must be the same as the window or you
slouken@2870
   334
           get a BadMatch error when trying to putimage or copyarea.
slouken@2874
   335
         */
slouken@2870
   336
        if (texture->format != display->current_mode.format) {
slouken@2870
   337
            SDL_SetError("Texture format doesn't match window format");
slouken@2870
   338
            return -1;
slouken@2870
   339
        }
slouken@2810
   340
        data->format = texture->format;
slouken@2810
   341
    }
slouken@2814
   342
    data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format);
slouken@2916
   343
    data->pitch = (data->pitch + pitch_alignmask) & ~pitch_alignmask;
slouken@2810
   344
slouken@2810
   345
    if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@2810
   346
#ifndef NO_SHARED_MEMORY
slouken@2810
   347
        XShmSegmentInfo *shminfo = &data->shminfo;
slouken@2810
   348
slouken@2810
   349
        shm_error = True;
slouken@2810
   350
slouken@2810
   351
        if (SDL_X11_HAVE_SHM) {
slouken@2814
   352
            shminfo->shmid =
slouken@2814
   353
                shmget(IPC_PRIVATE, texture->h * data->pitch,
slouken@2814
   354
                       IPC_CREAT | 0777);
slouken@2810
   355
            if (shminfo->shmid >= 0) {
slouken@2814
   356
                shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
slouken@2810
   357
                shminfo->readOnly = False;
slouken@2814
   358
                if (shminfo->shmaddr != (char *) -1) {
slouken@2810
   359
                    shm_error = False;
slouken@2810
   360
                    X_handler = XSetErrorHandler(shm_errhandler);
slouken@2810
   361
                    XShmAttach(renderdata->display, shminfo);
slouken@2810
   362
                    XSync(renderdata->display, True);
slouken@2810
   363
                    XSetErrorHandler(X_handler);
slouken@2810
   364
                    if (shm_error) {
slouken@2810
   365
                        shmdt(shminfo->shmaddr);
slouken@2810
   366
                    }
slouken@2810
   367
                }
slouken@2810
   368
                shmctl(shminfo->shmid, IPC_RMID, NULL);
slouken@2810
   369
            }
slouken@2810
   370
        }
slouken@2810
   371
        if (!shm_error) {
slouken@2810
   372
            data->pixels = shminfo->shmaddr;
slouken@2810
   373
slouken@2814
   374
            data->image =
slouken@2874
   375
                XShmCreateImage(renderdata->display, renderdata->visual,
slouken@2874
   376
                                renderdata->depth, ZPixmap, shminfo->shmaddr,
slouken@2874
   377
                                shminfo, texture->w, texture->h);
slouken@2814
   378
            if (!data->image) {
slouken@2810
   379
                XShmDetach(renderdata->display, shminfo);
slouken@2810
   380
                XSync(renderdata->display, False);
slouken@2810
   381
                shmdt(shminfo->shmaddr);
slouken@2810
   382
                shm_error = True;
slouken@2810
   383
            }
slouken@2810
   384
        }
slouken@2810
   385
        if (shm_error) {
slouken@2810
   386
            shminfo->shmaddr = NULL;
slouken@2810
   387
        }
slouken@2810
   388
        if (!data->image)
slouken@2810
   389
#endif /* not NO_SHARED_MEMORY */
slouken@2810
   390
        {
slouken@2810
   391
            data->pixels = SDL_malloc(texture->h * data->pitch);
slouken@2810
   392
            if (!data->pixels) {
slouken@2868
   393
                X11_DestroyTexture(renderer, texture);
slouken@2810
   394
                SDL_OutOfMemory();
slouken@2810
   395
                return -1;
slouken@2810
   396
            }
slouken@2810
   397
slouken@2814
   398
            data->image =
slouken@2874
   399
                XCreateImage(renderdata->display, renderdata->visual,
slouken@2874
   400
                             renderdata->depth, ZPixmap, 0, data->pixels,
slouken@2874
   401
                             texture->w, texture->h,
slouken@2874
   402
                             SDL_BYTESPERPIXEL(data->format) * 8,
slouken@2874
   403
                             data->pitch);
slouken@2810
   404
            if (!data->image) {
slouken@2868
   405
                X11_DestroyTexture(renderer, texture);
slouken@2810
   406
                SDL_SetError("XCreateImage() failed");
slouken@2810
   407
                return -1;
slouken@2810
   408
            }
slouken@2810
   409
        }
slouken@2810
   410
    } else {
slouken@2814
   411
        data->pixmap =
slouken@2814
   412
            XCreatePixmap(renderdata->display, renderdata->window, texture->w,
slouken@2870
   413
                          texture->h, renderdata->depth);
slouken@2810
   414
        if (data->pixmap == None) {
slouken@2868
   415
            X11_DestroyTexture(renderer, texture);
bob@3044
   416
            SDL_SetError("XCreatePixmap() failed");
slouken@2810
   417
            return -1;
slouken@2810
   418
        }
slouken@2810
   419
slouken@2814
   420
        data->image =
slouken@2874
   421
            XCreateImage(renderdata->display, renderdata->visual,
slouken@2874
   422
                         renderdata->depth, ZPixmap, 0, NULL, texture->w,
slouken@2874
   423
                         texture->h, SDL_BYTESPERPIXEL(data->format) * 8,
slouken@2874
   424
                         data->pitch);
slouken@2810
   425
        if (!data->image) {
slouken@2868
   426
            X11_DestroyTexture(renderer, texture);
slouken@2810
   427
            SDL_SetError("XCreateImage() failed");
slouken@2810
   428
            return -1;
slouken@2810
   429
        }
slouken@2810
   430
    }
slouken@2810
   431
slouken@2810
   432
    return 0;
slouken@2810
   433
}
slouken@2810
   434
slouken@2810
   435
static int
slouken@2810
   436
X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
   437
                       void **pixels, int *pitch)
slouken@2810
   438
{
slouken@2810
   439
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   440
slouken@2810
   441
    if (data->yuv) {
slouken@2810
   442
        return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
slouken@2810
   443
    } else {
slouken@2810
   444
        *pixels = data->pixels;
slouken@2810
   445
        *pitch = data->pitch;
slouken@2810
   446
        return 0;
slouken@2810
   447
    }
slouken@2810
   448
}
slouken@2810
   449
slouken@2810
   450
static int
slouken@2810
   451
X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
   452
{
slouken@2810
   453
    switch (texture->blendMode) {
slouken@2884
   454
    case SDL_BLENDMODE_NONE:
slouken@2810
   455
        return 0;
slouken@2810
   456
    default:
slouken@2810
   457
        SDL_Unsupported();
slouken@2884
   458
        texture->blendMode = SDL_BLENDMODE_NONE;
slouken@2810
   459
        return -1;
slouken@2810
   460
    }
slouken@2810
   461
}
slouken@2810
   462
slouken@2810
   463
static int
slouken@2810
   464
X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
   465
{
slouken@2828
   466
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2828
   467
slouken@2810
   468
    switch (texture->scaleMode) {
slouken@2810
   469
    case SDL_TEXTURESCALEMODE_NONE:
slouken@2810
   470
        return 0;
slouken@2828
   471
    case SDL_TEXTURESCALEMODE_FAST:
slouken@2828
   472
        /* We can sort of fake it for streaming textures */
slouken@2828
   473
        if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@2828
   474
            return 0;
slouken@2828
   475
        }
slouken@2828
   476
        /* Fall through to unsupported case */
slouken@2810
   477
    default:
slouken@2810
   478
        SDL_Unsupported();
slouken@2810
   479
        texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
slouken@2810
   480
        return -1;
slouken@2810
   481
    }
slouken@2810
   482
    return 0;
slouken@2810
   483
}
slouken@2810
   484
slouken@2810
   485
static int
slouken@2810
   486
X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
   487
                  const SDL_Rect * rect, const void *pixels, int pitch)
slouken@2810
   488
{
slouken@2810
   489
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   490
slouken@2810
   491
    if (data->yuv) {
slouken@2810
   492
        if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
slouken@2810
   493
            return -1;
slouken@2810
   494
        }
slouken@2810
   495
        UpdateYUVTextureData(texture);
slouken@2810
   496
        return 0;
slouken@2810
   497
    } else {
slouken@2810
   498
        X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
slouken@2810
   499
slouken@2810
   500
        if (data->pixels) {
slouken@2810
   501
            Uint8 *src, *dst;
slouken@2810
   502
            int row;
slouken@2810
   503
            size_t length;
slouken@2810
   504
slouken@2810
   505
            src = (Uint8 *) pixels;
slouken@2810
   506
            dst =
slouken@2810
   507
                (Uint8 *) data->pixels + rect->y * data->pitch +
slouken@2810
   508
                rect->x * SDL_BYTESPERPIXEL(texture->format);
slouken@2810
   509
            length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@2810
   510
            for (row = 0; row < rect->h; ++row) {
slouken@2810
   511
                SDL_memcpy(dst, src, length);
slouken@2810
   512
                src += pitch;
slouken@2810
   513
                dst += data->pitch;
slouken@2810
   514
            }
slouken@2810
   515
        } else {
slouken@2810
   516
            data->image->width = rect->w;
slouken@2810
   517
            data->image->height = rect->h;
slouken@2814
   518
            data->image->data = (char *) pixels;
slouken@2810
   519
            data->image->bytes_per_line = pitch;
slouken@2814
   520
            XPutImage(renderdata->display, data->pixmap, renderdata->gc,
slouken@2814
   521
                      data->image, 0, 0, rect->x, rect->y, rect->w, rect->h);
slouken@2810
   522
        }
slouken@2810
   523
        return 0;
slouken@2810
   524
    }
slouken@2810
   525
}
slouken@2810
   526
slouken@2810
   527
static int
slouken@2810
   528
X11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
   529
                const SDL_Rect * rect, int markDirty, void **pixels,
slouken@2810
   530
                int *pitch)
slouken@2810
   531
{
slouken@2810
   532
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   533
slouken@2810
   534
    if (data->yuv) {
slouken@2810
   535
        return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
slouken@2810
   536
                                     pitch);
slouken@2810
   537
    } else if (data->pixels) {
slouken@2810
   538
        *pixels =
slouken@2810
   539
            (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
slouken@2810
   540
                      rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@2810
   541
        *pitch = data->pitch;
slouken@2810
   542
        return 0;
slouken@2810
   543
    } else {
slouken@2810
   544
        SDL_SetError("No pixels available");
slouken@2810
   545
        return -1;
slouken@2810
   546
    }
slouken@2810
   547
}
slouken@2810
   548
slouken@2810
   549
static void
slouken@2810
   550
X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
   551
{
slouken@2810
   552
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   553
slouken@2810
   554
    if (data->yuv) {
slouken@2810
   555
        SDL_SW_UnlockYUVTexture(data->yuv);
slouken@2810
   556
        UpdateYUVTextureData(texture);
slouken@2810
   557
    }
slouken@2810
   558
}
slouken@2810
   559
slouken@2810
   560
static int
slouken@2884
   561
X11_SetDrawBlendMode(SDL_Renderer * renderer)
slouken@2884
   562
{
slouken@2884
   563
    switch (renderer->blendMode) {
slouken@2884
   564
    case SDL_BLENDMODE_NONE:
slouken@2884
   565
        return 0;
slouken@2884
   566
    default:
slouken@2884
   567
        SDL_Unsupported();
slouken@2884
   568
        renderer->blendMode = SDL_BLENDMODE_NONE;
slouken@2884
   569
        return -1;
slouken@2884
   570
    }
slouken@2884
   571
}
slouken@2884
   572
slouken@2884
   573
static Uint32
slouken@2884
   574
renderdrawcolor(SDL_Renderer * renderer, int premult)
slouken@2884
   575
{
slouken@2884
   576
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2884
   577
    Uint8 r = renderer->r;
slouken@2884
   578
    Uint8 g = renderer->g;
slouken@2884
   579
    Uint8 b = renderer->b;
slouken@2884
   580
    Uint8 a = renderer->a;
slouken@2884
   581
    if (premult)
slouken@2967
   582
        return SDL_MapRGBA(&data->format, ((int) r * (int) a) / 255,
slouken@2884
   583
                           ((int) g * (int) a) / 255,
slouken@2884
   584
                           ((int) b * (int) a) / 255, 255);
slouken@2884
   585
    else
slouken@2967
   586
        return SDL_MapRGBA(&data->format, r, g, b, a);
slouken@2884
   587
}
slouken@2884
   588
slouken@2884
   589
static int
slouken@2901
   590
X11_RenderPoint(SDL_Renderer * renderer, int x, int y)
slouken@2901
   591
{
slouken@2901
   592
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2901
   593
    unsigned long foreground;
slouken@2901
   594
slouken@2901
   595
    if (data->makedirty) {
slouken@2901
   596
        SDL_Rect rect;
slouken@2901
   597
slouken@2901
   598
        rect.x = x;
slouken@2901
   599
        rect.y = y;
slouken@2901
   600
        rect.w = 1;
slouken@2901
   601
        rect.h = 1;
slouken@2901
   602
        SDL_AddDirtyRect(&data->dirty, &rect);
slouken@2901
   603
    }
slouken@2901
   604
slouken@2901
   605
    foreground = renderdrawcolor(renderer, 1);
slouken@2901
   606
    XSetForeground(data->display, data->gc, foreground);
slouken@2901
   607
    XDrawPoint(data->display, data->drawable, data->gc, x, y);
slouken@2901
   608
    return 0;
slouken@2901
   609
}
slouken@2901
   610
slouken@2901
   611
static int
slouken@2884
   612
X11_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
slouken@2884
   613
{
slouken@2884
   614
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2884
   615
    unsigned long foreground;
slouken@2888
   616
slouken@2884
   617
    if (data->makedirty) {
slouken@2884
   618
        SDL_Rect rect;
slouken@2884
   619
slouken@2884
   620
        if (x1 < x2) {
slouken@2884
   621
            rect.x = x1;
slouken@2884
   622
            rect.w = (x2 - x1) + 1;
slouken@2884
   623
        } else {
slouken@2884
   624
            rect.x = x2;
slouken@2884
   625
            rect.w = (x1 - x2) + 1;
slouken@2884
   626
        }
slouken@2884
   627
        if (y1 < y2) {
slouken@2884
   628
            rect.y = y1;
slouken@2884
   629
            rect.h = (y2 - y1) + 1;
slouken@2884
   630
        } else {
slouken@2884
   631
            rect.y = y2;
slouken@2884
   632
            rect.h = (y1 - y2) + 1;
slouken@2884
   633
        }
slouken@2884
   634
        SDL_AddDirtyRect(&data->dirty, &rect);
slouken@2884
   635
    }
slouken@2884
   636
slouken@2884
   637
    foreground = renderdrawcolor(renderer, 1);
slouken@2884
   638
    XSetForeground(data->display, data->gc, foreground);
slouken@2884
   639
    XDrawLine(data->display, data->drawable, data->gc, x1, y1, x2, y2);
slouken@2894
   640
    return 0;
slouken@2884
   641
}
slouken@2884
   642
slouken@2884
   643
static int
slouken@2884
   644
X11_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
slouken@2810
   645
{
slouken@2810
   646
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2810
   647
    unsigned long foreground;
slouken@2810
   648
slouken@2810
   649
    if (data->makedirty) {
slouken@2810
   650
        SDL_AddDirtyRect(&data->dirty, rect);
slouken@2810
   651
    }
slouken@2810
   652
slouken@2884
   653
    foreground = renderdrawcolor(renderer, 1);
slouken@2810
   654
    XSetForeground(data->display, data->gc, foreground);
slouken@2884
   655
    XFillRectangle(data->display, data->drawable, data->gc, rect->x, rect->y,
slouken@2814
   656
                   rect->w, rect->h);
slouken@2810
   657
    return 0;
slouken@2810
   658
}
slouken@2810
   659
slouken@2810
   660
static int
slouken@2810
   661
X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
   662
               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@2810
   663
{
slouken@2810
   664
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2810
   665
    X11_TextureData *texturedata = (X11_TextureData *) texture->driverdata;
slouken@2810
   666
slouken@2810
   667
    if (data->makedirty) {
slouken@2810
   668
        SDL_AddDirtyRect(&data->dirty, dstrect);
slouken@2810
   669
    }
slouken@2828
   670
    if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
slouken@2810
   671
#ifndef NO_SHARED_MEMORY
slouken@2828
   672
        if (texturedata->shminfo.shmaddr) {
slouken@2828
   673
            XShmPutImage(data->display, data->drawable, data->gc,
slouken@2828
   674
                         texturedata->image, srcrect->x, srcrect->y,
slouken@2828
   675
                         dstrect->x, dstrect->y, srcrect->w, srcrect->h,
slouken@2828
   676
                         False);
slouken@2828
   677
        } else
slouken@2810
   678
#endif
slouken@2828
   679
        if (texturedata->pixels) {
slouken@2828
   680
            XPutImage(data->display, data->drawable, data->gc,
slouken@2828
   681
                      texturedata->image, srcrect->x, srcrect->y, dstrect->x,
slouken@2828
   682
                      dstrect->y, srcrect->w, srcrect->h);
slouken@2828
   683
        } else {
slouken@2828
   684
            XCopyArea(data->display, texturedata->pixmap, data->drawable,
slouken@2828
   685
                      data->gc, srcrect->x, srcrect->y, dstrect->w,
slouken@3066
   686
                      dstrect->h, dstrect->x, dstrect->y);
slouken@2828
   687
        }
slouken@2828
   688
    } else if (texturedata->yuv
slouken@2828
   689
               || texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@2828
   690
        SDL_Surface src, dst;
slouken@2828
   691
        SDL_PixelFormat fmt;
slouken@2828
   692
        SDL_Rect rect;
slouken@2828
   693
        XImage *image = texturedata->scaling_image;
slouken@2828
   694
slouken@2828
   695
        if (!image) {
slouken@2828
   696
            int depth;
slouken@2828
   697
            void *pixels;
slouken@2828
   698
            int pitch;
slouken@2828
   699
slouken@2828
   700
            pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
slouken@2828
   701
            pixels = SDL_malloc(dstrect->h * pitch);
slouken@2828
   702
            if (!pixels) {
slouken@2828
   703
                SDL_OutOfMemory();
slouken@2828
   704
                return -1;
slouken@2828
   705
            }
slouken@2828
   706
slouken@2828
   707
            image =
slouken@2874
   708
                XCreateImage(data->display, data->visual, data->depth,
slouken@2874
   709
                             ZPixmap, 0, pixels, dstrect->w, dstrect->h,
slouken@2828
   710
                             SDL_BYTESPERPIXEL(texturedata->format) * 8,
slouken@2828
   711
                             pitch);
slouken@2828
   712
            if (!image) {
slouken@2828
   713
                SDL_SetError("XCreateImage() failed");
slouken@2828
   714
                return -1;
slouken@2828
   715
            }
slouken@2828
   716
            texturedata->scaling_image = image;
slouken@2828
   717
slouken@2828
   718
        } else if (image->width != dstrect->w || image->height != dstrect->h
slouken@2828
   719
                   || !image->data) {
slouken@2828
   720
            image->width = dstrect->w;
slouken@2828
   721
            image->height = dstrect->h;
slouken@2828
   722
            image->bytes_per_line =
slouken@2828
   723
                image->width * SDL_BYTESPERPIXEL(texturedata->format);
slouken@2828
   724
            image->data =
slouken@2828
   725
                (char *) SDL_realloc(image->data,
slouken@2828
   726
                                     image->height * image->bytes_per_line);
slouken@2828
   727
            if (!image->data) {
slouken@2828
   728
                SDL_OutOfMemory();
slouken@2828
   729
                return -1;
slouken@2828
   730
            }
slouken@2828
   731
        }
slouken@2828
   732
slouken@2828
   733
        /* Set up fake surfaces for SDL_SoftStretch() */
slouken@2882
   734
        SDL_zero(src);
slouken@2828
   735
        src.format = &fmt;
slouken@2828
   736
        src.w = texture->w;
slouken@2828
   737
        src.h = texture->h;
slouken@2828
   738
#ifndef NO_SHARED_MEMORY
slouken@2828
   739
        if (texturedata->shminfo.shmaddr) {
slouken@2828
   740
            src.pixels = texturedata->shminfo.shmaddr;
slouken@2828
   741
        } else
slouken@2828
   742
#endif
slouken@2828
   743
            src.pixels = texturedata->pixels;
slouken@2828
   744
        src.pitch = texturedata->pitch;
slouken@2828
   745
slouken@2882
   746
        SDL_zero(dst);
slouken@2828
   747
        dst.format = &fmt;
slouken@2828
   748
        dst.w = image->width;
slouken@2828
   749
        dst.h = image->height;
slouken@2828
   750
        dst.pixels = image->data;
slouken@2828
   751
        dst.pitch = image->bytes_per_line;
slouken@2828
   752
slouken@2828
   753
        fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
slouken@2828
   754
slouken@2828
   755
        rect.x = 0;
slouken@2828
   756
        rect.y = 0;
slouken@2828
   757
        rect.w = dstrect->w;
slouken@2828
   758
        rect.h = dstrect->h;
slouken@2828
   759
        if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
slouken@2828
   760
            return -1;
slouken@2828
   761
        }
slouken@2828
   762
        XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
slouken@2828
   763
                  dstrect->x, dstrect->y, dstrect->w, dstrect->h);
slouken@2810
   764
    } else {
slouken@2827
   765
        XCopyArea(data->display, texturedata->pixmap, data->drawable,
slouken@2827
   766
                  data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
slouken@2827
   767
                  srcrect->x, srcrect->y);
slouken@2810
   768
    }
slouken@2810
   769
    return 0;
slouken@2810
   770
}
slouken@2810
   771
slouken@2810
   772
static void
slouken@2810
   773
X11_RenderPresent(SDL_Renderer * renderer)
slouken@2810
   774
{
slouken@2810
   775
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2810
   776
    SDL_DirtyRect *dirty;
slouken@2810
   777
slouken@2810
   778
    /* Send the data to the display */
slouken@2810
   779
    if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) {
slouken@2810
   780
        for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
slouken@2810
   781
            const SDL_Rect *rect = &dirty->rect;
slouken@2810
   782
            XCopyArea(data->display, data->drawable, data->window,
slouken@2810
   783
                      data->gc, rect->x, rect->y, rect->w, rect->h,
slouken@2810
   784
                      rect->x, rect->y);
slouken@2810
   785
        }
slouken@2810
   786
        SDL_ClearDirtyRects(&data->dirty);
slouken@2810
   787
    }
slouken@2810
   788
    XSync(data->display, False);
slouken@2810
   789
slouken@2810
   790
    /* Update the flipping chain, if any */
slouken@2810
   791
    if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
slouken@2810
   792
        data->current_pixmap = (data->current_pixmap + 1) % 2;
slouken@2810
   793
        data->drawable = data->pixmaps[data->current_pixmap];
slouken@2810
   794
    } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
slouken@2810
   795
        data->current_pixmap = (data->current_pixmap + 1) % 3;
slouken@2810
   796
        data->drawable = data->pixmaps[data->current_pixmap];
slouken@2810
   797
    }
slouken@2810
   798
}
slouken@2810
   799
slouken@2810
   800
static void
slouken@2810
   801
X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
   802
{
slouken@2810
   803
    X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
slouken@2810
   804
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   805
slouken@2810
   806
    if (!data) {
slouken@2810
   807
        return;
slouken@2810
   808
    }
slouken@2810
   809
    if (data->yuv) {
slouken@2810
   810
        SDL_SW_DestroyYUVTexture(data->yuv);
slouken@2810
   811
    }
slouken@2810
   812
    if (data->pixmap != None) {
slouken@2810
   813
        XFreePixmap(renderdata->display, data->pixmap);
slouken@2810
   814
    }
slouken@2810
   815
    if (data->image) {
slouken@2810
   816
        data->image->data = NULL;
slouken@2810
   817
        XDestroyImage(data->image);
slouken@2810
   818
    }
slouken@2810
   819
#ifndef NO_SHARED_MEMORY
slouken@2810
   820
    if (data->shminfo.shmaddr) {
slouken@2810
   821
        XShmDetach(renderdata->display, &data->shminfo);
slouken@2810
   822
        XSync(renderdata->display, False);
slouken@2810
   823
        shmdt(data->shminfo.shmaddr);
slouken@2810
   824
        data->pixels = NULL;
slouken@2810
   825
    }
slouken@2810
   826
#endif
slouken@2828
   827
    if (data->scaling_image) {
slouken@2828
   828
        SDL_free(data->scaling_image->data);
slouken@2828
   829
        data->scaling_image->data = NULL;
slouken@2828
   830
        XDestroyImage(data->scaling_image);
slouken@2828
   831
    }
slouken@2810
   832
    if (data->pixels) {
slouken@2810
   833
        SDL_free(data->pixels);
slouken@2810
   834
    }
slouken@2810
   835
    SDL_free(data);
slouken@2810
   836
    texture->driverdata = NULL;
slouken@2810
   837
}
slouken@2810
   838
slouken@2810
   839
static void
slouken@2810
   840
X11_DestroyRenderer(SDL_Renderer * renderer)
slouken@2810
   841
{
slouken@2810
   842
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2810
   843
    int i;
slouken@2810
   844
slouken@2810
   845
    if (data) {
slouken@2810
   846
        for (i = 0; i < SDL_arraysize(data->pixmaps); ++i) {
slouken@2810
   847
            if (data->pixmaps[i] != None) {
slouken@2810
   848
                XFreePixmap(data->display, data->pixmaps[i]);
slouken@2810
   849
            }
slouken@2810
   850
        }
slouken@2810
   851
        if (data->gc) {
slouken@2810
   852
            XFreeGC(data->display, data->gc);
slouken@2810
   853
        }
slouken@2810
   854
        SDL_FreeDirtyRects(&data->dirty);
slouken@2810
   855
        SDL_free(data);
slouken@2810
   856
    }
slouken@2810
   857
    SDL_free(renderer);
slouken@2810
   858
}
slouken@2810
   859
slouken@2810
   860
#endif /* SDL_VIDEO_RENDER_X11 */
slouken@2810
   861
slouken@2810
   862
/* vi: set ts=4 sw=4 expandtab: */