src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 06 Mar 2011 21:12:19 -0800
changeset 5423 b69fa50e80d7
parent 5404 6717e01acbe0
child 5428 cff5d3cd5777
permissions -rw-r--r--
a Nintendo ds update

Frank Zago to SDL

For those interested, here's a snapshot of the current port. I did away with
most of the previous attempt which was based of the sprite engine, because the
support is limited to 128 64x64 sprites. Instead I'm using the gl engine.
The drawback is that either the frame buffer or the gl engine can be used
because there's not that much video memory on a DS.

With minimal changes to their code, it can now run the following tests: ,
testspriteminimal, testscale and testsprite2. The last 2 only run under the
emulator for some reason. The tests are not included in this patch for size
reason.

In 16 bits mode, the 16th bit indicated transparency/opacity. If 0, the color
is not displayed. So I had to patch a few core file to set that bit to 1. See
patch for src/video/SDL_RLEaccel.c and src/video/SDL_blit.h. Is that ok, or is
there a better way ?

The nds also doesn't support windowed mode, so I force the fullscreen in
src/video/SDL_video.c. Is that ok, or is there a better way ?

To get a smaller library, I also tried to not compile the software renderer
when the hardware renderer is compiled in, and define SDL_NO_COMPAT; however
the compilation eventually fails in SDL_surface.c because SDL_SRCCOLORKEY is
defined in SDL_compat.h. Is SDL_NO_COMPAT only for application and not SDL
itself ?
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@5262
     3
    Copyright (C) 1997-2011 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* The high-level video driver subsystem */
slouken@0
    25
slouken@2999
    26
#include "SDL.h"
slouken@2984
    27
#include "SDL_video.h"
slouken@0
    28
#include "SDL_sysvideo.h"
slouken@0
    29
#include "SDL_blit.h"
slouken@0
    30
#include "SDL_pixels_c.h"
slouken@5294
    31
#include "SDL_rect_c.h"
slouken@1361
    32
#include "../events/SDL_events_c.h"
slouken@0
    33
slouken@5209
    34
#if SDL_VIDEO_OPENGL
slouken@5209
    35
#include "SDL_opengl.h"
slouken@5209
    36
#endif /* SDL_VIDEO_OPENGL */
slouken@5209
    37
hfutrell@2745
    38
#if SDL_VIDEO_OPENGL_ES
hfutrell@2745
    39
#include "SDL_opengles.h"
slouken@2753
    40
#endif /* SDL_VIDEO_OPENGL_ES */
hfutrell@2745
    41
slouken@5209
    42
#if SDL_VIDEO_OPENGL_ES2
slouken@5209
    43
#include "SDL_opengles2.h"
slouken@5209
    44
#endif /* SDL_VIDEO_OPENGL_ES2 */
slouken@4900
    45
slouken@4900
    46
#include "SDL_syswm.h"
slouken@1926
    47
slouken@1926
    48
/* On Windows, windows.h defines CreateWindow */
slouken@1926
    49
#ifdef CreateWindow
slouken@1926
    50
#undef CreateWindow
slouken@1926
    51
#endif
slouken@1926
    52
slouken@0
    53
/* Available video drivers */
lestat@3166
    54
static VideoBootStrap *bootstrap[] = {
slouken@1931
    55
#if SDL_VIDEO_DRIVER_COCOA
slouken@2753
    56
    &COCOA_bootstrap,
icculus@1133
    57
#endif
slouken@1361
    58
#if SDL_VIDEO_DRIVER_X11
slouken@2753
    59
    &X11_bootstrap,
slouken@0
    60
#endif
slouken@1361
    61
#if SDL_VIDEO_DRIVER_DIRECTFB
slouken@2753
    62
    &DirectFB_bootstrap,
slouken@167
    63
#endif
slouken@5062
    64
#if SDL_VIDEO_DRIVER_WINDOWS
slouken@5062
    65
    &WINDOWS_bootstrap,
slouken@1361
    66
#endif
slouken@1361
    67
#if SDL_VIDEO_DRIVER_BWINDOW
slouken@2753
    68
    &BWINDOW_bootstrap,
slouken@1361
    69
#endif
slouken@5150
    70
#if SDL_VIDEO_DRIVER_PANDORA
slouken@5150
    71
    &PND_bootstrap,
slouken@1361
    72
#endif
hfutrell@2743
    73
#if SDL_VIDEO_DRIVER_NDS
slouken@2753
    74
    &NDS_bootstrap,
slouken@2735
    75
#endif
hfutrell@2745
    76
#if SDL_VIDEO_DRIVER_UIKIT
slouken@2753
    77
    &UIKIT_bootstrap,
hfutrell@2745
    78
#endif
slouken@5150
    79
#if SDL_VIDEO_DRIVER_ANDROID
slouken@5150
    80
    &Android_bootstrap,
slouken@5150
    81
#endif
slouken@1361
    82
#if SDL_VIDEO_DRIVER_DUMMY
slouken@2753
    83
    &DUMMY_bootstrap,
slouken@610
    84
#endif
slouken@2753
    85
    NULL
slouken@0
    86
};
slouken@173
    87
slouken@1895
    88
static SDL_VideoDevice *_this = NULL;
slouken@0
    89
slouken@3695
    90
#define CHECK_WINDOW_MAGIC(window, retval) \
slouken@3695
    91
    if (!_this) { \
slouken@3695
    92
        SDL_UninitializedVideo(); \
slouken@3695
    93
        return retval; \
slouken@3695
    94
    } \
slouken@3701
    95
    if (!window || window->magic != &_this->window_magic) { \
slouken@3695
    96
        SDL_SetError("Invalid window"); \
slouken@3695
    97
        return retval; \
slouken@3695
    98
    }
slouken@3695
    99
slouken@5244
   100
#define CHECK_DISPLAY_INDEX(displayIndex, retval) \
slouken@5244
   101
    if (!_this) { \
slouken@5244
   102
        SDL_UninitializedVideo(); \
slouken@5244
   103
        return retval; \
slouken@5244
   104
    } \
slouken@5244
   105
    if (displayIndex < 0 || displayIndex >= _this->num_displays) { \
slouken@5244
   106
        SDL_SetError("displayIndex must be in the range 0 - %d", \
slouken@5244
   107
                     _this->num_displays - 1); \
slouken@5244
   108
        return retval; \
slouken@5244
   109
    }
slouken@5244
   110
slouken@5166
   111
/* Support for framebuffer emulation using an accelerated renderer */
slouken@5166
   112
slouken@5166
   113
#define SDL_WINDOWTEXTUREDATA   "_SDL_WindowTextureData"
slouken@5166
   114
slouken@5166
   115
typedef struct {
slouken@5166
   116
    SDL_Renderer *renderer;
slouken@5166
   117
    SDL_Texture *texture;
slouken@5166
   118
    void *pixels;
slouken@5166
   119
    int pitch;
slouken@5172
   120
    int bytes_per_pixel;
slouken@5166
   121
} SDL_WindowTextureData;
slouken@5166
   122
slouken@5190
   123
static SDL_bool
slouken@5190
   124
ShouldUseTextureFramebuffer()
slouken@5190
   125
{
slouken@5190
   126
    const char *hint;
slouken@5190
   127
slouken@5190
   128
    /* If there's no native framebuffer support then there's no option */
slouken@5190
   129
    if (!_this->CreateWindowFramebuffer) {
slouken@5190
   130
        return SDL_TRUE;
slouken@5190
   131
    }
slouken@5190
   132
slouken@5192
   133
    /* If the user has specified a software renderer we can't use a
slouken@5192
   134
       texture framebuffer, or renderer creation will go recursive.
slouken@5192
   135
     */
slouken@5192
   136
    hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
slouken@5192
   137
    if (hint && SDL_strcasecmp(hint, "software") == 0) {
slouken@5192
   138
        return SDL_FALSE;
slouken@5192
   139
    }
slouken@5192
   140
slouken@5190
   141
    /* See if the user or application wants a specific behavior */
slouken@5190
   142
    hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
slouken@5190
   143
    if (hint) {
slouken@5190
   144
        if (*hint == '0') {
slouken@5190
   145
            return SDL_FALSE;
slouken@5190
   146
        } else {
slouken@5190
   147
            return SDL_TRUE;
slouken@5190
   148
        }
slouken@5190
   149
    }
slouken@5190
   150
slouken@5190
   151
    /* Each platform has different performance characteristics */
slouken@5190
   152
#if defined(__WIN32__)
slouken@5190
   153
    /* GDI BitBlt() is way faster than Direct3D dynamic textures right now.
slouken@5190
   154
     */
slouken@5190
   155
    return SDL_FALSE;
slouken@5190
   156
slouken@5190
   157
#elif defined(__MACOSX__)
slouken@5190
   158
    /* Mac OS X uses OpenGL as the native fast path */
slouken@5190
   159
    return SDL_TRUE;
slouken@5190
   160
slouken@5190
   161
#elif defined(__LINUX__)
slouken@5190
   162
    /* Properly configured OpenGL drivers are faster than MIT-SHM */
slouken@5190
   163
#if SDL_VIDEO_OPENGL
slouken@5190
   164
    /* Ugh, find a way to cache this value! */
slouken@5190
   165
    {
slouken@5190
   166
        SDL_Window *window;
slouken@5190
   167
        SDL_GLContext context;
slouken@5190
   168
        SDL_bool hasAcceleratedOpenGL = SDL_FALSE;
slouken@5190
   169
slouken@5385
   170
        window = SDL_CreateWindow("OpenGL test", -32, -32, 32, 32, SDL_WINDOW_OPENGL|SDL_WINDOW_HIDDEN);
slouken@5190
   171
        if (window) {
slouken@5190
   172
            context = SDL_GL_CreateContext(window);
slouken@5190
   173
            if (context) {
slouken@5190
   174
                const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
slouken@5190
   175
                const char *vendor = NULL;
slouken@5190
   176
slouken@5190
   177
                glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
slouken@5190
   178
                if (glGetStringFunc) {
slouken@5190
   179
                    vendor = (const char *) glGetStringFunc(GL_VENDOR);
slouken@5190
   180
                }
slouken@5190
   181
                /* Add more vendors here at will... */
slouken@5190
   182
                if (vendor &&
slouken@5190
   183
                    (SDL_strstr(vendor, "ATI Technologies") ||
slouken@5190
   184
                     SDL_strstr(vendor, "NVIDIA"))) {
slouken@5190
   185
                    hasAcceleratedOpenGL = SDL_TRUE;
slouken@5190
   186
                }
slouken@5190
   187
                SDL_GL_DeleteContext(context);
slouken@5190
   188
            }
slouken@5190
   189
            SDL_DestroyWindow(window);
slouken@5190
   190
        }
slouken@5190
   191
        return hasAcceleratedOpenGL;
slouken@5190
   192
    }
slouken@5190
   193
#else
slouken@5190
   194
    return SDL_FALSE;
slouken@5190
   195
#endif
slouken@5190
   196
slouken@5190
   197
#else
slouken@5190
   198
    /* Play it safe, assume that if there is a framebuffer driver that it's
slouken@5190
   199
       optimized for the current platform.
slouken@5190
   200
    */
slouken@5190
   201
    return SDL_FALSE;
slouken@5190
   202
#endif
slouken@5190
   203
}
slouken@5190
   204
slouken@5166
   205
static int
slouken@5166
   206
SDL_CreateWindowTexture(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
slouken@5166
   207
{
slouken@5166
   208
    SDL_WindowTextureData *data;
slouken@5166
   209
    SDL_RendererInfo info;
slouken@5166
   210
    Uint32 i;
slouken@5166
   211
slouken@5166
   212
    data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
slouken@5166
   213
    if (!data) {
slouken@5291
   214
        SDL_Renderer *renderer = NULL;
slouken@5168
   215
        SDL_RendererInfo info;
slouken@5168
   216
        int i;
slouken@5191
   217
        const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
slouken@5168
   218
slouken@5191
   219
        /* Check to see if there's a specific driver requested */
slouken@5191
   220
        if (hint && *hint != '0' && *hint != '1' &&
slouken@5191
   221
            SDL_strcasecmp(hint, "software") != 0) {
slouken@5191
   222
            for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
slouken@5191
   223
                SDL_GetRenderDriverInfo(i, &info);
slouken@5191
   224
                if (SDL_strcasecmp(info.name, hint) == 0) {
slouken@5191
   225
                    renderer = SDL_CreateRenderer(window, i, 0);
slouken@5168
   226
                    break;
slouken@5168
   227
                }
slouken@5168
   228
            }
slouken@5168
   229
        }
slouken@5191
   230
slouken@5191
   231
        if (!renderer) {
slouken@5191
   232
            for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
slouken@5191
   233
                SDL_GetRenderDriverInfo(i, &info);
slouken@5191
   234
                if (SDL_strcmp(info.name, "software") != 0) {
slouken@5191
   235
                    renderer = SDL_CreateRenderer(window, i, 0);
slouken@5191
   236
                    if (renderer) {
slouken@5191
   237
                        break;
slouken@5191
   238
                    }
slouken@5191
   239
                }
slouken@5191
   240
            }
slouken@5191
   241
        }
slouken@5166
   242
        if (!renderer) {
slouken@5166
   243
            return -1;
slouken@5166
   244
        }
slouken@5275
   245
slouken@5275
   246
        /* Create the data after we successfully create the renderer (bug #1116) */
slouken@5275
   247
        data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
slouken@5275
   248
        if (!data) {
slouken@5275
   249
            SDL_DestroyRenderer(renderer);
slouken@5275
   250
            SDL_OutOfMemory();
slouken@5275
   251
            return -1;
slouken@5275
   252
        }
slouken@5275
   253
        SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data);
slouken@5275
   254
slouken@5166
   255
        data->renderer = renderer;
slouken@5166
   256
    }
slouken@5166
   257
slouken@5166
   258
    /* Free any old texture and pixel data */
slouken@5166
   259
    if (data->texture) {
slouken@5166
   260
        SDL_DestroyTexture(data->texture);
slouken@5166
   261
        data->texture = NULL;
slouken@5166
   262
    }
slouken@5166
   263
    if (data->pixels) {
slouken@5166
   264
        SDL_free(data->pixels);
slouken@5166
   265
        data->pixels = NULL;
slouken@5166
   266
    }
slouken@5166
   267
slouken@5291
   268
    if (SDL_GetRendererInfo(data->renderer, &info) < 0) {
slouken@5166
   269
        return -1;
slouken@5166
   270
    }
slouken@5166
   271
slouken@5166
   272
    /* Find the first format without an alpha channel */
slouken@5166
   273
    *format = info.texture_formats[0];
slouken@5166
   274
    for (i = 0; i < info.num_texture_formats; ++i) {
slouken@5268
   275
        if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
slouken@5268
   276
            !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
slouken@5166
   277
            *format = info.texture_formats[i];
slouken@5166
   278
            break;
slouken@5166
   279
        }
slouken@5166
   280
    }
slouken@5166
   281
slouken@5291
   282
    data->texture = SDL_CreateTexture(data->renderer, *format,
slouken@5166
   283
                                      SDL_TEXTUREACCESS_STREAMING,
slouken@5166
   284
                                      window->w, window->h);
slouken@5166
   285
    if (!data->texture) {
slouken@5166
   286
        return -1;
slouken@5166
   287
    }
slouken@5166
   288
slouken@5166
   289
    /* Create framebuffer data */
slouken@5172
   290
    data->bytes_per_pixel = SDL_BYTESPERPIXEL(*format);
slouken@5172
   291
    data->pitch = (((window->w * data->bytes_per_pixel) + 3) & ~3);
slouken@5166
   292
    data->pixels = SDL_malloc(window->h * data->pitch);
slouken@5166
   293
    if (!data->pixels) {
slouken@5166
   294
        SDL_OutOfMemory();
slouken@5166
   295
        return -1;
slouken@5166
   296
    }
