src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 11 Jul 2013 22:59:20 -0700
changeset 7412 50211a1fd557
parent 7399 f35ff854121a
child 7429 ff7edbf76a73
permissions -rw-r--r--
Fixed bug 1946 - OpenGL contexts in threads

The SDL OpenGL context code is now properly thread aware. There are two new functions which return the current OpenGL window and context for the current thread.

There are still places in the cocoa driver where the OpenGL context needs to be updated when the view changes. These will need a different solution and still use the last globally set context to avoid changing behavior.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
slouken@1402
    21
#include "SDL_config.h"
slouken@0
    22
slouken@0
    23
/* The high-level video driver subsystem */
slouken@0
    24
slouken@2999
    25
#include "SDL.h"
slouken@2984
    26
#include "SDL_video.h"
slouken@0
    27
#include "SDL_sysvideo.h"
slouken@0
    28
#include "SDL_blit.h"
slouken@0
    29
#include "SDL_pixels_c.h"
slouken@5294
    30
#include "SDL_rect_c.h"
slouken@1361
    31
#include "../events/SDL_events_c.h"
urkle@7139
    32
#include "../timer/SDL_timer_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@2745
    73
#if SDL_VIDEO_DRIVER_UIKIT
slouken@2753
    74
    &UIKIT_bootstrap,
hfutrell@2745
    75
#endif
slouken@5150
    76
#if SDL_VIDEO_DRIVER_ANDROID
slouken@5150
    77
    &Android_bootstrap,
slouken@5150
    78
#endif
kimonline@7009
    79
#if SDL_VIDEO_DRIVER_PSP
kimonline@7009
    80
    &PSP_bootstrap,
kimonline@7009
    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@6188
   193
#elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@6188
   194
    /* Let's be optimistic about this! */
slouken@6188
   195
    return SDL_TRUE;
slouken@5190
   196
#else
slouken@5190
   197
    return SDL_FALSE;
slouken@5190
   198
#endif
slouken@5190
   199
slouken@5190
   200
#else
slouken@5190
   201
    /* Play it safe, assume that if there is a framebuffer driver that it's
slouken@5190
   202
       optimized for the current platform.
slouken@5190
   203
    */
slouken@5190
   204
    return SDL_FALSE;
slouken@5190
   205
#endif
slouken@5190
   206
}
slouken@5190
   207
slouken@5166
   208
static int
slouken@5166
   209
SDL_CreateWindowTexture(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
slouken@5166
   210
{
slouken@5166
   211
    SDL_WindowTextureData *data;
slouken@5166
   212
    SDL_RendererInfo info;
slouken@5166
   213
    Uint32 i;
slouken@5166
   214
slouken@5166
   215
    data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
slouken@5166
   216
    if (!data) {
slouken@5291
   217
        SDL_Renderer *renderer = NULL;
slouken@5168
   218
        SDL_RendererInfo info;
slouken@5168
   219
        int i;
slouken@5191
   220
        const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
slouken@5168
   221
slouken@5191
   222
        /* Check to see if there's a specific driver requested */
slouken@5191
   223
        if (hint && *hint != '0' && *hint != '1' &&
slouken@5191
   224
            SDL_strcasecmp(hint, "software") != 0) {
slouken@5191
   225
            for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
slouken@5191
   226
                SDL_GetRenderDriverInfo(i, &info);
slouken@5191
   227
                if (SDL_strcasecmp(info.name, hint) == 0) {
slouken@5191
   228
                    renderer = SDL_CreateRenderer(window, i, 0);
slouken@5168
   229
                    break;
slouken@5168
   230
                }
slouken@5168
   231
            }
slouken@5168
   232
        }
slouken@5191
   233
slouken@5191
   234
        if (!renderer) {
slouken@5191
   235
            for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
slouken@5191
   236
                SDL_GetRenderDriverInfo(i, &info);
slouken@5191
   237
                if (SDL_strcmp(info.name, "software") != 0) {
slouken@5191
   238
                    renderer = SDL_CreateRenderer(window, i, 0);
slouken@5191
   239
                    if (renderer) {
slouken@5191
   240
                        break;
slouken@5191
   241
                    }
slouken@5191
   242
                }
slouken@5191
   243
            }
slouken@5191
   244
        }
slouken@5166
   245
        if (!renderer) {
icculus@7037
   246
            return SDL_SetError("No hardware accelerated renderers available");
slouken@5166
   247
        }
slouken@5275
   248
slouken@5275
   249
        /* Create the data after we successfully create the renderer (bug #1116) */
slouken@5275
   250
        data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
slouken@5275
   251
        if (!data) {
slouken@5275
   252
            SDL_DestroyRenderer(renderer);
icculus@7037
   253
            return SDL_OutOfMemory();
slouken@5275
   254
        }
slouken@5275
   255
        SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data);
slouken@5275
   256
slouken@5166
   257
        data->renderer = renderer;
slouken@5166
   258
    }
slouken@5166
   259
slouken@5166
   260
    /* Free any old texture and pixel data */
slouken@5166
   261
    if (data->texture) {
slouken@5166
   262
        SDL_DestroyTexture(data->texture);
slouken@5166
   263
        data->texture = NULL;
slouken@5166
   264
    }
slouken@5166
   265
    if (data->pixels) {
slouken@5166
   266
        SDL_free(data->pixels);
slouken@5166
   267
        data->pixels = NULL;
slouken@5166
   268
    }
slouken@5166
   269
slouken@5291
   270
    if (SDL_GetRendererInfo(data->renderer, &info) < 0) {
slouken@5166
   271
        return -1;
slouken@5166
   272
    }
slouken@5166
   273
slouken@5166
   274
    /* Find the first format without an alpha channel */
slouken@5166
   275
    *format = info.texture_formats[0];
slouken@5166
   276
    for (i = 0; i < info.num_texture_formats; ++i) {
slouken@5268
   277
        if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
slouken@5268
   278
            !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
slouken@5166
   279
            *format = info.texture_formats[i];
slouken@5166
   280
            break;
slouken@5166
   281
        }
slouken@5166
   282
    }
slouken@5166
   283
slouken@5291
   284
    data->texture = SDL_CreateTexture(data->renderer, *format,
slouken@5166
   285
                                      SDL_TEXTUREACCESS_STREAMING,
slouken@5166
   286
                                      window->w, window->h);
slouken@5166
   287
    if (!data->texture) {
slouken@5166
   288
        return -1;
slouken@5166
   289
    }
slouken@5166
   290
slouken@5166
   291
    /* Create framebuffer data */
slouken@5172
   292
    data->bytes_per_pixel = SDL_BYTESPERPIXEL(*format);
slouken@5172
   293
    data->pitch = (((window->w * data->bytes_per_pixel) + 3) & ~3);
slouken@5166
   294
    data->pixels = SDL_malloc(window->h * data->pitch);
slouken@5166
   295
    if (!data->pixels) {
icculus@7037
   296
        return SDL_OutOfMemory();
slouken@5166
   297
    }
slouken@5166
   298
slouken@5166
   299
    *pixels = data->pixels;
slouken@5166
   300
    *pitch = data->pitch;
slouken@5297
   301
slouken@5297
   302
    /* Make sure we're not double-scaling the viewport */
slouken@5297
   303
    SDL_RenderSetViewport(data->renderer, NULL);
slouken@5297
   304
slouken@5166
   305
    return 0;
slouken@5166
   306
}
slouken@5166
   307
slouken@5166
   308
static int
slouken@7014
   309
