src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 13 Sep 2014 02:15:18 -0700
changeset 9135 6cd8e6b54f4d
parent 9127 a8c38ed1a674
child 9163 d05b5b2775ae
permissions -rw-r--r--
Fixed bug 2415 - Message Boxes aren't implemented on Android

Philipp Wiesemann

I attached a patch for an incomplete implementation of the messagebox parts.

It was not tested on lots of devices yet and features a very fragile workaround to block the calling SDL thread while the dialog is handled on Android's UI thread. Although it works for testmessage.c I assume there are lot of situations were it may fail (standby, device rotation and other changes). Also not all flags and colors are implemented.

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