slouken@5166
   297
slouken@5166
   298
    *pixels = data->pixels;
slouken@5166
   299
    *pitch = data->pitch;
slouken@5297
   300
slouken@5297
   301
    /* Make sure we're not double-scaling the viewport */
slouken@5297
   302
    SDL_RenderSetViewport(data->renderer, NULL);
slouken@5297
   303
slouken@5166
   304
    return 0;
slouken@5166
   305
}
slouken@5166
   306
slouken@5166
   307
static int
slouken@5297
   308
SDL_UpdateWindowTexture(_THIS, SDL_Window * window, SDL_Rect * rects, int numrects)
slouken@5166
   309
{
slouken@5166
   310
    SDL_WindowTextureData *data;
slouken@5294
   311
    SDL_Rect rect;
slouken@5294
   312
    void *src;
slouken@5166
   313
slouken@5166
   314
    data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
slouken@5166
   315
    if (!data || !data->texture) {
slouken@5166
   316
        SDL_SetError("No window texture data");
slouken@5166
   317
        return -1;
slouken@5166
   318
    }
slouken@5166
   319
slouken@5294
   320
    /* Update a single rect that contains subrects for best DMA performance */
slouken@5294
   321
    if (SDL_GetSpanEnclosingRect(window->w, window->h, numrects, rects, &rect)) {
slouken@5172
   322
        src = (void *)((Uint8 *)data->pixels +
slouken@5294
   323
                        rect.y * data->pitch +
slouken@5294
   324
                        rect.x * data->bytes_per_pixel);
slouken@5294
   325
        if (SDL_UpdateTexture(data->texture, &rect, src, data->pitch) < 0) {
slouken@5172
   326
            return -1;
slouken@5172
   327
        }
slouken@5294
   328
slouken@5294
   329
        if (SDL_RenderCopy(data->renderer, data->texture, NULL, NULL) < 0) {
slouken@5294
   330
            return -1;
slouken@5172
   331
        }
slouken@5294
   332
slouken@5294
   333
        SDL_RenderPresent(data->renderer);
slouken@5172
   334
    }
slouken@5166
   335
    return 0;
slouken@5166
   336
}
slouken@5166
   337
slouken@5166
   338
static void
slouken@5166
   339
SDL_DestroyWindowTexture(_THIS, SDL_Window * window)
slouken@5166
   340
{
slouken@5166
   341
    SDL_WindowTextureData *data;
slouken@5166
   342
slouken@5166
   343
    data = SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, NULL);
slouken@5166
   344
    if (!data) {
slouken@5166
   345
        return;
slouken@5166
   346
    }
slouken@5166
   347
    if (data->texture) {
slouken@5166
   348
        SDL_DestroyTexture(data->texture);
slouken@5166
   349
    }
slouken@5166
   350
    if (data->renderer) {
slouken@5166
   351
        SDL_DestroyRenderer(data->renderer);
slouken@5166
   352
    }
slouken@5166
   353
    if (data->pixels) {
slouken@5166
   354
        SDL_free(data->pixels);
slouken@5166
   355
    }
slouken@5166
   356
    SDL_free(data);
slouken@5166
   357
}
slouken@5166
   358
slouken@5166
   359
slouken@1895
   360
static int
slouken@1895
   361
cmpmodes(const void *A, const void *B)
slouken@1895
   362
{
slouken@2753
   363
    SDL_DisplayMode a = *(const SDL_DisplayMode *) A;
slouken@2753
   364
    SDL_DisplayMode b = *(const SDL_DisplayMode *) B;
slouken@0
   365
slouken@2753
   366
    if (a.w != b.w) {
slouken@2753
   367
        return b.w - a.w;
slouken@2753
   368
    }
slouken@2753
   369
    if (a.h != b.h) {
slouken@2753
   370
        return b.h - a.h;
slouken@2753
   371
    }
slouken@2753
   372
    if (SDL_BITSPERPIXEL(a.format) != SDL_BITSPERPIXEL(b.format)) {
slouken@2753
   373
        return SDL_BITSPERPIXEL(b.format) - SDL_BITSPERPIXEL(a.format);
slouken@2753
   374
    }
lestat@3178
   375
    if (SDL_PIXELLAYOUT(a.format) != SDL_PIXELLAYOUT(b.format)) {
lestat@3178
   376
        return SDL_PIXELLAYOUT(b.format) - SDL_PIXELLAYOUT(a.format);
lestat@3178
   377
    }
slouken@2753
   378
    if (a.refresh_rate != b.refresh_rate) {
slouken@2753
   379
        return b.refresh_rate - a.refresh_rate;
slouken@2753
   380
    }
slouken@2753
   381
    return 0;
slouken@1895
   382
}
slouken@1895
   383
slouken@1912
   384
static void
slouken@1912
   385
SDL_UninitializedVideo()
slouken@1912
   386
{
slouken@2753
   387
    SDL_SetError("Video subsystem has not been initialized");
slouken@1912
   388
}
slouken@1912
   389
slouken@1895
   390
int
slouken@1895
   391
SDL_GetNumVideoDrivers(void)
slouken@1895
   392
{
slouken@2753
   393
    return SDL_arraysize(bootstrap) - 1;
slouken@1895
   394
}
slouken@1895
   395
slouken@2753
   396
const char *
slouken@1895
   397
SDL_GetVideoDriver(int index)
slouken@1895
   398
{
slouken@2753
   399
    if (index >= 0 && index < SDL_GetNumVideoDrivers()) {
slouken@2753
   400
        return bootstrap[index]->name;
slouken@2753
   401
    }
slouken@2753
   402
    return NULL;
slouken@1895
   403
}
slouken@0
   404
slouken@0
   405
/*
slouken@0
   406
 * Initialize the video and event subsystems -- determine native pixel format
slouken@0
   407
 */
slouken@1895
   408
int
slouken@5123
   409
SDL_VideoInit(const char *driver_name)
slouken@0
   410
{
slouken@2753
   411
    SDL_VideoDevice *video;
slouken@2753
   412
    int index;
slouken@2753
   413
    int i;
slouken@0
   414
slouken@3694
   415
    /* Check to make sure we don't overwrite '_this' */
slouken@3694
   416
    if (_this != NULL) {
slouken@3694
   417
        SDL_VideoQuit();
slouken@3694
   418
    }
slouken@3694
   419
slouken@2753
   420
    /* Start the event loop */
slouken@5123
   421
    if (SDL_StartEventLoop() < 0 ||
slouken@5123
   422
        SDL_KeyboardInit() < 0 ||
slouken@5123
   423
        SDL_MouseInit() < 0 ||
slouken@5123
   424
        SDL_TouchInit() < 0 ||
slouken@5123
   425
        SDL_QuitInit() < 0) {
slouken@2753
   426
        return -1;
slouken@2753
   427
    }
slouken@3694
   428
slouken@2753
   429
    /* Select the proper video driver */
slouken@2753
   430
    index = 0;
slouken@2753
   431
    video = NULL;
slouken@2753
   432
    if (driver_name == NULL) {
slouken@2753
   433
        driver_name = SDL_getenv("SDL_VIDEODRIVER");
slouken@2753
   434
    }
slouken@2753
   435
    if (driver_name != NULL) {
slouken@2753
   436
        for (i = 0; bootstrap[i]; ++i) {
slouken@2753
   437
            if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
slouken@3448
   438
                video = bootstrap[i]->create(index);
slouken@2753
   439
                break;
slouken@2753
   440
            }
slouken@2753
   441
        }
slouken@2753
   442
    } else {
slouken@2753
   443
        for (i = 0; bootstrap[i]; ++i) {
slouken@2753
   444
            if (bootstrap[i]->available()) {
slouken@2753
   445
                video = bootstrap[i]->create(index);
slouken@2753
   446
                if (video != NULL) {
slouken@2753
   447
                    break;
slouken@2753
   448
                }
slouken@2753
   449
            }
slouken@2753
   450
        }
slouken@2753
   451
    }
slouken@2753
   452
    if (video == NULL) {
slouken@2753
   453
        if (driver_name) {
slouken@2753
   454
            SDL_SetError("%s not available", driver_name);
slouken@2753
   455
        } else {
slouken@2753
   456
            SDL_SetError("No available video device");
slouken@2753
   457
        }
slouken@2753
   458
        return -1;
slouken@2753
   459
    }
slouken@2753
   460
    _this = video;
slouken@2753
   461
    _this->name = bootstrap[i]->name;
slouken@2753
   462
    _this->next_object_id = 1;
slouken@0
   463
slouken@0
   464
slouken@2753
   465
    /* Set some very sane GL defaults */
slouken@2753
   466
    _this->gl_config.driver_loaded = 0;
slouken@2753
   467
    _this->gl_config.dll_handle = NULL;
slouken@2753
   468
    _this->gl_config.red_size = 3;
slouken@2753
   469
    _this->gl_config.green_size = 3;
slouken@2753
   470
    _this->gl_config.blue_size = 2;
slouken@2753
   471
    _this->gl_config.alpha_size = 0;
slouken@2753
   472
    _this->gl_config.buffer_size = 0;
slouken@2753
   473
    _this->gl_config.depth_size = 16;
slouken@2753
   474
    _this->gl_config.stencil_size = 0;
slouken@2753
   475
    _this->gl_config.double_buffer = 1;
slouken@2753
   476
    _this->gl_config.accum_red_size = 0;
slouken@2753
   477
    _this->gl_config.accum_green_size = 0;
slouken@2753
   478
    _this->gl_config.accum_blue_size = 0;
slouken@2753
   479
    _this->gl_config.accum_alpha_size = 0;
slouken@2753
   480
    _this->gl_config.stereo = 0;
slouken@2753
   481
    _this->gl_config.multisamplebuffers = 0;
slouken@2753
   482
    _this->gl_config.multisamplesamples = 0;
slouken@2753
   483
    _this->gl_config.retained_backing = 1;
slouken@3571
   484
    _this->gl_config.accelerated = -1;  /* accelerated or not, both are fine */
slouken@5209
   485
#if SDL_VIDEO_OPENGL
slouken@3100
   486
    _this->gl_config.major_version = 2;
slouken@3100
   487
    _this->gl_config.minor_version = 1;
slouken@5217
   488
#elif SDL_VIDEO_OPENGL_ES
slouken@5217
   489
    _this->gl_config.major_version = 1;
slouken@5217
   490
    _this->gl_config.minor_version = 1;
slouken@5209
   491
#elif SDL_VIDEO_OPENGL_ES2
slouken@5209
   492
    _this->gl_config.major_version = 2;
slouken@5209
   493
    _this->gl_config.minor_version = 0;
slouken@5209
   494
#endif
slouken@0
   495
slouken@2753
   496
    /* Initialize the video subsystem */
slouken@2753
   497
    if (_this->VideoInit(_this) < 0) {
slouken@2753
   498
        SDL_VideoQuit();
slouken@2753
   499
        return -1;
slouken@2753
   500
    }
slouken@5166
   501
slouken@2753
   502
    /* Make sure some displays were added */
slouken@2753
   503
    if (_this->num_displays == 0) {
slouken@2753
   504
        SDL_SetError("The video driver did not add any displays");
slouken@2753
   505
        SDL_VideoQuit();
slouken@2753
   506
        return (-1);
slouken@2753
   507
    }
slouken@0
   508
slouken@5190
   509
    /* Add the renderer framebuffer emulation if desired */
slouken@5190
   510
    if (ShouldUseTextureFramebuffer()) {
slouken@5166
   511
        _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
slouken@5166
   512
        _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
slouken@5166
   513
        _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
slouken@5166
   514
    }
slouken@5166
   515
slouken@2753
   516
    /* We're ready to go! */
slouken@2753
   517
    return 0;
slouken@0
   518
}
slouken@0
   519
slouken@2753
   520
const char *
slouken@1895
   521
SDL_GetCurrentVideoDriver()
slouken@0
   522
{
slouken@2753
   523
    if (!_this) {
slouken@2753
   524
        SDL_UninitializedVideo();
slouken@2753
   525
        return NULL;
slouken@2753
   526
    }
slouken@2753
   527
    return _this->name;
slouken@0
   528
}
slouken@0
   529
slouken@1895
   530
SDL_VideoDevice *
slouken@4472
   531
SDL_GetVideoDevice(void)
slouken@0
   532
{
slouken@2753
   533
    return _this;
slouken@0
   534
}
slouken@0
   535
slouken@1895
   536
int
slouken@1895
   537
SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
slouken@0
   538
{
slouken@2753
   539
    SDL_VideoDisplay display;
slouken@0
   540
slouken@2753
   541
    SDL_zero(display);
slouken@2753
   542
    if (desktop_mode) {
slouken@2753
   543
        display.desktop_mode = *desktop_mode;
slouken@2753
   544
    }
slouken@2753
   545
    display.current_mode = display.desktop_mode;
slouken@1895
   546
slouken@2753
   547
    return SDL_AddVideoDisplay(&display);
slouken@0
   548
}
slouken@0
   549
slouken@1895
   550
int
slouken@1895
   551
SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
slouken@0
   552
{
slouken@2753
   553
    SDL_VideoDisplay *displays;
slouken@2753
   554
    int index = -1;
slouken@0
   555
slouken@2753
   556
    displays =
slouken@2753
   557
        SDL_realloc(_this->displays,
slouken@2753
   558
                    (_this->num_displays + 1) * sizeof(*displays));
slouken@2753
   559
    if (displays) {
slouken@2753
   560
        index = _this->num_displays++;
slouken@2753
   561
        displays[index] = *display;
slouken@2753
   562
        displays[index].device = _this;
slouken@2753
   563
        _this->displays = displays;
slouken@2753
   564
    } else {
slouken@2753
   565
        SDL_OutOfMemory();
slouken@2753
   566
    }
slouken@2753
   567
    return index;
slouken@0
   568
}
slouken@0
   569
slouken@1895
   570
int
slouken@1895
   571
SDL_GetNumVideoDisplays(void)
slouken@0
   572
{
slouken@2753
   573
    if (!_this) {
slouken@2753
   574
        SDL_UninitializedVideo();
slouken@2753
   575
        return 0;
slouken@2753
   576
    }
slouken@2753
   577
    return _this->num_displays;
slouken@0
   578
}
slouken@0
   579
slouken@1895
   580
int
slouken@5380
   581
SDL_GetIndexOfDisplay(SDL_VideoDisplay *display)
slouken@5380
   582
{
slouken@5380
   583
    int displayIndex;
slouken@5380
   584
slouken@5380
   585
    for (displayIndex = 0; displayIndex < _this->num_displays; ++displayIndex) {
slouken@5380
   586
        if (display == &_this->displays[displayIndex]) {
slouken@5380
   587
            return displayIndex;
slouken@5380
   588
        }
slouken@5380
   589
    }
slouken@5380
   590
slouken@5380
   591
    /* Couldn't find the display, just use index 0 */
slouken@5380
   592
    return 0;
slouken@5380
   593
}
slouken@5380
   594
slouken@5380
   595
int
slouken@5244
   596
SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
slouken@3528
   597
{
slouken@5244
   598
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   599
slouken@3528
   600
    if (rect) {
slouken@5244
   601
        SDL_VideoDisplay *display = &_this->displays[displayIndex];
slouken@3528
   602
slouken@3528
   603
        if (_this->GetDisplayBounds) {
slouken@5249
   604
            if (_this->GetDisplayBounds(_this, display, rect) == 0) {
slouken@5249
   605
                return 0;
slouken@3528
   606
            }
slouken@5249
   607
        }
slouken@5249
   608
slouken@5249
   609
        /* Assume that the displays are left to right */
slouken@5249
   610
        if (displayIndex == 0) {
slouken@5249
   611
            rect->x = 0;
slouken@5249
   612
            rect->y = 0;
slouken@3528
   613
        } else {
slouken@5249
   614
            SDL_GetDisplayBounds(displayIndex-1, rect);
slouken@5249
   615
            rect->x += rect->w;
slouken@3528
   616
        }
slouken@5249
   617
        rect->w = display->desktop_mode.w;
slouken@5249
   618
        rect->h = display->desktop_mode.h;
slouken@3528
   619
    }
slouken@3528
   620
    return 0;
slouken@3528
   621
}
slouken@3528
   622