SDL_UpdateWindowTexture(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
slouken@5166
   310
{
slouken@5166
   311
    SDL_WindowTextureData *data;
slouken@5294
   312
    SDL_Rect rect;
slouken@5294
   313
    void *src;
slouken@5166
   314
slouken@5166
   315
    data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
slouken@5166
   316
    if (!data || !data->texture) {
icculus@7037
   317
        return SDL_SetError("No window texture data");
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
icculus@7037
   384
static int
slouken@1912
   385
SDL_UninitializedVideo()
slouken@1912
   386
{
icculus@7037
   387
    return 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@7191
   419
urkle@7139
   420
#if !SDL_TIMERS_DISABLED
urkle@7139
   421
    SDL_InitTicks();
urkle@7139
   422
#endif
slouken@3694
   423
slouken@2753
   424
    /* Start the event loop */
slouken@7360
   425
    if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0 ||
slouken@5123
   426
        SDL_KeyboardInit() < 0 ||
slouken@5123
   427
        SDL_MouseInit() < 0 ||
slouken@7360
   428
        SDL_TouchInit() < 0) {
slouken@2753
   429
        return -1;
slouken@2753
   430
    }
slouken@3694
   431
slouken@2753
   432
    /* Select the proper video driver */
slouken@2753
   433
    index = 0;
slouken@2753
   434
    video = NULL;
slouken@2753
   435
    if (driver_name == NULL) {
slouken@2753
   436
        driver_name = SDL_getenv("SDL_VIDEODRIVER");
slouken@2753
   437
    }
slouken@2753
   438
    if (driver_name != NULL) {
slouken@2753
   439
        for (i = 0; bootstrap[i]; ++i) {
slouken@6900
   440
            if (SDL_strncasecmp(bootstrap[i]->name, driver_name, SDL_strlen(driver_name)) == 0) {
slouken@3448
   441
                video = bootstrap[i]->create(index);
slouken@2753
   442
                break;
slouken@2753
   443
            }
slouken@2753
   444
        }
slouken@2753
   445
    } else {
slouken@2753
   446
        for (i = 0; bootstrap[i]; ++i) {
slouken@2753
   447
            if (bootstrap[i]->available()) {
slouken@2753
   448
                video = bootstrap[i]->create(index);
slouken@2753
   449
                if (video != NULL) {
slouken@2753
   450
                    break;
slouken@2753
   451
                }
slouken@2753
   452
            }
slouken@2753
   453
        }
slouken@2753
   454
    }
slouken@2753
   455
    if (video == NULL) {
slouken@2753
   456
        if (driver_name) {
icculus@7037
   457
            return SDL_SetError("%s not available", driver_name);
slouken@2753
   458
        }
icculus@7037
   459
        return SDL_SetError("No available video device");
slouken@2753
   460
    }
slouken@2753
   461
    _this = video;
slouken@2753
   462
    _this->name = bootstrap[i]->name;
slouken@2753
   463
    _this->next_object_id = 1;
slouken@0
   464
slouken@0
   465
slouken@2753
   466
    /* Set some very sane GL defaults */
slouken@2753
   467
    _this->gl_config.driver_loaded = 0;
slouken@2753
   468
    _this->gl_config.dll_handle = NULL;
slouken@2753
   469
    _this->gl_config.red_size = 3;
slouken@2753
   470
    _this->gl_config.green_size = 3;
slouken@2753
   471
    _this->gl_config.blue_size = 2;
slouken@2753
   472
    _this->gl_config.alpha_size = 0;
slouken@2753
   473
    _this->gl_config.buffer_size = 0;
slouken@2753
   474
    _this->gl_config.depth_size = 16;
slouken@2753
   475
    _this->gl_config.stencil_size = 0;
slouken@2753
   476
    _this->gl_config.double_buffer = 1;
slouken@2753
   477
    _this->gl_config.accum_red_size = 0;
slouken@2753
   478
    _this->gl_config.accum_green_size = 0;
slouken@2753
   479
    _this->gl_config.accum_blue_size = 0;
slouken@2753
   480
    _this->gl_config.accum_alpha_size = 0;
slouken@2753
   481
    _this->gl_config.stereo = 0;
slouken@2753
   482
    _this->gl_config.multisamplebuffers = 0;
slouken@2753
   483
    _this->gl_config.multisamplesamples = 0;
slouken@2753
   484
    _this->gl_config.retained_backing = 1;
slouken@3571
   485
    _this->gl_config.accelerated = -1;  /* accelerated or not, both are fine */
slouken@5209
   486
#if SDL_VIDEO_OPENGL
slouken@3100
   487
    _this->gl_config.major_version = 2;
slouken@3100
   488
    _this->gl_config.minor_version = 1;
slouken@6370
   489
    _this->gl_config.use_egl = 0;
slouken@5217
   490
#elif SDL_VIDEO_OPENGL_ES
slouken@5217
   491
    _this->gl_config.major_version = 1;
slouken@5217
   492
    _this->gl_config.minor_version = 1;
slouken@6370
   493
    _this->gl_config.use_egl = 1;
slouken@5209
   494
#elif SDL_VIDEO_OPENGL_ES2
slouken@5209
   495
    _this->gl_config.major_version = 2;
slouken@5209
   496
    _this->gl_config.minor_version = 0;
slouken@6370
   497
    _this->gl_config.use_egl = 1;
slouken@5209
   498
#endif
slouken@6296
   499
    _this->gl_config.flags = 0;
slouken@6296
   500
    _this->gl_config.profile_mask = 0;
slouken@6393
   501
    _this->gl_config.share_with_current_context = 0;
slouken@0
   502
slouken@7412
   503
    _this->current_glwin_tls = SDL_TLSCreate();
slouken@7412
   504
    _this->current_glctx_tls = SDL_TLSCreate();
slouken@7412
   505
slouken@2753
   506
    /* Initialize the video subsystem */
slouken@2753
   507
    if (_this->VideoInit(_this) < 0) {
slouken@2753
   508
        SDL_VideoQuit();
slouken@2753
   509
        return -1;
slouken@2753
   510
    }
slouken@5166
   511
slouken@2753
   512
    /* Make sure some displays were added */
slouken@2753
   513
    if (_this->num_displays == 0) {
slouken@2753
   514
        SDL_VideoQuit();
icculus@7037
   515
        return SDL_SetError("The video driver did not add any displays");
slouken@2753
   516
    }
slouken@0
   517
slouken@5190
   518
    /* Add the renderer framebuffer emulation if desired */
slouken@5190
   519
    if (ShouldUseTextureFramebuffer()) {
slouken@5166
   520
        _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
slouken@5166
   521
        _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
slouken@5166
   522
        _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
slouken@5166
   523
    }
slouken@5166
   524
slouken@6670
   525
    /* If we don't use a screen keyboard, turn on text input by default,
slouken@6670
   526
       otherwise programs that expect to get text events without enabling
slouken@6670
   527
       UNICODE input won't get any events.
slouken@6670
   528
slouken@6670
   529
       Actually, come to think of it, you needed to call SDL_EnableUNICODE(1)
slouken@6670
   530
       in SDL 1.2 before you got text input events.  Hmm...
slouken@6670
   531
     */
slouken@6670
   532
    if (!SDL_HasScreenKeyboardSupport()) {
slouken@6670
   533
        SDL_StartTextInput();
slouken@6670
   534
    }
slouken@6670
   535
slouken@2753
   536
    /* We're ready to go! */
slouken@2753
   537
    return 0;
slouken@0
   538
}
slouken@0
   539
slouken@2753
   540
const char *
slouken@1895
   541
SDL_GetCurrentVideoDriver()
slouken@0
   542
{
slouken@2753
   543
    if (!_this) {
slouken@2753
   544
        SDL_UninitializedVideo();
slouken@2753
   545
        return NULL;
slouken@2753
   546
    }
slouken@2753
   547
    return _this->name;
slouken@0
   548
}
slouken@0
   549
slouken@1895
   550
SDL_VideoDevice *
slouken@4472
   551
SDL_GetVideoDevice(void)
slouken@0
   552
{
slouken@2753
   553
    return _this;
slouken@0
   554
}
slouken@0
   555
slouken@1895
   556
int
slouken@1895
   557
SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
slouken@0
   558
{
slouken@2753
   559
    SDL_VideoDisplay display;
slouken@0
   560
slouken@2753
   561
    SDL_zero(display);
slouken@2753
   562
    if (desktop_mode) {
slouken@2753
   563
        display.desktop_mode = *desktop_mode;
slouken@2753
   564
    }
slouken@2753
   565
    display.current_mode = display.desktop_mode;
slouken@1895
   566
slouken@2753
   567
    return SDL_AddVideoDisplay(&display);
slouken@0
   568
}
slouken@0
   569
slouken@1895
   570
int
slouken@1895
   571
SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
slouken@0
   572
{
slouken@2753
   573
    SDL_VideoDisplay *displays;
slouken@2753
   574
    int index = -1;
slouken@0
   575
slouken@2753
   576
    displays =
slouken@2753
   577
        SDL_realloc(_this->displays,
slouken@2753
   578
                    (_this->num_displays + 1) * sizeof(*displays));
slouken@2753
   579
    if (displays) {
slouken@2753
   580
        index = _this->num_displays++;
slouken@2753
   581
        displays[index] = *display;
slouken@2753
   582
        displays[index].device = _this;
slouken@2753
   583
        _this->displays = displays;
slouken@6787
   584
slouken@6787
   585
        if (display->name) {
slouken@6787
   586
            displays[index].name = SDL_strdup(display->name);
slouken@6787
   587
        } else {
slouken@6787
   588
            char name[32];
slouken@6787
   589
slouken@6787
   590
            SDL_itoa(index, name, 10);
slouken@6787
   591
            displays[index].name = SDL_strdup(name);
slouken@6787
   592
        }
slouken@2753
   593
    } else {
slouken@2753
   594
        SDL_OutOfMemory();
slouken@2753
   595
    }
slouken@2753
   596
    return index;
slouken@0
   597
}
slouken@0
   598
slouken@1895
   599
int
slouken@1895
   600
SDL_GetNumVideoDisplays(void)
slouken@0
   601
{
slouken@2753
   602
    if (!_this) {
slouken@2753
   603
        SDL_UninitializedVideo();
slouken@2753
   604
        return 0;
slouken@2753
   605
    }
slouken@2753
   606
    return _this->num_displays;
slouken@0
   607
}
slouken@0
   608
slouken@6044
   609
static int
slouken@5380
   610
SDL_GetIndexOfDisplay(SDL_VideoDisplay *display)
slouken@5380
   611
{
slouken@5380
   612
    int displayIndex;
slouken@5380
   613
slouken@5380
   614
    for (displayIndex = 0; displayIndex < _this->num_displays; ++displayIndex) {
slouken@5380
   615
        if (display == &_this->displays[displayIndex]) {
slouken@5380
   616
            return displayIndex;
slouken@5380
   617
        }
slouken@5380
   618
    }
slouken@5380
   619
slouken@5380
   620
    /* Couldn't find the display, just use index 0 */
slouken@5380
   621
    return 0;
slouken@5380
   622
}
slouken@5380
   623
slouken@6787
   624
const char *
slouken@6787
   625
SDL_GetDisplayName(int displayIndex)
slouken@6787
   626
{
slouken@6787
   627
    CHECK_DISPLAY_INDEX(displayIndex, NULL);
slouken@6787
   628
slouken@6787
   629
    return _this->displays[displayIndex].name;
slouken@6787
   630
}
slouken@6787
   631
slouken@5380
   632
int
slouken@5244
   633
SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
slouken@3528
   634
{
slouken@5244
   635
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   636
slouken@3528
   637
    if (rect) {
slouken@5244
   638
        SDL_VideoDisplay *display = &_this->displays[displayIndex];
slouken@3528
   639
slouken@3528
   640
        if (_this->GetDisplayBounds) {
slouken@5249
   641
            if (_this->GetDisplayBounds(_this, display, rect) == 0) {
slouken@5249
   642
                return 0;
slouken@3528
   643
            }
slouken@5249
   644
        }
slouken@5249
   645
slouken@5249
   646
        /* Assume that the displays are left to right */
slouken@5249
   647
        if (displayIndex == 0) {
slouken@5249
   648
            rect->x = 0;
slouken@5249
   649
            rect->y = 0;
slouken@3528
   650
        } else {
slouken@5249
   651
            SDL_GetDisplayBounds(displayIndex-1, rect);
slouken@5249
   652
            rect->x += rect->w;
slouken@3528
   653
        }
slouken@6518
   654
        rect->w = display->current_mode.w;
slouken@6518
   655
        rect->h = display->current_mode.h;
slouken@3528
   656
    }
slouken@3528
   657
    return 0;
slouken@3528
   658
}
slouken@3528
   659
slouken@1895
   660
SDL_bool
slouken@3500
   661
SDL_AddDisplayMode(SDL_VideoDisplay * display,  const SDL_DisplayMode * mode)
slouken@0
   662
{
slouken@2753
   663
    SDL_DisplayMode *modes;
slouken@2753
   664
    int i, nmodes;
slouken@0
   665
slouken@2753
   666
    /* Make sure we don't already have the mode in the list */
slouken@2753
   667
    modes = display->display_modes;
slouken@2753
   668
    nmodes = display->num_display_modes;
slouken@2753
   669
    for (i = nmodes; i--;) {
slouken@2753
   670
        if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) {
slouken@2753
   671
            return SDL_FALSE;
slouken@2753
   672
        }
slouken@2753
   673
    }
slouken@1895
   674
slouken@2753
   675
    /* Go ahead and add the new mode */
slouken@2753
   676
    if (nmodes == display->max_display_modes) {
slouken@2753
   677
        modes =
slouken@2753
   678
            SDL_realloc(modes,
slouken@2753
   679
                        (display->max_display_modes + 32) * sizeof(*modes));
slouken@2753
   680
        if (!modes) {
slouken@2753
   681
            return SDL_FALSE;
slouken@2753
   682
        }
slouken@2753
   683
        display->display_modes = modes;
slouken@2753
   684
        display->max_display_modes += 32;
slouken@2753
   685
    }
slouken@2753
   686
    modes[nmodes] = *mode;
slouken@2753
   687
    display->num_display_modes++;
slouken@1895
   688
lestat@3178
   689
    /* Re-sort video modes */
lestat@3178
   690
    SDL_qsort(display->display_modes, display->num_display_modes,
slouken@3186
   691
              sizeof(SDL_DisplayMode), cmpmodes);
lestat@3178
   692
slouken@2753
   693
    return SDL_TRUE;
slouken@0
   694
}
slouken@0
   695
slouken@5244
   696
static int
slouken@3500
   697
SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
slouken@3500
   698
{
slouken@3500
   699
    if (!display->num_display_modes && _this->GetDisplayModes) {
slouken@3500
   700
        _this->GetDisplayModes(_this, display);
slouken@3500
   701
        SDL_qsort(display->display_modes, display->num_display_modes,
slouken@3500
   702
                  sizeof(SDL_DisplayMode), cmpmodes);
slouken@3500
   703
    }
slouken@3500
   704
    return display->num_display_modes;
slouken@3500
   705
}
slouken@3500
   706
slouken@3500
   707
int
slouken@5244
   708
SDL_GetNumDisplayModes(int displayIndex)
slouken@0
   709
{
slouken@5244
   710
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   711
slouken@5244
   712
    return SDL_GetNumDisplayModesForDisplay(&_this->displays[displayIndex]);
slouken@3500
   713
}
slouken@3500
   714
slouken@3500
   715
int
slouken@5244
   716
SDL_GetDisplayMode(int displayIndex, int index, SDL_DisplayMode * mode)
slouken@3500
   717
{
slouken@5244
   718
    SDL_VideoDisplay *display;
slouken@5244
   719
slouken@5244
   720
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   721
slouken@5244
   722
    display = &_this->displays[displayIndex];
slouken@3500
   723
    if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
icculus@7037
   724
        return SDL_SetError("index must be in the range of 0 - %d",
icculus@7037
   725
                            SDL_GetNumDisplayModesForDisplay(display) - 1);
slouken@3500
   726
    }
slouken@3500
   727
    if (mode) {
slouken@3500
   728
        *mode = display->display_modes[index];
slouken@2753
   729
    }
slouken@2753
   730
    return 0;
slouken@0
   731
}
slouken@0
   732
slouken@1967
   733
int
slouken@5244
   734
SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode)
slouken@0
   735
{
slouken@5244
   736
    SDL_VideoDisplay *display;
slouken@3500
   737
slouken@5244
   738
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   739
slouken@5244
   740
    display = &_this->displays[displayIndex];
slouken@2753
   741
    if (mode) {
slouken@3500
   742
        *mode = display->desktop_mode;
slouken@2753
   743
    }
slouken@2753
   744
    return 0;
slouken@0
   745
}
slouken@0
   746
slouken@1967
   747
int
slouken@5244
   748
SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode)
slouken@0
   749
{
slouken@5244
   750
    SDL_VideoDisplay *display;
slouken@3500
   751
slouken@5244
   752
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@5244
   753
slouken@5244
   754
    display = &_this->displays[displayIndex];
slouken@2753
   755
    if (mode) {
slouken@3500
   756
        *mode = display->current_mode;
slouken@2753
   757
    }
slouken@2753
   758
    return 0;
slouken@0
   759
}
slouken@0
   760
slouken@5244
   761
static SDL_DisplayMode *
slouken@3500
   762
SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
slouken@3500
   763
                                    const SDL_DisplayMode * mode,
slouken@3500
   764
                                    SDL_DisplayMode * closest)
slouken@0
   765
{
slouken@2753
   766
    Uint32 target_format;
slouken@2753
   767
    int target_refresh_rate;
slouken@2753
   768
    int i;
slouken@2753
   769
    SDL_DisplayMode *current, *match;
slouken@0
   770
slouken@3500
   771
    if (!mode || !closest) {
slouken@3500
   772
        SDL_SetError("Missing desired mode or closest mode parameter");
slouken@2753
   773
        return NULL;
slouken@2753
   774
    }
slouken@3500
   775
slouken@2753
   776
    /* Default to the desktop format */
slouken@2753
   777
    if (mode->format) {
slouken@2753
   778
        target_format = mode->format;
slouken@2753
   779
    } else {
slouken@3500
   780
        target_format = display->desktop_mode.format;
slouken@2753
   781
    }
slouken@0
   782
slouken@2753
   783
    /* Default to the desktop refresh rate */
slouken@2753
   784
    if (mode->refresh_rate) {
slouken@2753
   785
        target_refresh_rate = mode->refresh_rate;
slouken@2753
   786
    } else {
slouken@3500
   787
        target_refresh_rate = display->desktop_mode.refresh_rate;
slouken@2753
   788
    }
slouken@0
   789
slouken@2753
   790
    match = NULL;
slouken@3500
   791
    for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
slouken@3500
   792
        current = &display->display_modes[i];
slouken@0
   793
slouken@2789
   794
        if (current->w && (current->w < mode->w)) {
slouken@2753
   795
            /* Out of sorted modes large enough here */
slouken@2753
   796
            break;
slouken@2753
   797
        }
slouken@2789
   798
        if (current->h && (current->h < mode->h)) {
slouken@2789
   799
            if (current->w && (current->w == mode->w)) {
slouken@2789
   800
                /* Out of sorted modes large enough here */
slouken@2789
   801
                break;
slouken@2789
   802
            }
slouken@2789
   803
            /* Wider, but not tall enough, due to a different
slouken@2789
   804
               aspect ratio. This mode must be skipped, but closer
slouken@2789
   805
               modes may still follow. */
slouken@2789
   806
            continue;
slouken@2789
   807
        }
slouken@2753
   808
        if (!match || current->w < match->w || current->h < match->h) {
slouken@2753
   809
            match = current;
slouken@2753
   810
            continue;
slouken@2753
   811
        }
slouken@2753
   812
        if (current->format != match->format) {
slouken@2753
   813
            /* Sorted highest depth to lowest */
slouken@2753
   814
            if (current->format == target_format ||
slouken@2753
   815
                (SDL_BITSPERPIXEL(current->format) >=
slouken@2753
   816
                 SDL_BITSPERPIXEL(target_format)
slouken@2753
   817
                 && SDL_PIXELTYPE(current->format) ==
slouken@2753
   818
                 SDL_PIXELTYPE(target_format))) {
slouken@2753
   819
                match = current;
slouken@2753
   820
            }
slouken@2753
   821
            continue;
slouken@2753
   822
        }
slouken@2753
   823
        if (current->refresh_rate != match->refresh_rate) {
slouken@2753
   824
            /* Sorted highest refresh to lowest */
slouken@2753
   825
            if (current->refresh_rate >= target_refresh_rate) {
slouken@2753
   826
                match = current;
slouken@2753
   827
            }
slouken@2753
   828
        }
slouken@2753
   829
    }
slouken@2753
   830
    if (match) {
slouken@2753
   831
        if (match->format) {
slouken@2753
   832
            closest->format = match->format;
slouken@2753
   833
        } else {
slouken@2753
   834
            closest->format = mode->format;
slouken@2753
   835
        }
slouken@2753
   836
        if (match->w && match->h) {
slouken@2753
   837
            closest->w = match->w;
slouken@2753
   838
            closest->h = match->h;
slouken@2753
   839
        } else {
slouken@2753
   840
            closest->w = mode->w;
slouken@2753
   841
            closest->h = mode->h;
slouken@2753
   842
        }
slouken@2753
   843
        if (match->refresh_rate) {
slouken@2753
   844
            closest->refresh_rate = match->refresh_rate;
slouken@2753
   845
        } else {
slouken@2753
   846
            closest->refresh_rate = mode->refresh_rate;
slouken@2753
   847
        }
slouken@2753
   848
        closest->driverdata = match->driverdata;
slouken@1895
   849
slouken@2753
   850
        /*
slouken@2753
   851
         * Pick some reasonable defaults if the app and driver don't
slouken@2753
   852
         * care
slouken@2753
   853
         */
slouken@2753
   854
        if (!closest->format) {
slouken@2753
   855
            closest->format = SDL_PIXELFORMAT_RGB888;
slouken@2753
   856
        }
slouken@2753
   857
        if (!closest->w) {
slouken@2753
   858
            closest->w = 640;
slouken@2753
   859
        }
slouken@2753
   860
        if (!closest->h) {
slouken@2753
   861
            closest->h = 480;
slouken@2753
   862
        }
slouken@2753
   863
        return closest;
slouken@2753
   864
    }
slouken@2753
   865
    return NULL;
slouken@0
   866
}
slouken@0
   867
slouken@3500
   868
SDL_DisplayMode *
slouken@5244
   869
SDL_GetClosestDisplayMode(int displayIndex,
slouken@5244
   870
                          const SDL_DisplayMode * mode,
slouken@3500
   871
                          SDL_DisplayMode * closest)
