src/video/x11/SDL_x11render.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Dec 2009 08:11:06 +0000
changeset 3565 f43c8f688f77
parent 3559 5f26a7eb5ff0
child 3596 f638ded38b8a
permissions -rw-r--r--
Fixed bug #906

Added better error reporting for OpenGL context creation failing.
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@3543
    26
#include <limits.h> /* For INT_MIN and INT_MAX */
slouken@3543
    27
slouken@2810
    28
#include "SDL_x11video.h"
slouken@2810
    29
#include "../SDL_rect_c.h"
slouken@2810
    30
#include "../SDL_pixels_c.h"
slouken@2810
    31
#include "../SDL_yuv_sw_c.h"
slouken@2810
    32
slouken@2810
    33
/* X11 renderer implementation */
slouken@2810
    34
slouken@2810
    35
static SDL_Renderer *X11_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@2810
    36
static int X11_DisplayModeChanged(SDL_Renderer * renderer);
slouken@2810
    37
static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@2810
    38
static int X11_QueryTexturePixels(SDL_Renderer * renderer,
slouken@2810
    39
                                  SDL_Texture * texture, void **pixels,
slouken@2810
    40
                                  int *pitch);
slouken@2810
    41
static int X11_SetTextureBlendMode(SDL_Renderer * renderer,
slouken@2810
    42
                                   SDL_Texture * texture);
slouken@2810
    43
static int X11_SetTextureScaleMode(SDL_Renderer * renderer,
slouken@2810
    44
                                   SDL_Texture * texture);
slouken@2810
    45
static int X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
    46
                             const SDL_Rect * rect, const void *pixels,
slouken@2810
    47
                             int pitch);
slouken@2810
    48
static int X11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
    49
                           const SDL_Rect * rect, int markDirty,
slouken@2810
    50
                           void **pixels, int *pitch);
slouken@2810
    51
static void X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@2884
    52
static int X11_SetDrawBlendMode(SDL_Renderer * renderer);
slouken@3538
    53
static int X11_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3538
    54
                            int count);
slouken@3538
    55
static int X11_RenderLines(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3538
    56
                           int count);
slouken@3538
    57
static int X11_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
slouken@3538
    58
                           int count);
slouken@2810
    59
static int X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
    60
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@3559
    61
static int X11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3559
    62
                                Uint32 format, void * pixels, int pitch);
slouken@3559
    63
static int X11_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3559
    64
                                 Uint32 format, const void * pixels, int pitch);
slouken@2810
    65
static void X11_RenderPresent(SDL_Renderer * renderer);
slouken@2810
    66
static void X11_DestroyTexture(SDL_Renderer * renderer,
slouken@2810
    67
                               SDL_Texture * texture);
slouken@2810
    68
static void X11_DestroyRenderer(SDL_Renderer * renderer);
slouken@2810
    69
slouken@2810
    70
slouken@2810
    71
SDL_RenderDriver X11_RenderDriver = {
slouken@2810
    72
    X11_CreateRenderer,
slouken@2810
    73
    {
slouken@2810
    74
     "x11",
slouken@2810
    75
     (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
slouken@2810
    76
      SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
slouken@2810
    77
      SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED),
slouken@2810
    78
     SDL_TEXTUREMODULATE_NONE,
slouken@2884
    79
     SDL_BLENDMODE_NONE,
slouken@2810
    80
     SDL_TEXTURESCALEMODE_NONE,
slouken@2810
    81
     0,
slouken@2810
    82
     {0},
slouken@2810
    83
     0,
slouken@2810
    84
     0}
slouken@2810
    85
};
slouken@2810
    86
slouken@2810
    87
typedef struct
slouken@2810
    88
{
slouken@2810
    89
    Display *display;
slouken@2810
    90
    int screen;
slouken@2870
    91
    Visual *visual;
slouken@2870
    92
    int depth;
slouken@2916
    93
    int scanline_pad;
slouken@2810
    94
    Window window;
slouken@2810
    95
    Pixmap pixmaps[3];
slouken@2810
    96
    int current_pixmap;
slouken@2810
    97
    Drawable drawable;
slouken@2967
    98
    SDL_PixelFormat format;
slouken@2810
    99
    GC gc;
slouken@2810
   100
    SDL_DirtyRectList dirty;
slouken@2810
   101
    SDL_bool makedirty;
slouken@2810
   102
} X11_RenderData;
slouken@2810
   103
slouken@2810
   104
typedef struct
slouken@2810
   105
{
slouken@2810
   106
    SDL_SW_YUVTexture *yuv;
slouken@2810
   107
    Uint32 format;
slouken@2810
   108
    Pixmap pixmap;
slouken@2810
   109
    XImage *image;
slouken@2810
   110
#ifndef NO_SHARED_MEMORY
slouken@2810
   111
    /* MIT shared memory extension information */
slouken@2810
   112
    XShmSegmentInfo shminfo;
slouken@2810
   113
#endif
slouken@2828
   114
    XImage *scaling_image;
slouken@2810
   115
    void *pixels;
slouken@2810
   116
    int pitch;
slouken@2810
   117
} X11_TextureData;
slouken@2810
   118
slouken@2810
   119
#ifndef NO_SHARED_MEMORY
slouken@2810
   120
/* Shared memory error handler routine */
slouken@2810
   121
static int shm_error;
slouken@2814
   122
static int (*X_handler) (Display *, XErrorEvent *) = NULL;
slouken@2814
   123
static int
slouken@2814
   124
shm_errhandler(Display * d, XErrorEvent * e)
slouken@2810
   125
{
slouken@2814
   126
    if (e->error_code == BadAccess) {
slouken@2814
   127
        shm_error = True;
slouken@2814
   128
        return (0);
slouken@2814
   129
    } else {
slouken@2814
   130
        return (X_handler(d, e));
slouken@2814
   131
    }
slouken@2810
   132
}
slouken@2810
   133
#endif /* ! NO_SHARED_MEMORY */
slouken@2810
   134
slouken@2810
   135
static void
slouken@2810
   136
UpdateYUVTextureData(SDL_Texture * texture)
slouken@2810
   137
{
slouken@2810
   138
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   139
    SDL_Rect rect;
slouken@2810
   140
slouken@2810
   141
    rect.x = 0;
slouken@2810
   142
    rect.y = 0;
slouken@2810
   143
    rect.w = texture->w;
slouken@2810
   144
    rect.h = texture->h;
slouken@2810
   145
    SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
slouken@2810
   146
                        texture->h, data->pixels, data->pitch);
slouken@2810
   147
}
slouken@2810
   148
slouken@2810
   149
void
slouken@2810
   150