slouken@1895
   623
SDL_bool
slouken@3500
   624
SDL_AddDisplayMode(SDL_VideoDisplay * display,  const SDL_DisplayMode * mode)
slouken@0
   625
{
slouken@2753
   626
    SDL_DisplayMode *modes;
slouken@2753
   627
    int i, nmodes;
slouken@0
   628
slouken@2753
   629
    /* Make sure we don't already have the mode in the list */
slouken@2753
   630
    modes = display->display_modes;
slouken@2753
   631
    nmodes = display->num_display_modes;
slouken@2753
   632
    for (i = nmodes; i--;) {
slouken@2753
   633
        if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) {
slouken@2753
   634
            return SDL_FALSE;
slouken@2753
   635
        }
slouken@2753
   636
    }
slouken@1895
   637
slouken@2753
   638
    /* Go ahead and add the new mode */
slouken@2753
   639
    if (nmodes == display->max_display_modes) {
slouken@2753
   640
        modes =
slouken@2753
   641
            SDL_realloc(modes,
slouken@2753
   642
                        (display->max_display_modes + 32) * sizeof(*modes));
slouken@2753
   643
        if (!modes) {
slouken@2753
   644
            return SDL_FALSE;
slouken@2753
   645
        }
slouken@2753
   646
        display->display_modes = modes;
slouken@2753
   647
        display->max_display_modes += 32;
slouken@2753
   648
    }
slouken@2753
   649
    modes[nmodes] = *mode;
slouken@2753
   650
    display->num_display_modes++;
slouken@1895
   651
lestat@3178
   652
    /* Re-sort video modes */
lestat@3178
   653
    SDL_qsort(display->display_modes, display->num_display_modes,
slouken@3186
   654
              sizeof(SDL_DisplayMode), cmpmodes);
lestat@3178
   655
slouken@2753
   656
    return SDL_TRUE;
slouken@0
   657
}
slouken@0
   658
slouken@5246
   659
SDL_VideoDisplay *
slouken@5246
   660
SDL_GetFirstDisplay(void)
slouken@5246
   661
{
slouken@5246
   662
    return &_this->displays[0];
slouken@5246
   663
}
slouken@5246
   664
slouken@5244
   665
static int
slouken@3500
   666
SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
slouken@3500
   667
{
slouken@3500
   668
    if (!display->num_display_modes && _this->GetDisplayModes) {
slouken@3500
   669
        _this->GetDisplayModes(_this, display);
slouken@3500
   670
        SDL_qsort(display->display_modes, display->num_display_modes,
slouken@3500
   671
                  sizeof(SDL_DisplayMode), cmpmodes);
slouken@3500
   672
    }
slouken@3500
   673
    return display->num_display_modes;
slouken@3500
   674
}
slouken@3500
   675
slouken@3500
   676
int
slouken@5244
   677
SDL_GetNumDisplayModes(int displayIndex)
slouken@0
   678
{
slouken@5244
   679
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   680
slouken@5244
   681
    return SDL_GetNumDisplayModesForDisplay(&_this->displays[displayIndex]);
slouken@3500
   682
}
slouken@3500
   683
slouken@3500
   684
int
slouken@5244
   685
SDL_GetDisplayMode(int displayIndex, int index, SDL_DisplayMode * mode)
slouken@3500
   686
{
slouken@5244
   687
    SDL_VideoDisplay *display;
slouken@5244
   688
slouken@5244
   689
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   690
slouken@5244
   691
    display = &_this->displays[displayIndex];
slouken@3500
   692
    if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
slouken@3500
   693
        SDL_SetError("index must be in the range of 0 - %d",
slouken@3500
   694
                     SDL_GetNumDisplayModesForDisplay(display) - 1);
slouken@3500
   695
        return -1;
slouken@3500
   696
    }
slouken@3500
   697
    if (mode) {
slouken@3500
   698
        *mode = display->display_modes[index];
slouken@2753
   699
    }
slouken@2753
   700
    return 0;
slouken@0
   701
}
slouken@0
   702
slouken@1967
   703
int
slouken@5244
   704
SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode)
slouken@0
   705
{
slouken@5244
   706
    SDL_VideoDisplay *display;
slouken@3500
   707
slouken@5244
   708
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   709
slouken@5244
   710
    display = &_this->displays[displayIndex];
slouken@2753
   711
    if (mode) {
slouken@3500
   712
        *mode = display->desktop_mode;
slouken@2753
   713
    }
slouken@2753
   714
    return 0;
slouken@0
   715
}
slouken@0
   716
slouken@1967
   717
int
slouken@5244
   718
SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode)
slouken@0
   719
{
slouken@5244
   720
    SDL_VideoDisplay *display;
slouken@3500
   721
slouken@5244
   722
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   723
slouken@5244
   724
    display = &_this->displays[displayIndex];
slouken@2753
   725
    if (mode) {
slouken@3500
   726
        *mode = display->current_mode;
slouken@2753
   727
    }
slouken@2753
   728
    return 0;
slouken@0
   729
}
slouken@0
   730
slouken@5244
   731
static SDL_DisplayMode *
slouken@3500
   732
SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
slouken@3500
   733
                                    const SDL_DisplayMode * mode,
slouken@3500
   734
                                    SDL_DisplayMode * closest)
slouken@0
   735
{
slouken@2753
   736
    Uint32 target_format;
slouken@2753
   737
    int target_refresh_rate;
slouken@2753
   738
    int i;
slouken@2753
   739
    SDL_DisplayMode *current, *match;
slouken@0
   740
slouken@3500
   741
    if (!mode || !closest) {
slouken@3500
   742
        SDL_SetError("Missing desired mode or closest mode parameter");
slouken@2753
   743
        return NULL;
slouken@2753
   744
    }
slouken@3500
   745
slouken@2753
   746
    /* Default to the desktop format */
slouken@2753
   747
    if (mode->format) {
slouken@2753
   748
        target_format = mode->format;
slouken@2753
   749
    } else {
slouken@3500
   750
        target_format = display->desktop_mode.format;
slouken@2753
   751
    }
slouken@0
   752
slouken@2753
   753
    /* Default to the desktop refresh rate */
slouken@2753
   754
    if (mode->refresh_rate) {
slouken@2753
   755
        target_refresh_rate = mode->refresh_rate;
slouken@2753
   756
    } else {
slouken@3500
   757
        target_refresh_rate = display->desktop_mode.refresh_rate;
slouken@2753
   758
    }
slouken@0
   759
slouken@2753
   760
    match = NULL;
slouken@3500
   761
    for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
slouken@3500
   762
        current = &display->display_modes[i];
slouken@0
   763
slouken@2789
   764
        if (current->w && (current->w < mode->w)) {
slouken@2753
   765
            /* Out of sorted modes large enough here */
slouken@2753
   766
            break;
slouken@2753
   767
        }
slouken@2789
   768
        if (current->h && (current->h < mode->h)) {
slouken@2789
   769
            if (current->w && (current->w == mode->w)) {
slouken@2789
   770
                /* Out of sorted modes large enough here */
slouken@2789
   771
                break;
slouken@2789
   772
            }
slouken@2789
   773
            /* Wider, but not tall enough, due to a different
slouken@2789
   774
               aspect ratio. This mode must be skipped, but closer
slouken@2789
   775
               modes may still follow. */
slouken@2789
   776
            continue;
slouken@2789
   777
        }
slouken@2753
   778
        if (!match || current->w < match->w || current->h < match->h) {
slouken@2753
   779
            match = current;
slouken@2753
   780
            continue;
slouken@2753
   781
        }
slouken@2753
   782
        if (current->format != match->format) {
slouken@2753
   783
            /* Sorted highest depth to lowest */
slouken@2753
   784
            if (current->format == target_format ||
slouken@2753
   785
                (SDL_BITSPERPIXEL(current->format) >=
slouken@2753
   786
                 SDL_BITSPERPIXEL(target_format)
slouken@2753
   787
                 && SDL_PIXELTYPE(current->format) ==
slouken@2753
   788
                 SDL_PIXELTYPE(target_format))) {
slouken@2753
   789
                match = current;
slouken@2753
   790
            }
slouken@2753
   791
            continue;
slouken@2753
   792
        }
slouken@2753
   793
        if (current->refresh_rate != match->refresh_rate) {
slouken@2753
   794
            /* Sorted highest refresh to lowest */
slouken@2753
   795
            if (current->refresh_rate >= target_refresh_rate) {
slouken@2753
   796
                match = current;
slouken@2753
   797
            }
slouken@2753
   798
        }
slouken@2753
   799
    }
slouken@2753
   800
    if (match) {
slouken@2753
   801
        if (match->format) {
slouken@2753
   802
            closest->format = match->format;
slouken@2753
   803
        } else {
slouken@2753
   804
            closest->format = mode->format;
slouken@2753
   805
        }
slouken@2753
   806
        if (match->w && match->h) {
slouken@2753
   807
            closest->w = match->w;
slouken@2753
   808
            closest->h = match->h;
slouken@2753
   809
        } else {
slouken@2753
   810
            closest->w = mode->w;
slouken@2753
   811
            closest->h = mode->h;
slouken@2753
   812
        }
slouken@2753
   813
        if (match->refresh_rate) {
slouken@2753
   814
            closest->refresh_rate = match->refresh_rate;
slouken@2753
   815
        } else {
slouken@2753
   816
            closest->refresh_rate = mode->refresh_rate;
slouken@2753
   817
        }
slouken@2753
   818
        closest->driverdata = match->driverdata;
slouken@1895
   819
slouken@2753
   820
        /*
slouken@2753
   821
         * Pick some reasonable defaults if the app and driver don't
slouken@2753
   822
         * care
slouken@2753
   823
         */
slouken@2753
   824
        if (!closest->format) {
slouken@2753
   825
            closest->format = SDL_PIXELFORMAT_RGB888;
slouken@2753
   826
        }
slouken@2753
   827
        if (!closest->w) {
slouken@2753
   828
            closest->w = 640;
slouken@2753
   829
        }
slouken@2753
   830
        if (!closest->h) {
slouken@2753
   831
            closest->h = 480;
slouken@2753
   832
        }
slouken@2753
   833
        return closest;
slouken@2753
   834
    }
slouken@2753
   835
    return NULL;
slouken@0
   836
}
slouken@0
   837
slouken@3500
   838
SDL_DisplayMode *
slouken@5244
   839
SDL_GetClosestDisplayMode(int displayIndex,
slouken@5244
   840
                          const SDL_DisplayMode * mode,
slouken@3500
   841
                          SDL_DisplayMode * closest)
slouken@3500
   842
{
slouken@5244
   843
    SDL_VideoDisplay *display;
slouken@5244
   844
slouken@5244
   845
    CHECK_DISPLAY_INDEX(displayIndex, NULL);
slouken@5244
   846
slouken@5244
   847
    display = &_this->displays[displayIndex];
slouken@5244
   848
    return SDL_GetClosestDisplayModeForDisplay(display, mode, closest);
slouken@3500
   849
}
slouken@3500
   850
slouken@1895
   851
int
slouken@3500
   852
SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
slouken@0
   853
{
slouken@2753
   854
    SDL_DisplayMode display_mode;
slouken@2753
   855
    SDL_DisplayMode current_mode;
slouken@0
   856
slouken@3502
   857
    if (mode) {
slouken@3502
   858
        display_mode = *mode;
slouken@3502
   859
slouken@3502
   860
        /* Default to the current mode */
slouken@3502
   861
        if (!display_mode.format) {
slouken@3502
   862
            display_mode.format = display->current_mode.format;
slouken@3502
   863
        }
slouken@3502
   864
        if (!display_mode.w) {
slouken@3502
   865
            display_mode.w = display->current_mode.w;
slouken@3502
   866
        }
slouken@3502
   867
        if (!display_mode.h) {
slouken@3502
   868
            display_mode.h = display->current_mode.h;
slouken@3502
   869
        }
slouken@3502
   870
        if (!display_mode.refresh_rate) {
slouken@3502
   871
            display_mode.refresh_rate = display->current_mode.refresh_rate;
slouken@3502
   872
        }
slouken@3502
   873
slouken@3502
   874
        /* Get a good video mode, the closest one possible */
slouken@3502
   875
        if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
slouken@3502
   876
            SDL_SetError("No video mode large enough for %dx%d",
slouken@3502
   877
                         display_mode.w, display_mode.h);
slouken@3502
   878
            return -1;
slouken@3502
   879
        }
slouken@3502
   880
    } else {
slouken@3502
   881
        display_mode = display->desktop_mode;
slouken@2753
   882
    }
slouken@3500
   883
slouken@2753
   884
    /* See if there's anything left to do */
slouken@5244
   885
    current_mode = display->current_mode;
slouken@2753
   886
    if (SDL_memcmp(&display_mode, &current_mode, sizeof(display_mode)) == 0) {
slouken@2753
   887
        return 0;
slouken@2753
   888
    }
slouken@3500
   889
slouken@2753
   890
    /* Actually change the display mode */
slouken@4978
   891
    if (!_this->SetDisplayMode) {
slouken@4978
   892
        SDL_SetError("Video driver doesn't support changing display mode");
slouken@4978
   893
        return -1;
slouken@4978
   894
    }
slouken@3500
   895
    if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
slouken@2753
   896
        return -1;
slouken@2753
   897
    }
slouken@2753
   898
    display->current_mode = display_mode;
slouken@2753
   899
    return 0;
slouken@0
   900
}
slouken@0
   901
slouken@1895
   902
int
slouken@5373
   903
SDL_GetWindowDisplay(SDL_Window * window)
slouken@5246
   904
{
slouken@5246
   905
    int displayIndex;
slouken@5246
   906
    int i, dist;
slouken@5246
   907
    int closest = -1;
slouken@5246
   908
    int closest_dist = 0x7FFFFFFF;
slouken@5246
   909
    SDL_Point center;
slouken@5246
   910
    SDL_Point delta;
slouken@5246
   911
    SDL_Rect rect;
slouken@5246
   912
slouken@5246
   913
    CHECK_WINDOW_MAGIC(window, -1);
slouken@5246
   914
slouken@5246
   915
    if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
slouken@5246
   916
        SDL_WINDOWPOS_ISCENTERED(window->x)) {
slouken@5246
   917
        displayIndex = (window->x & 0xFFFF);
slouken@5246
   918
        if (displayIndex >= _this->num_displays) {
slouken@5246
   919
            displayIndex = 0;
slouken@5246
   920
        }
slouken@5246
   921
        return displayIndex;
slouken@5246
   922
    }
slouken@5246
   923
    if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
slouken@5246
   924
        SDL_WINDOWPOS_ISCENTERED(window->y)) {
slouken@5246
   925
        displayIndex = (window->y & 0xFFFF);
slouken@5246
   926
        if (displayIndex >= _this->num_displays) {
slouken@5246
   927
            displayIndex = 0;
slouken@5246
   928
        }
slouken@5246
   929
        return displayIndex;
slouken@5246
   930
    }
slouken@5246
   931
slouken@5246
   932
    /* Find the display containing the window */
slouken@5246
   933
    center.x = window->x + window->w / 2;
slouken@5246
   934
    center.y = window->y + window->h / 2;