slouken@3500
   872
{
slouken@5244
   873
    SDL_VideoDisplay *display;
slouken@5244
   874
slouken@5244
   875
    CHECK_DISPLAY_INDEX(displayIndex, NULL);
slouken@5244
   876
slouken@5244
   877
    display = &_this->displays[displayIndex];
slouken@5244
   878
    return SDL_GetClosestDisplayModeForDisplay(display, mode, closest);
slouken@3500
   879
}
slouken@3500
   880
slouken@6044
   881
static int
slouken@3500
   882
SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
slouken@0
   883
{
slouken@2753
   884
    SDL_DisplayMode display_mode;
slouken@2753
   885
    SDL_DisplayMode current_mode;
slouken@0
   886
slouken@3502
   887
    if (mode) {
slouken@3502
   888
        display_mode = *mode;
slouken@3502
   889
slouken@3502
   890
        /* Default to the current mode */
slouken@3502
   891
        if (!display_mode.format) {
slouken@3502
   892
            display_mode.format = display->current_mode.format;
slouken@3502
   893
        }
slouken@3502
   894
        if (!display_mode.w) {
slouken@3502
   895
            display_mode.w = display->current_mode.w;
slouken@3502
   896
        }
slouken@3502
   897
        if (!display_mode.h) {
slouken@3502
   898
            display_mode.h = display->current_mode.h;
slouken@3502
   899
        }
slouken@3502
   900
        if (!display_mode.refresh_rate) {
slouken@3502
   901
            display_mode.refresh_rate = display->current_mode.refresh_rate;
slouken@3502
   902
        }
slouken@3502
   903
slouken@3502
   904
        /* Get a good video mode, the closest one possible */
slouken@3502
   905
        if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
icculus@7037
   906
            return SDL_SetError("No video mode large enough for %dx%d",
icculus@7037
   907
                                display_mode.w, display_mode.h);
slouken@3502
   908
        }
slouken@3502
   909
    } else {
slouken@3502
   910
        display_mode = display->desktop_mode;
slouken@2753
   911
    }
slouken@3500
   912
slouken@2753
   913
    /* See if there's anything left to do */
slouken@5244
   914
    current_mode = display->current_mode;
slouken@2753
   915
    if (SDL_memcmp(&display_mode, &current_mode, sizeof(display_mode)) == 0) {
slouken@2753
   916
        return 0;
slouken@2753
   917
    }
slouken@3500
   918
slouken@2753
   919
    /* Actually change the display mode */
slouken@4978
   920
    if (!_this->SetDisplayMode) {
icculus@7037
   921
        return SDL_SetError("Video driver doesn't support changing display mode");
slouken@4978
   922
    }
slouken@3500
   923
    if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
slouken@2753
   924
        return -1;
slouken@2753
   925
    }
slouken@2753
   926
    display->current_mode = display_mode;
slouken@2753
   927
    return 0;
slouken@0
   928
}
slouken@0
   929
slouken@1895
   930
int
slouken@6786
   931
SDL_GetWindowDisplayIndex(SDL_Window * window)
slouken@5246
   932
{
slouken@5246
   933
    int displayIndex;
slouken@5246
   934
    int i, dist;
slouken@5246
   935
    int closest = -1;
slouken@5246
   936
    int closest_dist = 0x7FFFFFFF;
slouken@5246
   937
    SDL_Point center;
slouken@5246
   938
    SDL_Point delta;
slouken@5246
   939
    SDL_Rect rect;
slouken@5246
   940
slouken@5246
   941
    CHECK_WINDOW_MAGIC(window, -1);
slouken@5246
   942
slouken@5246
   943
    if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
slouken@5246
   944
        SDL_WINDOWPOS_ISCENTERED(window->x)) {
slouken@5246
   945
        displayIndex = (window->x & 0xFFFF);
slouken@5246
   946
        if (displayIndex >= _this->num_displays) {
slouken@5246
   947
            displayIndex = 0;
slouken@5246
   948
        }
slouken@5246
   949
        return displayIndex;
slouken@5246
   950
    }
slouken@5246
   951
    if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
slouken@5246
   952
        SDL_WINDOWPOS_ISCENTERED(window->y)) {
slouken@5246
   953
        displayIndex = (window->y & 0xFFFF);
slouken@5246
   954
        if (displayIndex >= _this->num_displays) {
slouken@5246
   955
            displayIndex = 0;
slouken@5246
   956
        }
slouken@5246
   957
        return displayIndex;
slouken@5246
   958
    }
slouken@5246
   959
slouken@5246
   960
    /* Find the display containing the window */
slouken@6547
   961
    for (i = 0; i < _this->num_displays; ++i) {
slouken@6547
   962
        SDL_VideoDisplay *display = &_this->displays[i];
slouken@6547
   963
slouken@6547
   964
        if (display->fullscreen_window == window) {
slouken@6547
   965
            return i;
slouken@6547
   966
        }
slouken@6547
   967
    }
slouken@5246
   968
    center.x = window->x + window->w / 2;
slouken@5246
   969
    center.y = window->y + window->h / 2;
slouken@5246
   970
    for (i = 0; i < _this->num_displays; ++i) {
slouken@5246
   971
        SDL_GetDisplayBounds(i, &rect);
slouken@6547
   972
        if (SDL_EnclosePoints(&center, 1, &rect, NULL)) {
slouken@5246
   973
            return i;
slouken@5246
   974
        }
slouken@5246
   975
slouken@5246
   976
        delta.x = center.x - (rect.x + rect.w / 2);
slouken@5246
   977
        delta.y = center.y - (rect.y + rect.h / 2);
slouken@5246
   978
        dist = (delta.x*delta.x + delta.y*delta.y);
slouken@5246
   979
        if (dist < closest_dist) {
slouken@5246
   980
            closest = i;
slouken@5246
   981
            closest_dist = dist;
slouken@5246
   982
        }
slouken@5246
   983
    }
slouken@5246
   984
    if (closest < 0) {
slouken@5246
   985
        SDL_SetError("Couldn't find any displays");
slouken@5246
   986
    }
slouken@5246
   987
    return closest;
slouken@5246
   988
}
slouken@5246
   989
slouken@5246
   990
SDL_VideoDisplay *
slouken@5246
   991
SDL_GetDisplayForWindow(SDL_Window *window)
slouken@5246
   992
{
slouken@6786
   993
    int displayIndex = SDL_GetWindowDisplayIndex(window);
slouken@5373
   994
    if (displayIndex >= 0) {
slouken@5373
   995
        return &_this->displays[displayIndex];
slouken@5373
   996
    } else {
slouken@5373
   997
        return NULL;
slouken@5373
   998
    }
slouken@5246
   999
}
slouken@5246
  1000
slouken@5246
  1001
int
slouken@3685
  1002
SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
slouken@3500
  1003
{
slouken@3695
  1004
    CHECK_WINDOW_MAGIC(window, -1);
slouken@3500
  1005
slouken@2753
  1006
    if (mode) {
slouken@3500
  1007
        window->fullscreen_mode = *mode;
slouken@3500
  1008
    } else {
slouken@3500
  1009
        SDL_zero(window->fullscreen_mode);
slouken@3500
  1010
    }
slouken@3526
  1011
    return 0;
slouken@3500
  1012
}
slouken@3500
  1013
slouken@3500
  1014
int
slouken@3685
  1015
SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
slouken@3500
  1016
{
slouken@3500
  1017
    SDL_DisplayMode fullscreen_mode;
slouken@7191
  1018
    SDL_VideoDisplay *display;
slouken@3500
  1019
aschiffler@6936
  1020
    if (!mode) {
icculus@7037
  1021
      return SDL_InvalidParamError("mode");
aschiffler@6936
  1022
    }
slouken@7191
  1023
slouken@3695
  1024
    CHECK_WINDOW_MAGIC(window, -1);
slouken@3500
  1025
slouken@3500
  1026
    fullscreen_mode = window->fullscreen_mode;
slouken@3500
  1027
    if (!fullscreen_mode.w) {
slouken@3500
  1028
        fullscreen_mode.w = window->w;
slouken@3500
  1029
    }
slouken@3500
  1030
    if (!fullscreen_mode.h) {
slouken@3500
  1031
        fullscreen_mode.h = window->h;
slouken@3500
  1032
    }
slouken@7191
  1033
slouken@7191
  1034
    display = SDL_GetDisplayForWindow(window);
slouken@7191
  1035
slouken@7191
  1036
    /* if in desktop size mode, just return the size of the desktop */
slouken@7191
  1037
    if ( ( window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP )
slouken@7191
  1038
    {
slouken@7191
  1039
        fullscreen_mode = display->desktop_mode;
slouken@7191
  1040
    }
slouken@7191
  1041
    else if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
slouken@3500
  1042
                                             &fullscreen_mode,
slouken@3500
  1043
                                             &fullscreen_mode)) {
icculus@7037
  1044
        return SDL_SetError("Couldn't find display mode match");
slouken@3500
  1045
    }
slouken@3500
  1046
slouken@3500
  1047
    if (mode) {
slouken@3500
  1048
        *mode = fullscreen_mode;
slouken@2753
  1049
    }
slouken@2753
  1050
    return 0;
slouken@0
  1051
}
slouken@0
  1052
slouken@5154
  1053
Uint32
slouken@5154
  1054
SDL_GetWindowPixelFormat(SDL_Window * window)
slouken@5154
  1055
{
slouken@5246
  1056
    SDL_VideoDisplay *display;
slouken@5246
  1057
slouken@5246
  1058
    CHECK_WINDOW_MAGIC(window, SDL_PIXELFORMAT_UNKNOWN);
slouken@5246
  1059
slouken@5246
  1060
    display = SDL_GetDisplayForWindow(window);
slouken@5246
  1061
    return display->current_mode.format;
slouken@5154
  1062
}
slouken@5154
  1063
slouken@3502
  1064
static void
slouken@5479
  1065
SDL_RestoreMousePosition(SDL_Window *window)
slouken@5479
  1066
{
slouken@5479
  1067
    int x, y;
slouken@5479
  1068
slouken@5479
  1069
    if (window == SDL_GetMouseFocus()) {
slouken@5479
  1070
        SDL_GetMouseState(&x, &y);
slouken@5479
  1071
        SDL_WarpMouseInWindow(window, x, y);
slouken@5479
  1072
    }
slouken@5479
  1073
}
slouken@5479
  1074
slouken@5479
  1075
static void
slouken@5404
  1076
SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
slouken@3502
  1077
{
slouken@5246
  1078
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5249
  1079
    SDL_Window *other;
slouken@3502
  1080
slouken@5404
  1081
    if (fullscreen) {
slouken@3502
  1082
        /* Hide any other fullscreen windows */
slouken@5249
  1083
        if (display->fullscreen_window &&
slouken@5249
  1084
            display->fullscreen_window != window) {
slouken@5246
  1085
            SDL_MinimizeWindow(display->fullscreen_window);
slouken@3502
  1086
        }
slouken@3502
  1087
    }
slouken@3502
  1088
slouken@5305
  1089
    /* See if anything needs to be done now */
slouken@5404
  1090
    if ((display->fullscreen_window == window) == fullscreen) {
slouken@5305
  1091
        return;
slouken@5305
  1092
    }
slouken@5305
  1093
slouken@5249
  1094
    /* See if there are any fullscreen windows */
slouken@5249
  1095
    for (other = _this->windows; other; other = other->next) {
slouken@5404
  1096
        SDL_bool setDisplayMode = SDL_FALSE;
slouken@5404
  1097
slouken@5404
  1098
        if (other == window) {
slouken@5404
  1099
            setDisplayMode = fullscreen;
slouken@5404
  1100
        } else if (FULLSCREEN_VISIBLE(other) &&
slouken@5404
  1101
                   SDL_GetDisplayForWindow(other) == display) {
slouken@5404
  1102
            setDisplayMode = SDL_TRUE;
slouken@5404
  1103
        }
slouken@5404
  1104
slouken@5404
  1105
        if (setDisplayMode) {
slouken@5249
  1106
            SDL_DisplayMode fullscreen_mode;
slouken@5404
  1107
slouken@5249
  1108
            if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
slouken@5306
  1109
                SDL_bool resized = SDL_TRUE;
slouken@5306
  1110
slouken@5306
  1111
                if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
slouken@5306
  1112
                    resized = SDL_FALSE;
slouken@5249
  1113
                }
slouken@3502
  1114
slouken@7191
  1115
                /* only do the mode change if we want exclusive fullscreen */
slouken@7191
  1116
                if ( ( window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) != SDL_WINDOW_FULLSCREEN_DESKTOP )
slouken@7191
  1117
                    SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
slouken@7191
  1118
                else
slouken@7191
  1119
                    SDL_SetDisplayModeForDisplay(display, NULL);
slouken@7191
  1120
slouken@7191
  1121
slouken@5249
  1122
                if (_this->SetWindowFullscreen) {
slouken@5305
  1123
                    _this->SetWindowFullscreen(_this, other, display, SDL_TRUE);
slouken@5249
  1124
                }
slouken@5249
  1125
                display->fullscreen_window = other;
slouken@5249
  1126
slouken@5306
  1127
                /* Generate a mode change event here */
slouken@5306
  1128
                if (resized) {
slouken@5306
  1129
                    SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
slouken@5306
  1130
                                        fullscreen_mode.w, fullscreen_mode.h);
slouken@5306
  1131
                } else {
slouken@5306
  1132
                    SDL_OnWindowResized(other);
slouken@5306
  1133
                }
slouken@5479
  1134
slouken@5479
  1135
                SDL_RestoreMousePosition(other);
slouken@3502
  1136
                return;
slouken@3502
  1137
            }
slouken@3502
  1138
        }
slouken@3502
  1139
    }
slouken@3502
  1140
slouken@3502
  1141
    /* Nope, restore the desktop mode */
slouken@3502
  1142
    SDL_SetDisplayModeForDisplay(display, NULL);
slouken@5249
  1143
slouken@5249
  1144
    if (_this->SetWindowFullscreen) {
slouken@5305
  1145
        _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
slouken@5249
  1146
    }
slouken@3517
  1147
    display->fullscreen_window = NULL;
slouken@5306
  1148
slouken@5306
  1149
    /* Generate a mode change event here */
slouken@5306
  1150
    SDL_OnWindowResized(window);
slouken@5479
  1151
slouken@5479
  1152
    /* Restore the cursor position */
slouken@5479
  1153
    SDL_RestoreMousePosition(window);
slouken@3502
  1154
}
slouken@3502
  1155
slouken@5380
  1156
#define CREATE_FLAGS \
slouken@5380
  1157
    (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE)
slouken@5380
  1158
slouken@5380
  1159
static void
slouken@5380
  1160
SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
slouken@5380
  1161
{
slouken@5398
  1162
    window->windowed.x = window->x;
slouken@5398
  1163
    window->windowed.y = window->y;
slouken@5398
  1164
    window->windowed.w = window->w;
slouken@5398
  1165
    window->windowed.h = window->h;
slouken@5398
  1166
slouken@5380
  1167
    if (flags & SDL_WINDOW_MAXIMIZED) {
slouken@5380
  1168
        SDL_MaximizeWindow(window);
slouken@5380
  1169
    }
slouken@5380
  1170
    if (flags & SDL_WINDOW_MINIMIZED) {
slouken@5380
  1171
        SDL_MinimizeWindow(window);
slouken@5380
  1172
    }
slouken@5380
  1173
    if (flags & SDL_WINDOW_FULLSCREEN) {
slouken@6755
  1174
        SDL_SetWindowFullscreen(window, flags);
slouken@5380
  1175
    }
slouken@5380
  1176
    if (flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@5380
  1177
        SDL_SetWindowGrab(window, SDL_TRUE);
slouken@5380
  1178
    }
slouken@5380
  1179
    if (!(flags & SDL_WINDOW_HIDDEN)) {
slouken@5380
  1180
        SDL_ShowWindow(window);
slouken@5380
  1181
    }
slouken@5380
  1182
}
slouken@5380
  1183
slouken@3685
  1184
SDL_Window *
slouken@1895
  1185
SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
slouken@0
  1186
{
slouken@3685
  1187
    SDL_Window *window;
slouken@0
  1188
slouken@2753
  1189
    if (!_this) {
slouken@3417
  1190
        /* Initialize the video system if needed */
slouken@5123
  1191
        if (SDL_VideoInit(NULL) < 0) {
slouken@3685
  1192
            return NULL;
slouken@3417
  1193
        }
slouken@2753
  1194
    }
slouken@5249
  1195
slouken@6266
  1196
    /* Some platforms can't create zero-sized windows */
slouken@6266
  1197
    if (w < 1) {
slouken@6266
  1198
        w = 1;
slouken@6266
  1199
    }
slouken@6266
  1200
    if (h < 1) {
slouken@6266
  1201
        h = 1;
slouken@6266
  1202
    }
slouken@6266
  1203
slouken@5249
  1204
    /* Some platforms have OpenGL enabled by default */
slouken@6188
  1205
#if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__
slouken@5249
  1206
    flags |= SDL_WINDOW_OPENGL;
slouken@5249
  1207
#endif
slouken@3057
  1208
    if (flags & SDL_WINDOW_OPENGL) {
slouken@3057
  1209
        if (!_this->GL_CreateContext) {
slouken@3057
  1210
            SDL_SetError("No OpenGL support in video driver");
slouken@3685
  1211
            return NULL;
slouken@3057
  1212
        }
slouken@6611
  1213
        if (SDL_GL_LoadLibrary(NULL) < 0) {
slouken@6611
  1214
            return NULL;
slouken@6611
  1215
        }
slouken@2753
  1216
    }
slouken@3685
  1217
    window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
slouken@7399
  1218
    if (!window) {
slouken@7399
  1219
        SDL_OutOfMemory();
slouken@7399
  1220
        return NULL;
slouken@7399
  1221
    }
slouken@3695
  1222
    window->magic = &_this->window_magic;
slouken@3685
  1223
    window->id = _this->next_object_id++;
slouken@3685
  1224
    window->x = x;
slouken@3685
  1225
    window->y = y;
slouken@3685
  1226
    window->w = w;
slouken@3685
  1227
    window->h = h;
slouken@5380
  1228
    if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
slouken@5380
  1229
        SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
slouken@5380
  1230
        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5380
  1231
        int displayIndex;
slouken@5380
  1232
        SDL_Rect bounds;
slouken@5380
  1233
slouken@5380
  1234
        displayIndex = SDL_GetIndexOfDisplay(display);
slouken@5380
  1235
        SDL_GetDisplayBounds(displayIndex, &bounds);
slouken@5404
  1236
        if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
slouken@5380
  1237
            window->x = bounds.x + (bounds.w - w) / 2;
slouken@5380
  1238
        }
slouken@5380
  1239
        if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
slouken@5380
  1240
            window->y = bounds.y + (bounds.h - h) / 2;
slouken@5380
  1241
        }
slouken@5380
  1242
    }
slouken@5380
  1243
    window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
slouken@5466
  1244
    window->brightness = 1.0f;
slouken@5246
  1245
    window->next = _this->windows;
slouken@5246
  1246
    if (_this->windows) {
slouken@5246
  1247
        _this->windows->prev = window;
slouken@3693
  1248
    }
slouken@5246
  1249
    _this->windows = window;
slouken@3685
  1250
slouken@3685
  1251
    if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
slouken@3685
  1252
        SDL_DestroyWindow(window);
slouken@3685
  1253
        return NULL;
slouken@3685
  1254
    }
slouken@0
  1255
slouken@2753
  1256
    if (title) {
slouken@3685
  1257
        SDL_SetWindowTitle(window, title);
slouken@2753
  1258
    }
slouken@5380
  1259
    SDL_FinishWindowCreation(window, flags);
slouken@7191
  1260
slouken@6063
  1261
    /* If the window was created fullscreen, make sure the mode code matches */
slouken@6063
  1262
    SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
slouken@3685
  1263
slouken@3685
  1264
    return window;
slouken@1895
  1265
}
slouken@0
  1266
slouken@3685
  1267
SDL_Window *
slouken@1895
  1268
SDL_CreateWindowFrom(const void *data)
slouken@1895
  1269
{
slouken@3685
  1270
    SDL_Window *window;
slouken@0
  1271
slouken@2753
  1272
    if (!_this) {
slouken@2753
  1273
        SDL_UninitializedVideo();
slouken@3685
  1274
        return NULL;
slouken@3685
  1275
    }
slouken@3685
  1276
    window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
slouken@7399
  1277
    if (!window) {
slouken@7399
  1278
        SDL_OutOfMemory();
slouken@7399
  1279
        return NULL;
slouken@7399
  1280
    }
slouken@3695
  1281
    window->magic = &_this->window_magic;
slouken@3685
  1282
    window->id = _this->next_object_id++;
slouken@3685
  1283
    window->flags = SDL_WINDOW_FOREIGN;
slouken@5466
  1284
    window->brightness = 1.0f;
slouken@5246
  1285
    window->next = _this->windows;
slouken@5246
  1286
    if (_this->windows) {
slouken@5246
  1287
        _this->windows->prev = window;
slouken@3693
  1288
    }
slouken@5246
  1289
    _this->windows = window;
slouken@1895
  1290
slouken@2753
  1291
    if (!_this->CreateWindowFrom ||
slouken@3685
  1292
        _this->CreateWindowFrom(_this, window, data) < 0) {
slouken@3685
  1293
        SDL_DestroyWindow(window);
slouken@3685
  1294
        return NULL;
slouken@3685
  1295
    }
slouken@3685
  1296
    return window;
slouken@1895
  1297
}
slouken@1895
  1298
slouken@1924
  1299
int
slouken@1928
  1300
SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
slouken@1924
  1301
{
slouken@2753
  1302
    char *title = window->title;
slouken@1956
  1303
slouken@2753
  1304
    if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
icculus@7037
  1305
        return SDL_SetError("No OpenGL support in video driver");
slouken@2753
  1306
    }
slouken@3057
  1307
slouken@3057
  1308
    if (window->flags & SDL_WINDOW_FOREIGN) {
slouken@3057
  1309
        /* Can't destroy and re-create foreign windows, hrm */
slouken@3057
  1310
        flags |= SDL_WINDOW_FOREIGN;
slouken@3057
  1311
    } else {
slouken@3057
  1312
        flags &= ~SDL_WINDOW_FOREIGN;
slouken@3057
  1313
    }
slouken@3057
  1314
slouken@5249
  1315
    /* Restore video mode, etc. */
slouken@5305
  1316
    SDL_HideWindow(window);
slouken@5249
  1317
slouken@5249
  1318
    /* Tear down the old native window */
slouken@5249
  1319
    if (window->surface) {
slouken@5288
  1320
        window->surface->flags &= ~SDL_DONTFREE;
slouken@5249
  1321
        SDL_FreeSurface(window->surface);
slouken@5249
  1322
    }
slouken@5249
  1323
    if (_this->DestroyWindowFramebuffer) {
slouken@5249
  1324
        _this->DestroyWindowFramebuffer(_this, window);
slouken@5249
  1325
    }
slouken@3057
  1326
    if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
slouken@2753
  1327
        _this->DestroyWindow(_this, window);
slouken@2753
  1328
    }
slouken@3057
  1329
slouken@5249
  1330
    if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
slouken@5249
  1331
        if (flags & SDL_WINDOW_OPENGL) {
slouken@6775
  1332
            if (SDL_GL_LoadLibrary(NULL) < 0) {
slouken@6775
  1333
                return -1;
slouken@6775
  1334
            }
slouken@5249
  1335
        } else {
slouken@5249
  1336
            SDL_GL_UnloadLibrary();
slouken@5249
  1337
        }
slouken@5249
  1338
    }
slouken@5249
  1339
slouken@2753
  1340
    window->title = NULL;
slouken@5380
  1341
    window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
slouken@1956
  1342
slouken@3057
  1343
    if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
slouken@3057
  1344
        if (_this->CreateWindow(_this, window) < 0) {
slouken@3057
  1345
            if (flags & SDL_WINDOW_OPENGL) {
slouken@3057
  1346
                SDL_GL_UnloadLibrary();
slouken@3057
  1347
            }
slouken@3057
  1348
            return -1;
slouken@3057
  1349
        }
slouken@2753
  1350
    }
slouken@3057
  1351
slouken@2753
  1352
    if (title) {
slouken@3685
  1353
        SDL_SetWindowTitle(window, title);
slouken@2753
  1354
        SDL_free(title);
slouken@2753
  1355
    }
slouken@5380
  1356
    SDL_FinishWindowCreation(window, flags);
slouken@2875
  1357
slouken@2753
  1358
    return 0;
slouken@1924
  1359
}
slouken@1924
  1360
slouken@1895
  1361
Uint32
slouken@3685
  1362
SDL_GetWindowID(SDL_Window * window)
slouken@1895
  1363
{
slouken@3695
  1364
    CHECK_WINDOW_MAGIC(window, 0);
slouken@3695
  1365
slouken@3685
  1366
    return window->id;
slouken@3685
  1367
}
slouken@3685
  1368
slouken@3685
  1369
SDL_Window *
slouken@3685
  1370
SDL_GetWindowFromID(Uint32 id)
slouken@3685
  1371
{
slouken@3685
  1372
    SDL_Window *window;
slouken@3685
  1373
slouken@3685
  1374
    if (!_this) {
slouken@3685
  1375
        return NULL;
slouken@3685
  1376
    }
slouken@5246
  1377
    for (window = _this->windows; window; window = window->next) {
slouken@5246
  1378
        if (window->id == id) {
slouken@5246
  1379
            return window;
slouken@3685
  1380
        }
slouken@3685
  1381
    }
slouken@3685
  1382
    return NULL;
slouken@3685
  1383
}
slouken@3685
  1384
slouken@3685
  1385
Uint32
slouken@3685
  1386
SDL_GetWindowFlags(SDL_Window * window)
slouken@3685
  1387
{
slouken@3695
  1388
    CHECK_WINDOW_MAGIC(window, 0);
slouken@3695
  1389
slouken@2753
  1390
    return window->flags;
slouken@1895
  1391
}
slouken@1895
  1392
slouken@1895
  1393
void
slouken@3685
  1394
SDL_SetWindowTitle(SDL_Window * window, const char *title)
slouken@1895
  1395
{
slouken@3695
  1396
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1397
slouken@3695
  1398
    if (title == window->title) {
slouken@2753
  1399
        return;
slouken@2753
  1400
    }
slouken@2753
  1401
    if (window->title) {
slouken@2753
  1402
        SDL_free(window->title);
slouken@2753
  1403
    }
slouken@4871
  1404
    if (title && *title) {
slouken@2753
  1405
        window->title = SDL_strdup(title);
slouken@2753
  1406
    } else {
slouken@2753
  1407
        window->title = NULL;
slouken@2753
  1408
    }
slouken@1956
  1409
slouken@2753
  1410
    if (_this->SetWindowTitle) {
slouken@2753
  1411
        _this->SetWindowTitle(_this, window);
slouken@2753
  1412
    }
slouken@1895
  1413
}
slouken@1895
  1414
slouken@2753
  1415
const char *
slouken@3685
  1416
SDL_GetWindowTitle(SDL_Window * window)
slouken@1895
  1417
{
slouken@4872
  1418
    CHECK_WINDOW_MAGIC(window, "");
slouken@3695
  1419
slouken@4871
  1420
    return window->title ? window->title : "";
slouken@1895
  1421
}
slouken@1895
  1422
slouken@1895
  1423
void
slouken@3685
  1424
SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
slouken@2967
  1425
{
slouken@3695
  1426
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1427
slouken@5375
  1428
    if (!icon) {
slouken@5375
  1429
        return;
slouken@5375
  1430
    }
slouken@5375
  1431
slouken@2967
  1432
    if (_this->SetWindowIcon) {
slouken@2967
  1433
        _this->SetWindowIcon(_this, window, icon);
slouken@2967
  1434
    }
slouken@2967
  1435
}
slouken@2967
  1436
slouken@5165
  1437
void*
slouken@5165
  1438
SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
slouken@1895
  1439
{
slouken@5165
  1440
    SDL_WindowUserData *prev, *data;
slouken@3695
  1441
slouken@5165
  1442
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@7191
  1443
aschiffler@7046
  1444
    /* Input validation */
aschiffler@7046
  1445
    if (name == NULL || SDL_strlen(name) == 0) {
aschiffler@7046
  1446
      SDL_InvalidParamError("name");
aschiffler@7046
  1447
      return NULL;
aschiffler@7046
  1448
    }
slouken@5165
  1449
slouken@5165
  1450
    /* See if the named data already exists */
slouken@5165
  1451
    prev = NULL;
slouken@5165
  1452
    for (data = window->data; data; prev = data, data = data->next) {
aschiffler@7046
  1453
        if (data->name && SDL_strcmp(data->name, name) == 0) {
slouken@5165
  1454
            void *last_value = data->data;
slouken@5165
  1455
slouken@5165
  1456
            if (userdata) {
slouken@5165
  1457
                /* Set the new value */
slouken@5165
  1458
                data->data = userdata;
slouken@5165
  1459
            } else {
slouken@5165
  1460
                /* Delete this value */
slouken@5165
  1461
                if (prev) {
slouken@5165
  1462
                    prev->next = data->next;
slouken@5165
  1463
                } else {
slouken@5165
  1464
                    window->data = data->next;
slouken@5165
  1465
                }
slouken@5165
  1466
                SDL_free(data->name);
slouken@5165
  1467
                SDL_free(data);
slouken@5165
  1468
            }
slouken@5165
  1469
            return last_value;
slouken@5165
  1470
        }
slouken@5165
  1471
    }
slouken@5165
  1472
slouken@5165
  1473
    /* Add new data to the window */
slouken@5165
  1474
    if (userdata) {
slouken@5165
  1475
        data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
slouken@5165
  1476
        data->name = SDL_strdup(name);
slouken@5165
  1477
        data->data = userdata;
slouken@5165
  1478
        data->next = window->data;
slouken@5165
  1479
        window->data = data;
slouken@5165
  1480
    }
slouken@5165
  1481
    return NULL;
slouken@1895
  1482
}
slouken@1895
  1483
slouken@2753
  1484
