src/video/SDL_video.c
author Jørgen P. Tjernø <jorgen@valvesoftware.com>
Wed, 24 Apr 2013 12:20:51 -0700
changeset 7107 2fcf7bf1d2b2
parent 7091 ff07fad908f8
child 7112 a1a723edea64
permissions -rw-r--r--
Move cursor into window when enabling relative mode or gaining focus in relative mode.

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