slouken@5246
   935
    for (i = 0; i < _this->num_displays; ++i) {
slouken@5246
   936
        SDL_VideoDisplay *display = &_this->displays[i];
slouken@5246
   937
slouken@5246
   938
        SDL_GetDisplayBounds(i, &rect);
slouken@5246
   939
        if (display->fullscreen_window == window || SDL_EnclosePoints(&center, 1, &rect, NULL)) {
slouken@5246
   940
            return i;
slouken@5246
   941
        }
slouken@5246
   942
slouken@5246
   943
        delta.x = center.x - (rect.x + rect.w / 2);
slouken@5246
   944
        delta.y = center.y - (rect.y + rect.h / 2);
slouken@5246
   945
        dist = (delta.x*delta.x + delta.y*delta.y);
slouken@5246
   946
        if (dist < closest_dist) {
slouken@5246
   947
            closest = i;
slouken@5246
   948
            closest_dist = dist;
slouken@5246
   949
        }
slouken@5246
   950
    }
slouken@5246
   951
    if (closest < 0) {
slouken@5246
   952
        SDL_SetError("Couldn't find any displays");
slouken@5246
   953
    }
slouken@5246
   954
    return closest;
slouken@5246
   955
}
slouken@5246
   956
slouken@5246
   957
SDL_VideoDisplay *
slouken@5246
   958
SDL_GetDisplayForWindow(SDL_Window *window)
slouken@5246
   959
{
slouken@5373
   960
    int displayIndex = SDL_GetWindowDisplay(window);
slouken@5373
   961
    if (displayIndex >= 0) {
slouken@5373
   962
        return &_this->displays[displayIndex];
slouken@5373
   963
    } else {
slouken@5373
   964
        return NULL;
slouken@5373
   965
    }
slouken@5246
   966
}
slouken@5246
   967
slouken@5246
   968
int
slouken@3685
   969
SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
slouken@3500
   970
{
slouken@3695
   971
    CHECK_WINDOW_MAGIC(window, -1);
slouken@3500
   972
slouken@2753
   973
    if (mode) {
slouken@3500
   974
        window->fullscreen_mode = *mode;
slouken@3500
   975
    } else {
slouken@3500
   976
        SDL_zero(window->fullscreen_mode);
slouken@3500
   977
    }
slouken@3526
   978
    return 0;
slouken@3500
   979
}
slouken@3500
   980
slouken@3500
   981
int
slouken@3685
   982
SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
slouken@3500
   983
{
slouken@3500
   984
    SDL_DisplayMode fullscreen_mode;
slouken@3500
   985
slouken@3695
   986
    CHECK_WINDOW_MAGIC(window, -1);
slouken@3500
   987
slouken@3500
   988
    fullscreen_mode = window->fullscreen_mode;
slouken@3500
   989
    if (!fullscreen_mode.w) {
slouken@3500
   990
        fullscreen_mode.w = window->w;
slouken@3500
   991
    }
slouken@3500
   992
    if (!fullscreen_mode.h) {
slouken@3500
   993
        fullscreen_mode.h = window->h;
slouken@3500
   994
    }
slouken@3500
   995
slouken@5246
   996
    if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
slouken@3500
   997
                                             &fullscreen_mode,
slouken@3500
   998
                                             &fullscreen_mode)) {
slouken@3500
   999
        SDL_SetError("Couldn't find display mode match");
slouken@3500
  1000
        return -1;
slouken@3500
  1001
    }
slouken@3500
  1002
slouken@3500
  1003
    if (mode) {
slouken@3500
  1004
        *mode = fullscreen_mode;
slouken@2753
  1005
    }
slouken@2753
  1006
    return 0;
slouken@0
  1007
}
slouken@0
  1008
slouken@5154
  1009
Uint32
slouken@5154
  1010
SDL_GetWindowPixelFormat(SDL_Window * window)
slouken@5154
  1011
{
slouken@5246
  1012
    SDL_VideoDisplay *display;
slouken@5246
  1013
slouken@5246
  1014
    CHECK_WINDOW_MAGIC(window, SDL_PIXELFORMAT_UNKNOWN);
slouken@5246
  1015
slouken@5246
  1016
    display = SDL_GetDisplayForWindow(window);
slouken@5246
  1017
    return display->current_mode.format;
slouken@5154
  1018
}
slouken@5154
  1019
slouken@3502
  1020
static void
slouken@5404
  1021
SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
slouken@3502
  1022
{
slouken@5246
  1023
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5249
  1024
    SDL_Window *other;
slouken@3502
  1025
slouken@5404
  1026
    if (fullscreen) {
slouken@3502
  1027
        /* Hide any other fullscreen windows */
slouken@5249
  1028
        if (display->fullscreen_window &&
slouken@5249
  1029
            display->fullscreen_window != window) {
slouken@5246
  1030
            SDL_MinimizeWindow(display->fullscreen_window);
slouken@3502
  1031
        }
slouken@3502
  1032
    }
slouken@3502
  1033
slouken@5305
  1034
    /* See if anything needs to be done now */
slouken@5404
  1035
    if ((display->fullscreen_window == window) == fullscreen) {
slouken@5305
  1036
        return;
slouken@5305
  1037
    }
slouken@5305
  1038
slouken@5249
  1039
    /* See if there are any fullscreen windows */
slouken@5249
  1040
    for (other = _this->windows; other; other = other->next) {
slouken@5404
  1041
        SDL_bool setDisplayMode = SDL_FALSE;
slouken@5404
  1042
slouken@5404
  1043
        if (other == window) {
slouken@5404
  1044
            setDisplayMode = fullscreen;
slouken@5404
  1045
        } else if (FULLSCREEN_VISIBLE(other) &&
slouken@5404
  1046
                   SDL_GetDisplayForWindow(other) == display) {
slouken@5404
  1047
            setDisplayMode = SDL_TRUE;
slouken@5404
  1048
        }
slouken@5404
  1049
slouken@5404
  1050
        if (setDisplayMode) {
slouken@5249
  1051
            SDL_DisplayMode fullscreen_mode;
slouken@5404
  1052
slouken@5249
  1053
            if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
slouken@5306
  1054
                SDL_bool resized = SDL_TRUE;
slouken@5306
  1055
slouken@5306
  1056
                if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
slouken@5306
  1057
                    resized = SDL_FALSE;
slouken@5249
  1058
                }
slouken@3502
  1059
slouken@3502
  1060
                SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
slouken@5249
  1061
                if (_this->SetWindowFullscreen) {
slouken@5305
  1062
                    _this->SetWindowFullscreen(_this, other, display, SDL_TRUE);
slouken@5249
  1063
                }
slouken@5249
  1064
                display->fullscreen_window = other;
slouken@5249
  1065
slouken@5306
  1066
                /* Generate a mode change event here */
slouken@5306
  1067
                if (resized) {
slouken@5306
  1068
                    SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
slouken@5306
  1069
                                        fullscreen_mode.w, fullscreen_mode.h);
slouken@5306
  1070
                } else {
slouken@5306
  1071
                    SDL_OnWindowResized(other);
slouken@5306
  1072
                }
slouken@3502
  1073
                return;
slouken@3502
  1074
            }
slouken@3502
  1075
        }
slouken@3502
  1076
    }
slouken@3502
  1077
slouken@3502
  1078
    /* Nope, restore the desktop mode */
slouken@3502
  1079
    SDL_SetDisplayModeForDisplay(display, NULL);
slouken@5249
  1080
slouken@5249
  1081
    if (_this->SetWindowFullscreen) {
slouken@5305
  1082
        _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
slouken@5249
  1083
    }
slouken@3517
  1084
    display->fullscreen_window = NULL;
slouken@5306
  1085
slouken@5306
  1086
    /* Generate a mode change event here */
slouken@5306
  1087
    SDL_OnWindowResized(window);
slouken@3502
  1088
}
slouken@3502
  1089
slouken@5380
  1090
#define CREATE_FLAGS \
slouken@5380
  1091
    (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE)
slouken@5380
  1092
slouken@5380
  1093
static void
slouken@5380
  1094
SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
slouken@5380
  1095
{
slouken@5398
  1096
    window->windowed.x = window->x;
slouken@5398
  1097
    window->windowed.y = window->y;
slouken@5398
  1098
    window->windowed.w = window->w;
slouken@5398
  1099
    window->windowed.h = window->h;
slouken@5398
  1100
slouken@5380
  1101
    if (flags & SDL_WINDOW_MAXIMIZED) {
slouken@5380
  1102
        SDL_MaximizeWindow(window);
slouken@5380
  1103
    }
slouken@5380
  1104
    if (flags & SDL_WINDOW_MINIMIZED) {
slouken@5380
  1105
        SDL_MinimizeWindow(window);
slouken@5380
  1106
    }
slouken@5380
  1107
    if (flags & SDL_WINDOW_FULLSCREEN) {
slouken@5380
  1108
        SDL_SetWindowFullscreen(window, SDL_TRUE);
slouken@5380
  1109
    }
slouken@5380
  1110
    if (flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@5380
  1111
        SDL_SetWindowGrab(window, SDL_TRUE);
slouken@5380
  1112
    }
slouken@5380
  1113
    if (!(flags & SDL_WINDOW_HIDDEN)) {
slouken@5380
  1114
        SDL_ShowWindow(window);
slouken@5380
  1115
    }
slouken@5380
  1116
}
slouken@5380
  1117
slouken@3685
  1118
SDL_Window *
slouken@1895
  1119
SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
slouken@0
  1120
{
slouken@3685
  1121
    SDL_Window *window;
slouken@0
  1122
slouken@2753
  1123
    if (!_this) {
slouken@3417
  1124
        /* Initialize the video system if needed */
slouken@5123
  1125
        if (SDL_VideoInit(NULL) < 0) {
slouken@3685
  1126
            return NULL;
slouken@3417
  1127
        }
slouken@2753
  1128
    }
slouken@5249
  1129
slouken@5249
  1130
    /* Some platforms have OpenGL enabled by default */
slouken@5249
  1131
#if (SDL_VIDEO_OPENGL && __MACOSX__) || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@5249
  1132
    flags |= SDL_WINDOW_OPENGL;
slouken@5249
  1133
#endif
slouken@5423
  1134
#ifdef __NDS__
slouken@5423
  1135
	/* Always for Nintendo DS. */
slouken@5423
  1136
	flags |= SDL_WINDOW_FULLSCREEN;
slouken@5423
  1137
#endif
slouken@3057
  1138
    if (flags & SDL_WINDOW_OPENGL) {
slouken@3057
  1139
        if (!_this->GL_CreateContext) {
slouken@3057
  1140
            SDL_SetError("No OpenGL support in video driver");
slouken@3685
  1141
            return NULL;
slouken@3057
  1142
        }
slouken@3057
  1143
        SDL_GL_LoadLibrary(NULL);
slouken@2753
  1144
    }
slouken@3685
  1145
    window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
slouken@3695
  1146
    window->magic = &_this->window_magic;
slouken@3685
  1147
    window->id = _this->next_object_id++;
slouken@3685
  1148
    window->x = x;
slouken@3685
  1149
    window->y = y;
slouken@3685
  1150
    window->w = w;
slouken@3685
  1151
    window->h = h;
slouken@5380
  1152
    if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
slouken@5380
  1153
        SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
slouken@5380
  1154
        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5380
  1155
        int displayIndex;
slouken@5380
  1156
        SDL_Rect bounds;
slouken@5380
  1157
slouken@5380
  1158
        displayIndex = SDL_GetIndexOfDisplay(display);
slouken@5380
  1159
        SDL_GetDisplayBounds(displayIndex, &bounds);
slouken@5404
  1160
        if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
slouken@5380
  1161
            window->x = bounds.x + (bounds.w - w) / 2;
slouken@5380
  1162
        }
slouken@5380
  1163
        if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
slouken@5380
  1164
            window->y = bounds.y + (bounds.h - h) / 2;
slouken@5380
  1165
        }
slouken@5380
  1166
    }
slouken@5380
  1167
    window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
slouken@5246
  1168
    window->next = _this->windows;
slouken@5246
  1169
    if (_this->windows) {
slouken@5246
  1170
        _this->windows->prev = window;
slouken@3693
  1171
    }
slouken@5246
  1172
    _this->windows = window;
slouken@3685
  1173
slouken@3685
  1174
    if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
slouken@3685
  1175
        SDL_DestroyWindow(window);
slouken@3685
  1176
        return NULL;
slouken@3685
  1177
    }
slouken@0
  1178
slouken@2753
  1179
    if (title) {
slouken@3685
  1180
        SDL_SetWindowTitle(window, title);
slouken@2753
  1181
    }
slouken@5380
  1182
    SDL_FinishWindowCreation(window, flags);
slouken@3685
  1183
slouken@3685
  1184
    return window;
slouken@1895
  1185
}
slouken@0
  1186
slouken@3685
  1187
SDL_Window *
slouken@1895
  1188
SDL_CreateWindowFrom(const void *data)
slouken@1895
  1189
{
slouken@3685
  1190
    SDL_Window *window;
slouken@0
  1191
slouken@2753
  1192
    if (!_this) {
slouken@2753
  1193
        SDL_UninitializedVideo();
slouken@3685
  1194
        return NULL;
slouken@3685
  1195
    }
slouken@3685
  1196
    window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
slouken@3695
  1197
    window->magic = &_this->window_magic;
slouken@3685
  1198
    window->id = _this->next_object_id++;
slouken@3685
  1199
    window->flags = SDL_WINDOW_FOREIGN;
slouken@5246
  1200
    window->next = _this->windows;
slouken@5246
  1201
    if (_this->windows) {
slouken@5246
  1202
        _this->windows->prev = window;
slouken@3693
  1203
    }
slouken@5246
  1204
    _this->windows = window;
slouken@1895
  1205
slouken@2753
  1206
    if (!_this->CreateWindowFrom ||
slouken@3685
  1207
        _this->CreateWindowFrom(_this, window, data) < 0) {
slouken@3685
  1208
        SDL_DestroyWindow(window);
slouken@3685
  1209
        return NULL;
slouken@3685
  1210
    }
slouken@3685
  1211
    return window;
slouken@1895
  1212
}
slouken@1895
  1213
slouken@1924
  1214
int
slouken@1928
  1215
SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
slouken@1924
  1216
{
slouken@2753
  1217
    char *title = window->title;
slouken@1956
  1218
slouken@2753
  1219
    if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
slouken@2753
  1220
        SDL_SetError("No OpenGL support in video driver");
slouken@2753
  1221
        return -1;
slouken@2753
  1222
    }
slouken@3057
  1223
slouken@3057
  1224
    if (window->flags & SDL_WINDOW_FOREIGN) {
slouken@3057
  1225
        /* Can't destroy and re-create foreign windows, hrm */
slouken@3057
  1226
        flags |= SDL_WINDOW_FOREIGN;
slouken@3057
  1227
    } else {
slouken@3057
  1228
        flags &= ~SDL_WINDOW_FOREIGN;
slouken@3057
  1229
    }
slouken@3057
  1230
slouken@5249
  1231
    /* Restore video mode, etc. */
slouken@5305
  1232
    SDL_HideWindow(window);
slouken@5249
  1233
slouken@5249
  1234
    /* Tear down the old native window */
slouken@5249
  1235
    if (window->surface) {
slouken@5288
  1236
        window->surface->flags &= ~SDL_DONTFREE;
slouken@5249
  1237
        SDL_FreeSurface(window->surface);
slouken@5249
  1238
    }
slouken@5249
  1239
    if (_this->DestroyWindowFramebuffer) {
slouken@5249
  1240
        _this->DestroyWindowFramebuffer(_this, window);
slouken@5249
  1241
    }
slouken@3057
  1242
    if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
slouken@2753
  1243
        _this->DestroyWindow(_this, window);
slouken@2753
  1244
    }
slouken@3057
  1245
slouken@5249
  1246
    if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
slouken@5249
  1247
        if (flags & SDL_WINDOW_OPENGL) {
slouken@5249
  1248
            SDL_GL_LoadLibrary(NULL);
slouken@5249
  1249
        } else {
slouken@5249
  1250
            SDL_GL_UnloadLibrary();
slouken@5249
  1251
        }