void *
slouken@5165
  1485
SDL_GetWindowData(SDL_Window * window, const char *name)
slouken@1895
  1486
{
slouken@5165
  1487
    SDL_WindowUserData *data;
slouken@5165
  1488
slouken@3695
  1489
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@3695
  1490
aschiffler@7046
  1491
    /* Input validation */
aschiffler@7046
  1492
    if (name == NULL || SDL_strlen(name) == 0) {
aschiffler@7046
  1493
      SDL_InvalidParamError("name");
aschiffler@7046
  1494
      return NULL;
aschiffler@7046
  1495
    }
aschiffler@7046
  1496
slouken@5165
  1497
    for (data = window->data; data; data = data->next) {
aschiffler@7046
  1498
        if (data->name && SDL_strcmp(data->name, name) == 0) {
slouken@5165
  1499
            return data->data;
slouken@5165
  1500
        }
slouken@5165
  1501
    }
slouken@5165
  1502
    return NULL;
slouken@1895
  1503
}
slouken@1895
  1504
slouken@1895
  1505
void
slouken@3685
  1506
SDL_SetWindowPosition(SDL_Window * window, int x, int y)
slouken@1895
  1507
{
slouken@3695
  1508
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1509
slouken@7195
  1510
    if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
slouken@7195
  1511
        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@7195
  1512
        int displayIndex;
slouken@7195
  1513
        SDL_Rect bounds;
slouken@7195
  1514
slouken@7195
  1515
        displayIndex = SDL_GetIndexOfDisplay(display);
slouken@7195
  1516
        SDL_GetDisplayBounds(displayIndex, &bounds);
slouken@7195
  1517
        if (SDL_WINDOWPOS_ISCENTERED(x)) {
slouken@7195
  1518
            x = bounds.x + (bounds.w - window->w) / 2;
slouken@7195
  1519
        }
slouken@7195
  1520
        if (SDL_WINDOWPOS_ISCENTERED(y)) {
slouken@7195
  1521
            y = bounds.y + (bounds.h - window->h) / 2;
slouken@7195
  1522
        }
slouken@7195
  1523
    }
slouken@7195
  1524
slouken@5305
  1525
    if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
slouken@2753
  1526
        window->x = x;
slouken@2753
  1527
    }
slouken@5305
  1528
    if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
slouken@2753
  1529
        window->y = y;
slouken@2753
  1530
    }
slouken@7195
  1531
slouken@5246
  1532
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@5246
  1533
        if (_this->SetWindowPosition) {
slouken@5246
  1534
            _this->SetWindowPosition(_this, window);
slouken@5246
  1535
        }
slouken@5246
  1536
        SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@2753
  1537
    }
slouken@1895
  1538
}
slouken@1895
  1539
slouken@1895
  1540
void
slouken@3685
  1541
SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
slouken@1895
  1542
{
slouken@5246
  1543
    CHECK_WINDOW_MAGIC(window, );
slouken@5246
  1544
slouken@5246
  1545
    /* Fullscreen windows are always at their display's origin */
slouken@5246
  1546
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
aschiffler@6956
  1547
        if (x) {
aschiffler@6956
  1548
            *x = 0;
aschiffler@6956
  1549
        }
aschiffler@6956
  1550
        if (y) {
aschiffler@6956
  1551
            *y = 0;
aschiffler@6956
  1552
        }
slouken@5246
  1553
    } else {
slouken@5242
  1554
        if (x) {
slouken@5242
  1555
            *x = window->x;
slouken@5242
  1556
        }
slouken@5242
  1557
        if (y) {
slouken@5242
  1558
            *y = window->y;
slouken@5242
  1559
        }
slouken@2753
  1560
    }
slouken@1895
  1561
}
slouken@1895
  1562
slouken@1895
  1563
void
icculus@6422
  1564
SDL_SetWindowBordered(SDL_Window * window, SDL_bool bordered)
icculus@6422
  1565
{
icculus@6422
  1566
    CHECK_WINDOW_MAGIC(window, );
icculus@6422
  1567
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
icculus@6422
  1568
        const int want = (bordered != SDL_FALSE);  /* normalize the flag. */
icculus@6422
  1569
        const int have = ((window->flags & SDL_WINDOW_BORDERLESS) == 0);
icculus@6422
  1570
        if ((want != have) && (_this->SetWindowBordered)) {
icculus@6422
  1571
            if (want) {
icculus@6422
  1572
                window->flags &= ~SDL_WINDOW_BORDERLESS;
icculus@6422
  1573
            } else {
icculus@6422
  1574
                window->flags |= SDL_WINDOW_BORDERLESS;
icculus@6422
  1575
            }
icculus@6422
  1576
            _this->SetWindowBordered(_this, window, (SDL_bool) want);
icculus@6422
  1577
        }
icculus@6422
  1578
    }
icculus@6422
  1579
}
icculus@6422
  1580
icculus@6422
  1581
void
slouken@3685
  1582
SDL_SetWindowSize(SDL_Window * window, int w, int h)
slouken@1895
  1583
{
slouken@3695
  1584
    CHECK_WINDOW_MAGIC(window, );
aschiffler@6984
  1585
    if (w <= 0) {
aschiffler@6984
  1586
        SDL_InvalidParamError("w");
aschiffler@6984
  1587
        return;
aschiffler@6984
  1588
    }
aschiffler@6984
  1589
    if (h <= 0) {
aschiffler@6984
  1590
        SDL_InvalidParamError("h");
aschiffler@6984
  1591
        return;
aschiffler@6984
  1592
    }
slouken@3695
  1593
slouken@5249
  1594
    /* FIXME: Should this change fullscreen modes? */
slouken@5249
  1595
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@5276
  1596
        window->w = w;
slouken@5276
  1597
        window->h = h;
slouken@5249
  1598
        if (_this->SetWindowSize) {
slouken@5249
  1599
            _this->SetWindowSize(_this, window);
slouken@5249
  1600
        }
slouken@5276
  1601
        if (window->w == w && window->h == h) {
slouken@5276
  1602
            /* We didn't get a SDL_WINDOWEVENT_RESIZED event (by design) */
slouken@5276
  1603
            SDL_OnWindowResized(window);
slouken@5276
  1604
        }
slouken@2753
  1605
    }
slouken@1895
  1606
}
slouken@1895
  1607
slouken@1895
  1608
void
slouken@3685
  1609
SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
slouken@1895
  1610
{
aschiffler@6984
  1611
    CHECK_WINDOW_MAGIC(window, );
aschiffler@6984
  1612
    if (w) {
aschiffler@6984
  1613
        *w = window->w;
slouken@5246
  1614
    }
aschiffler@6984
  1615
    if (h) {
stopiccot@6681
  1616
        *h = window->h;
slouken@7191
  1617
    }
stopiccot@6681
  1618
}
stopiccot@6681
  1619
stopiccot@6681
  1620
void
stopiccot@6681
  1621
SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h)
stopiccot@6681
  1622
{
stopiccot@6681
  1623
    CHECK_WINDOW_MAGIC(window, );
aschiffler@6984
  1624
    if (min_w <= 0) {
aschiffler@6984
  1625
        SDL_InvalidParamError("min_w");
aschiffler@6984
  1626
        return;
aschiffler@6984
  1627
    }
aschiffler@6984
  1628
    if (min_h <= 0) {
aschiffler@6984
  1629
        SDL_InvalidParamError("min_h");
aschiffler@6984
  1630
        return;
aschiffler@6984
  1631
    }
slouken@7191
  1632
stopiccot@6681
  1633
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
stopiccot@6681
  1634
        window->min_w = min_w;
stopiccot@6681
  1635
        window->min_h = min_h;
stopiccot@6681
  1636
        if (_this->SetWindowMinimumSize) {
stopiccot@6681
  1637
            _this->SetWindowMinimumSize(_this, window);
slouken@2849
  1638
        }
stopiccot@6681
  1639
        /* Ensure that window is not smaller than minimal size */
stopiccot@6681
  1640
        SDL_SetWindowSize(window, SDL_max(window->w, window->min_w), SDL_max(window->h, window->min_h));
stopiccot@6681
  1641
    }
stopiccot@6681
  1642
}
stopiccot@6681
  1643
stopiccot@6681
  1644
void
stopiccot@6681
  1645
SDL_GetWindowMinimumSize(SDL_Window * window, int *min_w, int *min_h)
stopiccot@6681
  1646
{
aschiffler@6984
  1647
    CHECK_WINDOW_MAGIC(window, );
aschiffler@6984
  1648
    if (min_w) {
aschiffler@6984
  1649
        *min_w = window->min_w;
stopiccot@6681
  1650
    }
aschiffler@6984
  1651
    if (min_h) {
stopiccot@6681
  1652
        *min_h = window->min_h;
slouken@2753
  1653
    }
slouken@1895
  1654
}
slouken@1895
  1655
slouken@1895
  1656
void
slouken@6788
  1657
SDL_SetWindowMaximumSize(SDL_Window * window, int max_w, int max_h)
slouken@6788
  1658
{
slouken@6788
  1659
    CHECK_WINDOW_MAGIC(window, );
aschiffler@6984
  1660
    if (max_w <= 0) {
aschiffler@6984
  1661
        SDL_InvalidParamError("max_w");
aschiffler@6984
  1662
        return;
aschiffler@6984
  1663
    }
aschiffler@6984
  1664
    if (max_h <= 0) {
aschiffler@6984
  1665
        SDL_InvalidParamError("max_h");
aschiffler@6984
  1666
        return;
aschiffler@6984
  1667
    }
slouken@7191
  1668
slouken@6788
  1669
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@6788
  1670
        window->max_w = max_w;
slouken@6788
  1671
        window->max_h = max_h;
slouken@6788
  1672
        if (_this->SetWindowMaximumSize) {
slouken@6788
  1673
            _this->SetWindowMaximumSize(_this, window);
slouken@6788
  1674
        }
slouken@6788
  1675
        /* Ensure that window is not larger than maximal size */
slouken@6788
  1676
        SDL_SetWindowSize(window, SDL_min(window->w, window->max_w), SDL_min(window->h, window->max_h));
slouken@6788
  1677
    }
slouken@6788
  1678
}
slouken@6788
  1679
slouken@6788
  1680
void
slouken@6788
  1681
SDL_GetWindowMaximumSize(SDL_Window * window, int *max_w, int *max_h)
slouken@6788
  1682
{
aschiffler@6984
  1683
    CHECK_WINDOW_MAGIC(window, );
aschiffler@6984
  1684
    if (max_w) {
aschiffler@6984
  1685
        *max_w = window->max_w;
slouken@6788
  1686
    }
aschiffler@6984
  1687
    if (max_h) {
slouken@6788
  1688
        *max_h = window->max_h;
slouken@6788
  1689
    }
slouken@6788
  1690
}
slouken@6788
  1691
slouken@6788
  1692
void
slouken@3685
  1693
SDL_ShowWindow(SDL_Window * window)
slouken@1895
  1694
{
slouken@3695
  1695
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1696
slouken@3695
  1697
    if (window->flags & SDL_WINDOW_SHOWN) {
slouken@2753
  1698
        return;
slouken@2753
  1699
    }
slouken@1895
  1700
slouken@2753
  1701
    if (_this->ShowWindow) {
slouken@2753
  1702
        _this->ShowWindow(_this, window);
slouken@2753
  1703
    }
slouken@3685
  1704
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@1895
  1705
}
slouken@1895
  1706
slouken@1895
  1707
void
slouken@3685
  1708
SDL_HideWindow(SDL_Window * window)
slouken@1895
  1709
{
slouken@3695
  1710
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1711
slouken@3695
  1712
    if (!(window->flags & SDL_WINDOW_SHOWN)) {
slouken@2753
  1713
        return;
slouken@2753
  1714
    }
slouken@1895
  1715
slouken@5404
  1716
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@5404
  1717
slouken@2753
  1718
    if (_this->HideWindow) {
slouken@2753
  1719
        _this->HideWindow(_this, window);
slouken@2753
  1720
    }
slouken@3685
  1721
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@1895
  1722
}
slouken@1895
  1723
slouken@1895
  1724
void
slouken@3685
  1725
SDL_RaiseWindow(SDL_Window * window)
slouken@1895
  1726
{
slouken@3695
  1727
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1728
slouken@3695
  1729
    if (!(window->flags & SDL_WINDOW_SHOWN)) {
slouken@2753
  1730
        return;
slouken@2753
  1731
    }
slouken@2753
  1732
    if (_this->RaiseWindow) {
slouken@2753
  1733
        _this->RaiseWindow(_this, window);
slouken@2753
  1734
    }
slouken@1895
  1735
}
slouken@1895
  1736
slouken@1895
  1737
void
slouken@3685
  1738
SDL_MaximizeWindow(SDL_Window * window)
slouken@1895
  1739
{
slouken@3695
  1740
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1741
slouken@3695
  1742
    if (window->flags & SDL_WINDOW_MAXIMIZED) {
slouken@2753
  1743
        return;
slouken@2753
  1744
    }
slouken@1895
  1745
slouken@2753
  1746
    if (_this->MaximizeWindow) {
slouken@2753
  1747
        _this->MaximizeWindow(_this, window);
slouken@2753
  1748
    }
slouken@1895
  1749
}
slouken@1895
  1750
slouken@1895
  1751
void
slouken@3685
  1752
SDL_MinimizeWindow(SDL_Window * window)
slouken@1895
  1753
{
slouken@3695
  1754
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1755
slouken@3695
  1756
    if (window->flags & SDL_WINDOW_MINIMIZED) {
slouken@2753
  1757
        return;
slouken@2753
  1758
    }
slouken@1895
  1759
slouken@5404
  1760
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@5404
  1761
slouken@2753
  1762
    if (_this->MinimizeWindow) {
slouken@2753
  1763
        _this->MinimizeWindow(_this, window);
slouken@2753
  1764
    }
slouken@1895
  1765
}
slouken@1895
  1766
slouken@1895
  1767
void
slouken@3685
  1768
SDL_RestoreWindow(SDL_Window * window)
slouken@1895
  1769
{
slouken@3695
  1770
    CHECK_WINDOW_MAGIC(window, );
slouken@3695
  1771
slouken@3695
  1772
    if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
slouken@2753
  1773
        return;
slouken@2753
  1774
    }
slouken@1895
  1775
slouken@2753
  1776
    if (_this->RestoreWindow) {
slouken@2753
  1777
        _this->RestoreWindow(_this, window);
slouken@2753
  1778
    }
slouken@1895
  1779
}
slouken@1895
  1780
slouken@6755
  1781
#define FULLSCREEN_MASK ( SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN )
slouken@1895
  1782
int
slouken@6755
  1783
SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
slouken@1895
  1784
{
slouken@3695
  1785
    CHECK_WINDOW_MAGIC(window, -1);
slouken@3695
  1786
slouken@7191
  1787
    flags &= FULLSCREEN_MASK;
slouken@7191
  1788
slouken@6755
  1789
    if ( flags == (window->flags & FULLSCREEN_MASK) ) {
slouken@2753
  1790
        return 0;
slouken@2753
  1791
    }
slouken@7191
  1792
slouken@7191
  1793
    /* clear the previous flags and OR in the new ones */
slouken@7191
  1794
    window->flags &= ~FULLSCREEN_MASK;
slouken@6755
  1795
    window->flags |= flags;
slouken@6755
  1796
slouken@5404
  1797
    SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
slouken@1895
  1798
slouken@2753
  1799
    return 0;
slouken@1895
  1800
}
slouken@1895
  1801