X11_AddRenderDriver(_THIS)
slouken@2810
   151
{
slouken@2810
   152
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@2810
   153
    SDL_RendererInfo *info = &X11_RenderDriver.info;
slouken@2870
   154
    SDL_DisplayMode *mode = &SDL_CurrentDisplay.desktop_mode;
slouken@3520
   155
    int i;
slouken@2810
   156
slouken@2870
   157
    info->texture_formats[info->num_texture_formats++] = mode->format;
slouken@2870
   158
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YV12;
slouken@2870
   159
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
slouken@2870
   160
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2;
slouken@2870
   161
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
slouken@2870
   162
    info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU;
slouken@2810
   163
slouken@3520
   164
    for (i = 0; i < _this->num_displays; ++i) {
slouken@3520
   165
        SDL_AddRenderDriver(&_this->displays[i], &X11_RenderDriver);
slouken@3520
   166
    }
slouken@2810
   167
}
slouken@2810
   168
slouken@2810
   169
SDL_Renderer *
slouken@2810
   170
X11_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@2810
   171
{
slouken@2870
   172
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@2870
   173
    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
slouken@2810
   174
    SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
slouken@2810
   175
    SDL_Renderer *renderer;
slouken@2810
   176
    SDL_RendererInfo *info;
slouken@2810
   177
    X11_RenderData *data;
slouken@2810
   178
    XGCValues gcv;
slouken@2810
   179
    int i, n;
slouken@2810
   180
    int bpp;
slouken@2810
   181
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@2810
   182
slouken@2810
   183
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@2810
   184
    if (!renderer) {
slouken@2810
   185
        SDL_OutOfMemory();
slouken@2810
   186
        return NULL;
slouken@2810
   187
    }
slouken@2810
   188
slouken@2810
   189
    data = (X11_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@2810
   190
    if (!data) {
slouken@2810
   191
        X11_DestroyRenderer(renderer);
slouken@2810
   192
        SDL_OutOfMemory();
slouken@2810
   193
        return NULL;
slouken@2810
   194
    }
slouken@2810
   195
    data->display = windowdata->videodata->display;
slouken@2810
   196
    data->screen = displaydata->screen;
slouken@2870
   197
    data->visual = displaydata->visual;
slouken@2870
   198
    data->depth = displaydata->depth;
slouken@2916
   199
    data->scanline_pad = displaydata->scanline_pad;
slouken@2810
   200
    data->window = windowdata->window;
slouken@2810
   201
slouken@2810
   202
    renderer->DisplayModeChanged = X11_DisplayModeChanged;
slouken@2810
   203
    renderer->CreateTexture = X11_CreateTexture;
slouken@2810
   204
    renderer->QueryTexturePixels = X11_QueryTexturePixels;
slouken@2810
   205
    renderer->SetTextureBlendMode = X11_SetTextureBlendMode;
slouken@2810
   206
    renderer->SetTextureScaleMode = X11_SetTextureScaleMode;
slouken@2810
   207
    renderer->UpdateTexture = X11_UpdateTexture;
slouken@2810
   208
    renderer->LockTexture = X11_LockTexture;
slouken@2810
   209
    renderer->UnlockTexture = X11_UnlockTexture;
slouken@2884
   210
    renderer->SetDrawBlendMode = X11_SetDrawBlendMode;
slouken@3538
   211
    renderer->RenderPoints = X11_RenderPoints;
slouken@3538
   212
    renderer->RenderLines = X11_RenderLines;
slouken@3538
   213
    renderer->RenderRects = X11_RenderRects;
slouken@2810
   214
    renderer->RenderCopy = X11_RenderCopy;
slouken@3559
   215
    renderer->RenderReadPixels = X11_RenderReadPixels;
slouken@3559
   216
    renderer->RenderWritePixels = X11_RenderWritePixels;
slouken@2810
   217
    renderer->RenderPresent = X11_RenderPresent;
slouken@2810
   218
    renderer->DestroyTexture = X11_DestroyTexture;
slouken@2810
   219
    renderer->DestroyRenderer = X11_DestroyRenderer;
slouken@2810
   220
    renderer->info = X11_RenderDriver.info;
slouken@2810
   221
    renderer->window = window->id;
slouken@2810
   222
    renderer->driverdata = data;
slouken@2810
   223
slouken@2810
   224
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
slouken@2810
   225
slouken@2810
   226
    if (flags & SDL_RENDERER_SINGLEBUFFER) {
slouken@2810
   227
        renderer->info.flags |=
slouken@2810
   228
            (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY);
slouken@2810
   229
        n = 0;
slouken@2810
   230
    } else if (flags & SDL_RENDERER_PRESENTFLIP2) {
slouken@2810
   231
        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
slouken@2810
   232
        n = 2;
slouken@2810
   233
    } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
slouken@2810
   234
        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
slouken@2810
   235
        n = 3;
slouken@2810
   236
    } else {
slouken@2810
   237
        renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
slouken@2810
   238
        n = 1;
slouken@2810
   239
    }
slouken@2810
   240
    for (i = 0; i < n; ++i) {
slouken@2814
   241
        data->pixmaps[i] =
slouken@2814
   242
            XCreatePixmap(data->display, data->window, window->w, window->h,
slouken@2870
   243
                          displaydata->depth);
slouken@2810
   244
        if (data->pixmaps[i] == None) {
slouken@2810
   245
            X11_DestroyRenderer(renderer);
slouken@2810
   246
            SDL_SetError("XCreatePixmap() failed");
slouken@2810
   247
            return NULL;
slouken@2810
   248
        }
slouken@2810
   249
    }
slouken@2810
   250
    if (n > 0) {
slouken@2810
   251
        data->drawable = data->pixmaps[0];
slouken@2810
   252
        data->makedirty = SDL_TRUE;
slouken@2810
   253
    } else {
slouken@2810
   254
        data->drawable = data->window;
slouken@2810
   255
        data->makedirty = SDL_FALSE;
slouken@2810
   256
    }
slouken@2810
   257
    data->current_pixmap = 0;
slouken@2810
   258
slouken@2810
   259
    /* Get the format of the window */
slouken@2874
   260
    if (!SDL_PixelFormatEnumToMasks
slouken@2874
   261
        (display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask,
slouken@2874
   262
         &Amask)) {
slouken@2870
   263
        SDL_SetError("Unknown display format");
slouken@2870
   264
        X11_DestroyRenderer(renderer);
slouken@2870
   265
        return NULL;
slouken@2810
   266
    }
slouken@2967
   267
    SDL_InitFormat(&data->format, bpp, Rmask, Gmask, Bmask, Amask);
slouken@2810
   268
slouken@2810
   269
    /* Create the drawing context */
slouken@2810
   270
    gcv.graphics_exposures = False;
slouken@2814
   271
    data->gc =
slouken@2814
   272
        XCreateGC(data->display, data->window, GCGraphicsExposures, &gcv);
slouken@2810
   273
    if (!data->gc) {
slouken@2810
   274
        X11_DestroyRenderer(renderer);
slouken@2810
   275
        SDL_SetError("XCreateGC() failed");
slouken@2810
   276
        return NULL;
slouken@2810
   277
    }
slouken@2810
   278
slouken@2810
   279
    return renderer;
slouken@2810
   280
}
slouken@2810
   281