slouken@5249
  1252
    }
slouken@5249
  1253
slouken@2753
  1254
    window->title = NULL;
slouken@5380
  1255
    window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
slouken@1956
  1256
slouken@3057
  1257
    if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
slouken@3057
  1258
        if (_this->CreateWindow(_this, window) < 0) {
slouken@3057
  1259
            if (flags & SDL_WINDOW_OPENGL) {
slouken@3057
  1260
                SDL_GL_UnloadLibrary();
slouken@3057
  1261
            }
slouken@3057
  1262
            return -1;
slouken@3057
  1263
        }
slouken@2753
  1264
    }
slouken@3057
  1265
slouken@2753
  1266
    if (title) {
slouken@3685
  1267
        SDL_SetWindowTitle(window, title);
slouken@2753
  1268
        SDL_free(title);
slouken@2753
  1269
    }
slouken@5380
  1270
    SDL_FinishWindowCreation(window, flags);
slouken@2875
  1271
slouken@2753
  1272
    return 0;
slouken@1924
  1273
}
slouken@1924
  1274
slouken@1895
  1275
Uint32
slouken@3685
  1276
SDL_GetWindowID(SDL_Window * window)
slouken@1895
  1277
{
slouken@3695
  1278
    CHECK_WINDOW_MAGIC(window, 0);
slouken@3695
  1279
slouken@3685
  1280
    return window->id;
slouken@3685
  1281
}
slouken@3685
  1282
slouken@3685
  1283
SDL_Window *
slouken@3685
  1284
SDL_GetWindowFromID(Uint32 id)
slouken@3685
  1285
{
slouken@3685
  1286
    SDL_Window *window;
slouken@3685
  1287
slouken@3685
  1288
    if (!_this) {
slouken@3685
  1289
        return NULL;
slouken@3685
  1290
    }
slouken@5246
  1291
    for (window = _this->windows; window; window = window->next) {
slouken@5246
  1292
        if (window->id == id) {
slouken@5246
  1293
            return window;
slouken@3685
  1294
        }
slouken@3685
  1295
    }
slouken@3685
  1296
    return NULL;
slouken@3685
  1297
}
slouken@3685
  1298
slouken@3685
  1299
Uint32
slouken@3685
  1300
SDL_GetWindowFlags(SDL_Window * window)
slouken@3685
  1301
{
slouken@3695
  1302
    CHECK_WINDOW_MAGIC(window, 0);
slouken@3695
  1303
slouken@2753
  1304
    return window->flags;
slouken@1895
  1305
}
slouken@1895
  1306
slouken@1895
  1307
void
slouken@3685
  1308
SDL_SetWindowTitle(SDL_Window * window, const char *title)
slouken@1895
  1309
{
slouken@3695
  1310
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1311
slouken@3695
  1312
    if (title == window->title) {
slouken@2753
  1313
        return;
slouken@2753
  1314
    }
slouken@2753
  1315
    if (window->title) {
slouken@2753
  1316
        SDL_free(window->title);
slouken@2753
  1317
    }
slouken@4871
  1318
    if (title && *title) {
slouken@2753
  1319
        window->title = SDL_strdup(title);
slouken@2753
  1320
    } else {
slouken@2753
  1321
        window->title = NULL;
slouken@2753
  1322
    }
slouken@1956
  1323
slouken@2753
  1324
    if (_this->SetWindowTitle) {
slouken@2753
  1325
        _this->SetWindowTitle(_this, window);
slouken@2753
  1326
    }
slouken@1895
  1327
}
slouken@1895
  1328
slouken@2753
  1329
const char *
slouken@3685
  1330
SDL_GetWindowTitle(SDL_Window * window)
slouken@1895
  1331
{
slouken@4872
  1332
    CHECK_WINDOW_MAGIC(window, "");
slouken@3695
  1333
slouken@4871
  1334
    return window->title ? window->title : "";
slouken@1895
  1335
}
slouken@1895
  1336
slouken@1895
  1337
void
slouken@3685
  1338
SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
slouken@2967
  1339
{
slouken@3695
  1340
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1341
slouken@5375
  1342
    if (!icon) {
slouken@5375
  1343
        return;
slouken@5375
  1344
    }
slouken@5375
  1345
slouken@2967
  1346
    if (_this->SetWindowIcon) {
slouken@2967
  1347
        _this->SetWindowIcon(_this, window, icon);
slouken@2967
  1348
    }
slouken@2967
  1349
}
slouken@2967
  1350
slouken@5165
  1351
void*
slouken@5165
  1352
SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
slouken@1895
  1353
{
slouken@5165
  1354
    SDL_WindowUserData *prev, *data;
slouken@3695
  1355
slouken@5165
  1356
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@5165
  1357
slouken@5165
  1358
    /* See if the named data already exists */
slouken@5165
  1359
    prev = NULL;
slouken@5165
  1360
    for (data = window->data; data; prev = data, data = data->next) {
slouken@5165
  1361
        if (SDL_strcmp(data->name, name) == 0) {
slouken@5165
  1362
            void *last_value = data->data;
slouken@5165
  1363
slouken@5165
  1364
            if (userdata) {
slouken@5165
  1365
                /* Set the new value */
slouken@5165
  1366
                data->data = userdata;
slouken@5165
  1367
            } else {
slouken@5165
  1368
                /* Delete this value */
slouken@5165
  1369
                if (prev) {
slouken@5165
  1370
                    prev->next = data->next;
slouken@5165
  1371
                } else {
slouken@5165
  1372
                    window->data = data->next;
slouken@5165
  1373
                }
slouken@5165
  1374
                SDL_free(data->name);
slouken@5165
  1375
                SDL_free(data);
slouken@5165
  1376
            }
slouken@5165
  1377
            return last_value;
slouken@5165
  1378
        }
slouken@5165
  1379
    }
slouken@5165
  1380
slouken@5165
  1381
    /* Add new data to the window */
slouken@5165
  1382
    if (userdata) {
slouken@5165
  1383
        data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
slouken@5165
  1384
        data->name = SDL_strdup(name);
slouken@5165
  1385
        data->data = userdata;
slouken@5165
  1386
        data->next = window->data;
slouken@5165
  1387
        window->data = data;
slouken@5165
  1388
    }
slouken@5165
  1389
    return NULL;
slouken@1895
  1390
}
slouken@1895
  1391
slouken@2753
  1392
void *
slouken@5165
  1393
SDL_GetWindowData(SDL_Window * window, const char *name)
slouken@1895
  1394
{
slouken@5165
  1395
    SDL_WindowUserData *data;
slouken@5165
  1396
slouken@3695
  1397
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@3695
  1398
slouken@5165
  1399
    for (data = window->data; data; data = data->next) {
slouken@5165
  1400
        if (SDL_strcmp(data->name, name) == 0) {
slouken@5165
  1401
            return data->data;
slouken@5165
  1402
        }
slouken@5165
  1403
    }
slouken@5165
  1404
    return NULL;
slouken@1895
  1405
}
slouken@1895
  1406
slouken@1895
  1407
void
slouken@3685
  1408
SDL_SetWindowPosition(SDL_Window * window, int x, int y)
slouken@1895
  1409
{
slouken@3695
  1410
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1411
slouken@5305
  1412
    if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
slouken@2753
  1413
        window->x = x;
slouken@2753
  1414
    }
slouken@5305
  1415
    if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
slouken@2753
  1416
        window->y = y;
slouken@2753
  1417
    }
slouken@5246
  1418
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@5246
  1419
        if (_this->SetWindowPosition) {
slouken@5246
  1420
            _this->SetWindowPosition(_this, window);
slouken@5246
  1421
        }
slouken@5246
  1422
        SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@2753
  1423
    }
slouken@1895
  1424
}
slouken@1895
  1425
slouken@1895
  1426
void
slouken@3685
  1427
SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
slouken@1895
  1428
{
slouken@5246
  1429
    /* Clear the values */
slouken@5246
  1430
    if (x) {
slouken@5246
  1431
        *x = 0;
slouken@5246
  1432
    }
slouken@5246
  1433
    if (y) {
slouken@5246
  1434
        *y = 0;
slouken@5246
  1435
    }
slouken@5246
  1436
slouken@5246
  1437
    CHECK_WINDOW_MAGIC(window, );
slouken@5246
  1438
slouken@5246
  1439
    /* Fullscreen windows are always at their display's origin */
slouken@5246
  1440
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@5246
  1441
    } else {
slouken@5242
  1442
        if (x) {
slouken@5242
  1443
            *x = window->x;
slouken@5242
  1444
        }
slouken@5242
  1445
        if (y) {
slouken@5242
  1446
            *y = window->y;
slouken@5242
  1447
        }
slouken@2753
  1448
    }
slouken@1895
  1449
}
slouken@1895
  1450
slouken@1895
  1451
void
slouken@3685
  1452
SDL_SetWindowSize(SDL_Window * window, int w, int h)
slouken@1895
  1453
{
slouken@3695
  1454
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1455
slouken@5249
  1456
    /* FIXME: Should this change fullscreen modes? */
slouken@5249
  1457
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@5276
  1458
        window->w = w;
slouken@5276
  1459
        window->h = h;
slouken@5249
  1460
        if (_this->SetWindowSize) {
slouken@5249
  1461
            _this->SetWindowSize(_this, window);
slouken@5249
  1462
        }
slouken@5276
  1463
        if (window->w == w && window->h == h) {
slouken@5276
  1464
            /* We didn't get a SDL_WINDOWEVENT_RESIZED event (by design) */
slouken@5276
  1465
            SDL_OnWindowResized(window);
slouken@5276
  1466
        }
slouken@2753
  1467
    }
slouken@1895
  1468
}
slouken@1895
  1469
slouken@1895
  1470
void
slouken@3685
  1471
SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
slouken@1895
  1472
{
slouken@5246
  1473
    int dummy;
slouken@5246
  1474
slouken@5246
  1475
    if (!w) {
slouken@5246
  1476
        w = &dummy;
slouken@5246
  1477
    }
slouken@5246
  1478
    if (!h) {
slouken@5246
  1479
        h = &dummy;
slouken@5246
  1480
    }
slouken@5246
  1481
slouken@5246
  1482
    *w = 0;
slouken@5246
  1483
    *h = 0;
slouken@5246
  1484
slouken@5246
  1485
    CHECK_WINDOW_MAGIC(window, );
slouken@5246
  1486
slouken@5242
  1487
    if (_this && window && window->magic == &_this->window_magic) {
slouken@2849
  1488
        if (w) {
slouken@2849
  1489
            *w = window->w;
slouken@2849
  1490
        }
slouken@2849
  1491
        if (h) {
slouken@2849
  1492
            *h = window->h;
slouken@2849
  1493
        }
slouken@2849
  1494
    } else {
slouken@2849
  1495
        if (w) {
slouken@2849
  1496
            *w = 0;
slouken@2849
  1497
        }
slouken@2849
  1498
        if (h) {
slouken@2849
  1499
            *h = 0;
slouken@2849
  1500
        }
slouken@2753
  1501
    }
slouken@1895
  1502
}
slouken@1895
  1503
slouken@1895
  1504
void
slouken@3685
  1505
SDL_ShowWindow(SDL_Window * window)
slouken@1895
  1506
{
slouken@3695
  1507
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1508
slouken@3695
  1509
    if (window->flags & SDL_WINDOW_SHOWN) {
slouken@2753
  1510
        return;
slouken@2753
  1511
    }
slouken@1895
  1512
slouken@2753
  1513
    if (_this->ShowWindow) {
slouken@2753
  1514
        _this->ShowWindow(_this, window);
slouken@2753
  1515
    }
slouken@3685
  1516
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@1895
  1517
}
slouken@1895
  1518
slouken@1895
  1519
void
slouken@3685
  1520
SDL_HideWindow(SDL_Window * window)
slouken@1895
  1521
{
slouken@3695
  1522
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1523
slouken@3695
  1524
    if (!(window->flags & SDL_WINDOW_SHOWN)) {
slouken@2753
  1525
        return;
slouken@2753
  1526
    }
slouken@1895
  1527
slouken@5404
  1528
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@5404
  1529
slouken@2753
  1530
    if (_this->HideWindow) {
slouken@2753
  1531
        _this->HideWindow(_this, window);
slouken@2753
  1532
    }
slouken@3685
  1533
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@1895
  1534
}
slouken@1895
  1535
slouken@1895
  1536
void
slouken@3685
  1537
SDL_RaiseWindow(SDL_Window * window)
slouken@1895
  1538
{
slouken@3695
  1539
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1540
slouken@3695
  1541
    if (!(window->flags & SDL_WINDOW_SHOWN)) {
slouken@2753
  1542
        return;
slouken@2753
  1543
    }
slouken@2753
  1544
    if (_this->RaiseWindow) {
slouken@2753
  1545
        _this->RaiseWindow(_this, window);
slouken@2753
  1546
    }
slouken@1895
  1547
}
slouken@1895
  1548
slouken@1895
  1549
void
slouken@3685
  1550
SDL_MaximizeWindow(SDL_Window * window)
slouken@1895
  1551
{
slouken@3695
  1552
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1553
slouken@3695
  1554
    if (window->flags & SDL_WINDOW_MAXIMIZED) {
slouken@2753
  1555
        return;
slouken@2753
  1556
    }
slouken@1895
  1557
slouken@2753
  1558
    if (_this->MaximizeWindow) {
slouken@2753
  1559
        _this->MaximizeWindow(_this, window);
slouken@2753
  1560
    }
slouken@1895
  1561
}
slouken@1895
  1562
slouken@1895
  1563
void
slouken@3685
  1564
SDL_MinimizeWindow(SDL_Window * window)
slouken@1895
  1565
{
slouken@3695
  1566
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1567
slouken@3695
  1568
    if (window->flags & SDL_WINDOW_MINIMIZED) {
slouken@2753
  1569
        return;
slouken@2753
  1570
    }
slouken@1895
  1571
slouken@5404
  1572
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@5404
  1573
slouken@2753
  1574
    if (_this->MinimizeWindow) {
slouken@2753
  1575
        _this->MinimizeWindow(_this, window);
slouken@2753
  1576
    }
slouken@1895
  1577
}
slouken@1895
  1578
slouken@1895
  1579
void
slouken@3685
  1580
SDL_RestoreWindow(SDL_Window * window)
slouken@1895
  1581
{
slouken@3695
  1582
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1583
slouken@3695
  1584
    if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
slouken@2753
  1585
        return;
slouken@2753
  1586
    }
slouken@1895
  1587
slouken@2753
  1588
    if (_this->RestoreWindow) {
slouken@2753
  1589
        _this->RestoreWindow(_this, window);
slouken@2753
  1590
    }
slouken@1895
  1591
}
slouken@1895
  1592
slouken@1895
  1593
int
slouken@5246
  1594
SDL_SetWindowFullscreen(SDL_Window * window, SDL_bool fullscreen)
slouken@1895
  1595
{
slouken@3695
  1596
    CHECK_WINDOW_MAGIC(window, -1);
slouken@3695
  1597
slouken@5404
  1598
    if (!!fullscreen == !!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@2753
  1599
        return 0;
slouken@2753
  1600
    }
slouken@2753
  1601
    if (fullscreen) {
slouken@2753
  1602
        window->flags |= SDL_WINDOW_FULLSCREEN;
slouken@2753
  1603
    } else {
slouken@2753
  1604
        window->flags &= ~SDL_WINDOW_FULLSCREEN;
slouken@5305
  1605
    }
slouken@5404
  1606
    SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
slouken@1895
  1607
slouken@2753
  1608
    return 0;
slouken@1895
  1609
}
slouken@1895
  1610
slouken@5166
  1611
static SDL_Surface *
slouken@5166
  1612