slouken@5166
  1802
static SDL_Surface *
slouken@5166
  1803
SDL_CreateWindowFramebuffer(SDL_Window * window)
slouken@5166
  1804
{
slouken@5166
  1805
    Uint32 format;
slouken@5166
  1806
    void *pixels;
slouken@5166
  1807
    int pitch;
slouken@5166
  1808
    int bpp;
slouken@5166
  1809
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@5166
  1810
slouken@5166
  1811
    if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
slouken@5166
  1812
        return NULL;
slouken@5166
  1813
    }
slouken@5166
  1814
slouken@5166
  1815
    if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
slouken@5166
  1816
        return NULL;
slouken@5166
  1817
    }
slouken@5166
  1818
slouken@5166
  1819
    if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@5166
  1820
        return NULL;
slouken@5166
  1821
    }
slouken@5166
  1822
slouken@5166
  1823
    return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
slouken@5166
  1824
}
slouken@5166
  1825
slouken@5166
  1826
SDL_Surface *
slouken@5166
  1827
SDL_GetWindowSurface(SDL_Window * window)
slouken@5166
  1828
{
slouken@5166
  1829
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@5166
  1830
slouken@5172
  1831
    if (!window->surface_valid) {
slouken@5172
  1832
        if (window->surface) {
slouken@5288
  1833
            window->surface->flags &= ~SDL_DONTFREE;
slouken@5172
  1834
            SDL_FreeSurface(window->surface);
slouken@5172
  1835
        }
slouken@5166
  1836
        window->surface = SDL_CreateWindowFramebuffer(window);
slouken@5169
  1837
        if (window->surface) {
slouken@5172
  1838
            window->surface_valid = SDL_TRUE;
slouken@5288
  1839
            window->surface->flags |= SDL_DONTFREE;
slouken@5169
  1840
        }
slouken@5166
  1841
    }
slouken@5166
  1842
    return window->surface;
slouken@5166
  1843
}
slouken@5166
  1844
slouken@5166
  1845
int
slouken@5166
  1846
SDL_UpdateWindowSurface(SDL_Window * window)
slouken@5166
  1847
{
slouken@5166
  1848
    SDL_Rect full_rect;
slouken@5166
  1849
slouken@5166
  1850
    CHECK_WINDOW_MAGIC(window, -1);
slouken@5166
  1851
slouken@5166
  1852
    full_rect.x = 0;
slouken@5166
  1853
    full_rect.y = 0;
slouken@5166
  1854
    full_rect.w = window->w;
slouken@5166
  1855
    full_rect.h = window->h;
slouken@5297
  1856
    return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
slouken@5166
  1857
}
slouken@5166
  1858
slouken@5166
  1859
int
slouken@7014
  1860
SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects,
slouken@5297
  1861
                             int numrects)
slouken@5166
  1862
{
slouken@5166
  1863
    CHECK_WINDOW_MAGIC(window, -1);
slouken@5166
  1864
slouken@5172
  1865
    if (!window->surface_valid) {
icculus@7037
  1866
        return SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
slouken@5166
  1867
    }
slouken@5166
  1868
slouken@5297
  1869
    return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
slouken@5166
  1870
}
slouken@5166
  1871
slouken@5466
  1872
int
slouken@5466
  1873
SDL_SetWindowBrightness(SDL_Window * window, float brightness)
slouken@5466
  1874
{
slouken@5466
  1875
    Uint16 ramp[256];
slouken@5466
  1876
    int status;
slouken@5466
  1877
slouken@5466
  1878
    CHECK_WINDOW_MAGIC(window, -1);
slouken@5466
  1879
slouken@5466
  1880
    SDL_CalculateGammaRamp(brightness, ramp);
slouken@5466
  1881
    status = SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
slouken@5466
  1882
    if (status == 0) {
slouken@5466
  1883
        window->brightness = brightness;
slouken@5466
  1884
    }
slouken@5466
  1885
    return status;
slouken@5466
  1886
}
slouken@5466
  1887
slouken@5466
  1888
float
slouken@5466
  1889
SDL_GetWindowBrightness(SDL_Window * window)
slouken@5466
  1890
{
slouken@5466
  1891
    CHECK_WINDOW_MAGIC(window, 1.0f);
slouken@5466
  1892
slouken@5466
  1893
    return window->brightness;
slouken@5466
  1894
}
slouken@5466
  1895
slouken@5466
  1896
int
slouken@5466
  1897
SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
slouken@5466
  1898
                                            const Uint16 * green,
slouken@5466
  1899
                                            const Uint16 * blue)
slouken@5466
  1900
{
slouken@5466
  1901
    CHECK_WINDOW_MAGIC(window, -1);
slouken@5466
  1902
slouken@5466
  1903
    if (!_this->SetWindowGammaRamp) {
icculus@7037
  1904
        return SDL_Unsupported();
slouken@5466
  1905
    }
slouken@5466
  1906
slouken@5466
  1907
    if (!window->gamma) {
slouken@5466
  1908
        if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) {
slouken@5466
  1909
            return -1;
slouken@5466
  1910
        }
slouken@5466
  1911
    }
slouken@5466
  1912
slouken@5466
  1913
    if (red) {
slouken@5466
  1914
        SDL_memcpy(&window->gamma[0*256], red, 256*sizeof(Uint16));
slouken@5466
  1915
    }
slouken@5466
  1916
    if (green) {
slouken@5466
  1917
        SDL_memcpy(&window->gamma[1*256], green, 256*sizeof(Uint16));
slouken@5466
  1918
    }
slouken@5466
  1919
    if (blue) {
slouken@5466
  1920
        SDL_memcpy(&window->gamma[2*256], blue, 256*sizeof(Uint16));
slouken@5466
  1921
    }
slouken@5466
  1922
    if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
slouken@5466
  1923
        return _this->SetWindowGammaRamp(_this, window, window->gamma);
slouken@5466
  1924
    } else {
slouken@5466
  1925
        return 0;
slouken@5466
  1926
    }
slouken@5466
  1927
}
slouken@5466
  1928
slouken@5466
  1929
int
slouken@5466
  1930
SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
slouken@5466
  1931
                                            Uint16 * green,
slouken@5466
  1932
                                            Uint16 * blue)
slouken@5466
  1933
{
slouken@5466
  1934
    CHECK_WINDOW_MAGIC(window, -1);
slouken@5466
  1935
slouken@5466
  1936
    if (!window->gamma) {
slouken@5466
  1937
        int i;
slouken@5466
  1938
slouken@5466
  1939
        window->gamma = (Uint16 *)SDL_malloc(256*6*sizeof(Uint16));
slouken@5466
  1940
        if (!window->gamma) {
icculus@7037
  1941
            return SDL_OutOfMemory();
slouken@5466
  1942
        }
slouken@5466
  1943
        window->saved_gamma = window->gamma + 3*256;
slouken@5466
  1944
slouken@5466
  1945
        if (_this->GetWindowGammaRamp) {
slouken@5466
  1946
            if (_this->GetWindowGammaRamp(_this, window, window->gamma) < 0) {
slouken@5466
  1947
                return -1;
slouken@5466
  1948
            }
slouken@5466
  1949
        } else {
slouken@5466
  1950
            /* Create an identity gamma ramp */
slouken@5466
  1951
            for (i = 0; i < 256; ++i) {
slouken@5466
  1952
                Uint16 value = (Uint16)((i << 8) | i);
slouken@5466
  1953
slouken@5466
  1954
                window->gamma[0*256+i] = value;
slouken@5466
  1955
                window->gamma[1*256+i] = value;
slouken@5466
  1956
                window->gamma[2*256+i] = value;
slouken@5466
  1957
            }
slouken@5466
  1958
        }
slouken@5466
  1959
        SDL_memcpy(window->saved_gamma, window->gamma, 3*256*sizeof(Uint16));
slouken@5466
  1960
    }
slouken@5466
  1961
slouken@5466
  1962
    if (red) {
slouken@5466
  1963
        SDL_memcpy(red, &window->gamma[0*256], 256*sizeof(Uint16));
slouken@5466
  1964
    }
slouken@5466
  1965
    if (green) {
slouken@5466
  1966
        SDL_memcpy(green, &window->gamma[1*256], 256*sizeof(Uint16));
slouken@5466
  1967
    }
slouken@5466
  1968
    if (blue) {
slouken@5466
  1969
        SDL_memcpy(blue, &window->gamma[2*256], 256*sizeof(Uint16));
slouken@5466
  1970
    }
slouken@5466
  1971
    return 0;
slouken@5466
  1972
}
slouken@5466
  1973
slouken@6662
  1974
void
slouken@2876
  1975
SDL_UpdateWindowGrab(SDL_Window * window)
slouken@2875
  1976
{
slouken@6662
  1977
    if (_this->SetWindowGrab) {
slouken@6662
  1978
        SDL_bool grabbed;
slouken@6662
  1979
        if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
slouken@6662
  1980
            (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@6662
  1981
            grabbed = SDL_TRUE;
slouken@6662
  1982
        } else {
slouken@6662
  1983
            grabbed = SDL_FALSE;
slouken@6662
  1984
        }
slouken@6662
  1985
        _this->SetWindowGrab(_this, window, grabbed);
slouken@2753
  1986
    }
slouken@1895
  1987
}
slouken@1895
  1988
slouken@5403
  1989
void
slouken@5403
  1990
SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
slouken@5403
  1991
{
slouken@5403
  1992
    CHECK_WINDOW_MAGIC(window, );
slouken@5403
  1993
slouken@5404
  1994
    if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
slouken@5403
  1995
        return;
slouken@5403
  1996
    }
slouken@5403
  1997
    if (grabbed) {
slouken@5403
  1998
        window->flags |= SDL_WINDOW_INPUT_GRABBED;
slouken@5403
  1999
    } else {
slouken@5403
  2000
        window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
slouken@5403
  2001
    }
slouken@5403
  2002
    SDL_UpdateWindowGrab(window);
slouken@5403
  2003
}
slouken@5403
  2004
slouken@5403
  2005
SDL_bool
slouken@3685
  2006
SDL_GetWindowGrab(SDL_Window * window)
slouken@1895
  2007
{
slouken@5466
  2008
    CHECK_WINDOW_MAGIC(window, SDL_FALSE);
slouken@3695
  2009
slouken@2753
  2010
    return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
slouken@1895
  2011
}
slouken@1895
  2012
slouken@1895
  2013
void
slouken@1895
  2014
SDL_OnWindowShown(SDL_Window * window)
slouken@1895
  2015
{
slouken@5404
  2016
    SDL_OnWindowRestored(window);
slouken@1895
  2017
}
slouken@1895
  2018
slouken@1895
  2019
void
slouken@1895
  2020
SDL_OnWindowHidden(SDL_Window * window)
slouken@1895
  2021
{
slouken@5404
  2022
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@1895
  2023
}
slouken@1895
  2024
slouken@1895
  2025
void
slouken@5166
  2026
SDL_OnWindowResized(SDL_Window * window)
slouken@5166
  2027
{
slouken@5172
  2028
    window->surface_valid = SDL_FALSE;
slouken@5276
  2029
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
slouken@5166
  2030
}
slouken@5166
  2031
slouken@5166
  2032
void
slouken@3502
  2033
SDL_OnWindowMinimized(SDL_Window * window)
slouken@3502
  2034
{
slouken@5404
  2035
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@3502
  2036
}
slouken@3502
  2037
slouken@3502
  2038
void
slouken@3502
  2039
SDL_OnWindowRestored(SDL_Window * window)
slouken@3502
  2040
{
slouken@3685
  2041
    SDL_RaiseWindow(window);
slouken@5404
  2042
slouken@5404
  2043
    if (FULLSCREEN_VISIBLE(window)) {
slouken@5404
  2044
        SDL_UpdateFullscreenMode(window, SDL_TRUE);
slouken@5404
  2045
    }
slouken@3502
  2046
}
slouken@3502
  2047
slouken@3502
  2048
void
jorgen@7089
  2049
SDL_OnWindowEnter(SDL_Window * window)
jorgen@7089
  2050
{
jorgen@7089
  2051
    if (_this->OnWindowEnter) {
jorgen@7089
  2052
        _this->OnWindowEnter(_this, window);
jorgen@7089
  2053
    }
jorgen@7089
  2054
}
jorgen@7089
  2055
jorgen@7089
  2056
void
jorgen@7089
  2057
SDL_OnWindowLeave(SDL_Window * window)
jorgen@7089
  2058
{
jorgen@7089
  2059
}
jorgen@7089
  2060
jorgen@7089
  2061
void
slouken@1895
  2062
SDL_OnWindowFocusGained(SDL_Window * window)
slouken@1895
  2063
{
jorgen@7107
  2064
    SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7107
  2065
slouken@5466
  2066
    if (window->gamma && _this->SetWindowGammaRamp) {
slouken@5466
  2067
        _this->SetWindowGammaRamp(_this, window, window->gamma);
slouken@5466
  2068
    }
slouken@5466
  2069
jorgen@7107
  2070
    if (mouse && mouse->relative_mode) {
jorgen@7107
  2071
        SDL_SetMouseFocus(window);
jorgen@7107
  2072
        SDL_WarpMouseInWindow(window, window->w/2, window->h/2);
jorgen@7107
  2073
    }
jorgen@7107
  2074
slouken@6662
  2075
    SDL_UpdateWindowGrab(window);
slouken@1895
  2076
}
slouken@1895
  2077
slouken@6755
  2078
static SDL_bool ShouldMinimizeOnFocusLoss()
slouken@6755
  2079
{
slouken@7191
  2080
    const char *hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
slouken@7191
  2081
    if (hint) {
slouken@7191
  2082
        if (*hint == '0') {
slouken@7191
  2083
            return SDL_FALSE;
slouken@7191
  2084
        } else {
slouken@7191
  2085
            return SDL_TRUE;
slouken@7191
  2086
        }
slouken@7191
  2087
    }
slouken@7191
  2088
    return SDL_TRUE;
slouken@6755
  2089
}
slouken@6755
  2090
slouken@1895
  2091
void
slouken@1895
  2092
SDL_OnWindowFocusLost(SDL_Window * window)
slouken@1895
  2093
{
slouken@5466
  2094
    if (window->gamma && _this->SetWindowGammaRamp) {
slouken@5466
  2095
        _this->SetWindowGammaRamp(_this, window, window->saved_gamma);
slouken@3512
  2096
    }
slouken@3512
  2097
slouken@6662
  2098
    SDL_UpdateWindowGrab(window);
slouken@5466
  2099
jorgen@7269
  2100
    /* If we're fullscreen and lose focus, minimize unless the hint tells us otherwise */
slouken@7191
  2101
     if ((window->flags & SDL_WINDOW_FULLSCREEN) && ShouldMinimizeOnFocusLoss() ) {
slouken@7191
  2102
            SDL_MinimizeWindow(window);
slouken@5466
  2103
    }
slouken@1895
  2104
}
slouken@1895
  2105