slouken@2810
   282
static int
slouken@2810
   283
X11_DisplayModeChanged(SDL_Renderer * renderer)
slouken@2810
   284
{
slouken@2810
   285
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2810
   286
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@2810
   287
    int i, n;
slouken@2810
   288
slouken@2810
   289
    if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) {
slouken@2810
   290
        n = 0;
slouken@2810
   291
    } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
slouken@2810
   292
        n = 2;
slouken@2810
   293
    } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
slouken@2810
   294
        n = 3;
slouken@2810
   295
    } else {
slouken@2810
   296
        n = 1;
slouken@2810
   297
    }
slouken@2810
   298
    for (i = 0; i < n; ++i) {
slouken@2810
   299
        if (data->pixmaps[i] != None) {
slouken@2810
   300
            XFreePixmap(data->display, data->pixmaps[i]);
slouken@2810
   301
            data->pixmaps[i] = None;
slouken@2810
   302
        }
slouken@2810
   303
    }
slouken@2810
   304
    for (i = 0; i < n; ++i) {
slouken@2814
   305
        data->pixmaps[i] =
slouken@2814
   306
            XCreatePixmap(data->display, data->window, window->w, window->h,
slouken@2870
   307
                          data->depth);
slouken@2810
   308
        if (data->pixmaps[i] == None) {
slouken@2810
   309
            SDL_SetError("XCreatePixmap() failed");
slouken@2810
   310
            return -1;
slouken@2810
   311
        }
slouken@2810
   312
    }
slouken@2810
   313
    if (n > 0) {
slouken@2810
   314
        data->drawable = data->pixmaps[0];
slouken@2810
   315
    }
slouken@2810
   316
    data->current_pixmap = 0;
slouken@2810
   317
slouken@2810
   318
    return 0;
slouken@2810
   319
}
slouken@2810
   320
slouken@2810
   321
static int
slouken@2810
   322
X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
   323
{
slouken@2810
   324
    X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
slouken@2810
   325
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@2810
   326
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@2810
   327
    X11_TextureData *data;
slouken@2916
   328
    int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1);
slouken@2810
   329
slouken@2810
   330
    data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
slouken@2810
   331
    if (!data) {
slouken@2810
   332
        SDL_OutOfMemory();
slouken@2810
   333
        return -1;
slouken@2810
   334
    }
slouken@2810
   335
slouken@2810
   336
    texture->driverdata = data;
slouken@2810
   337
slouken@2810
   338
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@2810
   339
        data->yuv =
slouken@2810
   340
            SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
slouken@2810
   341
        if (!data->yuv) {
slouken@2810
   342
            return -1;
slouken@2810
   343
        }
slouken@2810
   344
        data->format = display->current_mode.format;
slouken@2810
   345
    } else {
slouken@2870
   346
        /* The image/pixmap depth must be the same as the window or you
slouken@2870
   347
           get a BadMatch error when trying to putimage or copyarea.
slouken@2874
   348
         */
slouken@2870
   349
        if (texture->format != display->current_mode.format) {
slouken@2870
   350
            SDL_SetError("Texture format doesn't match window format");
slouken@2870
   351
            return -1;
slouken@2870
   352
        }
slouken@2810
   353
        data->format = texture->format;
slouken@2810
   354
    }
slouken@2814
   355
    data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format);
slouken@2916
   356
    data->pitch = (data->pitch + pitch_alignmask) & ~pitch_alignmask;
slouken@2810
   357
slouken@2810
   358
    if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@2810
   359
#ifndef NO_SHARED_MEMORY
slouken@2810
   360
        XShmSegmentInfo *shminfo = &data->shminfo;
slouken@2810
   361
slouken@2810
   362
        shm_error = True;
slouken@2810
   363
slouken@2810
   364
        if (SDL_X11_HAVE_SHM) {
slouken@2814
   365
            shminfo->shmid =
slouken@2814
   366
                shmget(IPC_PRIVATE, texture->h * data->pitch,
slouken@2814
   367
                       IPC_CREAT | 0777);
slouken@2810
   368
            if (shminfo->shmid >= 0) {
slouken@2814
   369
                shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
slouken@2810
   370
                shminfo->readOnly = False;
slouken@2814
   371
                if (shminfo->shmaddr != (char *) -1) {
slouken@2810
   372
                    shm_error = False;
slouken@2810
   373
                    X_handler = XSetErrorHandler(shm_errhandler);
slouken@2810
   374
                    XShmAttach(renderdata->display, shminfo);
slouken@3239
   375
                    XSync(renderdata->display, False);
slouken@2810
   376
                    XSetErrorHandler(X_handler);
slouken@2810
   377
                    if (shm_error) {
slouken@2810
   378
                        shmdt(shminfo->shmaddr);
slouken@2810
   379
                    }
slouken@2810
   380
                }
slouken@2810
   381
                shmctl(shminfo->shmid, IPC_RMID, NULL);
slouken@2810
   382
            }
slouken@2810
   383
        }
slouken@2810
   384
        if (!shm_error) {
slouken@2810
   385
            data->pixels = shminfo->shmaddr;
slouken@2810
   386
slouken@2814
   387
            data->image =
slouken@2874
   388
                XShmCreateImage(renderdata->display, renderdata->visual,
slouken@2874
   389
                                renderdata->depth, ZPixmap, shminfo->shmaddr,
slouken@2874
   390
                                shminfo, texture->w, texture->h);
slouken@2814
   391
            if (!data->image) {
slouken@2810
   392
                XShmDetach(renderdata->display, shminfo);
slouken@2810
   393
                XSync(renderdata->display, False);
slouken@2810
   394
                shmdt(shminfo->shmaddr);
slouken@2810
   395
                shm_error = True;
slouken@2810
   396
            }
slouken@2810
   397
        }
slouken@2810
   398
        if (shm_error) {
slouken@2810
   399
            shminfo->shmaddr = NULL;
slouken@2810
   400
        }
slouken@2810
   401
        if (!data->image)
slouken@2810
   402
#endif /* not NO_SHARED_MEMORY */
slouken@2810
   403
        {
slouken@2810
   404
            data->pixels = SDL_malloc(texture->h * data->pitch);
slouken@2810
   405
            if (!data->pixels) {
slouken@2868
   406
                X11_DestroyTexture(renderer, texture);
slouken@2810
   407
                SDL_OutOfMemory();
slouken@2810
   408
                return -1;
slouken@2810
   409
            }
slouken@2810
   410
slouken@2814
   411
            data->image =
slouken@2874
   412
                XCreateImage(renderdata->display, renderdata->visual,
slouken@2874
   413
                             renderdata->depth, ZPixmap, 0, data->pixels,
slouken@2874
   414
                             texture->w, texture->h,
slouken@2874
   415
                             SDL_BYTESPERPIXEL(data->format) * 8,
slouken@2874
   416
                             data->pitch);
slouken@2810
   417
            if (!data->image) {
slouken@2868
   418
                X11_DestroyTexture(renderer, texture);
slouken@2810
   419
                SDL_SetError("XCreateImage() failed");
slouken@2810
   420
                return -1;
slouken@2810
   421
            }
slouken@2810
   422
        }
