src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 18 Jul 2012 15:17:27 -0700
changeset 6370 93187f7f7d5d
parent 6296 b42657486c0d
child 6382 64d54101773a
permissions -rwxr-xr-x
Improved simultaneous support for OpenGL and OpenGL ES

From Scott Percival

Okay, I think I have something for this. Tested it on GL and GLES
machines, it seems to work okay.

- Add a new SDL GL attribute SDL_GL_CONTEXT_EGL:
- Only useful for the X11 video driver at the moment
- Set to 1 for an EGL context, 0 to use the default for the video driver
- Default is 0, unless library is built for EGL only
- Should be set after SDL init, but before window/context
creation (i.e. same place you'd specify attributes for major/minor GL
version)
- After a lot of agony pondering the least-terrible way to go about
it, made it so that X11_GL_LoadLibrary and X11_GLES_LoadLibrary check
SDL_GL_CONTEXT_EGL. If no GL context exists yet, and the attribute
choice doesn't match with the checking function, then it changes all
the function pointers in the video driver and passes control on to the
new LoadLibrary method.
- Likewise, make X11_CreateWindow check this attribute before firing
off a call to X11_GL_GetVisual/X11_GLES_GetVisual
- Added a sanity check to the start of X11_GL_LoadLibrary
- Tidied up SDL_x11opengles.h
- Moved ownership of the gles_data structure over to
X11_GLES_LoadLibrary/UnloadLibrary
- Should incorporate the 3 fixes posted by Andre Heider

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