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