slouken@2810
   423
    } else {
slouken@2814
   424
        data->pixmap =
slouken@2814
   425
            XCreatePixmap(renderdata->display, renderdata->window, texture->w,
slouken@2870
   426
                          texture->h, renderdata->depth);
slouken@2810
   427
        if (data->pixmap == None) {
slouken@2868
   428
            X11_DestroyTexture(renderer, texture);
bob@3044
   429
            SDL_SetError("XCreatePixmap() failed");
slouken@2810
   430
            return -1;
slouken@2810
   431
        }
slouken@2810
   432
slouken@2814
   433
        data->image =
slouken@2874
   434
            XCreateImage(renderdata->display, renderdata->visual,
slouken@2874
   435
                         renderdata->depth, ZPixmap, 0, NULL, texture->w,
slouken@2874
   436
                         texture->h, SDL_BYTESPERPIXEL(data->format) * 8,
slouken@2874
   437
                         data->pitch);
slouken@2810
   438
        if (!data->image) {
slouken@2868
   439
            X11_DestroyTexture(renderer, texture);
slouken@2810
   440
            SDL_SetError("XCreateImage() failed");
slouken@2810
   441
            return -1;
slouken@2810
   442
        }
slouken@2810
   443
    }
slouken@2810
   444
slouken@2810
   445
    return 0;
slouken@2810
   446
}
slouken@2810
   447
slouken@2810
   448
static int
slouken@2810
   449
X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
   450
                       void **pixels, int *pitch)
slouken@2810
   451
{
slouken@2810
   452
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   453
slouken@2810
   454
    if (data->yuv) {
slouken@2810
   455
        return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
slouken@2810
   456
    } else {
slouken@2810
   457
        *pixels = data->pixels;
slouken@2810
   458
        *pitch = data->pitch;
slouken@2810
   459
        return 0;
slouken@2810
   460
    }
slouken@2810
   461
}
slouken@2810
   462
slouken@2810
   463
static int
slouken@2810
   464
X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
   465
{
slouken@2810
   466
    switch (texture->blendMode) {
slouken@2884
   467
    case SDL_BLENDMODE_NONE:
slouken@2810
   468
        return 0;
slouken@2810
   469
    default:
slouken@2810
   470
        SDL_Unsupported();
slouken@2884
   471
        texture->blendMode = SDL_BLENDMODE_NONE;
slouken@2810
   472
        return -1;
slouken@2810
   473
    }
slouken@2810
   474
}
slouken@2810
   475
slouken@2810
   476
static int
slouken@2810
   477
X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
   478
{
slouken@2828
   479
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2828
   480
slouken@2810
   481
    switch (texture->scaleMode) {
slouken@2810
   482
    case SDL_TEXTURESCALEMODE_NONE:
slouken@2810
   483
        return 0;
slouken@2828
   484
    case SDL_TEXTURESCALEMODE_FAST:
slouken@2828
   485
        /* We can sort of fake it for streaming textures */
slouken@2828
   486
        if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@2828
   487
            return 0;
slouken@2828
   488
        }
slouken@2828
   489
        /* Fall through to unsupported case */
slouken@2810
   490
    default:
slouken@2810
   491
        SDL_Unsupported();
slouken@2810
   492
        texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
slouken@2810
   493
        return -1;
slouken@2810
   494
    }
slouken@2810
   495
    return 0;
slouken@2810
   496
}
slouken@2810
   497
slouken@2810
   498
static int
slouken@2810
   499
X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
   500
                  const SDL_Rect * rect, const void *pixels, int pitch)
slouken@2810
   501
{
slouken@2810
   502
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   503
slouken@2810
   504
    if (data->yuv) {
slouken@2810
   505
        if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
slouken@2810
   506
            return -1;
slouken@2810
   507
        }
slouken@2810
   508
        UpdateYUVTextureData(texture);
slouken@2810
   509
        return 0;
slouken@2810
   510
    } else {
slouken@2810
   511
        X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
slouken@2810
   512
slouken@2810
   513
        if (data->pixels) {
slouken@2810
   514
            Uint8 *src, *dst;
slouken@2810
   515
            int row;
slouken@2810
   516
            size_t length;
slouken@2810
   517
slouken@2810
   518
            src = (Uint8 *) pixels;
slouken@2810
   519
            dst =
slouken@2810
   520
                (Uint8 *) data->pixels + rect->y * data->pitch +
slouken@2810
   521
                rect->x * SDL_BYTESPERPIXEL(texture->format);
slouken@2810
   522
            length = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@2810
   523
            for (row = 0; row < rect->h; ++row) {
slouken@2810
   524
                SDL_memcpy(dst, src, length);
slouken@2810
   525
                src += pitch;
slouken@2810
   526
                dst += data->pitch;
slouken@2810
   527
            }
slouken@2810
   528
        } else {
slouken@2810
   529
            data->image->width = rect->w;
slouken@2810
   530
            data->image->height = rect->h;
slouken@2814
   531
            data->image->data = (char *) pixels;
slouken@2810
   532
            data->image->bytes_per_line = pitch;
slouken@2814
   533
            XPutImage(renderdata->display, data->pixmap, renderdata->gc,
slouken@2814
   534
                      data->image, 0, 0, rect->x, rect->y, rect->w, rect->h);
slouken@2810
   535
        }
slouken@2810
   536
        return 0;
slouken@2810
   537
    }
slouken@2810
   538
}
slouken@2810
   539
slouken@2810
   540
static int
slouken@2810
   541
X11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
   542
                const SDL_Rect * rect, int markDirty, void **pixels,
slouken@2810
   543
                int *pitch)
slouken@2810
   544
{
slouken@2810
   545
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   546
slouken@2810
   547
    if (data->yuv) {
slouken@2810
   548
        return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
slouken@2810
   549
                                     pitch);
slouken@2810
   550
    } else if (data->pixels) {
slouken@2810
   551
        *pixels =
slouken@2810
   552
            (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
slouken@2810
   553
                      rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@2810
   554
        *pitch = data->pitch;
slouken@2810
   555
        return 0;
slouken@2810
   556
    } else {
slouken@2810
   557
        SDL_SetError("No pixels available");
slouken@2810
   558
        return -1;
slouken@2810
   559
    }
slouken@2810
   560
}
slouken@2810
   561
slouken@2810
   562
static void
slouken@2810
   563
X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
   564
{
slouken@2810
   565
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
   566
slouken@2810
   567
    if (data->yuv) {
slouken@2810
   568
        SDL_SW_UnlockYUVTexture(data->yuv);
slouken@2810
   569
        UpdateYUVTextureData(texture);
slouken@2810
   570
    }
slouken@2810
   571
}
slouken@2810
   572