SDL_CreateWindowFramebuffer(SDL_Window * window)
slouken@5166
  1613
{
slouken@5166
  1614
    Uint32 format;
slouken@5166
  1615
    void *pixels;
slouken@5166
  1616
    int pitch;
slouken@5166
  1617
    int bpp;
slouken@5166
  1618
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@5166
  1619
slouken@5166
  1620
    if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
slouken@5166
  1621
        return NULL;
slouken@5166
  1622
    }
slouken@5166
  1623
slouken@5166
  1624
    if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
slouken@5166
  1625
        return NULL;
slouken@5166
  1626
    }
slouken@5166
  1627
slouken@5166
  1628
    if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@5166
  1629
        return NULL;
slouken@5166
  1630
    }
slouken@5166
  1631
slouken@5166
  1632
    return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
slouken@5166
  1633
}
slouken@5166
  1634
slouken@5166
  1635
SDL_Surface *
slouken@5166
  1636
SDL_GetWindowSurface(SDL_Window * window)
slouken@5166
  1637
{
slouken@5166
  1638
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@5166
  1639
slouken@5172
  1640
    if (!window->surface_valid) {
slouken@5172
  1641
        if (window->surface) {
slouken@5288
  1642
            window->surface->flags &= ~SDL_DONTFREE;
slouken@5172
  1643
            SDL_FreeSurface(window->surface);
slouken@5172
  1644
        }
slouken@5166
  1645
        window->surface = SDL_CreateWindowFramebuffer(window);
slouken@5169
  1646
        if (window->surface) {
slouken@5172
  1647
            window->surface_valid = SDL_TRUE;
slouken@5288
  1648
            window->surface->flags |= SDL_DONTFREE;
slouken@5169
  1649
        }
slouken@5166
  1650
    }
slouken@5166
  1651
    return window->surface;
slouken@5166
  1652
}
slouken@5166
  1653
slouken@5166
  1654
int
slouken@5166
  1655
SDL_UpdateWindowSurface(SDL_Window * window)
slouken@5166
  1656
{
slouken@5166
  1657
    SDL_Rect full_rect;
slouken@5166
  1658
slouken@5166
  1659
    CHECK_WINDOW_MAGIC(window, -1);
slouken@5166
  1660
slouken@5166
  1661
    full_rect.x = 0;
slouken@5166
  1662
    full_rect.y = 0;
slouken@5166
  1663
    full_rect.w = window->w;
slouken@5166
  1664
    full_rect.h = window->h;
slouken@5297
  1665
    return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
slouken@5166
  1666
}
slouken@5166
  1667
slouken@5166
  1668
int
slouken@5297
  1669
SDL_UpdateWindowSurfaceRects(SDL_Window * window, SDL_Rect * rects,
slouken@5297
  1670
                             int numrects)
slouken@5166
  1671
{
slouken@5166
  1672
    CHECK_WINDOW_MAGIC(window, -1);
slouken@5166
  1673
slouken@5172
  1674
    if (!window->surface_valid) {
slouken@5166
  1675
        SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
slouken@5166
  1676
        return -1;
slouken@5166
  1677
    }
slouken@5166
  1678
slouken@5297
  1679
    return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
slouken@5166
  1680
}
slouken@5166
  1681
slouken@2875
  1682
static void
slouken@2876
  1683
SDL_UpdateWindowGrab(SDL_Window * window)
slouken@2875
  1684
{
slouken@2753
  1685
    if ((window->flags & SDL_WINDOW_INPUT_FOCUS) && _this->SetWindowGrab) {
slouken@2753
  1686
        _this->SetWindowGrab(_this, window);
slouken@2753
  1687
    }
slouken@1895
  1688
}
slouken@1895
  1689
slouken@5403
  1690
void
slouken@5403
  1691
SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
slouken@5403
  1692
{
slouken@5403
  1693
    CHECK_WINDOW_MAGIC(window, );
slouken@5403
  1694
slouken@5404
  1695
    if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
slouken@5403
  1696
        return;
slouken@5403
  1697
    }
slouken@5403
  1698
    if (grabbed) {
slouken@5403
  1699
        window->flags |= SDL_WINDOW_INPUT_GRABBED;
slouken@5403
  1700
    } else {
slouken@5403
  1701
        window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
slouken@5403
  1702
    }
slouken@5403
  1703
    SDL_UpdateWindowGrab(window);
slouken@5403
  1704
}
slouken@5403
  1705
slouken@5403
  1706
SDL_bool
slouken@3685
  1707
SDL_GetWindowGrab(SDL_Window * window)
slouken@1895
  1708
{
slouken@3695
  1709
    CHECK_WINDOW_MAGIC(window, 0);
slouken@3695
  1710
slouken@2753
  1711
    return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
slouken@1895
  1712
}
slouken@1895
  1713
slouken@1895
  1714
void
slouken@1895
  1715
SDL_OnWindowShown(SDL_Window * window)
slouken@1895
  1716
{
slouken@5404
  1717
    SDL_OnWindowRestored(window);
slouken@1895
  1718
}
slouken@1895
  1719
slouken@1895
  1720
void
slouken@1895
  1721
SDL_OnWindowHidden(SDL_Window * window)
slouken@1895
  1722
{
slouken@5404
  1723
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@1895
  1724
}
slouken@1895
  1725
slouken@1895
  1726
void
slouken@5166
  1727
SDL_OnWindowResized(SDL_Window * window)
slouken@5166
  1728
{
slouken@5172
  1729
    window->surface_valid = SDL_FALSE;
slouken@5276
  1730
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
slouken@5166
  1731
}
slouken@5166
  1732
slouken@5166
  1733
void
slouken@3502
  1734
SDL_OnWindowMinimized(SDL_Window * window)
slouken@3502
  1735
{
slouken@5404
  1736
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@3502
  1737
}
slouken@3502
  1738
slouken@3502
  1739
void
slouken@3502
  1740
SDL_OnWindowRestored(SDL_Window * window)
slouken@3502
  1741
{
slouken@3685
  1742
    SDL_RaiseWindow(window);
slouken@5404
  1743
slouken@5404
  1744
    if (FULLSCREEN_VISIBLE(window)) {
slouken@5404
  1745
        SDL_UpdateFullscreenMode(window, SDL_TRUE);
slouken@5404
  1746
    }
slouken@3502
  1747
}
slouken@3502
  1748
slouken@3502
  1749
void
slouken@1895
  1750
SDL_OnWindowFocusGained(SDL_Window * window)
slouken@1895
  1751
{
slouken@2876
  1752
    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
slouken@2876
  1753
        && _this->SetWindowGrab) {
slouken@2753
  1754
        _this->SetWindowGrab(_this, window);
slouken@2753
  1755
    }
slouken@1895
  1756
}
slouken@1895
  1757
slouken@1895
  1758
void
slouken@1895
  1759
SDL_OnWindowFocusLost(SDL_Window * window)
slouken@1895
  1760
{
slouken@3512
  1761
    /* If we're fullscreen on a single-head system and lose focus, minimize */
slouken@3512
  1762
    if ((window->flags & SDL_WINDOW_FULLSCREEN) &&
slouken@3512
  1763
        _this->num_displays == 1) {
slouken@3685
  1764
        SDL_MinimizeWindow(window);
slouken@3512
  1765
    }
slouken@3512
  1766
slouken@2876
  1767
    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
slouken@2876
  1768
        && _this->SetWindowGrab) {
slouken@2753
  1769
        _this->SetWindowGrab(_this, window);
slouken@2753
  1770
    }
slouken@1895
  1771
}
slouken@1895
  1772
slouken@3685
  1773
SDL_Window *
slouken@1895
  1774
SDL_GetFocusWindow(void)
slouken@1895
  1775
{
slouken@3685
  1776
    SDL_Window *window;
slouken@1895
  1777
slouken@2753
  1778
    if (!_this) {
slouken@3685
  1779
        return NULL;
slouken@3685
  1780
    }
slouken@5246
  1781
    for (window = _this->windows; window; window = window->next) {
slouken@2753
  1782
        if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
slouken@3685
  1783
            return window;
slouken@2753
  1784
        }
slouken@2753
  1785
    }
slouken@3685
  1786
    return NULL;
slouken@1895
  1787
}
slouken@1895
  1788
slouken@1895
  1789
void
slouken@3685
  1790
SDL_DestroyWindow(SDL_Window * window)
slouken@1895
  1791
{
slouken@3685
  1792
    SDL_VideoDisplay *display;
slouken@3685
  1793
slouken@3695
  1794
    CHECK_WINDOW_MAGIC(window, );
slouken@3503
  1795
slouken@3685
  1796
    /* Restore video mode, etc. */
slouken@5305
  1797
    SDL_HideWindow(window);
slouken@3685
  1798
slouken@5169
  1799
    if (window->surface) {
slouken@5288
  1800
        window->surface->flags &= ~SDL_DONTFREE;
slouken@5169
  1801
        SDL_FreeSurface(window->surface);
slouken@5169
  1802
    }
slouken@5166
  1803
    if (_this->DestroyWindowFramebuffer) {
slouken@5166
  1804
        _this->DestroyWindowFramebuffer(_this, window);
slouken@5166
  1805
    }
slouken@3685
  1806
    if (_this->DestroyWindow) {
slouken@3685
  1807
        _this->DestroyWindow(_this, window);
slouken@3685
  1808
    }
slouken@3685
  1809
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@3685
  1810
        SDL_GL_UnloadLibrary();
slouken@3685
  1811
    }
slouken@3685
  1812
slouken@5246
  1813
    display = SDL_GetDisplayForWindow(window);
slouken@5246
  1814
    if (display->fullscreen_window == window) {
slouken@5246
  1815
        display->fullscreen_window = NULL;
slouken@5246
  1816
    }
slouken@5246
  1817
slouken@4901
  1818
    /* Now invalidate magic */
slouken@4897
  1819
    window->magic = NULL;
slouken@4897
  1820
slouken@5165
  1821
    /* Free memory associated with the window */
slouken@5165
  1822
    if (window->title) {
slouken@5165
  1823
        SDL_free(window->title);
slouken@5165
  1824
    }
slouken@5165
  1825
    while (window->data) {
slouken@5165
  1826
        SDL_WindowUserData *data = window->data;
slouken@5165
  1827
slouken@5165
  1828
        window->data = data->next;
slouken@5165
  1829
        SDL_free(data->name);
slouken@5165
  1830
        SDL_free(data);
slouken@5165
  1831
    }
slouken@5165
  1832
slouken@3685
  1833
    /* Unlink the window from the list */
slouken@3693
  1834
    if (window->next) {
slouken@3693
  1835
        window->next->prev = window->prev;
slouken@3693
  1836
    }
slouken@3685
  1837
    if (window->prev) {
slouken@3685
  1838
        window->prev->next = window->next;
slouken@3685
  1839
    } else {
slouken@5246
  1840
        _this->windows = window->next;
slouken@3685
  1841
    }
slouken@3685
  1842
slouken@3685
  1843
    SDL_free(window);
slouken@1895
  1844
}
slouken@1895
  1845
slouken@3025
  1846
SDL_bool
slouken@3025
  1847
SDL_IsScreenSaverEnabled()
slouken@3025
  1848
{
slouken@3025
  1849
    if (!_this) {
slouken@3025
  1850
        return SDL_TRUE;
slouken@3025
  1851
    }
slouken@3025
  1852
    return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
slouken@3025
  1853
}
slouken@3025
  1854
slouken@3025
  1855
void
slouken@3025
  1856
SDL_EnableScreenSaver()
slouken@3025
  1857
{
slouken@3025
  1858
    if (!_this) {
slouken@3025
  1859
        return;
slouken@3025
  1860
    }
slouken@3025
  1861
    if (!_this->suspend_screensaver) {
slouken@3025
  1862
        return;
slouken@3025
  1863
    }
slouken@3025
  1864
    _this->suspend_screensaver = SDL_FALSE;
slouken@3025
  1865
    if (_this->SuspendScreenSaver) {
slouken@3025
  1866
        _this->SuspendScreenSaver(_this);
slouken@3025
  1867
    }
slouken@3025
  1868
}
slouken@3025
  1869
slouken@3025
  1870
void
slouken@3025
  1871
SDL_DisableScreenSaver()
slouken@3025
  1872
{
slouken@3025
  1873
    if (!_this) {
slouken@3025
  1874
        return;
slouken@3025
  1875
    }
slouken@3025
  1876
    if (_this->suspend_screensaver) {
slouken@3025
  1877
        return;
slouken@3025
  1878
    }
slouken@3025
  1879
    _this->suspend_screensaver = SDL_TRUE;
slouken@3025
  1880
    if (_this->SuspendScreenSaver) {
slouken@3025
  1881
        _this->SuspendScreenSaver(_this);
slouken@3025
  1882
    }
slouken@3025
  1883
}
slouken@3025
  1884
slouken@1895
  1885
void
slouken@1895
  1886
SDL_VideoQuit(void)
slouken@1895
  1887
{
slouken@2753
  1888
    int i, j;
slouken@1895
  1889
slouken@2753
  1890
    if (!_this) {
slouken@2753
  1891
        return;
slouken@2753
  1892
    }
slouken@5123
  1893
slouken@2753
  1894
    /* Halt event processing before doing anything else */
slouken@5123
  1895
    SDL_QuitQuit();
slouken@5123
  1896
    SDL_MouseQuit();
slouken@5123
  1897
    SDL_KeyboardQuit();
slouken@2753
  1898
    SDL_StopEventLoop();
slouken@5123
  1899
slouken@3029
  1900
    SDL_EnableScreenSaver();
slouken@1895
  1901
slouken@2753
  1902
    /* Clean up the system video */
slouken@5246
  1903
    while (_this->windows) {
slouken@5246
  1904
        SDL_DestroyWindow(_this->windows);
slouken@2753
  1905
    }
slouken@2753
  1906
    _this->VideoQuit(_this);
slouken@1895
  1907
slouken@2753
  1908
    for (i = _this->num_displays; i--;) {
slouken@2753
  1909
        SDL_VideoDisplay *display = &_this->displays[i];
slouken@2753
  1910
        for (j = display->num_display_modes; j--;) {
slouken@2753
  1911
            if (display->display_modes[j].driverdata) {
slouken@2753
  1912
                SDL_free(display->display_modes[j].driverdata);
slouken@2753
  1913
                display->display_modes[j].driverdata = NULL;
slouken@2753
  1914
            }
slouken@2753
  1915
        }
slouken@2753
  1916
        if (display->display_modes) {
slouken@2753
  1917
            SDL_free(display->display_modes);
slouken@2753
  1918
            display->display_modes = NULL;
slouken@2753
  1919
        }
slouken@2753
  1920
        if (display->desktop_mode.driverdata) {
slouken@2753
  1921
            SDL_free(display->desktop_mode.driverdata);
slouken@2753
  1922
            display->desktop_mode.driverdata = NULL;
slouken@2753
  1923
        }
slouken@2753
  1924
        if (display->driverdata) {
slouken@2753
  1925
            SDL_free(display->driverdata);
slouken@2753
  1926
            display->driverdata = NULL;
slouken@2753
  1927
        }
slouken@2753
  1928
    }
slouken@2753
  1929
    if (_this->displays) {
slouken@2753
  1930
        SDL_free(_this->displays);
slouken@2753
  1931
        _this->displays = NULL;
slouken@2753
  1932
    }
slouken@4495
  1933
    if (_this->clipboard_text) {
slouken@4495
  1934
        SDL_free(_this->clipboard_text);
slouken@4495
  1935
        _this->clipboard_text = NULL;
slouken@4495
  1936
    }
slouken@2753
  1937
    _this->free(_this);
slouken@2753
  1938
    _this = NULL;
slouken@0
  1939
}
slouken@0
  1940
slouken@1895
  1941
int
slouken@1895
  1942