slouken@3685
  2106
SDL_Window *
slouken@1895
  2107
SDL_GetFocusWindow(void)
slouken@1895
  2108
{
slouken@3685
  2109
    SDL_Window *window;
slouken@1895
  2110
slouken@2753
  2111
    if (!_this) {
slouken@3685
  2112
        return NULL;
slouken@3685
  2113
    }
slouken@5246
  2114
    for (window = _this->windows; window; window = window->next) {
slouken@2753
  2115
        if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
slouken@3685
  2116
            return window;
slouken@2753
  2117
        }
slouken@2753
  2118
    }
slouken@3685
  2119
    return NULL;
slouken@1895
  2120
}
slouken@1895
  2121
slouken@1895
  2122
void
slouken@3685
  2123
SDL_DestroyWindow(SDL_Window * window)
slouken@1895
  2124
{
slouken@3685
  2125
    SDL_VideoDisplay *display;
slouken@3685
  2126
slouken@3695
  2127
    CHECK_WINDOW_MAGIC(window, );
slouken@3503
  2128
slouken@6214
  2129
    /* Restore video mode, etc. */
slouken@6214
  2130
    SDL_HideWindow(window);
slouken@6214
  2131
slouken@6214
  2132
    /* Make sure this window no longer has focus */
slouken@6214
  2133
    if (SDL_GetKeyboardFocus() == window) {
slouken@6214
  2134
        SDL_SetKeyboardFocus(NULL);
slouken@6214
  2135
    }
slouken@6214
  2136
    if (SDL_GetMouseFocus() == window) {
slouken@6214
  2137
        SDL_SetMouseFocus(NULL);
slouken@6214
  2138
    }
slouken@6214
  2139
icculus@5563
  2140
    /* make no context current if this is the current context window. */
icculus@5563
  2141
    if (window->flags & SDL_WINDOW_OPENGL) {
icculus@5563
  2142
        if (_this->current_glwin == window) {
slouken@6496
  2143
            SDL_GL_MakeCurrent(window, NULL);
icculus@5563
  2144
        }
icculus@5563
  2145
    }
icculus@5563
  2146
slouken@5169
  2147
    if (window->surface) {
slouken@5288
  2148
        window->surface->flags &= ~SDL_DONTFREE;
slouken@5169
  2149
        SDL_FreeSurface(window->surface);
slouken@5169
  2150
    }
slouken@5166
  2151
    if (_this->DestroyWindowFramebuffer) {
slouken@5166
  2152
        _this->DestroyWindowFramebuffer(_this, window);
slouken@5166
  2153
    }
slouken@3685
  2154
    if (_this->DestroyWindow) {
slouken@3685
  2155
        _this->DestroyWindow(_this, window);
slouken@3685
  2156
    }
slouken@3685
  2157
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@3685
  2158
        SDL_GL_UnloadLibrary();
slouken@3685
  2159
    }
slouken@3685
  2160
slouken@5246
  2161
    display = SDL_GetDisplayForWindow(window);
slouken@5246
  2162
    if (display->fullscreen_window == window) {
slouken@5246
  2163
        display->fullscreen_window = NULL;
slouken@5246
  2164
    }
slouken@5246
  2165
slouken@4901
  2166
    /* Now invalidate magic */
slouken@4897
  2167
    window->magic = NULL;
slouken@4897
  2168
slouken@5165
  2169
    /* Free memory associated with the window */
slouken@5165
  2170
    if (window->title) {
slouken@5165
  2171
        SDL_free(window->title);
slouken@5165
  2172
    }
slouken@5466
  2173
    if (window->gamma) {
slouken@5466
  2174
        SDL_free(window->gamma);
slouken@5466
  2175
    }
slouken@5165
  2176
    while (window->data) {
slouken@5165
  2177
        SDL_WindowUserData *data = window->data;
slouken@5165
  2178
slouken@5165
  2179
        window->data = data->next;
slouken@5165
  2180
        SDL_free(data->name);
slouken@5165
  2181
        SDL_free(data);
slouken@5165
  2182
    }
slouken@5165
  2183
slouken@3685
  2184
    /* Unlink the window from the list */
slouken@3693
  2185
    if (window->next) {
slouken@3693
  2186
        window->next->prev = window->prev;
slouken@3693
  2187
    }
slouken@3685
  2188
    if (window->prev) {
slouken@3685
  2189
        window->prev->next = window->next;
slouken@3685
  2190
    } else {
slouken@5246
  2191
        _this->windows = window->next;
slouken@3685
  2192
    }
slouken@3685
  2193
slouken@3685
  2194
    SDL_free(window);
slouken@1895
  2195
}
slouken@1895
  2196
slouken@3025
  2197
SDL_bool
slouken@3025
  2198
SDL_IsScreenSaverEnabled()
slouken@3025
  2199
{
slouken@3025
  2200
    if (!_this) {
slouken@3025
  2201
        return SDL_TRUE;
slouken@3025
  2202
    }
slouken@3025
  2203
    return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
slouken@3025
  2204
}
slouken@3025
  2205
slouken@3025
  2206
void
slouken@3025
  2207
SDL_EnableScreenSaver()
slouken@3025
  2208
{
slouken@3025
  2209
    if (!_this) {
slouken@3025
  2210
        return;
slouken@3025
  2211
    }
slouken@3025
  2212
    if (!_this->suspend_screensaver) {
slouken@3025
  2213
        return;
slouken@3025
  2214
    }
slouken@3025
  2215
    _this->suspend_screensaver = SDL_FALSE;
slouken@3025
  2216
    if (_this->SuspendScreenSaver) {
slouken@3025
  2217
        _this->SuspendScreenSaver(_this);
slouken@3025
  2218
    }
slouken@3025
  2219
}
slouken@3025
  2220
slouken@3025
  2221
void
slouken@3025
  2222
SDL_DisableScreenSaver()
slouken@3025
  2223
{
slouken@3025
  2224
    if (!_this) {
slouken@3025
  2225
        return;
slouken@3025
  2226
    }
slouken@3025
  2227
    if (_this->suspend_screensaver) {
slouken@3025
  2228
        return;
slouken@3025
  2229
    }
slouken@3025
  2230
    _this->suspend_screensaver = SDL_TRUE;
slouken@3025
  2231
    if (_this->SuspendScreenSaver) {
slouken@3025
  2232
        _this->SuspendScreenSaver(_this);
slouken@3025
  2233
    }
slouken@3025
  2234
}
slouken@3025
  2235
slouken@1895
  2236
void
slouken@1895
  2237
SDL_VideoQuit(void)
slouken@1895
  2238
{
slouken@2753
  2239
    int i, j;
slouken@1895
  2240
slouken@2753
  2241
    if (!_this) {
slouken@2753
  2242
        return;
slouken@2753
  2243
    }
slouken@5123
  2244
slouken@2753
  2245
    /* Halt event processing before doing anything else */
slouken@7360
  2246
    SDL_TouchQuit();
slouken@5123
  2247
    SDL_MouseQuit();
slouken@5123
  2248
    SDL_KeyboardQuit();
slouken@7360
  2249
    SDL_QuitSubSystem(SDL_INIT_EVENTS);
slouken@5123
  2250
slouken@3029
  2251
    SDL_EnableScreenSaver();
slouken@1895
  2252
slouken@2753
  2253
    /* Clean up the system video */
slouken@5246
  2254
    while (_this->windows) {
slouken@5246
  2255
        SDL_DestroyWindow(_this->windows);
slouken@2753
  2256
    }
slouken@2753
  2257
    _this->VideoQuit(_this);
slouken@1895
  2258
slouken@2753
  2259
    for (i = _this->num_displays; i--;) {
slouken@2753
  2260
        SDL_VideoDisplay *display = &_this->displays[i];
slouken@2753
  2261
        for (j = display->num_display_modes; j--;) {
slouken@2753
  2262
            if (display->display_modes[j].driverdata) {
slouken@2753
  2263
                SDL_free(display->display_modes[j].driverdata);
slouken@2753
  2264
                display->display_modes[j].driverdata = NULL;
slouken@2753
  2265
            }
slouken@2753
  2266
        }
slouken@2753
  2267
        if (display->display_modes) {
slouken@2753
  2268
            SDL_free(display->display_modes);
slouken@2753
  2269
            display->display_modes = NULL;
slouken@2753
  2270
        }
slouken@2753
  2271
        if (display->desktop_mode.driverdata) {
slouken@2753
  2272
            SDL_free(display->desktop_mode.driverdata);
slouken@2753
  2273
            display->desktop_mode.driverdata = NULL;
slouken@2753
  2274
        }
slouken@2753
  2275
        if (display->driverdata) {
slouken@2753
  2276
            SDL_free(display->driverdata);
slouken@2753
  2277
            display->driverdata = NULL;
slouken@2753
  2278
        }
slouken@2753
  2279
    }
slouken@2753
  2280
    if (_this->displays) {
slouken@6787
  2281
        for (i = 0; i < _this->num_displays; ++i) {
slouken@6787
  2282
            SDL_free(_this->displays[i].name);
slouken@6787
  2283
        }
slouken@2753
  2284
        SDL_free(_this->displays);
slouken@2753
  2285
        _this->displays = NULL;
slouken@6787
  2286
        _this->num_displays = 0;
slouken@2753
  2287
    }
slouken@4495
  2288
    if (_this->clipboard_text) {
slouken@4495
  2289
        SDL_free(_this->clipboard_text);
slouken@4495
  2290
        _this->clipboard_text = NULL;
slouken@4495
  2291
    }
slouken@2753
  2292
    _this->free(_this);
slouken@2753
  2293
    _this = NULL;
slouken@0
  2294
}
slouken@0
  2295
slouken@1895
  2296
int
slouken@1895
  2297
SDL_GL_LoadLibrary(const char *path)
slouken@0
  2298
{
slouken@2753
  2299
    int retval;
slouken@0
  2300
slouken@2753
  2301
    if (!_this) {
icculus@7037
  2302
        return SDL_UninitializedVideo();
slouken@2753
  2303
    }
slouken@3057
  2304
    if (_this->gl_config.driver_loaded) {
slouken@3057
  2305
        if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
icculus@7037
  2306
            return SDL_SetError("OpenGL library already loaded");
slouken@3057
  2307
        }
slouken@3057
  2308
        retval = 0;
slouken@3057
  2309
    } else {
slouken@3057
  2310
        if (!_this->GL_LoadLibrary) {
icculus@7037
  2311
            return  SDL_SetError("No dynamic GL support in video driver");
slouken@3057
  2312
        }
slouken@2753
  2313
        retval = _this->GL_LoadLibrary(_this, path);
slouken@3057
  2314
    }
slouken@3057
  2315
    if (retval == 0) {
slouken@3057
  2316
        ++_this->gl_config.driver_loaded;
slouken@2753
  2317
    }
slouken@2753
  2318
    return (retval);
slouken@0
  2319
}
slouken@0
  2320
slouken@2753
  2321
void *
slouken@1895
  2322
SDL_GL_GetProcAddress(const char *proc)
slouken@0
  2323
{
slouken@2753
  2324
    void *func;
slouken@0
  2325
slouken@2753
  2326
    if (!_this) {
slouken@2753
  2327
        SDL_UninitializedVideo();
slouken@2753
  2328
        return NULL;
slouken@2753
  2329
    }
slouken@2753
  2330
    func = NULL;
slouken@2753
  2331
    if (_this->GL_GetProcAddress) {
slouken@2753
  2332
        if (_this->gl_config.driver_loaded) {
slouken@2753
  2333
            func = _this->GL_GetProcAddress(_this, proc);
slouken@2753
  2334
        } else {
slouken@2753
  2335
            SDL_SetError("No GL driver has been loaded");
slouken@2753
  2336
        }
slouken@2753
  2337
    } else {
slouken@2753
  2338
        SDL_SetError("No dynamic GL support in video driver");
slouken@2753
  2339
    }
slouken@2753
  2340
    return func;
slouken@0
  2341
}
slouken@0
  2342
slouken@3057
  2343
void
slouken@3057
  2344
SDL_GL_UnloadLibrary(void)
slouken@3057
  2345
{
slouken@3057
  2346
    if (!_this) {
slouken@3057
  2347
        SDL_UninitializedVideo();
slouken@3057
  2348
        return;
slouken@3057
  2349
    }
slouken@3057
  2350
    if (_this->gl_config.driver_loaded > 0) {
slouken@3057
  2351
        if (--_this->gl_config.driver_loaded > 0) {
slouken@3057
  2352
            return;
slouken@3057
  2353
        }
slouken@3057
  2354
        if (_this->GL_UnloadLibrary) {
slouken@3057
  2355
            _this->GL_UnloadLibrary(_this);
slouken@3057
  2356
        }
slouken@3057
  2357
    }
slouken@3057
  2358
}
slouken@3057
  2359
icculus@7210
  2360
static __inline__ SDL_bool
icculus@7210
  2361
isAtLeastGL3(const char *verstr)
icculus@7210
  2362
{
icculus@7210
  2363
    return ( verstr && (SDL_atoi(verstr) >= 3) );
icculus@7210
  2364
}
icculus@7210
  2365
slouken@1926
  2366
SDL_bool
slouken@1926
  2367