slouken@2810
   573
static int
slouken@2884
   574
X11_SetDrawBlendMode(SDL_Renderer * renderer)
slouken@2884
   575
{
slouken@2884
   576
    switch (renderer->blendMode) {
slouken@2884
   577
    case SDL_BLENDMODE_NONE:
slouken@2884
   578
        return 0;
slouken@2884
   579
    default:
slouken@2884
   580
        SDL_Unsupported();
slouken@2884
   581
        renderer->blendMode = SDL_BLENDMODE_NONE;
slouken@2884
   582
        return -1;
slouken@2884
   583
    }
slouken@2884
   584
}
slouken@2884
   585
slouken@2884
   586
static Uint32
slouken@2884
   587
renderdrawcolor(SDL_Renderer * renderer, int premult)
slouken@2884
   588
{
slouken@2884
   589
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2884
   590
    Uint8 r = renderer->r;
slouken@2884
   591
    Uint8 g = renderer->g;
slouken@2884
   592
    Uint8 b = renderer->b;
slouken@2884
   593
    Uint8 a = renderer->a;
slouken@2884
   594
    if (premult)
slouken@2967
   595
        return SDL_MapRGBA(&data->format, ((int) r * (int) a) / 255,
slouken@2884
   596
                           ((int) g * (int) a) / 255,
slouken@2884
   597
                           ((int) b * (int) a) / 255, 255);
slouken@2884
   598
    else
slouken@2967
   599
        return SDL_MapRGBA(&data->format, r, g, b, a);
slouken@2884
   600
}
slouken@2884
   601
slouken@2884
   602
static int
slouken@3538
   603
X11_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points, int count)
slouken@2901
   604
{
slouken@2901
   605
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@3538
   606
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@2901
   607
    unsigned long foreground;
slouken@3538
   608
    XPoint *xpoints, *xpoint;
slouken@3538
   609
    int i, xcount;
slouken@2901
   610
slouken@2901
   611
    if (data->makedirty) {
slouken@2901
   612
        SDL_Rect rect;
slouken@2901
   613
slouken@3538
   614
        /* Get the smallest rectangle that contains everything */
slouken@3538
   615
        rect.x = 0;
slouken@3538
   616
        rect.y = 0;
slouken@3538
   617
        rect.w = window->w;
slouken@3538
   618
        rect.h = window->h;
slouken@3538
   619
        if (!SDL_EnclosePoints(points, count, &rect, &rect)) {
slouken@3538
   620
            /* Nothing to draw */
slouken@3538
   621
            return 0;
slouken@2884
   622
        }
slouken@2884
   623
        SDL_AddDirtyRect(&data->dirty, &rect);
slouken@2884
   624
    }
slouken@2884
   625
slouken@2884
   626
    foreground = renderdrawcolor(renderer, 1);
slouken@2884
   627
    XSetForeground(data->display, data->gc, foreground);
slouken@3538
   628
slouken@3538
   629
    xpoint = xpoints = SDL_stack_alloc(XPoint, count);
slouken@3538
   630
    xcount = 0;
slouken@3538
   631
    for (i = 0; i < count; ++i) {
slouken@3538
   632
        int x = points[i].x;
slouken@3538
   633
        int y = points[i].y;
slouken@3538
   634
        if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
slouken@3538
   635
            continue;
slouken@3538
   636
        }
slouken@3538
   637
        xpoint->x = (short)x;
slouken@3538
   638
        xpoint->y = (short)y;
slouken@3538
   639
        ++xpoint;
slouken@3538
   640
        ++xcount;
slouken@3538
   641
    }
slouken@3538
   642
    if (xcount > 0) {
slouken@3538
   643
        XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount,
slouken@3538
   644
                    CoordModeOrigin);
slouken@3538
   645
    }
slouken@3538
   646
    SDL_stack_free(xpoints);
slouken@3538
   647
slouken@2894
   648
    return 0;
slouken@2884
   649
}
slouken@2884
   650
slouken@2884
   651
static int
slouken@3538
   652
X11_RenderLines(SDL_Renderer * renderer, const SDL_Point * points, int count)
slouken@2810
   653
{
slouken@2810
   654
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@3538
   655
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@3538
   656
    SDL_Rect clip, rect;
slouken@2810
   657
    unsigned long foreground;
slouken@3543
   658
    XPoint *xpoints, *xpoint;
slouken@3543
   659
    int i, xcount;
slouken@3543
   660
    int minx, miny;
slouken@3543
   661
    int maxx, maxy;
slouken@2810
   662
slouken@3538
   663
    clip.x = 0;
slouken@3538
   664
    clip.y = 0;
slouken@3538
   665
    clip.w = window->w;
slouken@3538
   666
    clip.h = window->h;
slouken@3538
   667
slouken@2884
   668
    foreground = renderdrawcolor(renderer, 1);
slouken@2810
   669
    XSetForeground(data->display, data->gc, foreground);
slouken@3543
   670
slouken@3543
   671
    xpoint = xpoints = SDL_stack_alloc(XPoint, count);
slouken@3543
   672
    xcount = 0;
slouken@3543
   673
    minx = INT_MAX;
slouken@3543
   674
    miny = INT_MAX;
slouken@3543
   675
    maxx = INT_MIN;
slouken@3543
   676
    maxy = INT_MIN;
slouken@3543
   677
    for (i = 0; i < count; ++i) {
slouken@3543
   678
        int x = points[i].x;
slouken@3543
   679
        int y = points[i].y;
slouken@3543
   680
slouken@3543
   681
        /* If the point is inside the window, add it to the list */
slouken@3543
   682
        if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
slouken@3543
   683
            if (x < minx) {
slouken@3543
   684
                minx = x;
slouken@3543
   685
            } else if (x > maxx) {
slouken@3543
   686
                maxx = x;
slouken@3543
   687
            }
slouken@3543
   688
            if (y < miny) {
slouken@3543
   689
                miny = y;
slouken@3543
   690
            } else if (y > maxy) {
slouken@3543
   691
                maxy = y;
slouken@3543
   692
            }
slouken@3543
   693
            xpoint->x = (short)x;
slouken@3543
   694
            xpoint->y = (short)y;
slouken@3543
   695
            ++xpoint;
slouken@3543
   696
            ++xcount;
slouken@3543
   697
            continue;
slouken@3543
   698
        }
slouken@3543
   699
slouken@3543
   700
        /* We need to clip the line segments joined by this point */
slouken@3543
   701
        if (xcount > 0) {
slouken@3543
   702
            int x1 = xpoint[-1].x;
slouken@3543
   703
            int y1 = xpoint[-1].y;
slouken@3543
   704
            int x2 = x;
slouken@3543
   705
            int y2 = y;
slouken@3543
   706
            if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
slouken@3543
   707
                if (x2 < minx) {
slouken@3543
   708
                    minx = x2;
slouken@3543
   709
                } else if (x2 > maxx) {
slouken@3543
   710
                    maxx = x2;
slouken@3543
   711
                }
slouken@3543
   712
                if (y2 < miny) {
slouken@3543
   713
                    miny = y2;
slouken@3543
   714
                } else if (y2 > maxy) {
slouken@3543
   715
                    maxy = y2;
slouken@3543
   716
                }
slouken@3543
   717
                xpoint->x = (short)x2;
slouken@3543
   718
                xpoint->y = (short)y2;
slouken@3543
   719
                ++xpoint;
slouken@3543
   720
                ++xcount;
slouken@3543
   721
            }
slouken@3543
   722
            XDrawLines(data->display, data->drawable, data->gc,
slouken@3543
   723
                       xpoints, xcount, CoordModeOrigin);
slouken@3543
   724
            if (xpoints[0].x != x2 || xpoints[0].y != y2) {
slouken@3543
   725
                XDrawPoint(data->display, data->drawable, data->gc, x2, y2);
slouken@3543
   726
            }
slouken@3543
   727
            if (data->makedirty) {
slouken@3543
   728
                SDL_Rect rect;
slouken@3543
   729
slouken@3543
   730
                rect.x = minx;
slouken@3543
   731
                rect.y = miny;
slouken@3543
   732
                rect.w = (maxx - minx) + 1;
slouken@3543
   733
                rect.h = (maxy - miny) + 1;
slouken@3543
   734
                SDL_AddDirtyRect(&data->dirty, &rect);
slouken@3543
   735
            }
slouken@3543
   736
            xpoint = xpoints;
slouken@3543
   737
            xcount = 0;
slouken@3543
   738
            minx = INT_MAX;
slouken@3543
   739
            miny = INT_MAX;
slouken@3543
   740
            maxx = INT_MIN;
slouken@3543
   741
            maxy = INT_MIN;
slouken@3543
   742
        }