SDL_GL_LoadLibrary(const char *path)
slouken@0
  1943
{
slouken@2753
  1944
    int retval;
slouken@0
  1945
slouken@2753
  1946
    if (!_this) {
slouken@2753
  1947
        SDL_UninitializedVideo();
slouken@2753
  1948
        return -1;
slouken@2753
  1949
    }
slouken@3057
  1950
    if (_this->gl_config.driver_loaded) {
slouken@3057
  1951
        if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
slouken@3057
  1952
            SDL_SetError("OpenGL library already loaded");
slouken@3057
  1953
            return -1;
slouken@3057
  1954
        }
slouken@3057
  1955
        retval = 0;
slouken@3057
  1956
    } else {
slouken@3057
  1957
        if (!_this->GL_LoadLibrary) {
slouken@3057
  1958
            SDL_SetError("No dynamic GL support in video driver");
slouken@3057
  1959
            return -1;
slouken@3057
  1960
        }
slouken@2753
  1961
        retval = _this->GL_LoadLibrary(_this, path);
slouken@3057
  1962
    }
slouken@3057
  1963
    if (retval == 0) {
slouken@3057
  1964
        ++_this->gl_config.driver_loaded;
slouken@2753
  1965
    }
slouken@2753
  1966
    return (retval);
slouken@0
  1967
}
slouken@0
  1968
slouken@2753
  1969
void *
slouken@1895
  1970
SDL_GL_GetProcAddress(const char *proc)
slouken@0
  1971
{
slouken@2753
  1972
    void *func;
slouken@0
  1973
slouken@2753
  1974
    if (!_this) {
slouken@2753
  1975
        SDL_UninitializedVideo();
slouken@2753
  1976
        return NULL;
slouken@2753
  1977
    }
slouken@2753
  1978
    func = NULL;
slouken@2753
  1979
    if (_this->GL_GetProcAddress) {
slouken@2753
  1980
        if (_this->gl_config.driver_loaded) {
slouken@2753
  1981
            func = _this->GL_GetProcAddress(_this, proc);
slouken@2753
  1982
        } else {
slouken@2753
  1983
            SDL_SetError("No GL driver has been loaded");
slouken@2753
  1984
        }
slouken@2753
  1985
    } else {
slouken@2753
  1986
        SDL_SetError("No dynamic GL support in video driver");
slouken@2753
  1987
    }
slouken@2753
  1988
    return func;
slouken@0
  1989
}
slouken@0
  1990
slouken@3057
  1991
void
slouken@3057
  1992
SDL_GL_UnloadLibrary(void)
slouken@3057
  1993
{
slouken@3057
  1994
    if (!_this) {
slouken@3057
  1995
        SDL_UninitializedVideo();
slouken@3057
  1996
        return;
slouken@3057
  1997
    }
slouken@3057
  1998
    if (_this->gl_config.driver_loaded > 0) {
slouken@3057
  1999
        if (--_this->gl_config.driver_loaded > 0) {
slouken@3057
  2000
            return;
slouken@3057
  2001
        }
slouken@3057
  2002
        if (_this->GL_UnloadLibrary) {
slouken@3057
  2003
            _this->GL_UnloadLibrary(_this);
slouken@3057
  2004
        }
slouken@3057
  2005
    }
slouken@3057
  2006
}
slouken@3057
  2007
slouken@1926
  2008
SDL_bool
slouken@1926
  2009
SDL_GL_ExtensionSupported(const char *extension)
slouken@1926
  2010
{
slouken@5209
  2011
#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@2753
  2012
    const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
slouken@2753
  2013
    const char *extensions;
slouken@2753
  2014
    const char *start;
slouken@2753
  2015
    const char *where, *terminator;
slouken@1926
  2016
slouken@2753
  2017
    /* Extension names should not have spaces. */
slouken@2753
  2018
    where = SDL_strchr(extension, ' ');
slouken@2753
  2019
    if (where || *extension == '\0') {
slouken@2753
  2020
        return SDL_FALSE;
slouken@2753
  2021
    }
slouken@2753
  2022
    /* See if there's an environment variable override */
slouken@2753
  2023
    start = SDL_getenv(extension);
slouken@2753
  2024
    if (start && *start == '0') {
slouken@2753
  2025
        return SDL_FALSE;
slouken@2753
  2026
    }
slouken@2753
  2027
    /* Lookup the available extensions */
slouken@2753
  2028
    glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
slouken@2753
  2029
    if (glGetStringFunc) {
slouken@2753
  2030
        extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
slouken@2753
  2031
    } else {
slouken@2753
  2032
        extensions = NULL;
slouken@2753
  2033
    }
slouken@2753
  2034
    if (!extensions) {
slouken@2753
  2035
        return SDL_FALSE;
slouken@2753
  2036
    }
slouken@2753
  2037
    /*
slouken@2753
  2038
     * It takes a bit of care to be fool-proof about parsing the OpenGL
slouken@2753
  2039
     * extensions string. Don't be fooled by sub-strings, etc.
slouken@2753
  2040
     */
slouken@1926
  2041
slouken@2753
  2042
    start = extensions;
slouken@1926
  2043
slouken@2753
  2044
    for (;;) {
slouken@2753
  2045
        where = SDL_strstr(start, extension);
slouken@2753
  2046
        if (!where)
slouken@2753
  2047
            break;
slouken@1926
  2048
slouken@2753
  2049
        terminator = where + SDL_strlen(extension);
slouken@2753
  2050
        if (where == start || *(where - 1) == ' ')
slouken@2753
  2051
            if (*terminator == ' ' || *terminator == '\0')
slouken@2753
  2052
                return SDL_TRUE;
slouken@1926
  2053
slouken@2753
  2054
        start = terminator;
slouken@2753
  2055
    }
slouken@2753
  2056
    return SDL_FALSE;
slouken@1926
  2057
#else
slouken@2753
  2058
    return SDL_FALSE;
slouken@1926
  2059
#endif
slouken@1926
  2060
}
slouken@1926
  2061
slouken@1895
  2062
int
slouken@1895
  2063
SDL_GL_SetAttribute(SDL_GLattr attr, int value)
slouken@0
  2064
{
slouken@5209
  2065
#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@2753
  2066
    int retval;
slouken@0
  2067
slouken@2753
  2068
    if (!_this) {
slouken@2753
  2069
        SDL_UninitializedVideo();
slouken@2753
  2070
        return -1;
slouken@2753
  2071
    }
slouken@2753
  2072
    retval = 0;
slouken@2753
  2073
    switch (attr) {
slouken@2753
  2074
    case SDL_GL_RED_SIZE:
slouken@2753
  2075
        _this->gl_config.red_size = value;
slouken@2753
  2076
        break;
slouken@2753
  2077
    case SDL_GL_GREEN_SIZE:
slouken@2753
  2078
        _this->gl_config.green_size = value;
slouken@2753
  2079
        break;
slouken@2753
  2080
    case SDL_GL_BLUE_SIZE:
slouken@2753
  2081
        _this->gl_config.blue_size = value;
slouken@2753
  2082
        break;
slouken@2753
  2083
    case SDL_GL_ALPHA_SIZE:
slouken@2753
  2084
        _this->gl_config.alpha_size = value;
slouken@2753
  2085
        break;
slouken@2753
  2086
    case SDL_GL_DOUBLEBUFFER:
slouken@2753
  2087
        _this->gl_config.double_buffer = value;
slouken@2753
  2088
        break;
slouken@2753
  2089
    case SDL_GL_BUFFER_SIZE:
slouken@2753
  2090
        _this->gl_config.buffer_size = value;
slouken@2753
  2091
        break;
slouken@2753
  2092
    case SDL_GL_DEPTH_SIZE:
slouken@2753
  2093
        _this->gl_config.depth_size = value;
slouken@2753
  2094
        break;
slouken@2753
  2095
    case SDL_GL_STENCIL_SIZE:
slouken@2753
  2096
        _this->gl_config.stencil_size = value;
slouken@2753
  2097
        break;
slouken@2753
  2098
    case SDL_GL_ACCUM_RED_SIZE:
slouken@2753
  2099
        _this->gl_config.accum_red_size = value;
slouken@2753
  2100
        break;
slouken@2753
  2101
    case SDL_GL_ACCUM_GREEN_SIZE:
slouken@2753
  2102
        _this->gl_config.accum_green_size = value;
slouken@2753
  2103
        break;
slouken@2753
  2104
    case SDL_GL_ACCUM_BLUE_SIZE:
slouken@2753
  2105
        _this->gl_config.accum_blue_size = value;
slouken@2753
  2106
        break;
slouken@2753
  2107
    case SDL_GL_ACCUM_ALPHA_SIZE:
slouken@2753
  2108
        _this->gl_config.accum_alpha_size = value;
slouken@2753
  2109
        break;
slouken@2753
  2110
    case SDL_GL_STEREO:
slouken@2753
  2111
        _this->gl_config.stereo = value;
slouken@2753
  2112
        break;
slouken@2753
  2113
    case SDL_GL_MULTISAMPLEBUFFERS:
slouken@2753
  2114
        _this->gl_config.multisamplebuffers = value;
slouken@2753
  2115
        break;
slouken@2753
  2116
    case SDL_GL_MULTISAMPLESAMPLES:
slouken@2753
  2117
        _this->gl_config.multisamplesamples = value;
slouken@2753
  2118
        break;
slouken@2753
  2119
    case SDL_GL_ACCELERATED_VISUAL:
slouken@2753
  2120
        _this->gl_config.accelerated = value;
slouken@2753
  2121
        break;
slouken@2753
  2122
    case SDL_GL_RETAINED_BACKING:
slouken@2753
  2123
        _this->gl_config.retained_backing = value;
slouken@2753
  2124
        break;
slouken@3100
  2125
    case SDL_GL_CONTEXT_MAJOR_VERSION:
slouken@3100
  2126
        _this->gl_config.major_version = value;
slouken@3100
  2127
        break;
slouken@3100
  2128
    case SDL_GL_CONTEXT_MINOR_VERSION:
slouken@3100
  2129
        _this->gl_config.minor_version = value;
slouken@3100
  2130
        break;
slouken@2753
  2131
    default:
slouken@2753
  2132
        SDL_SetError("Unknown OpenGL attribute");
slouken@2753
  2133
        retval = -1;
slouken@2753
  2134
        break;
slouken@2753
  2135
    }
slouken@2753
  2136
    return retval;
slouken@1936
  2137
#else
slouken@2753
  2138
    SDL_Unsupported();
slouken@2753
  2139
    return -1;
slouken@2753
  2140
#endif /* SDL_VIDEO_OPENGL */
slouken@0
  2141
}
slouken@0
  2142
slouken@1895
  2143
int
slouken@1936
  2144
SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
slouken@0
  2145
{
slouken@5209
  2146
#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@2753
  2147
    void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
slouken@3139
  2148
    GLenum(APIENTRY * glGetErrorFunc) (void);
slouken@2753
  2149
    GLenum attrib = 0;
slouken@3099
  2150
    GLenum error = 0;
slouken@1912
  2151
slouken@2753
  2152
    glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
slouken@2753
  2153
    if (!glGetIntegervFunc) {
slouken@2753
  2154
        return -1;
slouken@2753
  2155
    }
slouken@3099
  2156
slouken@3099
  2157
    glGetErrorFunc = SDL_GL_GetProcAddress("glGetError");
slouken@3099
  2158
    if (!glGetErrorFunc) {
slouken@3099
  2159
        return -1;
slouken@3099
  2160
    }
slouken@3099
  2161
slouken@3099
  2162
    /* Clear value in any case */
slouken@3139
  2163
    *value = 0;
slouken@3099
  2164
slouken@2753
  2165
    switch (attr) {
slouken@2753
  2166
    case SDL_GL_RED_SIZE:
slouken@2753
  2167
        attrib = GL_RED_BITS;
slouken@2753
  2168
        break;
slouken@2753
  2169
    case SDL_GL_BLUE_SIZE:
slouken@2753
  2170
        attrib = GL_BLUE_BITS;
slouken@2753
  2171
        break;
slouken@2753
  2172
    case SDL_GL_GREEN_SIZE:
slouken@2753
  2173
        attrib = GL_GREEN_BITS;
slouken@2753
  2174
        break;
slouken@2753
  2175
    case SDL_GL_ALPHA_SIZE:
slouken@2753
  2176
        attrib = GL_ALPHA_BITS;
slouken@2753
  2177
        break;
slouken@2753
  2178
    case SDL_GL_DOUBLEBUFFER:
slouken@5209
  2179
#if SDL_VIDEO_OPENGL
slouken@2753
  2180
        attrib = GL_DOUBLEBUFFER;
slouken@2753
  2181
        break;
hfutrell@2745
  2182
#else
slouken@3099
  2183
        /* OpenGL ES 1.0 and above specifications have EGL_SINGLE_BUFFER      */
slouken@3099
  2184
        /* parameter which switches double buffer to single buffer. OpenGL ES */
slouken@3099
  2185
        /* SDL driver must set proper value after initialization              */
slouken@3099
  2186
        *value = _this->gl_config.double_buffer;
slouken@2753
  2187
        return 0;
hfutrell@2745
  2188
#endif
slouken@2753
  2189
    case SDL_GL_DEPTH_SIZE:
slouken@2753
  2190
        attrib = GL_DEPTH_BITS;
slouken@2753
  2191
        break;
slouken@2753
  2192
    case SDL_GL_STENCIL_SIZE:
slouken@2753
  2193
        attrib = GL_STENCIL_BITS;
slouken@2753
  2194
        break;
slouken@5209
  2195
#if SDL_VIDEO_OPENGL
slouken@2753
  2196
    case SDL_GL_ACCUM_RED_SIZE:
slouken@2753
  2197
        attrib = GL_ACCUM_RED_BITS;
slouken@2753
  2198
        break;
slouken@2753
  2199
    case SDL_GL_ACCUM_GREEN_SIZE:
slouken@2753
  2200
        attrib = GL_ACCUM_GREEN_BITS;
slouken@2753
  2201
        break;
slouken@2753
  2202
    case SDL_GL_ACCUM_BLUE_SIZE:
slouken@2753
  2203
        attrib = GL_ACCUM_BLUE_BITS;
slouken@2753
  2204
        break;
slouken@2753
  2205
    case SDL_GL_ACCUM_ALPHA_SIZE:
slouken@2753
  2206
        attrib = GL_ACCUM_ALPHA_BITS;
slouken@2753
  2207
        break;
slouken@2753
  2208
    case SDL_GL_STEREO:
slouken@2753
  2209
        attrib = GL_STEREO;
slouken@2753
  2210
        break;
hfutrell@2745
  2211
#else
slouken@2753
  2212
    case SDL_GL_ACCUM_RED_SIZE:
slouken@2753
  2213
    case SDL_GL_ACCUM_GREEN_SIZE:
slouken@2753
  2214
    case SDL_GL_ACCUM_BLUE_SIZE:
slouken@2753
  2215
    case SDL_GL_ACCUM_ALPHA_SIZE:
slouken@2753
  2216
    case SDL_GL_STEREO:
slouken@2753
  2217
        /* none of these are supported in OpenGL ES */
slouken@2753
  2218
        *value = 0;
slouken@2753
  2219
        return 0;
hfutrell@2745
  2220
#endif
slouken@2753
  2221
    case SDL_GL_MULTISAMPLEBUFFERS:
slouken@5209
  2222
#if SDL_VIDEO_OPENGL
slouken@2753
  2223
        attrib = GL_SAMPLE_BUFFERS_ARB;
hfutrell@2745
  2224
#else
slouken@2753
  2225
        attrib = GL_SAMPLE_BUFFERS;
hfutrell@2745
  2226
#endif
slouken@2753
  2227
        break;
slouken@2753
  2228
    case SDL_GL_MULTISAMPLESAMPLES:
slouken@5209
  2229
#if SDL_VIDEO_OPENGL
slouken@2753
  2230
        attrib = GL_SAMPLES_ARB;
hfutrell@2745
  2231
#else
slouken@2753
  2232
        attrib = GL_SAMPLES;
hfutrell@2745
  2233
#endif
slouken@2753
  2234
        break;
slouken@2753
  2235
    case SDL_GL_BUFFER_SIZE:
slouken@2753
  2236
        {
slouken@2753
  2237
            GLint bits = 0;
slouken@2753
  2238
            GLint component;
slouken@1936
  2239
slouken@2753
  2240
            /*
slouken@2753
  2241
             * there doesn't seem to be a single flag in OpenGL
slouken@2753
  2242
             * for this!
slouken@2753
  2243
             */
slouken@2753
  2244
            glGetIntegervFunc(GL_RED_BITS, &component);
slouken@2753
  2245
            bits += component;
slouken@2753
  2246
            glGetIntegervFunc(GL_GREEN_BITS, &component);
slouken@2753
  2247
            bits += component;
slouken@2753
  2248
            glGetIntegervFunc(GL_BLUE_BITS, &component);
slouken@2753
  2249
            bits += component;
slouken@2753
  2250
            glGetIntegervFunc(GL_ALPHA_BITS, &component);
slouken@2753
  2251
            bits += component;
slouken@1936
  2252
slouken@2753
  2253
            *value = bits;
slouken@2753
  2254
            return 0;
slouken@2753
  2255
        }
slouken@2753
  2256
    case SDL_GL_ACCELERATED_VISUAL:
slouken@2753
  2257
        {
slouken@2753
  2258
            /* FIXME: How do we get this information? */
slouken@3571
  2259
            *value = (_this->gl_config.accelerated != 0);
slouken@2753
  2260
            return 0;
slouken@2753
  2261
        }
slouken@5210
  2262
    case SDL_GL_RETAINED_BACKING:
slouken@5210
  2263
        {
slouken@5210
  2264
            *value = _this->gl_config.retained_backing;
slouken@5210
  2265
            return 0;
slouken@5210
  2266
        }
slouken@5210
  2267
    case SDL_GL_CONTEXT_MAJOR_VERSION:
slouken@5210
  2268
        {
slouken@5210
  2269
            *value = _this->gl_config.major_version;
slouken@5210
  2270
            return 0;
slouken@5210
  2271
        }
slouken@5210
  2272
    case SDL_GL_CONTEXT_MINOR_VERSION:
slouken@5210
  2273
        {
slouken@5210
  2274
            *value = _this->gl_config.minor_version;
slouken@5210
  2275
            return 0;
slouken@5210
  2276
        }
slouken@2753
  2277
    default:
slouken@2753
  2278
        SDL_SetError("Unknown OpenGL attribute");
slouken@2753
  2279
        return -1;
slouken@2753
  2280
    }
slouken@0
  2281
slouken@2753
  2282
    glGetIntegervFunc(attrib, (GLint *) value);
slouken@3139
  2283
    error = glGetErrorFunc();
slouken@3139
  2284
    if (error != GL_NO_ERROR) {
slouken@3139
  2285
        switch (error) {
slouken@3139
  2286
        case GL_INVALID_ENUM:
slouken@3139
  2287
            {
slouken@3139
  2288
                SDL_SetError("OpenGL error: GL_INVALID_ENUM");
slouken@3139
  2289
            }
slouken@3139
  2290
            break;
slouken@3139
  2291
        case GL_INVALID_VALUE:
slouken@3139
  2292
            {
slouken@3139
  2293
                SDL_SetError("OpenGL error: GL_INVALID_VALUE");
slouken@3139
  2294
            }
slouken@3139
  2295
            break;
slouken@3139
  2296
        default:
slouken@3139
  2297
            {
slouken@3139
  2298
                SDL_SetError("OpenGL error: %08X", error);
slouken@3139
  2299
            }
slouken@3139
  2300
            break;
slouken@3139
  2301
        }
slouken@3139
  2302
        return -1;
slouken@3099
  2303
    }
slouken@2753
  2304
    return 0;
slouken@1936
  2305
#else
slouken@2753
  2306
    SDL_Unsupported();
slouken@2753
  2307
    return -1;
slouken@2753
  2308
#endif /* SDL_VIDEO_OPENGL */
slouken@0
  2309
}
slouken@0
  2310
