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