slouken@3543
   743
        if (i < (count-1)) {
slouken@3543
   744
            int x1 = x;
slouken@3543
   745
            int y1 = y;
slouken@3543
   746
            int x2 = points[i+1].x;
slouken@3543
   747
            int y2 = points[i+1].y;
slouken@3543
   748
            if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
slouken@3543
   749
                if (x1 < minx) {
slouken@3543
   750
                    minx = x1;
slouken@3543
   751
                } else if (x1 > maxx) {
slouken@3543
   752
                    maxx = x1;
slouken@3543
   753
                }
slouken@3543
   754
                if (y1 < miny) {
slouken@3543
   755
                    miny = y1;
slouken@3543
   756
                } else if (y1 > maxy) {
slouken@3543
   757
                    maxy = y1;
slouken@3543
   758
                }
slouken@3543
   759
                xpoint->x = (short)x1;
slouken@3543
   760
                xpoint->y = (short)y1;
slouken@3543
   761
                ++xpoint;
slouken@3543
   762
                ++xcount;
slouken@3543
   763
            }
slouken@3543
   764
        }
slouken@3543
   765
    }
slouken@3543
   766
    if (xcount > 1) {
slouken@3543
   767
        int x2 = xpoint[-1].x;
slouken@3543
   768
        int y2 = xpoint[-1].y;
slouken@3543
   769
        XDrawLines(data->display, data->drawable, data->gc, xpoints, xcount,
slouken@3543
   770
                   CoordModeOrigin);
slouken@3543
   771
        if (xpoints[0].x != x2 || xpoints[0].y != y2) {
slouken@3543
   772
            XDrawPoint(data->display, data->drawable, data->gc, x2, y2);
slouken@3543
   773
        }
slouken@3543
   774
        if (data->makedirty) {
slouken@3543
   775
            SDL_Rect rect;
slouken@3543
   776
slouken@3543
   777
            rect.x = minx;
slouken@3543
   778
            rect.y = miny;
slouken@3543
   779
            rect.w = (maxx - minx) + 1;
slouken@3543
   780
            rect.h = (maxy - miny) + 1;
slouken@3543
   781
            SDL_AddDirtyRect(&data->dirty, &rect);
slouken@3543
   782
        }
slouken@3543
   783
    }
slouken@3543
   784
    SDL_stack_free(xpoints);
slouken@3543
   785
slouken@3538
   786
    return 0;
slouken@3538
   787
}
slouken@3538
   788
slouken@3538
   789
static int
slouken@3538
   790
X11_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
slouken@3538
   791
{
slouken@3538
   792
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@3538
   793
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@3538
   794
    SDL_Rect clip, rect;
slouken@3538
   795
    unsigned long foreground;
slouken@3538
   796
    XRectangle *xrects, *xrect;
slouken@3538
   797
    int i, xcount;
slouken@3538
   798
slouken@3538
   799
    clip.x = 0;
slouken@3538
   800
    clip.y = 0;
slouken@3538
   801
    clip.w = window->w;
slouken@3538
   802
    clip.h = window->h;
slouken@3538
   803
slouken@3538
   804
    foreground = renderdrawcolor(renderer, 1);
slouken@3538
   805
    XSetForeground(data->display, data->gc, foreground);
slouken@3538
   806
slouken@3538
   807
    xrect = xrects = SDL_stack_alloc(XRectangle, count);
slouken@3538
   808
    xcount = 0;
slouken@3538
   809
    for (i = 0; i < count; ++i) {
slouken@3538
   810
        if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
slouken@3538
   811
            continue;
slouken@3538
   812
        }
slouken@3538
   813
slouken@3538
   814
        xrect->x = (short)rect.x;
slouken@3538
   815
        xrect->y = (short)rect.y;
slouken@3538
   816
        xrect->width = (unsigned short)rect.w;
slouken@3538
   817
        xrect->height = (unsigned short)rect.h;
slouken@3538
   818
        ++xrect;
slouken@3538
   819
        ++xcount;
slouken@3538
   820
slouken@3538
   821
        if (data->makedirty) {
slouken@3538
   822
            SDL_AddDirtyRect(&data->dirty, &rect);
slouken@3538
   823
        }
slouken@3538
   824
    }
slouken@3538
   825
    if (xcount > 0) {
slouken@3538
   826
        XFillRectangles(data->display, data->drawable, data->gc,
slouken@3538
   827
                        xrects, xcount);
slouken@3538
   828
    }
slouken@3538
   829
    SDL_stack_free(xpoints);
slouken@3538
   830
slouken@2810
   831
    return 0;
slouken@2810
   832
}
slouken@2810
   833
slouken@2810
   834
static int
slouken@2810
   835