slouken@1912
  2311
SDL_GLContext
slouken@3685
  2312
SDL_GL_CreateContext(SDL_Window * window)
slouken@1912
  2313
{
slouken@3695
  2314
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@3695
  2315
slouken@2753
  2316
    if (!(window->flags & SDL_WINDOW_OPENGL)) {
slouken@2753
  2317
        SDL_SetError("The specified window isn't an OpenGL window");
slouken@2753
  2318
        return NULL;
slouken@2753
  2319
    }
slouken@2753
  2320
    return _this->GL_CreateContext(_this, window);
slouken@1912
  2321
}
slouken@1912
  2322
slouken@1912
  2323
int
slouken@3685
  2324
SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext context)
slouken@1912
  2325
{
slouken@3695
  2326
    CHECK_WINDOW_MAGIC(window, -1);
slouken@3695
  2327
slouken@3695
  2328
    if (!(window->flags & SDL_WINDOW_OPENGL)) {
slouken@2753
  2329
        SDL_SetError("The specified window isn't an OpenGL window");
slouken@2753
  2330
        return -1;
slouken@2753
  2331
    }
slouken@2753
  2332
    if (!context) {
slouken@2753
  2333
        window = NULL;
slouken@2753
  2334
    }
slouken@2753
  2335
    return _this->GL_MakeCurrent(_this, window, context);
slouken@1912
  2336
}
slouken@1912
  2337
slouken@1912
  2338
int
slouken@1912
  2339
SDL_GL_SetSwapInterval(int interval)
slouken@1912
  2340
{
slouken@2753
  2341
    if (!_this) {
slouken@2753
  2342
        SDL_UninitializedVideo();
slouken@2753
  2343
        return -1;
slouken@2753
  2344
    }
slouken@2753
  2345
    if (_this->GL_SetSwapInterval) {
slouken@2753
  2346
        return _this->GL_SetSwapInterval(_this, interval);
slouken@2753
  2347
    } else {
slouken@2753
  2348
        SDL_SetError("Setting the swap interval is not supported");
slouken@2753
  2349
        return -1;
slouken@2753
  2350
    }
slouken@1912
  2351
}
slouken@1912
  2352
slouken@1912
  2353
int
slouken@1912
  2354
SDL_GL_GetSwapInterval(void)
slouken@1912
  2355
{
slouken@2753
  2356
    if (!_this) {
slouken@2753
  2357
        SDL_UninitializedVideo();
slouken@2753
  2358
        return -1;
slouken@2753
  2359
    }
slouken@2753
  2360
    if (_this->GL_GetSwapInterval) {
slouken@2753
  2361
        return _this->GL_GetSwapInterval(_this);
slouken@2753
  2362
    } else {
slouken@2753
  2363
        SDL_SetError("Getting the swap interval is not supported");
slouken@2753
  2364
        return -1;
slouken@2753
  2365
    }
slouken@1912
  2366
}
slouken@1912
  2367
slouken@1895
  2368
void
slouken@3685
  2369
SDL_GL_SwapWindow(SDL_Window * window)
slouken@0
  2370
{
slouken@3695
  2371
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  2372
slouken@2753
  2373
    if (!(window->flags & SDL_WINDOW_OPENGL)) {
slouken@2753
  2374
        SDL_SetError("The specified window isn't an OpenGL window");
slouken@2753
  2375
        return;
slouken@2753
  2376
    }
slouken@2753
  2377
    _this->GL_SwapWindow(_this, window);
slouken@1912
  2378
}
slouken@1912
  2379
slouken@1912
  2380
void
slouken@1912
  2381
SDL_GL_DeleteContext(SDL_GLContext context)
slouken@1912
  2382
{
slouken@4526
  2383
    if (!_this || !_this->gl_data || !context) {
slouken@2753
  2384
        return;
slouken@2753
  2385
    }
slouken@2753
  2386
    _this->GL_MakeCurrent(_this, NULL, NULL);
slouken@2753
  2387
    _this->GL_DeleteContext(_this, context);
slouken@0
  2388
}
slouken@0
  2389
slouken@1895
  2390
#if 0                           // FIXME
hfutrell@2744
  2391
/*
hfutrell@2744
  2392
 * Utility function used by SDL_WM_SetIcon(); flags & 1 for color key, flags
hfutrell@2744
  2393
 * & 2 for alpha channel.
hfutrell@2744
  2394
 */
slouken@1895
  2395
static void
slouken@1895
  2396
CreateMaskFromColorKeyOrAlpha(SDL_Surface * icon, Uint8 * mask, int flags)
slouken@0
  2397
{
slouken@2753
  2398
    int x, y;
slouken@2753
  2399
    Uint32 colorkey;
slouken@0
  2400
#define SET_MASKBIT(icon, x, y, mask) \
slouken@0
  2401
	mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
slouken@0
  2402
slouken@2753
  2403
    colorkey = icon->format->colorkey;
slouken@2753
  2404
    switch (icon->format->BytesPerPixel) {
slouken@2753
  2405
    case 1:
slouken@2753
  2406
        {
slouken@2753
  2407
            Uint8 *pixels;
slouken@2753
  2408
            for (y = 0; y < icon->h; ++y) {
slouken@2753
  2409
                pixels = (Uint8 *) icon->pixels + y * icon->pitch;
slouken@2753
  2410
                for (x = 0; x < icon->w; ++x) {
slouken@2753
  2411
                    if (*pixels++ == colorkey) {
slouken@2753
  2412
                        SET_MASKBIT(icon, x, y, mask);
slouken@2753
  2413
                    }
slouken@2753
  2414
                }
slouken@2753
  2415
            }
slouken@2753
  2416
        }
slouken@2753
  2417
        break;
slouken@0
  2418
slouken@2753
  2419
    case 2:
slouken@2753
  2420
        {
slouken@2753
  2421
            Uint16 *pixels;
slouken@2753
  2422
            for (y = 0; y < icon->h; ++y) {
slouken@2753
  2423
                pixels = (Uint16 *) icon->pixels + y * icon->pitch / 2;
slouken@2753
  2424
                for (x = 0; x < icon->w; ++x) {
slouken@2753
  2425
                    if ((flags & 1) && *pixels == colorkey) {
slouken@2753
  2426
                        SET_MASKBIT(icon, x, y, mask);
slouken@2753
  2427
                    } else if ((flags & 2)
slouken@2753
  2428
                               && (*pixels & icon->format->Amask) == 0) {
slouken@2753
  2429
                        SET_MASKBIT(icon, x, y, mask);
slouken@2753
  2430
                    }
slouken@2753
  2431
                    pixels++;
slouken@2753
  2432
                }
slouken@2753
  2433
            }
slouken@2753
  2434
        }
slouken@2753
  2435
        break;
slouken@0
  2436
slouken@2753
  2437
    case 4:
slouken@2753
  2438
        {
slouken@2753
  2439
            Uint32 *pixels;
slouken@2753
  2440
            for (y = 0; y < icon->h; ++y) {
slouken@2753
  2441
                pixels = (Uint32 *) icon->pixels + y * icon->pitch / 4;
slouken@2753
  2442
                for (x = 0; x < icon->w; ++x) {
slouken@2753
  2443
                    if ((flags & 1) && *pixels == colorkey) {
slouken@2753
  2444
                        SET_MASKBIT(icon, x, y, mask);
slouken@2753
  2445
                    } else if ((flags & 2)
slouken@2753
  2446
                               && (*pixels & icon->format->Amask) == 0) {
slouken@2753
  2447
                        SET_MASKBIT(icon, x, y, mask);
slouken@2753
  2448
                    }
slouken@2753
  2449
                    pixels++;
slouken@2753
  2450
                }
slouken@2753
  2451
            }
slouken@2753
  2452
        }
slouken@2753
  2453
        break;
slouken@2753
  2454
    }
slouken@0
  2455
}
slouken@0
  2456
slouken@0
  2457
/*
slouken@0
  2458
 * Sets the window manager icon for the display window.
slouken@0
  2459
 */
slouken@1895
  2460
void
slouken@1895
  2461
SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
slouken@0
  2462
{
slouken@2753
  2463
    if (icon && _this->SetIcon) {
slouken@2753
  2464
        /* Generate a mask if necessary, and create the icon! */
slouken@2753
  2465
        if (mask == NULL) {
slouken@2753
  2466
            int mask_len = icon->h * (icon->w + 7) / 8;
slouken@2753
  2467
            int flags = 0;
slouken@2753
  2468
            mask = (Uint8 *) SDL_malloc(mask_len);
slouken@2753
  2469
            if (mask == NULL) {
slouken@2753
  2470
                return;
slouken@2753
  2471
            }
slouken@2753
  2472
            SDL_memset(mask, ~0, mask_len);
slouken@2753
  2473
            if (icon->flags & SDL_SRCCOLORKEY)
slouken@2753
  2474
                flags |= 1;
slouken@2753
  2475
            if (icon->flags & SDL_SRCALPHA)
slouken@2753
  2476
                flags |= 2;
slouken@2753
  2477
            if (flags) {
slouken@2753
  2478
                CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
slouken@2753
  2479
            }
slouken@2753
  2480
            _this->SetIcon(_this, icon, mask);
slouken@2753
  2481
            SDL_free(mask);
slouken@2753
  2482
        } else {
slouken@2753
  2483
            _this->SetIcon(_this, icon, mask);
slouken@2753
  2484
        }
slouken@2753
  2485
    }
slouken@1895
  2486
}
slouken@1895
  2487
#endif
slouken@0
  2488
slouken@1895
  2489
SDL_bool
slouken@3685
  2490
SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info)
slouken@1895
  2491
{
slouken@3695
  2492
    CHECK_WINDOW_MAGIC(window, SDL_FALSE);
slouken@3695
  2493
slouken@4900
  2494
    if (!info) {
slouken@4900
  2495
        return SDL_FALSE;
slouken@4900
  2496
    }
slouken@4900
  2497
    info->subsystem = SDL_SYSWM_UNKNOWN;
slouken@4900
  2498
slouken@3695
  2499
    if (!_this->GetWindowWMInfo) {
slouken@2753
  2500
        return SDL_FALSE;
slouken@2753
  2501
    }
slouken@2753
  2502
    return (_this->GetWindowWMInfo(_this, window, info));
slouken@0
  2503
}
slouken@0
  2504
slouken@3280
  2505
void
slouken@3280
  2506
SDL_StartTextInput(void)
slouken@3280
  2507
{
slouken@3683
  2508
    if (_this && _this->StartTextInput) {
slouken@3280
  2509
        _this->StartTextInput(_this);
slouken@3280
  2510
    }
slouken@3280
  2511
    SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE);
slouken@3280
  2512
    SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE);
slouken@3280
  2513
}
slouken@3280
  2514
slouken@3280
  2515
void
slouken@3280
  2516
SDL_StopTextInput(void)
slouken@3280
  2517
{
slouken@3683
  2518
    if (_this && _this->StopTextInput) {
slouken@3280
  2519
        _this->StopTextInput(_this);
slouken@3280
  2520
    }
slouken@3280
  2521
    SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
slouken@3280
  2522
    SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
slouken@3280
  2523
}
slouken@3280
  2524
slouken@3280
  2525
void
slouken@3280
  2526
SDL_SetTextInputRect(SDL_Rect *rect)
slouken@3280
  2527
{
slouken@3683
  2528
    if (_this && _this->SetTextInputRect) {
slouken@3280
  2529
        _this->SetTextInputRect(_this, rect);
slouken@3280
  2530
    }
slouken@3280
  2531
}
slouken@3280
  2532
slouken@1895
  2533
/* vi: set ts=4 sw=4 expandtab: */