SDL_GL_ExtensionSupported(const char *extension)
slouken@1926
  2368
{
slouken@5209
  2369
#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@2753
  2370
    const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
slouken@2753
  2371
    const char *extensions;
slouken@2753
  2372
    const char *start;
slouken@2753
  2373
    const char *where, *terminator;
slouken@1926
  2374
slouken@2753
  2375
    /* Extension names should not have spaces. */
slouken@2753
  2376
    where = SDL_strchr(extension, ' ');
slouken@2753
  2377
    if (where || *extension == '\0') {
slouken@2753
  2378
        return SDL_FALSE;
slouken@2753
  2379
    }
slouken@2753
  2380
    /* See if there's an environment variable override */
slouken@2753
  2381
    start = SDL_getenv(extension);
slouken@2753
  2382
    if (start && *start == '0') {
slouken@2753
  2383
        return SDL_FALSE;
slouken@2753
  2384
    }
icculus@7210
  2385
slouken@2753
  2386
    /* Lookup the available extensions */
icculus@7210
  2387
slouken@2753
  2388
    glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
icculus@7210
  2389
    if (!glGetStringFunc) {
icculus@7210
  2390
        return SDL_FALSE;
slouken@2753
  2391
    }
icculus@7210
  2392
icculus@7210
  2393
    if (isAtLeastGL3((const char *) glGetStringFunc(GL_VERSION))) {
icculus@7210
  2394
        const GLubyte *(APIENTRY * glGetStringiFunc) (GLenum, GLuint);
icculus@7210
  2395
        void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
icculus@7210
  2396
        GLint num_exts = 0;
icculus@7210
  2397
        GLint i;
icculus@7210
  2398
icculus@7210
  2399
        glGetStringiFunc = SDL_GL_GetProcAddress("glGetStringi");
icculus@7210
  2400
        glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
icculus@7210
  2401
        if ((!glGetStringiFunc) || (!glGetIntegervFunc)) {
icculus@7210
  2402
            return SDL_FALSE;
icculus@7210
  2403
        }
icculus@7210
  2404
icculus@7212
  2405
        #ifndef GL_NUM_EXTENSIONS
icculus@7212
  2406
        #define GL_NUM_EXTENSIONS 0x821D
icculus@7212
  2407
        #endif
icculus@7210
  2408
        glGetIntegervFunc(GL_NUM_EXTENSIONS, &num_exts);
icculus@7210
  2409
        for (i = 0; i < num_exts; i++) {
icculus@7210
  2410
            const char *thisext = (const char *) glGetStringiFunc(GL_EXTENSIONS, i);
icculus@7210
  2411
            if (SDL_strcmp(thisext, extension) == 0) {
icculus@7210
  2412
                return SDL_TRUE;
icculus@7210
  2413
            }
icculus@7210
  2414
        }
icculus@7210
  2415
icculus@7210
  2416
        return SDL_FALSE;
icculus@7210
  2417
    }
icculus@7210
  2418
icculus@7210
  2419
    /* Try the old way with glGetString(GL_EXTENSIONS) ... */
icculus@7210
  2420
icculus@7210
  2421
    extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
slouken@2753
  2422
    if (!extensions) {
slouken@2753
  2423
        return SDL_FALSE;
slouken@2753
  2424
    }
slouken@2753
  2425
    /*
slouken@2753
  2426
     * It takes a bit of care to be fool-proof about parsing the OpenGL
slouken@2753
  2427
     * extensions string. Don't be fooled by sub-strings, etc.
slouken@2753
  2428
     */
slouken@1926
  2429
slouken@2753
  2430
    start = extensions;
slouken@1926
  2431
slouken@2753
  2432
    for (;;) {
slouken@2753
  2433
        where = SDL_strstr(start, extension);
slouken@2753
  2434
        if (!where)
slouken@2753
  2435
            break;
slouken@1926
  2436
slouken@2753
  2437
        terminator = where + SDL_strlen(extension);
slouken@2753
  2438
        if (where == start || *(where - 1) == ' ')
slouken@2753
  2439
            if (*terminator == ' ' || *terminator == '\0')
slouken@2753
  2440
                return SDL_TRUE;
slouken@1926
  2441
slouken@2753
  2442
        start = terminator;
slouken@2753
  2443
    }
slouken@2753
  2444
    return SDL_FALSE;
slouken@1926
  2445
#else
slouken@2753
  2446
    return SDL_FALSE;
slouken@1926
  2447
#endif
slouken@1926
  2448
}
slouken@1926
  2449
slouken@1895
  2450
int
slouken@1895
  2451
SDL_GL_SetAttribute(SDL_GLattr attr, int value)
slouken@0
  2452
{
slouken@5209
  2453
#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@2753
  2454
    int retval;
slouken@0
  2455
slouken@2753
  2456
    if (!_this) {
icculus@7037
  2457
        return SDL_UninitializedVideo();
slouken@2753
  2458
    }
slouken@2753
  2459
    retval = 0;
slouken@2753
  2460
    switch (attr) {
slouken@2753
  2461
    case SDL_GL_RED_SIZE:
slouken@2753
  2462
        _this->gl_config.red_size = value;
slouken@2753
  2463
        break;
slouken@2753
  2464
    case SDL_GL_GREEN_SIZE:
slouken@2753
  2465
        _this->gl_config.green_size = value;
slouken@2753
  2466
        break;
slouken@2753
  2467
    case SDL_GL_BLUE_SIZE:
slouken@2753
  2468
        _this->gl_config.blue_size = value;
slouken@2753
  2469
        break;
slouken@2753
  2470
    case SDL_GL_ALPHA_SIZE:
slouken@2753
  2471
        _this->gl_config.alpha_size = value;
slouken@2753
  2472
        break;
slouken@2753
  2473
    case SDL_GL_DOUBLEBUFFER:
slouken@2753
  2474
        _this->gl_config.double_buffer = value;
slouken@2753
  2475
        break;
slouken@2753
  2476
    case SDL_GL_BUFFER_SIZE:
slouken@2753
  2477
        _this->gl_config.buffer_size = value;
slouken@2753
  2478
        break;
slouken@2753
  2479
    case SDL_GL_DEPTH_SIZE:
slouken@2753
  2480
        _this->gl_config.depth_size = value;
slouken@2753
  2481
        break;
slouken@2753
  2482
    case SDL_GL_STENCIL_SIZE:
slouken@2753
  2483
        _this->gl_config.stencil_size = value;
slouken@2753
  2484
        break;
slouken@2753
  2485
    case SDL_GL_ACCUM_RED_SIZE:
slouken@2753
  2486
        _this->gl_config.accum_red_size = value;
slouken@2753
  2487
        break;
slouken@2753
  2488
    case SDL_GL_ACCUM_GREEN_SIZE:
slouken@2753
  2489
        _this->gl_config.accum_green_size = value;
slouken@2753
  2490
        break;
slouken@2753
  2491
    case SDL_GL_ACCUM_BLUE_SIZE:
slouken@2753
  2492
        _this->gl_config.accum_blue_size = value;
slouken@2753
  2493
        break;
slouken@2753
  2494
    case SDL_GL_ACCUM_ALPHA_SIZE:
slouken@2753
  2495
        _this->gl_config.accum_alpha_size = value;
slouken@2753
  2496
        break;
slouken@2753
  2497
    case SDL_GL_STEREO:
slouken@2753
  2498
        _this->gl_config.stereo = value;
slouken@2753
  2499
        break;
slouken@2753
  2500
    case SDL_GL_MULTISAMPLEBUFFERS:
slouken@2753
  2501
        _this->gl_config.multisamplebuffers = value;
slouken@2753
  2502
        break;
slouken@2753
  2503
    case SDL_GL_MULTISAMPLESAMPLES:
slouken@2753
  2504
        _this->gl_config.multisamplesamples = value;
slouken@2753
  2505
        break;
slouken@2753
  2506
    case SDL_GL_ACCELERATED_VISUAL:
slouken@2753
  2507
        _this->gl_config.accelerated = value;
slouken@2753
  2508
        break;
slouken@2753
  2509
    case SDL_GL_RETAINED_BACKING:
slouken@2753
  2510
        _this->gl_config.retained_backing = value;
slouken@2753
  2511
        break;
slouken@3100
  2512
    case SDL_GL_CONTEXT_MAJOR_VERSION:
slouken@3100
  2513
        _this->gl_config.major_version = value;
slouken@3100
  2514
        break;
slouken@3100
  2515
    case SDL_GL_CONTEXT_MINOR_VERSION:
slouken@3100
  2516
        _this->gl_config.minor_version = value;
slouken@3100
  2517
        break;
slouken@6370
  2518
    case SDL_GL_CONTEXT_EGL:
slouken@6370
  2519
        _this->gl_config.use_egl = value;
slouken@6370
  2520
        break;
slouken@6296
  2521
    case SDL_GL_CONTEXT_FLAGS:
slouken@6393
  2522
        if( value & ~(SDL_GL_CONTEXT_DEBUG_FLAG |
slouken@7191
  2523
              SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG |
slouken@7191
  2524
              SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG |
slouken@7191
  2525
              SDL_GL_CONTEXT_RESET_ISOLATION_FLAG) ) {
slouken@7191
  2526
        retval = SDL_SetError("Unknown OpenGL context flag %d", value);
slouken@7191
  2527
        break;
slouken@7191
  2528
    }
slouken@6296
  2529
        _this->gl_config.flags = value;
slouken@6296
  2530
        break;
slouken@6296
  2531
    case SDL_GL_CONTEXT_PROFILE_MASK:
slouken@6393
  2532
        if( value != 0 &&
slouken@7191
  2533
        value != SDL_GL_CONTEXT_PROFILE_CORE &&
slouken@7191
  2534
        value != SDL_GL_CONTEXT_PROFILE_COMPATIBILITY &&
slouken@7191
  2535
        value != SDL_GL_CONTEXT_PROFILE_ES ) {
slouken@7191
  2536
        retval = SDL_SetError("Unknown OpenGL context profile %d", value);
slouken@7191
  2537
        break;
slouken@7191
  2538
    }
slouken@6296
  2539
        _this->gl_config.profile_mask = value;
slouken@6296
  2540
        break;
slouken@6393
  2541
    case SDL_GL_SHARE_WITH_CURRENT_CONTEXT:
slouken@6393
  2542
        _this->gl_config.share_with_current_context = value;
slouken@7191
  2543
    break;
slouken@2753
  2544
    default:
icculus@7037
  2545
        retval = SDL_SetError("Unknown OpenGL attribute");
slouken@2753
  2546
        break;
slouken@2753
  2547
    }
slouken@2753
  2548
    return retval;
slouken@1936
  2549
#else
icculus@7037
  2550
    return SDL_Unsupported();
slouken@2753
  2551
#endif /* SDL_VIDEO_OPENGL */
slouken@0
  2552
}
slouken@0
  2553
slouken@1895
  2554
int
slouken@1936
  2555
SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
slouken@0
  2556
{
slouken@5209
  2557
#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@2753
  2558
    void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
slouken@3139
  2559
    GLenum(APIENTRY * glGetErrorFunc) (void);
slouken@2753
  2560
    GLenum attrib = 0;
slouken@3099
  2561
    GLenum error = 0;
slouken@1912
  2562
slouken@2753
  2563
    glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
slouken@2753
  2564
    if (!glGetIntegervFunc) {
slouken@2753
  2565
        return -1;
slouken@2753
  2566
    }
slouken@3099
  2567
slouken@3099
  2568
    glGetErrorFunc = SDL_GL_GetProcAddress("glGetError");
slouken@3099
  2569
    if (!glGetErrorFunc) {
slouken@3099
  2570
        return -1;
slouken@3099
  2571
    }
slouken@3099
  2572
slouken@3099
  2573
    /* Clear value in any case */
slouken@3139
  2574
    *value = 0;
slouken@3099
  2575
slouken@2753
  2576
    switch (attr) {
slouken@2753
  2577
    case SDL_GL_RED_SIZE:
slouken@2753
  2578
        attrib = GL_RED_BITS;
slouken@2753
  2579
        break;
slouken@2753
  2580
    case SDL_GL_BLUE_SIZE:
slouken@2753
  2581
        attrib = GL_BLUE_BITS;
slouken@2753
  2582
        break;
slouken@2753
  2583
    case SDL_GL_GREEN_SIZE:
slouken@2753
  2584
        attrib = GL_GREEN_BITS;
slouken@2753
  2585
        break;
slouken@2753
  2586
    case SDL_GL_ALPHA_SIZE:
slouken@2753
  2587
        attrib = GL_ALPHA_BITS;
slouken@2753
  2588
        break;
slouken@2753
  2589
    case SDL_GL_DOUBLEBUFFER:
slouken@5209
  2590
#if SDL_VIDEO_OPENGL
slouken@2753
  2591
        attrib = GL_DOUBLEBUFFER;
slouken@2753
  2592
        break;
hfutrell@2745
  2593
#else
slouken@3099
  2594
        /* OpenGL ES 1.0 and above specifications have EGL_SINGLE_BUFFER      */
slouken@3099
  2595
        /* parameter which switches double buffer to single buffer. OpenGL ES */
slouken@3099
  2596
        /* SDL driver must set proper value after initialization              */
slouken@3099
  2597
        *value = _this->gl_config.double_buffer;
slouken@2753
  2598
        return 0;
hfutrell@2745
  2599
#endif
slouken@2753
  2600
    case SDL_GL_DEPTH_SIZE:
slouken@2753
  2601
        attrib = GL_DEPTH_BITS;
slouken@2753
  2602
        break;
slouken@2753
  2603
    case SDL_GL_STENCIL_SIZE:
slouken@2753
  2604
        attrib = GL_STENCIL_BITS;
slouken@2753
  2605
        break;
slouken@5209
  2606
#if SDL_VIDEO_OPENGL
slouken@2753
  2607
    case SDL_GL_ACCUM_RED_SIZE:
slouken@2753
  2608
        attrib = GL_ACCUM_RED_BITS;
slouken@2753
  2609
        break;
slouken@2753
  2610
    case SDL_GL_ACCUM_GREEN_SIZE:
slouken@2753
  2611
        attrib = GL_ACCUM_GREEN_BITS;
slouken@2753
  2612
        break;
slouken@2753
  2613
    case SDL_GL_ACCUM_BLUE_SIZE:
slouken@2753
  2614
        attrib = GL_ACCUM_BLUE_BITS;
slouken@2753
  2615
        break;
slouken@2753
  2616
    case SDL_GL_ACCUM_ALPHA_SIZE:
slouken@2753
  2617
        attrib = GL_ACCUM_ALPHA_BITS;
slouken@2753
  2618
        break;
slouken@2753
  2619
    case SDL_GL_STEREO:
slouken@2753
  2620
        attrib = GL_STEREO;
slouken@2753
  2621
        break;
hfutrell@2745
  2622
#else
slouken@2753
  2623
    case SDL_GL_ACCUM_RED_SIZE:
slouken@2753
  2624
    case SDL_GL_ACCUM_GREEN_SIZE:
slouken@2753
  2625
    case SDL_GL_ACCUM_BLUE_SIZE:
slouken@2753
  2626
    case SDL_GL_ACCUM_ALPHA_SIZE:
slouken@2753
  2627
    case SDL_GL_STEREO:
slouken@2753
  2628
        /* none of these are supported in OpenGL ES */
slouken@2753
  2629
        *value = 0;
slouken@2753
  2630
        return 0;
hfutrell@2745
  2631
#endif
slouken@2753
  2632
    case SDL_GL_MULTISAMPLEBUFFERS:
slouken@5209
  2633
#if SDL_VIDEO_OPENGL
slouken@2753
  2634
        attrib = GL_SAMPLE_BUFFERS_ARB;
hfutrell@2745
  2635
#else
slouken@2753
  2636
        attrib = GL_SAMPLE_BUFFERS;
hfutrell@2745
  2637
#endif
slouken@2753
  2638
        break;
slouken@2753
  2639
    case SDL_GL_MULTISAMPLESAMPLES:
slouken@5209
  2640
#if SDL_VIDEO_OPENGL
slouken@2753
  2641
        attrib = GL_SAMPLES_ARB;
hfutrell@2745
  2642
#else
slouken@2753
  2643
        attrib = GL_SAMPLES;
hfutrell@2745
  2644
#endif
slouken@2753
  2645
        break;
slouken@2753
  2646
    case SDL_GL_BUFFER_SIZE:
slouken@2753
  2647
        {
slouken@2753
  2648
            GLint bits = 0;
slouken@2753
  2649
            GLint component;
slouken@1936
  2650
slouken@2753
  2651
            /*
slouken@2753
  2652
             * there doesn't seem to be a single flag in OpenGL
slouken@2753
  2653
             * for this!
slouken@2753
  2654
             */
slouken@2753
  2655
            glGetIntegervFunc(GL_RED_BITS, &component);
slouken@2753
  2656
            bits += component;
slouken@2753
  2657
            glGetIntegervFunc(GL_GREEN_BITS, &component);
slouken@2753
  2658
            bits += component;
slouken@2753
  2659
<