X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2810
   836
               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@2810
   837
{
slouken@2810
   838
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2810
   839
    X11_TextureData *texturedata = (X11_TextureData *) texture->driverdata;
slouken@2810
   840
slouken@2810
   841
    if (data->makedirty) {
slouken@2810
   842
        SDL_AddDirtyRect(&data->dirty, dstrect);
slouken@2810
   843
    }
slouken@2828
   844
    if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
slouken@2810
   845
#ifndef NO_SHARED_MEMORY
slouken@2828
   846
        if (texturedata->shminfo.shmaddr) {
slouken@2828
   847
            XShmPutImage(data->display, data->drawable, data->gc,
slouken@2828
   848
                         texturedata->image, srcrect->x, srcrect->y,
slouken@2828
   849
                         dstrect->x, dstrect->y, srcrect->w, srcrect->h,
slouken@2828
   850
                         False);
slouken@2828
   851
        } else
slouken@2810
   852
#endif
slouken@2828
   853
        if (texturedata->pixels) {
slouken@2828
   854
            XPutImage(data->display, data->drawable, data->gc,
slouken@2828
   855
                      texturedata->image, srcrect->x, srcrect->y, dstrect->x,
slouken@2828
   856
                      dstrect->y, srcrect->w, srcrect->h);
slouken@2828
   857
        } else {
slouken@2828
   858
            XCopyArea(data->display, texturedata->pixmap, data->drawable,
slouken@2828
   859
                      data->gc, srcrect->x, srcrect->y, dstrect->w,
slouken@3066
   860
                      dstrect->h, dstrect->x, dstrect->y);
slouken@2828
   861
        }
slouken@2828
   862
    } else if (texturedata->yuv
slouken@2828
   863
               || texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@2828
   864
        SDL_Surface src, dst;
slouken@2828
   865
        SDL_PixelFormat fmt;
slouken@2828
   866
        SDL_Rect rect;
slouken@2828
   867
        XImage *image = texturedata->scaling_image;
slouken@2828
   868
slouken@2828
   869
        if (!image) {
slouken@2828
   870
            int depth;
slouken@2828
   871
            void *pixels;
slouken@2828
   872
            int pitch;
slouken@2828
   873
slouken@2828
   874
            pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
slouken@2828
   875
            pixels = SDL_malloc(dstrect->h * pitch);
slouken@2828
   876
            if (!pixels) {
slouken@2828
   877
                SDL_OutOfMemory();
slouken@2828
   878
                return -1;
slouken@2828
   879
            }
slouken@2828
   880
slouken@2828
   881
            image =
slouken@2874
   882
                XCreateImage(data->display, data->visual, data->depth,
slouken@2874
   883
                             ZPixmap, 0, pixels, dstrect->w, dstrect->h,
slouken@2828
   884
                             SDL_BYTESPERPIXEL(texturedata->format) * 8,
slouken@2828
   885
                             pitch);
slouken@2828
   886
            if (!image) {
slouken@2828
   887
                SDL_SetError("XCreateImage() failed");
slouken@2828
   888
                return -1;
slouken@2828
   889
            }
slouken@2828
   890
            texturedata->scaling_image = image;
slouken@2828
   891
slouken@2828
   892
        } else if (image->width != dstrect->w || image->height != dstrect->h
slouken@2828
   893
                   || !image->data) {
slouken@2828
   894
            image->width = dstrect->w;
slouken@2828
   895
            image->height = dstrect->h;
slouken@2828
   896
            image->bytes_per_line =
slouken@2828
   897
                image->width * SDL_BYTESPERPIXEL(texturedata->format);
slouken@2828
   898
            image->data =
slouken@2828
   899
                (char *) SDL_realloc(image->data,
slouken@2828
   900
                                     image->height * image->bytes_per_line);
slouken@2828
   901
            if (!image->data) {
slouken@2828
   902
                SDL_OutOfMemory();
slouken@2828
   903
                return -1;
slouken@2828
   904
            }
slouken@2828
   905
        }
slouken@2828
   906
slouken@2828
   907
        /* Set up fake surfaces for SDL_SoftStretch() */
slouken@2882
   908
        SDL_zero(src);
slouken@2828
   909
        src.format = &fmt;
slouken@2828
   910
        src.w = texture->w;
slouken@2828
   911
        src.h = texture->h;
slouken@2828
   912
#ifndef NO_SHARED_MEMORY
slouken@2828
   913
        if (texturedata->shminfo.shmaddr) {
slouken@2828
   914
            src.pixels = texturedata->shminfo.shmaddr;
slouken@2828
   915
        } else
slouken@2828
   916
#endif
slouken@2828
   917
            src.pixels = texturedata->pixels;
slouken@2828
   918
        src.pitch = texturedata->pitch;
slouken@2828
   919
slouken@2882
   920
        SDL_zero(dst);
slouken@2828
   921
        dst.format = &fmt;
slouken@2828
   922
        dst.w = image->width;
slouken@2828
   923
        dst.h = image->height;
slouken@2828
   924
        dst.pixels = image->data;
slouken@2828
   925
        dst.pitch = image->bytes_per_line;
slouken@2828
   926
slouken@2828
   927
        fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
slouken@2828
   928
slouken@2828
   929
        rect.x = 0;
slouken@2828
   930
        rect.y = 0;
slouken@2828
   931
        rect.w = dstrect->w;
slouken@2828
   932
        rect.h = dstrect->h;
slouken@2828
   933
        if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
slouken@2828
   934
            return -1;
slouken@2828
   935
        }
slouken@2828
   936
        XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
slouken@2828
   937
                  dstrect->x, dstrect->y, dstrect->w, dstrect->h);
slouken@2810
   938
    } else {
slouken@2827
   939
        XCopyArea(data->display, texturedata->pixmap, data->drawable,
slouken@2827
   940
                  data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
slouken@2827
   941
                  srcrect->x, srcrect->y);
slouken@2810
   942
    }
slouken@2810
   943
    return 0;
slouken@2810
   944
}
slouken@2810
   945
slouken@3559
   946
static int
slouken@3559
   947
X11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3559
   948
                     Uint32 format, void * pixels, int pitch)
slouken@3559
   949
{
slouken@3559
   950
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@3559
   951
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@3559
   952
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@3559
   953
    Uint32 screen_format = display->current_mode.format;
slouken@3559
   954
    XImage *image;
slouken@3559
   955
slouken@3559
   956
    image = XGetImage(data->display, data->drawable, rect->x, rect->y,
slouken@3559
   957
                      rect->w, rect->h, AllPlanes, ZPixmap);
slouken@3559
   958
slouken@3559
   959
    SDL_ConvertPixels(rect->w, rect->h,
slouken@3559
   960
                      screen_format, image->data, image->bytes_per_line,
slouken@3559
   961
                      format, pixels, pitch);
slouken@3559
   962
slouken@3559
   963
    XDestroyImage(image);
slouken@3559
   964
    return 0;
slouken@3559
   965
}
slouken@3559
   966
slouken@3559
   967
static int
slouken@3559
   968
X11_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3559
   969
                      Uint32 format, const void * pixels, int pitch)
