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