src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 08 Jan 2012 02:23:37 -0500
changeset 6188 e82023802002
parent 6174 5f221b7a5952
child 6214 b1a71f8189a6
permissions -rwxr-xr-x
Fixed bug 1242 - PATCH: Improve support for OpenGL ES under X11

Scott Percival 2011-07-03 06:41:51 PDT

This submission is aimed at making life easier for OpenGL ES capable devices
running a X11 stack (e.g. Maemo, Meego, TrimSlice, other ARM SoC boards not
running Android). SDL's Pandora support already has the neccesary GLES-to-X11
glue code, however it's all ghetto'd off in Makefile.pandora and not very
flexible.

The patch:
- adds an awesome --enable-video-opengles option to configure
- re-modifies the opengles and opengles2 SDL_renderers to use function pointers
- no idea why this was removed?
- for SDL_Renderers, links in libGLESv1_CM, libGLES_CM (for PowerVR fans) or
libGLESv2 at runtime
- links in libEGL.so at runtime - the old code made an assumption that
eglFunctions could be pulled from the active GLES library, PowerVR for one
doesn't let you do that with their libGLESv2
- allows you to pick which of GLES v1 or v2 to load via
SDL_GL_CONTEXT_MAJOR_VERSION

So far I've tested this on a Nokia N900 (OMAP 3430/SGX 530 running Maemo 5) and
a Toshiba AC100 (Tegra 2 running Ubuntu 10.10). I haven't tested it on... well,
everything that isn't those two, such as a Pandora, iOS or Android device. The
Pandora specific code should be kept intact (fingers crossed), and nothing
painfully drastic has been added to the SDL_renderers. The library loading
sequence in SDL_x11opengles has been updated to accomodate both NVIDIA's
propensity to let developers get away with murder and PowerVR's alternative of
punishing every missed step.

The test apps work okay with GLES or GLES2 as the renderer. For some reason
alpha blending doesn't seem to work on the Tegra 2; last week NVIDIA pushed out
a new set of X11 GLES drivers, so I'll try and investigate once I upgrade
those. Also, this patch adds things to configure.in, include/SDL_config.h.in
and test/configure.in. I didn't know what the policy was re. committing
generated spaghetti from autotools, so ./autogen.sh has to be run again. Sorry.

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