slouken@3559
   970
{
slouken@3559
   971
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@3559
   972
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@3559
   973
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
slouken@3559
   974
    Uint32 screen_format = display->current_mode.format;
slouken@3559
   975
    XImage *image;
slouken@3559
   976
    void *image_pixels;
slouken@3559
   977
    int image_pitch;
slouken@3559
   978
slouken@3559
   979
    image_pitch = rect->w * SDL_BYTESPERPIXEL(screen_format);
slouken@3559
   980
    image_pixels = SDL_malloc(rect->h * image_pitch);
slouken@3559
   981
    if (!image_pixels) {
slouken@3559
   982
        SDL_OutOfMemory();
slouken@3559
   983
        return -1;
slouken@3559
   984
    }
slouken@3559
   985
slouken@3559
   986
    image = XCreateImage(data->display, data->visual,
slouken@3559
   987
                         data->depth, ZPixmap, 0, image_pixels,
slouken@3559
   988
                         rect->w, rect->h,
slouken@3559
   989
                         SDL_BYTESPERPIXEL(screen_format) * 8,
slouken@3559
   990
                         image_pitch);
slouken@3559
   991
    if (!image) {
slouken@3559
   992
        SDL_SetError("XCreateImage() failed");
slouken@3559
   993
        return -1;
slouken@3559
   994
    }
slouken@3559
   995
slouken@3559
   996
    SDL_ConvertPixels(rect->w, rect->h,
slouken@3559
   997
                      format, pixels, pitch,
slouken@3559
   998
                      screen_format, image->data, image->bytes_per_line);
slouken@3559
   999
slouken@3559
  1000
    XPutImage(data->display, data->drawable, data->gc,
slouken@3559
  1001
              image, 0, 0, rect->x, rect->y, rect->w, rect->h);
slouken@3559
  1002
slouken@3559
  1003
    image->data = NULL;
slouken@3559
  1004
    XDestroyImage(image);
slouken@3559
  1005
slouken@3559
  1006
    SDL_free(image_pixels);
slouken@3559
  1007
    return 0;
slouken@3559
  1008
}
slouken@3559
  1009
slouken@2810
  1010
static void
slouken@2810
  1011
X11_RenderPresent(SDL_Renderer * renderer)
slouken@2810
  1012
{
slouken@2810
  1013
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2810
  1014
    SDL_DirtyRect *dirty;
slouken@2810
  1015
slouken@2810
  1016
    /* Send the data to the display */
slouken@2810
  1017
    if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) {
slouken@2810
  1018
        for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
slouken@2810
  1019
            const SDL_Rect *rect = &dirty->rect;
slouken@2810
  1020
            XCopyArea(data->display, data->drawable, data->window,
slouken@2810
  1021
                      data->gc, rect->x, rect->y, rect->w, rect->h,
slouken@2810
  1022
                      rect->x, rect->y);
slouken@2810
  1023
        }
slouken@2810
  1024
        SDL_ClearDirtyRects(&data->dirty);
slouken@2810
  1025
    }
slouken@2810
  1026
    XSync(data->display, False);
slouken@2810
  1027
slouken@2810
  1028
    /* Update the flipping chain, if any */
slouken@2810
  1029
    if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
slouken@2810
  1030
        data->current_pixmap = (data->current_pixmap + 1) % 2;
slouken@2810
  1031
        data->drawable = data->pixmaps[data->current_pixmap];
slouken@2810
  1032
    } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
slouken@2810
  1033
        data->current_pixmap = (data->current_pixmap + 1) % 3;
slouken@2810
  1034
        data->drawable = data->pixmaps[data->current_pixmap];
slouken@2810
  1035
    }
slouken@2810
  1036
}
slouken@2810
  1037
slouken@2810
  1038
static void
slouken@2810
  1039
X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@2810
  1040
{
slouken@2810
  1041
    X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
slouken@2810
  1042
    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
slouken@2810
  1043
slouken@2810
  1044
    if (!data) {
slouken@2810
  1045
        return;
slouken@2810
  1046
    }
slouken@2810
  1047
    if (data->yuv) {
slouken@2810
  1048
        SDL_SW_DestroyYUVTexture(data->yuv);
slouken@2810
  1049
    }
slouken@2810
  1050
    if (data->pixmap != None) {
slouken@2810
  1051
        XFreePixmap(renderdata->display, data->pixmap);
slouken@2810
  1052
    }
slouken@2810
  1053
    if (data->image) {
slouken@2810
  1054
        data->image->data = NULL;
slouken@2810
  1055
        XDestroyImage(data->image);
slouken@2810
  1056
    }
slouken@2810
  1057
#ifndef NO_SHARED_MEMORY
slouken@2810
  1058
    if (data->shminfo.shmaddr) {
slouken@2810
  1059
        XShmDetach(renderdata->display, &data->shminfo);
slouken@2810
  1060
        XSync(renderdata->display, False);
slouken@2810
  1061
        shmdt(data->shminfo.shmaddr);
slouken@2810
  1062
        data->pixels = NULL;
slouken@2810
  1063
    }
slouken@2810
  1064
#endif
slouken@2828
  1065
    if (data->scaling_image) {
slouken@2828
  1066
        SDL_free(data->scaling_image->data);
slouken@2828
  1067
        data->scaling_image->data = NULL;
slouken@2828
  1068
        XDestroyImage(data->scaling_image);
slouken@2828
  1069
    }
slouken@2810
  1070
    if (data->pixels) {
slouken@2810
  1071
        SDL_free(data->pixels);
slouken@2810
  1072
    }
slouken@2810
  1073
    SDL_free(data);
slouken@2810
  1074
    texture->driverdata = NULL;
slouken@2810
  1075
}
slouken@2810
  1076
slouken@2810
  1077
static void
slouken@2810
  1078
X11_DestroyRenderer(SDL_Renderer * renderer)
slouken@2810
  1079
{
slouken@2810
  1080
    X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
slouken@2810
  1081
    int i;
slouken@2810
  1082
slouken@2810
  1083
    if (data) {
slouken@2810
  1084
        for (i = 0; i < SDL_arraysize(data->pixmaps); ++i) {
slouken@2810
  1085
            if (data->pixmaps[i] != None) {
slouken@2810
  1086
                XFreePixmap(data->display, data->pixmaps[i]);
slouken@2810
  1087
            }
slouken@2810
  1088
        }
slouken@2810
  1089
        if (data->gc) {
slouken@2810
  1090
            XFreeGC(data->display, data->gc);
slouken@2810
  1091
        }
slouken@2810
  1092
        SDL_FreeDirtyRects(&data->dirty);
slouken@2810
  1093
        SDL_free(data);
slouken@2810
  1094
    }
slouken@2810
  1095
    SDL_free(renderer);
slouken@2810
  1096
}
slouken@2810
  1097
slouken@2810
  1098
#endif /* SDL_VIDEO_RENDER_X11 */
slouken@2810
  1099
slouken@2810
  1100
/* vi: set ts=4 sw=4 expandtab: */