src/video/SDL_video.c
author Pierre-Loup A. Griffais <pgriffais@valvesoftware.com>
Wed, 26 Mar 2014 12:54:51 -0700
changeset 8683 79527cb2cf8a
parent 8671 5e7004e87dec
child 8684 fd192408b830
permissions -rw-r--r--
Remove the RaiseWindow call from OnWindowRestored for now.

It seems like a net improvement in all the scenarios Sam and I could
think of, and looking at hg history it was added for fullscreen
window management specifically. Much of that code has changed since
then, but maybe it needs to stay there for that and simply be moved
to a fullscreen condition check.

It would solve this issue:

https://bugzilla.libsdl.org/show_bug.cgi?id=2439

As well as cases where on SteamOS, we hide/show specific Steam
overlay windows while expecting them to stay in the background, since
changing the window stacking order really angers the NVIDIA driver.

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