src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 20 Dec 2008 12:00:00 +0000
changeset 2884 9dde605c7540
parent 2876 3fcb0d447bcd
child 2885 ca6499468250
permissions -rw-r--r--
Date: Fri, 19 Dec 2008 20:17:35 +0100
From: Couriersud
Subject: Re: Aw: Experience using SDL1.3 in sdlmame/Proposal for api additions

> For consistency you'd probably want:
> SDL_SetRenderDrawColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
> SDL_SetRenderDrawBlendMode(SDL_BlendMode blendMode);
> SDL_RenderLine(int x1, int y1, int x2, int y2);
> SDL_RenderFill(SDL_Rect *rect);
>
> You probably also want to add API functions query the current state.
>

I have implemented the above api for the opengl, x11, directfb and
software renderers. I have also renamed *TEXTUREBLENDMODE* constants to
BLENDMODE*. The unix build compiles. The windows renderer still needs to
be updated, but I have no windows development machine at hand. Have a
look at the x11 renderer for a sample.

Vector games now run at 90% both on opengl and directfb in comparison to
sdlmame's own opengl renderer. The same applies to raster games.

The diff also includes

a) Changed XDrawRect to XFillRect in x11 renderer
b) A number of changes to fix blending and modulation issues in the
directfb renderer.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* The high-level video driver subsystem */
    25 
    26 #include "SDL.h"
    27 #include "SDL_sysvideo.h"
    28 #include "SDL_blit.h"
    29 #include "SDL_pixels_c.h"
    30 #include "SDL_renderer_gl.h"
    31 #include "SDL_renderer_gles.h"
    32 #include "SDL_renderer_sw.h"
    33 #include "../events/SDL_sysevents.h"
    34 #include "../events/SDL_events_c.h"
    35 
    36 #if SDL_VIDEO_OPENGL_ES
    37 #include "SDL_opengles.h"
    38 #endif /* SDL_VIDEO_OPENGL_ES */
    39 
    40 #if SDL_VIDEO_OPENGL
    41 #include "SDL_opengl.h"
    42 
    43 /* On Windows, windows.h defines CreateWindow */
    44 #ifdef CreateWindow
    45 #undef CreateWindow
    46 #endif
    47 #endif /* SDL_VIDEO_OPENGL */
    48 
    49 /* Available video drivers */
    50 static VideoBootStrap *bootstrap[] = {
    51 #if SDL_VIDEO_DRIVER_COCOA
    52     &COCOA_bootstrap,
    53 #endif
    54 #if SDL_VIDEO_DRIVER_X11
    55     &X11_bootstrap,
    56 #endif
    57 #if SDL_VIDEO_DRIVER_NANOX
    58     &NX_bootstrap,
    59 #endif
    60 #if SDL_VIDEO_DRIVER_IPOD
    61     &iPod_bootstrap,
    62 #endif
    63 #if SDL_VIDEO_DRIVER_WSCONS
    64     &WSCONS_bootstrap,
    65 #endif
    66 #if SDL_VIDEO_DRIVER_FBCON
    67     &FBCON_bootstrap,
    68 #endif
    69 #if SDL_VIDEO_DRIVER_DIRECTFB
    70     &DirectFB_bootstrap,
    71 #endif
    72 #if SDL_VIDEO_DRIVER_PS2GS
    73     &PS2GS_bootstrap,
    74 #endif
    75 #if SDL_VIDEO_DRIVER_VGL
    76     &VGL_bootstrap,
    77 #endif
    78 #if SDL_VIDEO_DRIVER_SVGALIB
    79     &SVGALIB_bootstrap,
    80 #endif
    81 #if SDL_VIDEO_DRIVER_GAPI
    82     &GAPI_bootstrap,
    83 #endif
    84 #if SDL_VIDEO_DRIVER_WIN32
    85     &WIN32_bootstrap,
    86 #endif
    87 #if SDL_VIDEO_DRIVER_BWINDOW
    88     &BWINDOW_bootstrap,
    89 #endif
    90 #if SDL_VIDEO_DRIVER_PHOTON
    91     &ph_bootstrap,
    92 #endif
    93 #if SDL_VIDEO_DRIVER_EPOC
    94     &EPOC_bootstrap,
    95 #endif
    96 #if SDL_VIDEO_DRIVER_XBIOS
    97     &XBIOS_bootstrap,
    98 #endif
    99 #if SDL_VIDEO_DRIVER_GEM
   100     &GEM_bootstrap,
   101 #endif
   102 #if SDL_VIDEO_DRIVER_DC
   103     &DC_bootstrap,
   104 #endif
   105 #if SDL_VIDEO_DRIVER_RISCOS
   106     &RISCOS_bootstrap,
   107 #endif
   108 #if SDL_VIDEO_DRIVER_OS2FS
   109     &OS2FSLib_bootstrap,
   110 #endif
   111 #if SDL_VIDEO_DRIVER_NDS
   112     &NDS_bootstrap,
   113 #endif
   114 #if SDL_VIDEO_DRIVER_UIKIT
   115     &UIKIT_bootstrap,
   116 #endif
   117 #if SDL_VIDEO_DRIVER_DUMMY
   118     &DUMMY_bootstrap,
   119 #endif
   120     NULL
   121 };
   122 
   123 static SDL_VideoDevice *_this = NULL;
   124 
   125 /* Various local functions */
   126 static void SDL_UpdateWindowGrab(SDL_Window * window);
   127 
   128 static int
   129 cmpmodes(const void *A, const void *B)
   130 {
   131     SDL_DisplayMode a = *(const SDL_DisplayMode *) A;
   132     SDL_DisplayMode b = *(const SDL_DisplayMode *) B;
   133 
   134     if (a.w != b.w) {
   135         return b.w - a.w;
   136     }
   137     if (a.h != b.h) {
   138         return b.h - a.h;
   139     }
   140     if (SDL_BITSPERPIXEL(a.format) != SDL_BITSPERPIXEL(b.format)) {
   141         return SDL_BITSPERPIXEL(b.format) - SDL_BITSPERPIXEL(a.format);
   142     }
   143     if (a.refresh_rate != b.refresh_rate) {
   144         return b.refresh_rate - a.refresh_rate;
   145     }
   146     return 0;
   147 }
   148 
   149 static void
   150 SDL_UninitializedVideo()
   151 {
   152     SDL_SetError("Video subsystem has not been initialized");
   153 }
   154 
   155 int
   156 SDL_GetNumVideoDrivers(void)
   157 {
   158     return SDL_arraysize(bootstrap) - 1;
   159 }
   160 
   161 const char *
   162 SDL_GetVideoDriver(int index)
   163 {
   164     if (index >= 0 && index < SDL_GetNumVideoDrivers()) {
   165         return bootstrap[index]->name;
   166     }
   167     return NULL;
   168 }
   169 
   170 /*
   171  * Initialize the video and event subsystems -- determine native pixel format
   172  */
   173 int
   174 SDL_VideoInit(const char *driver_name, Uint32 flags)
   175 {
   176     SDL_VideoDevice *video;
   177     int index;
   178     int i;
   179 
   180     /* Toggle the event thread flags, based on OS requirements */
   181 #if defined(MUST_THREAD_EVENTS)
   182     flags |= SDL_INIT_EVENTTHREAD;
   183 #elif defined(CANT_THREAD_EVENTS)
   184     if ((flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD) {
   185         SDL_SetError("OS doesn't support threaded events");
   186         return -1;
   187     }
   188 #endif
   189 
   190     /* Start the event loop */
   191     if (SDL_StartEventLoop(flags) < 0) {
   192         return -1;
   193     }
   194     /* Check to make sure we don't overwrite '_this' */
   195     if (_this != NULL) {
   196         SDL_VideoQuit();
   197     }
   198     /* Select the proper video driver */
   199     index = 0;
   200     video = NULL;
   201     if (driver_name == NULL) {
   202         driver_name = SDL_getenv("SDL_VIDEODRIVER");
   203     }
   204     if (driver_name != NULL) {
   205         for (i = 0; bootstrap[i]; ++i) {
   206             if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
   207                 if (bootstrap[i]->available()) {
   208                     video = bootstrap[i]->create(index);
   209                 }
   210                 break;
   211             }
   212         }
   213     } else {
   214         for (i = 0; bootstrap[i]; ++i) {
   215             if (bootstrap[i]->available()) {
   216                 video = bootstrap[i]->create(index);
   217                 if (video != NULL) {
   218                     break;
   219                 }
   220             }
   221         }
   222     }
   223     if (video == NULL) {
   224         if (driver_name) {
   225             SDL_SetError("%s not available", driver_name);
   226         } else {
   227             SDL_SetError("No available video device");
   228         }
   229         return -1;
   230     }
   231     _this = video;
   232     _this->name = bootstrap[i]->name;
   233     _this->next_object_id = 1;
   234 
   235 
   236     /* Set some very sane GL defaults */
   237     _this->gl_config.driver_loaded = 0;
   238     _this->gl_config.dll_handle = NULL;
   239     _this->gl_config.red_size = 3;
   240     _this->gl_config.green_size = 3;
   241     _this->gl_config.blue_size = 2;
   242     _this->gl_config.alpha_size = 0;
   243     _this->gl_config.buffer_size = 0;
   244     _this->gl_config.depth_size = 16;
   245     _this->gl_config.stencil_size = 0;
   246     _this->gl_config.double_buffer = 1;
   247     _this->gl_config.accum_red_size = 0;
   248     _this->gl_config.accum_green_size = 0;
   249     _this->gl_config.accum_blue_size = 0;
   250     _this->gl_config.accum_alpha_size = 0;
   251     _this->gl_config.stereo = 0;
   252     _this->gl_config.multisamplebuffers = 0;
   253     _this->gl_config.multisamplesamples = 0;
   254     _this->gl_config.retained_backing = 1;
   255     _this->gl_config.accelerated = -1;  /* not known, don't set */
   256 
   257     /* Initialize the video subsystem */
   258     if (_this->VideoInit(_this) < 0) {
   259         SDL_VideoQuit();
   260         return -1;
   261     }
   262     /* Make sure some displays were added */
   263     if (_this->num_displays == 0) {
   264         SDL_SetError("The video driver did not add any displays");
   265         SDL_VideoQuit();
   266         return (-1);
   267     }
   268     /* The software renderer is always available */
   269     for (i = 0; i < _this->num_displays; ++i) {
   270 #if SDL_VIDEO_RENDER_OGL
   271         SDL_AddRenderDriver(i, &GL_RenderDriver);
   272 #endif
   273 
   274 #if SDL_VIDEO_RENDER_OGL_ES
   275         SDL_AddRenderDriver(i, &GL_ES_RenderDriver);
   276 #endif
   277         if (_this->displays[i].num_render_drivers > 0) {
   278             SDL_AddRenderDriver(i, &SW_RenderDriver);
   279         }
   280     }
   281 
   282     /* We're ready to go! */
   283     return 0;
   284 }
   285 
   286 const char *
   287 SDL_GetCurrentVideoDriver()
   288 {
   289     if (!_this) {
   290         SDL_UninitializedVideo();
   291         return NULL;
   292     }
   293     return _this->name;
   294 }
   295 
   296 SDL_VideoDevice *
   297 SDL_GetVideoDevice()
   298 {
   299     return _this;
   300 }
   301 
   302 int
   303 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
   304 {
   305     SDL_VideoDisplay display;
   306 
   307     SDL_zero(display);
   308     if (desktop_mode) {
   309         display.desktop_mode = *desktop_mode;
   310     }
   311     display.current_mode = display.desktop_mode;
   312 
   313     return SDL_AddVideoDisplay(&display);
   314 }
   315 
   316 int
   317 SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
   318 {
   319     SDL_VideoDisplay *displays;
   320     int index = -1;
   321 
   322     displays =
   323         SDL_realloc(_this->displays,
   324                     (_this->num_displays + 1) * sizeof(*displays));
   325     if (displays) {
   326         index = _this->num_displays++;
   327         displays[index] = *display;
   328         displays[index].device = _this;
   329         _this->displays = displays;
   330     } else {
   331         SDL_OutOfMemory();
   332     }
   333     return index;
   334 }
   335 
   336 int
   337 SDL_GetNumVideoDisplays(void)
   338 {
   339     if (!_this) {
   340         SDL_UninitializedVideo();
   341         return 0;
   342     }
   343     return _this->num_displays;
   344 }
   345 
   346 int
   347 SDL_SelectVideoDisplay(int index)
   348 {
   349     if (!_this) {
   350         SDL_UninitializedVideo();
   351         return (-1);
   352     }
   353     if (index < 0 || index >= _this->num_displays) {
   354         SDL_SetError("index must be in the range 0 - %d",
   355                      _this->num_displays - 1);
   356         return -1;
   357     }
   358     _this->current_display = index;
   359     return 0;
   360 }
   361 
   362 int
   363 SDL_GetCurrentVideoDisplay(void)
   364 {
   365     if (!_this) {
   366         SDL_UninitializedVideo();
   367         return (-1);
   368     }
   369     return _this->current_display;
   370 }
   371 
   372 SDL_bool
   373 SDL_AddDisplayMode(int displayIndex, const SDL_DisplayMode * mode)
   374 {
   375     SDL_VideoDisplay *display = &_this->displays[displayIndex];
   376     SDL_DisplayMode *modes;
   377     int i, nmodes;
   378 
   379     /* Make sure we don't already have the mode in the list */
   380     modes = display->display_modes;
   381     nmodes = display->num_display_modes;
   382     for (i = nmodes; i--;) {
   383         if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) {
   384             return SDL_FALSE;
   385         }
   386     }
   387 
   388     /* Go ahead and add the new mode */
   389     if (nmodes == display->max_display_modes) {
   390         modes =
   391             SDL_realloc(modes,
   392                         (display->max_display_modes + 32) * sizeof(*modes));
   393         if (!modes) {
   394             return SDL_FALSE;
   395         }
   396         display->display_modes = modes;
   397         display->max_display_modes += 32;
   398     }
   399     modes[nmodes] = *mode;
   400     display->num_display_modes++;
   401 
   402     return SDL_TRUE;
   403 }
   404 
   405 int
   406 SDL_GetNumDisplayModes()
   407 {
   408     if (_this) {
   409         SDL_VideoDisplay *display = &SDL_CurrentDisplay;
   410         if (!display->num_display_modes && _this->GetDisplayModes) {
   411             _this->GetDisplayModes(_this);
   412             SDL_qsort(display->display_modes, display->num_display_modes,
   413                       sizeof(SDL_DisplayMode), cmpmodes);
   414         }
   415         return display->num_display_modes;
   416     }
   417     return 0;
   418 }
   419 
   420 int
   421 SDL_GetDisplayMode(int index, SDL_DisplayMode * mode)
   422 {
   423     if (index < 0 || index >= SDL_GetNumDisplayModes()) {
   424         SDL_SetError("index must be in the range of 0 - %d",
   425                      SDL_GetNumDisplayModes() - 1);
   426         return -1;
   427     }
   428     if (mode) {
   429         *mode = SDL_CurrentDisplay.display_modes[index];
   430     }
   431     return 0;
   432 }
   433 
   434 int
   435 SDL_GetDesktopDisplayMode(SDL_DisplayMode * mode)
   436 {
   437     if (!_this) {
   438         SDL_UninitializedVideo();
   439         return -1;
   440     }
   441     if (mode) {
   442         *mode = SDL_CurrentDisplay.desktop_mode;
   443     }
   444     return 0;
   445 }
   446 
   447 int
   448 SDL_GetCurrentDisplayMode(SDL_DisplayMode * mode)
   449 {
   450     if (!_this) {
   451         SDL_UninitializedVideo();
   452         return -1;
   453     }
   454     if (mode) {
   455         *mode = SDL_CurrentDisplay.current_mode;
   456     }
   457     return 0;
   458 }
   459 
   460 SDL_DisplayMode *
   461 SDL_GetClosestDisplayMode(const SDL_DisplayMode * mode,
   462                           SDL_DisplayMode * closest)
   463 {
   464     Uint32 target_format;
   465     int target_refresh_rate;
   466     int i;
   467     SDL_DisplayMode *current, *match;
   468 
   469     if (!_this || !mode || !closest) {
   470         return NULL;
   471     }
   472     /* Default to the desktop format */
   473     if (mode->format) {
   474         target_format = mode->format;
   475     } else {
   476         target_format = SDL_CurrentDisplay.desktop_mode.format;
   477     }
   478 
   479     /* Default to the desktop refresh rate */
   480     if (mode->refresh_rate) {
   481         target_refresh_rate = mode->refresh_rate;
   482     } else {
   483         target_refresh_rate = SDL_CurrentDisplay.desktop_mode.refresh_rate;
   484     }
   485 
   486     match = NULL;
   487     for (i = 0; i < SDL_GetNumDisplayModes(); ++i) {
   488         current = &SDL_CurrentDisplay.display_modes[i];
   489 
   490         if (current->w && (current->w < mode->w)) {
   491             /* Out of sorted modes large enough here */
   492             break;
   493         }
   494         if (current->h && (current->h < mode->h)) {
   495             if (current->w && (current->w == mode->w)) {
   496                 /* Out of sorted modes large enough here */
   497                 break;
   498             }
   499             /* Wider, but not tall enough, due to a different
   500                aspect ratio. This mode must be skipped, but closer
   501                modes may still follow. */
   502             continue;
   503         }
   504         if (!match || current->w < match->w || current->h < match->h) {
   505             match = current;
   506             continue;
   507         }
   508         if (current->format != match->format) {
   509             /* Sorted highest depth to lowest */
   510             if (current->format == target_format ||
   511                 (SDL_BITSPERPIXEL(current->format) >=
   512                  SDL_BITSPERPIXEL(target_format)
   513                  && SDL_PIXELTYPE(current->format) ==
   514                  SDL_PIXELTYPE(target_format))) {
   515                 match = current;
   516             }
   517             continue;
   518         }
   519         if (current->refresh_rate != match->refresh_rate) {
   520             /* Sorted highest refresh to lowest */
   521             if (current->refresh_rate >= target_refresh_rate) {
   522                 match = current;
   523             }
   524         }
   525     }
   526     if (match) {
   527         if (match->format) {
   528             closest->format = match->format;
   529         } else {
   530             closest->format = mode->format;
   531         }
   532         if (match->w && match->h) {
   533             closest->w = match->w;
   534             closest->h = match->h;
   535         } else {
   536             closest->w = mode->w;
   537             closest->h = mode->h;
   538         }
   539         if (match->refresh_rate) {
   540             closest->refresh_rate = match->refresh_rate;
   541         } else {
   542             closest->refresh_rate = mode->refresh_rate;
   543         }
   544         closest->driverdata = match->driverdata;
   545 
   546         /*
   547          * Pick some reasonable defaults if the app and driver don't
   548          * care
   549          */
   550         if (!closest->format) {
   551             closest->format = SDL_PIXELFORMAT_RGB888;
   552         }
   553         if (!closest->w) {
   554             closest->w = 640;
   555         }
   556         if (!closest->h) {
   557             closest->h = 480;
   558         }
   559         return closest;
   560     }
   561     return NULL;
   562 }
   563 
   564 int
   565 SDL_SetDisplayMode(const SDL_DisplayMode * mode)
   566 {
   567     SDL_VideoDisplay *display;
   568     SDL_DisplayMode display_mode;
   569     SDL_DisplayMode current_mode;
   570     int i, ncolors;
   571 
   572     if (!_this) {
   573         SDL_UninitializedVideo();
   574         return -1;
   575     }
   576     display = &SDL_CurrentDisplay;
   577     if (!mode) {
   578         mode = &display->desktop_mode;
   579     }
   580     display_mode = *mode;
   581 
   582     /* Default to the current mode */
   583     if (!display_mode.format) {
   584         display_mode.format = display->current_mode.format;
   585     }
   586     if (!display_mode.w) {
   587         display_mode.w = display->current_mode.w;
   588     }
   589     if (!display_mode.h) {
   590         display_mode.h = display->current_mode.h;
   591     }
   592     if (!display_mode.refresh_rate) {
   593         display_mode.refresh_rate = display->current_mode.refresh_rate;
   594     }
   595     /* Get a good video mode, the closest one possible */
   596     if (!SDL_GetClosestDisplayMode(&display_mode, &display_mode)) {
   597         SDL_SetError("No video mode large enough for %dx%d",
   598                      display_mode.w, display_mode.h);
   599         return -1;
   600     }
   601     /* See if there's anything left to do */
   602     SDL_GetCurrentDisplayMode(&current_mode);
   603     if (SDL_memcmp(&display_mode, &current_mode, sizeof(display_mode)) == 0) {
   604         return 0;
   605     }
   606     /* Actually change the display mode */
   607     if (_this->SetDisplayMode(_this, &display_mode) < 0) {
   608         return -1;
   609     }
   610     display->current_mode = display_mode;
   611 
   612     /* Set up a palette, if necessary */
   613     if (SDL_ISPIXELFORMAT_INDEXED(display_mode.format)) {
   614         ncolors = (1 << SDL_BITSPERPIXEL(display_mode.format));
   615     } else {
   616         ncolors = 0;
   617     }
   618     if ((!ncolors && display->palette) || (ncolors && !display->palette)
   619         || (ncolors && ncolors != display->palette->ncolors)) {
   620         if (display->palette) {
   621             SDL_FreePalette(display->palette);
   622             display->palette = NULL;
   623         }
   624         if (ncolors) {
   625             display->palette = SDL_AllocPalette(ncolors);
   626             if (!display->palette) {
   627                 return -1;
   628             }
   629             SDL_DitherColors(display->palette->colors,
   630                              SDL_BITSPERPIXEL(display_mode.format));
   631         }
   632     }
   633     /* Move any fullscreen windows into position */
   634     for (i = 0; i < display->num_windows; ++i) {
   635         SDL_Window *window = &display->windows[i];
   636         if (FULLSCREEN_VISIBLE(window)) {
   637             SDL_SetWindowPosition(window->id, window->x, window->y);
   638         }
   639     }
   640 
   641     return 0;
   642 }
   643 
   644 int
   645 SDL_SetFullscreenDisplayMode(const SDL_DisplayMode * mode)
   646 {
   647     SDL_VideoDisplay *display;
   648     SDL_DisplayMode fullscreen_mode;
   649     int i;
   650 
   651     if (!_this) {
   652         SDL_UninitializedVideo();
   653         return -1;
   654     }
   655     display = &SDL_CurrentDisplay;
   656     if (!mode) {
   657         mode = &display->desktop_mode;
   658     }
   659     if (!SDL_GetClosestDisplayMode(mode, &fullscreen_mode)) {
   660         SDL_SetError("Couldn't find display mode match");
   661         return -1;
   662     }
   663     if (SDL_memcmp
   664         (&fullscreen_mode, &display->fullscreen_mode,
   665          sizeof(fullscreen_mode)) == 0) {
   666         /* Nothing to do... */
   667         return 0;
   668     }
   669     display->fullscreen_mode = fullscreen_mode;
   670 
   671     /* Actually set the mode if we have a fullscreen window visible */
   672     for (i = 0; i < display->num_windows; ++i) {
   673         SDL_Window *window = &display->windows[i];
   674         if (FULLSCREEN_VISIBLE(window)) {
   675             if (SDL_SetDisplayMode(&display->fullscreen_mode) < 0) {
   676                 return -1;
   677             }
   678         }
   679         if (window->flags & SDL_WINDOW_FULLSCREEN) {
   680             SDL_OnWindowResized(window);
   681         }
   682     }
   683     return 0;
   684 }
   685 
   686 int
   687 SDL_GetFullscreenDisplayMode(SDL_DisplayMode * mode)
   688 {
   689     if (!_this) {
   690         SDL_UninitializedVideo();
   691         return -1;
   692     }
   693     if (mode) {
   694         *mode = SDL_CurrentDisplay.fullscreen_mode;
   695     }
   696     return 0;
   697 }
   698 
   699 int
   700 SDL_SetDisplayPalette(const SDL_Color * colors, int firstcolor, int ncolors)
   701 {
   702     SDL_Palette *palette;
   703     int status = 0;
   704 
   705     if (!_this) {
   706         SDL_UninitializedVideo();
   707         return -1;
   708     }
   709     palette = SDL_CurrentDisplay.palette;
   710     if (!palette) {
   711         SDL_SetError("Display mode does not have a palette");
   712         return -1;
   713     }
   714     status = SDL_SetPaletteColors(palette, colors, firstcolor, ncolors);
   715 
   716     if (_this->SetDisplayPalette) {
   717         if (_this->SetDisplayPalette(_this, palette) < 0) {
   718             status = -1;
   719         }
   720     }
   721     return status;
   722 }
   723 
   724 int
   725 SDL_GetDisplayPalette(SDL_Color * colors, int firstcolor, int ncolors)
   726 {
   727     SDL_Palette *palette;
   728 
   729     if (!_this) {
   730         SDL_UninitializedVideo();
   731         return -1;
   732     }
   733     palette = SDL_CurrentDisplay.palette;
   734     if (!palette->ncolors) {
   735         SDL_SetError("Display mode does not have a palette");
   736         return -1;
   737     }
   738     if (firstcolor < 0 || (firstcolor + ncolors) > palette->ncolors) {
   739         SDL_SetError("Palette indices are out of range");
   740         return -1;
   741     }
   742     SDL_memcpy(colors, &palette->colors[firstcolor],
   743                ncolors * sizeof(*colors));
   744     return 0;
   745 }
   746 
   747 SDL_WindowID
   748 SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
   749 {
   750     const Uint32 allowed_flags = (SDL_WINDOW_FULLSCREEN |
   751                                   SDL_WINDOW_OPENGL |
   752                                   SDL_WINDOW_BORDERLESS |
   753                                   SDL_WINDOW_RESIZABLE |
   754                                   SDL_WINDOW_INPUT_GRABBED);
   755     SDL_VideoDisplay *display;
   756     SDL_Window window;
   757     int num_windows;
   758     SDL_Window *windows;
   759 
   760     if (!_this) {
   761         SDL_UninitializedVideo();
   762         return 0;
   763     }
   764     if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
   765         SDL_SetError("No OpenGL support in video driver");
   766         return 0;
   767     }
   768     SDL_zero(window);
   769     window.id = _this->next_object_id++;
   770     window.x = x;
   771     window.y = y;
   772     window.w = w;
   773     window.h = h;
   774     window.flags = (flags & allowed_flags);
   775     window.display = _this->current_display;
   776 
   777     if (_this->CreateWindow && _this->CreateWindow(_this, &window) < 0) {
   778         return 0;
   779     }
   780     display = &SDL_CurrentDisplay;
   781     num_windows = display->num_windows;
   782     windows =
   783         SDL_realloc(display->windows, (num_windows + 1) * sizeof(*windows));
   784     if (!windows) {
   785         if (_this->DestroyWindow) {
   786             _this->DestroyWindow(_this, &window);
   787         }
   788         return 0;
   789     }
   790     windows[num_windows] = window;
   791     display->windows = windows;
   792     display->num_windows++;
   793 
   794     if (title) {
   795         SDL_SetWindowTitle(window.id, title);
   796     }
   797     if (flags & SDL_WINDOW_MAXIMIZED) {
   798         SDL_MaximizeWindow(window.id);
   799     }
   800     if (flags & SDL_WINDOW_MINIMIZED) {
   801         SDL_MinimizeWindow(window.id);
   802     }
   803     if (flags & SDL_WINDOW_SHOWN) {
   804         SDL_ShowWindow(window.id);
   805     }
   806     SDL_UpdateWindowGrab(&window);
   807 
   808     return window.id;
   809 }
   810 
   811 SDL_WindowID
   812 SDL_CreateWindowFrom(const void *data)
   813 {
   814     SDL_VideoDisplay *display;
   815     SDL_Window window;
   816     int num_windows;
   817     SDL_Window *windows;
   818 
   819     if (!_this) {
   820         SDL_UninitializedVideo();
   821         return (0);
   822     }
   823     SDL_zero(window);
   824     window.id = _this->next_object_id++;
   825     window.display = _this->current_display;
   826 
   827     if (!_this->CreateWindowFrom ||
   828         _this->CreateWindowFrom(_this, &window, data) < 0) {
   829         return 0;
   830     }
   831     display = &SDL_CurrentDisplay;
   832     num_windows = display->num_windows;
   833     windows =
   834         SDL_realloc(display->windows, (num_windows + 1) * sizeof(*windows));
   835     if (!windows) {
   836         if (_this->DestroyWindow) {
   837             _this->DestroyWindow(_this, &window);
   838         }
   839         if (window.title) {
   840             SDL_free(window.title);
   841         }
   842         return 0;
   843     }
   844     windows[num_windows] = window;
   845     display->windows = windows;
   846     display->num_windows++;
   847 
   848     return window.id;
   849 }
   850 
   851 int
   852 SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
   853 {
   854     char *title = window->title;
   855 
   856     if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
   857         SDL_SetError("No OpenGL support in video driver");
   858         return -1;
   859     }
   860     if (_this->DestroyWindow) {
   861         _this->DestroyWindow(_this, window);
   862     }
   863     window->title = NULL;
   864     window->flags =
   865         (flags &
   866          ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED | SDL_WINDOW_SHOWN |
   867            SDL_WINDOW_INPUT_GRABBED));
   868 
   869     if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
   870         return -1;
   871     }
   872     if (title) {
   873         SDL_SetWindowTitle(window->id, title);
   874         SDL_free(title);
   875     }
   876     if (flags & SDL_WINDOW_MAXIMIZED) {
   877         SDL_MaximizeWindow(window->id);
   878     }
   879     if (flags & SDL_WINDOW_MINIMIZED) {
   880         SDL_MinimizeWindow(window->id);
   881     }
   882     if (flags & SDL_WINDOW_SHOWN) {
   883         SDL_ShowWindow(window->id);
   884     }
   885     SDL_UpdateWindowGrab(window);
   886 
   887     return 0;
   888 }
   889 
   890 SDL_Window *
   891 SDL_GetWindowFromID(SDL_WindowID windowID)
   892 {
   893     int i, j;
   894 
   895     if (!_this) {
   896         SDL_UninitializedVideo();
   897         return NULL;
   898     }
   899     for (i = 0; i < _this->num_displays; ++i) {
   900         SDL_VideoDisplay *display = &_this->displays[i];
   901         for (j = 0; j < display->num_windows; ++j) {
   902             SDL_Window *window = &display->windows[j];
   903             if (window->id == windowID) {
   904                 return window;
   905             }
   906         }
   907     }
   908     return NULL;
   909 }
   910 
   911 SDL_VideoDisplay *
   912 SDL_GetDisplayFromWindow(SDL_Window * window)
   913 {
   914     if (!_this) {
   915         SDL_UninitializedVideo();
   916         return NULL;
   917     }
   918     if (!window) {
   919         return NULL;
   920     }
   921     return &_this->displays[window->display];
   922 }
   923 
   924 Uint32
   925 SDL_GetWindowFlags(SDL_WindowID windowID)
   926 {
   927     SDL_Window *window = SDL_GetWindowFromID(windowID);
   928 
   929     if (!window) {
   930         return 0;
   931     }
   932     return window->flags;
   933 }
   934 
   935 void
   936 SDL_SetWindowTitle(SDL_WindowID windowID, const char *title)
   937 {
   938     SDL_Window *window = SDL_GetWindowFromID(windowID);
   939 
   940     if (!window || title == window->title) {
   941         return;
   942     }
   943     if (window->title) {
   944         SDL_free(window->title);
   945     }
   946     if (title) {
   947         window->title = SDL_strdup(title);
   948     } else {
   949         window->title = NULL;
   950     }
   951 
   952     if (_this->SetWindowTitle) {
   953         _this->SetWindowTitle(_this, window);
   954     }
   955 }
   956 
   957 const char *
   958 SDL_GetWindowTitle(SDL_WindowID windowID)
   959 {
   960     SDL_Window *window = SDL_GetWindowFromID(windowID);
   961 
   962     if (!window) {
   963         return NULL;
   964     }
   965     return window->title;
   966 }
   967 
   968 void
   969 SDL_SetWindowData(SDL_WindowID windowID, void *userdata)
   970 {
   971     SDL_Window *window = SDL_GetWindowFromID(windowID);
   972 
   973     if (!window) {
   974         return;
   975     }
   976     window->userdata = userdata;
   977 }
   978 
   979 void *
   980 SDL_GetWindowData(SDL_WindowID windowID)
   981 {
   982     SDL_Window *window = SDL_GetWindowFromID(windowID);
   983 
   984     if (!window) {
   985         return NULL;
   986     }
   987     return window->userdata;
   988 }
   989 
   990 void
   991 SDL_SetWindowPosition(SDL_WindowID windowID, int x, int y)
   992 {
   993     SDL_Window *window = SDL_GetWindowFromID(windowID);
   994     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   995 
   996     if (!window) {
   997         return;
   998     }
   999     if (x != SDL_WINDOWPOS_UNDEFINED) {
  1000         window->x = x;
  1001     }
  1002     if (y != SDL_WINDOWPOS_UNDEFINED) {
  1003         window->y = y;
  1004     }
  1005     if (_this->SetWindowPosition) {
  1006         _this->SetWindowPosition(_this, window);
  1007     }
  1008     SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MOVED, x, y);
  1009 }
  1010 
  1011 void
  1012 SDL_GetWindowPosition(SDL_WindowID windowID, int *x, int *y)
  1013 {
  1014     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1015 
  1016     if (!window) {
  1017         return;
  1018     }
  1019     if (x) {
  1020         *x = window->x;
  1021     }
  1022     if (y) {
  1023         *y = window->y;
  1024     }
  1025 }
  1026 
  1027 void
  1028 SDL_SetWindowSize(SDL_WindowID windowID, int w, int h)
  1029 {
  1030     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1031 
  1032     if (!window) {
  1033         return;
  1034     }
  1035     window->w = w;
  1036     window->h = h;
  1037 
  1038     if (_this->SetWindowSize) {
  1039         _this->SetWindowSize(_this, window);
  1040     }
  1041     SDL_OnWindowResized(window);
  1042 }
  1043 
  1044 void
  1045 SDL_GetWindowSize(SDL_WindowID windowID, int *w, int *h)
  1046 {
  1047     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1048 
  1049     if (window) {
  1050         if (w) {
  1051             *w = window->w;
  1052         }
  1053         if (h) {
  1054             *h = window->h;
  1055         }
  1056     } else {
  1057         if (w) {
  1058             *w = 0;
  1059         }
  1060         if (h) {
  1061             *h = 0;
  1062         }
  1063     }
  1064 }
  1065 
  1066 void
  1067 SDL_ShowWindow(SDL_WindowID windowID)
  1068 {
  1069     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1070 
  1071     if (!window || (window->flags & SDL_WINDOW_SHOWN)) {
  1072         return;
  1073     }
  1074 
  1075     if (_this->ShowWindow) {
  1076         _this->ShowWindow(_this, window);
  1077     }
  1078     SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_SHOWN, 0, 0);
  1079 }
  1080 
  1081 void
  1082 SDL_HideWindow(SDL_WindowID windowID)
  1083 {
  1084     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1085 
  1086     if (!window || !(window->flags & SDL_WINDOW_SHOWN)) {
  1087         return;
  1088     }
  1089 
  1090     if (_this->HideWindow) {
  1091         _this->HideWindow(_this, window);
  1092     }
  1093     SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_HIDDEN, 0, 0);
  1094 }
  1095 
  1096 void
  1097 SDL_RaiseWindow(SDL_WindowID windowID)
  1098 {
  1099     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1100 
  1101     if (!window || !(window->flags & SDL_WINDOW_SHOWN)) {
  1102         return;
  1103     }
  1104     if (_this->RaiseWindow) {
  1105         _this->RaiseWindow(_this, window);
  1106     }
  1107 }
  1108 
  1109 void
  1110 SDL_MaximizeWindow(SDL_WindowID windowID)
  1111 {
  1112     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1113 
  1114     if (!window || (window->flags & SDL_WINDOW_MAXIMIZED)) {
  1115         return;
  1116     }
  1117 
  1118     if (_this->MaximizeWindow) {
  1119         _this->MaximizeWindow(_this, window);
  1120     }
  1121     SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
  1122 }
  1123 
  1124 void
  1125 SDL_MinimizeWindow(SDL_WindowID windowID)
  1126 {
  1127     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1128 
  1129     if (!window || (window->flags & SDL_WINDOW_MINIMIZED)) {
  1130         return;
  1131     }
  1132 
  1133     if (_this->MinimizeWindow) {
  1134         _this->MinimizeWindow(_this, window);
  1135     }
  1136     SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
  1137 }
  1138 
  1139 void
  1140 SDL_RestoreWindow(SDL_WindowID windowID)
  1141 {
  1142     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1143 
  1144     if (!window
  1145         || (window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
  1146         return;
  1147     }
  1148 
  1149     if (_this->RestoreWindow) {
  1150         _this->RestoreWindow(_this, window);
  1151     }
  1152     SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESTORED, 0, 0);
  1153 }
  1154 
  1155 int
  1156 SDL_SetWindowFullscreen(SDL_WindowID windowID, int fullscreen)
  1157 {
  1158     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1159 
  1160     if (!window) {
  1161         return -1;
  1162     }
  1163     if (fullscreen) {
  1164         fullscreen = SDL_WINDOW_FULLSCREEN;
  1165     }
  1166     if ((window->flags & SDL_WINDOW_FULLSCREEN) == fullscreen) {
  1167         return 0;
  1168     }
  1169     if (fullscreen) {
  1170         window->flags |= SDL_WINDOW_FULLSCREEN;
  1171 
  1172         if (FULLSCREEN_VISIBLE(window)) {
  1173             SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
  1174 
  1175             /* Hide any other fullscreen windows */
  1176             int i;
  1177             for (i = 0; i < display->num_windows; ++i) {
  1178                 SDL_Window *other = &display->windows[i];
  1179                 if (other->id != windowID && FULLSCREEN_VISIBLE(other)) {
  1180                     SDL_MinimizeWindow(other->id);
  1181                 }
  1182             }
  1183 
  1184             SDL_SetDisplayMode(&display->fullscreen_mode);
  1185         }
  1186     } else {
  1187         window->flags &= ~SDL_WINDOW_FULLSCREEN;
  1188 
  1189         if (FULLSCREEN_VISIBLE(window)) {
  1190             SDL_SetDisplayMode(NULL);
  1191         }
  1192     }
  1193     return 0;
  1194 }
  1195 
  1196 void
  1197 SDL_SetWindowGrab(SDL_WindowID windowID, int mode)
  1198 {
  1199     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1200 
  1201     if (!window || (!!mode == !!(window->flags & SDL_WINDOW_INPUT_GRABBED))) {
  1202         return;
  1203     }
  1204     if (mode) {
  1205         window->flags |= SDL_WINDOW_INPUT_GRABBED;
  1206     } else {
  1207         window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
  1208     }
  1209     SDL_UpdateWindowGrab(window);
  1210 }
  1211 
  1212 static void
  1213 SDL_UpdateWindowGrab(SDL_Window * window)
  1214 {
  1215     if ((window->flags & SDL_WINDOW_INPUT_FOCUS) && _this->SetWindowGrab) {
  1216         _this->SetWindowGrab(_this, window);
  1217     }
  1218 }
  1219 
  1220 int
  1221 SDL_GetWindowGrab(SDL_WindowID windowID)
  1222 {
  1223     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1224 
  1225     if (!window) {
  1226         return 0;
  1227     }
  1228     return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
  1229 }
  1230 
  1231 void
  1232 SDL_OnWindowShown(SDL_Window * window)
  1233 {
  1234     if (window->flags & SDL_WINDOW_FULLSCREEN) {
  1235         SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
  1236     }
  1237 }
  1238 
  1239 void
  1240 SDL_OnWindowHidden(SDL_Window * window)
  1241 {
  1242     if (window->flags & SDL_WINDOW_FULLSCREEN) {
  1243         SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
  1244     }
  1245 }
  1246 
  1247 void
  1248 SDL_OnWindowResized(SDL_Window * window)
  1249 {
  1250     SDL_Renderer *renderer = window->renderer;
  1251 
  1252     if (renderer && renderer->DisplayModeChanged) {
  1253         renderer->DisplayModeChanged(renderer);
  1254     }
  1255 }
  1256 
  1257 void
  1258 SDL_OnWindowFocusGained(SDL_Window * window)
  1259 {
  1260     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
  1261 
  1262     if (window->flags & SDL_WINDOW_FULLSCREEN) {
  1263         SDL_SetDisplayMode(&display->fullscreen_mode);
  1264     }
  1265     if (display->gamma && _this->SetDisplayGammaRamp) {
  1266         _this->SetDisplayGammaRamp(_this, display->gamma);
  1267     }
  1268     if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
  1269         && _this->SetWindowGrab) {
  1270         _this->SetWindowGrab(_this, window);
  1271     }
  1272 }
  1273 
  1274 void
  1275 SDL_OnWindowFocusLost(SDL_Window * window)
  1276 {
  1277     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
  1278 
  1279     if (window->flags & SDL_WINDOW_FULLSCREEN) {
  1280         SDL_MinimizeWindow(window->id);
  1281         SDL_SetDisplayMode(NULL);
  1282     }
  1283     if (display->gamma && _this->SetDisplayGammaRamp) {
  1284         _this->SetDisplayGammaRamp(_this, display->saved_gamma);
  1285     }
  1286     if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
  1287         && _this->SetWindowGrab) {
  1288         _this->SetWindowGrab(_this, window);
  1289     }
  1290 }
  1291 
  1292 SDL_WindowID
  1293 SDL_GetFocusWindow(void)
  1294 {
  1295     SDL_VideoDisplay *display;
  1296     int i;
  1297 
  1298     if (!_this) {
  1299         return 0;
  1300     }
  1301     display = &SDL_CurrentDisplay;
  1302     for (i = 0; i < display->num_windows; ++i) {
  1303         SDL_Window *window = &display->windows[i];
  1304 
  1305         if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
  1306             return window->id;
  1307         }
  1308     }
  1309     return 0;
  1310 }
  1311 
  1312 void
  1313 SDL_DestroyWindow(SDL_WindowID windowID)
  1314 {
  1315     int i, j;
  1316 
  1317     if (!_this) {
  1318         return;
  1319     }
  1320     /* Restore video mode, etc. */
  1321     SDL_SendWindowEvent(windowID, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
  1322 
  1323     for (i = 0; i < _this->num_displays; ++i) {
  1324         SDL_VideoDisplay *display = &_this->displays[i];
  1325         for (j = 0; j < display->num_windows; ++j) {
  1326             SDL_Window *window = &display->windows[j];
  1327             if (window->id != windowID) {
  1328                 continue;
  1329             }
  1330             if (window->title) {
  1331                 SDL_free(window->title);
  1332                 window->title = NULL;
  1333             }
  1334             if (window->renderer) {
  1335                 SDL_DestroyRenderer(window->id);
  1336                 window->renderer = NULL;
  1337             }
  1338             if (_this->DestroyWindow) {
  1339                 _this->DestroyWindow(_this, window);
  1340             }
  1341             if (j != display->num_windows - 1) {
  1342                 SDL_memcpy(&display->windows[i],
  1343                            &display->windows[i + 1],
  1344                            (display->num_windows - i - 1) * sizeof(*window));
  1345             }
  1346             --display->num_windows;
  1347             return;
  1348         }
  1349     }
  1350 }
  1351 
  1352 void
  1353 SDL_AddRenderDriver(int displayIndex, const SDL_RenderDriver * driver)
  1354 {
  1355     SDL_VideoDisplay *display;
  1356     SDL_RenderDriver *render_drivers;
  1357 
  1358     if (displayIndex >= _this->num_displays) {
  1359         return;
  1360     }
  1361     display = &_this->displays[displayIndex];
  1362 
  1363     render_drivers =
  1364         SDL_realloc(display->render_drivers,
  1365                     (display->num_render_drivers +
  1366                      1) * sizeof(*render_drivers));
  1367     if (render_drivers) {
  1368         render_drivers[display->num_render_drivers] = *driver;
  1369         display->render_drivers = render_drivers;
  1370         display->num_render_drivers++;
  1371     }
  1372 }
  1373 
  1374 int
  1375 SDL_GetNumRenderDrivers(void)
  1376 {
  1377     if (_this) {
  1378         return SDL_CurrentDisplay.num_render_drivers;
  1379     }
  1380     return 0;
  1381 }
  1382 
  1383 int
  1384 SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info)
  1385 {
  1386     if (!_this) {
  1387         SDL_UninitializedVideo();
  1388         return -1;
  1389     }
  1390     if (index < 0 || index >= SDL_GetNumRenderDrivers()) {
  1391         SDL_SetError("index must be in the range of 0 - %d",
  1392                      SDL_GetNumRenderDrivers() - 1);
  1393         return -1;
  1394     }
  1395     *info = SDL_CurrentDisplay.render_drivers[index].info;
  1396     return 0;
  1397 }
  1398 
  1399 int
  1400 SDL_CreateRenderer(SDL_WindowID windowID, int index, Uint32 flags)
  1401 {
  1402     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1403 
  1404     if (!window) {
  1405         return 0;
  1406     }
  1407     if (index < 0) {
  1408         const char *override = SDL_getenv("SDL_VIDEO_RENDERER");
  1409         int n = SDL_GetNumRenderDrivers();
  1410         for (index = 0; index < n; ++index) {
  1411             SDL_RenderDriver *driver =
  1412                 &SDL_CurrentDisplay.render_drivers[index];
  1413 
  1414             if (override) {
  1415                 if (SDL_strcasecmp(override, driver->info.name) == 0) {
  1416                     break;
  1417                 }
  1418             } else {
  1419                 if ((driver->info.flags & flags) == flags) {
  1420                     break;
  1421                 }
  1422             }
  1423         }
  1424         if (index == n) {
  1425             SDL_SetError("Couldn't find matching render driver");
  1426             return -1;
  1427         }
  1428     }
  1429     if (index >= SDL_GetNumRenderDrivers()) {
  1430         SDL_SetError("index must be -1 or in the range of 0 - %d",
  1431                      SDL_GetNumRenderDrivers() - 1);
  1432         return -1;
  1433     }
  1434     /* Free any existing renderer */
  1435     SDL_DestroyRenderer(windowID);
  1436 
  1437     /* Create a new renderer instance */
  1438     window->renderer = SDL_CurrentDisplay.render_drivers[index]
  1439         .CreateRenderer(window, flags);
  1440     SDL_SelectRenderer(window->id);
  1441 
  1442     return 0;
  1443 }
  1444 
  1445 int
  1446 SDL_SelectRenderer(SDL_WindowID windowID)
  1447 {
  1448     SDL_Window *window = SDL_GetWindowFromID(windowID);
  1449     SDL_Renderer *renderer;
  1450 
  1451     if (!window || !window->renderer) {
  1452         return -1;
  1453     }
  1454     renderer = window->renderer;
  1455     if (renderer && renderer->ActivateRenderer) {
  1456         if (renderer->ActivateRenderer(renderer) < 0) {
  1457             return -1;
  1458         }
  1459     }
  1460     SDL_CurrentDisplay.current_renderer = renderer;
  1461     return 0;
  1462 }
  1463 
  1464 int
  1465 SDL_GetRendererInfo(SDL_RendererInfo * info)
  1466 {
  1467     if (!_this) {
  1468         SDL_UninitializedVideo();
  1469         return -1;
  1470     }
  1471     if (!SDL_CurrentDisplay.current_renderer) {
  1472         SDL_SetError("There is no current renderer");
  1473         return -1;
  1474     }
  1475     *info = SDL_CurrentDisplay.current_renderer->info;
  1476     return 0;
  1477 }
  1478 
  1479 SDL_TextureID
  1480 SDL_CreateTexture(Uint32 format, int access, int w, int h)
  1481 {
  1482     int hash;
  1483     SDL_Renderer *renderer;
  1484     SDL_Texture *texture;
  1485 
  1486     if (!_this) {
  1487         SDL_UninitializedVideo();
  1488         return 0;
  1489     }
  1490     renderer = SDL_CurrentDisplay.current_renderer;
  1491     if (!renderer) {
  1492         return 0;
  1493     }
  1494     if (!renderer->CreateTexture) {
  1495         SDL_Unsupported();
  1496         return 0;
  1497     }
  1498     texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
  1499     if (!texture) {
  1500         SDL_OutOfMemory();
  1501         return 0;
  1502     }
  1503     texture->id = _this->next_object_id++;
  1504     texture->format = format;
  1505     texture->access = access;
  1506     texture->w = w;
  1507     texture->h = h;
  1508     texture->r = 255;
  1509     texture->g = 255;
  1510     texture->b = 255;
  1511     texture->a = 255;
  1512     texture->renderer = renderer;
  1513 
  1514     if (renderer->CreateTexture(renderer, texture) < 0) {
  1515         if (renderer->DestroyTexture) {
  1516             renderer->DestroyTexture(renderer, texture);
  1517         }
  1518         SDL_free(texture);
  1519         return 0;
  1520     }
  1521     hash = (texture->id % SDL_arraysize(SDL_CurrentDisplay.textures));
  1522     texture->next = SDL_CurrentDisplay.textures[hash];
  1523     SDL_CurrentDisplay.textures[hash] = texture;
  1524 
  1525     return texture->id;
  1526 }
  1527 
  1528 SDL_TextureID
  1529 SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface)
  1530 {
  1531     SDL_TextureID textureID;
  1532     SDL_PixelFormat *fmt;
  1533     int bpp;
  1534     Uint32 Rmask, Gmask, Bmask, Amask;
  1535 
  1536     if (!surface) {
  1537         SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
  1538         return 0;
  1539     }
  1540     fmt = surface->format;
  1541 
  1542     if (format) {
  1543         if (!SDL_PixelFormatEnumToMasks
  1544             (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
  1545             SDL_SetError("Unknown pixel format");
  1546             return 0;
  1547         }
  1548     } else {
  1549         if (surface->format->Amask
  1550             || !(surface->map->info.flags &
  1551                  (SDL_COPY_COLORKEY | SDL_COPY_MASK | SDL_COPY_BLEND))) {
  1552             bpp = fmt->BitsPerPixel;
  1553             Rmask = fmt->Rmask;
  1554             Gmask = fmt->Gmask;
  1555             Bmask = fmt->Bmask;
  1556             Amask = fmt->Amask;
  1557         } else {
  1558             /* Need a format with alpha */
  1559             bpp = 32;
  1560             Rmask = 0x00FF0000;
  1561             Gmask = 0x0000FF00;
  1562             Bmask = 0x000000FF;
  1563             Amask = 0xFF000000;
  1564         }
  1565         format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
  1566         if (!format) {
  1567             SDL_SetError("Unknown pixel format");
  1568             return 0;
  1569         }
  1570     }
  1571 
  1572     textureID =
  1573         SDL_CreateTexture(format, SDL_TEXTUREACCESS_STATIC, surface->w,
  1574                           surface->h);
  1575     if (!textureID) {
  1576         return 0;
  1577     }
  1578     if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask
  1579         && Bmask == fmt->Bmask && Amask == fmt->Amask) {
  1580         if (SDL_MUSTLOCK(surface)) {
  1581             if (SDL_LockSurface(surface) < 0) {
  1582                 SDL_DestroyTexture(textureID);
  1583                 return 0;
  1584             }
  1585             SDL_UpdateTexture(textureID, NULL, surface->pixels,
  1586                               surface->pitch);
  1587             SDL_UnlockSurface(surface);
  1588         } else {
  1589             SDL_UpdateTexture(textureID, NULL, surface->pixels,
  1590                               surface->pitch);
  1591         }
  1592     } else {
  1593         SDL_PixelFormat *dst_fmt;
  1594         SDL_Surface *dst = NULL;
  1595 
  1596         /* Set up a destination surface for the texture update */
  1597         dst_fmt = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
  1598         if (dst_fmt) {
  1599             if (SDL_ISPIXELFORMAT_INDEXED(format)) {
  1600                 dst_fmt->palette =
  1601                     SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format)));
  1602                 if (dst_fmt->palette) {
  1603                     /*
  1604                      * FIXME: Should we try to copy
  1605                      * fmt->palette?
  1606                      */
  1607                     SDL_DitherColors(dst_fmt->palette->colors,
  1608                                      SDL_BITSPERPIXEL(format));
  1609                 }
  1610             }
  1611             dst = SDL_ConvertSurface(surface, dst_fmt, 0);
  1612             if (dst) {
  1613                 SDL_UpdateTexture(textureID, NULL, dst->pixels, dst->pitch);
  1614                 SDL_FreeSurface(dst);
  1615             }
  1616             if (dst_fmt->palette) {
  1617                 SDL_FreePalette(dst_fmt->palette);
  1618             }
  1619             SDL_FreeFormat(dst_fmt);
  1620         }
  1621         if (!dst) {
  1622             SDL_DestroyTexture(textureID);
  1623             return 0;
  1624         }
  1625     }
  1626 
  1627     if (SDL_ISPIXELFORMAT_INDEXED(format) && fmt->palette) {
  1628         SDL_SetTexturePalette(textureID, fmt->palette->colors, 0,
  1629                               fmt->palette->ncolors);
  1630     }
  1631     return textureID;
  1632 }
  1633 
  1634 static __inline__ SDL_Texture *
  1635 SDL_GetTextureFromID(SDL_TextureID textureID)
  1636 {
  1637     int hash;
  1638     SDL_Texture *texture;
  1639 
  1640     if (!_this) {
  1641         return NULL;
  1642     }
  1643     hash = (textureID % SDL_arraysize(SDL_CurrentDisplay.textures));
  1644     for (texture = SDL_CurrentDisplay.textures[hash]; texture;
  1645          texture = texture->next) {
  1646         if (texture->id == textureID) {
  1647             return texture;
  1648         }
  1649     }
  1650     return NULL;
  1651 }
  1652 
  1653 int
  1654 SDL_QueryTexture(SDL_TextureID textureID, Uint32 * format, int *access,
  1655                  int *w, int *h)
  1656 {
  1657     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1658 
  1659     if (!texture) {
  1660         return -1;
  1661     }
  1662     if (format) {
  1663         *format = texture->format;
  1664     }
  1665     if (access) {
  1666         *access = texture->access;
  1667     }
  1668     if (w) {
  1669         *w = texture->w;
  1670     }
  1671     if (h) {
  1672         *h = texture->h;
  1673     }
  1674     return 0;
  1675 }
  1676 
  1677 int
  1678 SDL_QueryTexturePixels(SDL_TextureID textureID, void **pixels, int *pitch)
  1679 {
  1680     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1681     SDL_Renderer *renderer;
  1682 
  1683     if (!texture) {
  1684         return -1;
  1685     }
  1686     renderer = texture->renderer;
  1687     if (!renderer->QueryTexturePixels) {
  1688         SDL_Unsupported();
  1689         return -1;
  1690     }
  1691     return renderer->QueryTexturePixels(renderer, texture, pixels, pitch);
  1692 }
  1693 
  1694 int
  1695 SDL_SetTexturePalette(SDL_TextureID textureID, const SDL_Color * colors,
  1696                       int firstcolor, int ncolors)
  1697 {
  1698     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1699     SDL_Renderer *renderer;
  1700 
  1701     if (!texture) {
  1702         return -1;
  1703     }
  1704     renderer = texture->renderer;
  1705     if (!renderer->SetTexturePalette) {
  1706         SDL_Unsupported();
  1707         return -1;
  1708     }
  1709     return renderer->SetTexturePalette(renderer, texture, colors, firstcolor,
  1710                                        ncolors);
  1711 }
  1712 
  1713 int
  1714 SDL_GetTexturePalette(SDL_TextureID textureID, SDL_Color * colors,
  1715                       int firstcolor, int ncolors)
  1716 {
  1717     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1718     SDL_Renderer *renderer;
  1719 
  1720     if (!texture) {
  1721         return -1;
  1722     }
  1723     renderer = texture->renderer;
  1724     if (!renderer->GetTexturePalette) {
  1725         SDL_Unsupported();
  1726         return -1;
  1727     }
  1728     return renderer->GetTexturePalette(renderer, texture, colors, firstcolor,
  1729                                        ncolors);
  1730 }
  1731 
  1732 int
  1733 SDL_SetTextureColorMod(SDL_TextureID textureID, Uint8 r, Uint8 g, Uint8 b)
  1734 {
  1735     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1736     SDL_Renderer *renderer;
  1737 
  1738     if (!texture) {
  1739         return -1;
  1740     }
  1741     renderer = texture->renderer;
  1742     if (!renderer->SetTextureColorMod) {
  1743         SDL_Unsupported();
  1744         return -1;
  1745     }
  1746     if (r < 255 || g < 255 || b < 255) {
  1747         texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
  1748     } else {
  1749         texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
  1750     }
  1751     texture->r = r;
  1752     texture->g = g;
  1753     texture->b = b;
  1754     return renderer->SetTextureColorMod(renderer, texture);
  1755 }
  1756 
  1757 int
  1758 SDL_GetTextureColorMod(SDL_TextureID textureID, Uint8 * r, Uint8 * g,
  1759                        Uint8 * b)
  1760 {
  1761     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1762     SDL_Renderer *renderer;
  1763 
  1764     if (!texture) {
  1765         return -1;
  1766     }
  1767     renderer = texture->renderer;
  1768     if (r) {
  1769         *r = texture->r;
  1770     }
  1771     if (g) {
  1772         *g = texture->g;
  1773     }
  1774     if (b) {
  1775         *b = texture->b;
  1776     }
  1777     return 0;
  1778 }
  1779 
  1780 int
  1781 SDL_SetTextureAlphaMod(SDL_TextureID textureID, Uint8 alpha)
  1782 {
  1783     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1784     SDL_Renderer *renderer;
  1785 
  1786     if (!texture) {
  1787         return -1;
  1788     }
  1789     renderer = texture->renderer;
  1790     if (!renderer->SetTextureAlphaMod) {
  1791         SDL_Unsupported();
  1792         return -1;
  1793     }
  1794     if (alpha < 255) {
  1795         texture->modMode |= SDL_TEXTUREMODULATE_ALPHA;
  1796     } else {
  1797         texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
  1798     }
  1799     texture->a = alpha;
  1800     return renderer->SetTextureAlphaMod(renderer, texture);
  1801 }
  1802 
  1803 int
  1804 SDL_GetTextureAlphaMod(SDL_TextureID textureID, Uint8 * alpha)
  1805 {
  1806     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1807 
  1808     if (!texture) {
  1809         return -1;
  1810     }
  1811     if (alpha) {
  1812         *alpha = texture->a;
  1813     }
  1814     return 0;
  1815 }
  1816 
  1817 int
  1818 SDL_SetTextureBlendMode(SDL_TextureID textureID, int blendMode)
  1819 {
  1820     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1821     SDL_Renderer *renderer;
  1822 
  1823     if (!texture) {
  1824         return -1;
  1825     }
  1826     renderer = texture->renderer;
  1827     if (!renderer->SetTextureBlendMode) {
  1828         SDL_Unsupported();
  1829         return -1;
  1830     }
  1831     texture->blendMode = blendMode;
  1832     return renderer->SetTextureBlendMode(renderer, texture);
  1833 }
  1834 
  1835 int
  1836 SDL_GetTextureBlendMode(SDL_TextureID textureID, int *blendMode)
  1837 {
  1838     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1839 
  1840     if (!texture) {
  1841         return -1;
  1842     }
  1843     if (blendMode) {
  1844         *blendMode = texture->blendMode;
  1845     }
  1846     return 0;
  1847 }
  1848 
  1849 int
  1850 SDL_SetTextureScaleMode(SDL_TextureID textureID, int scaleMode)
  1851 {
  1852     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1853     SDL_Renderer *renderer;
  1854 
  1855     if (!texture) {
  1856         return -1;
  1857     }
  1858     renderer = texture->renderer;
  1859     if (!renderer->SetTextureScaleMode) {
  1860         SDL_Unsupported();
  1861         return -1;
  1862     }
  1863     texture->scaleMode = scaleMode;
  1864     return renderer->SetTextureScaleMode(renderer, texture);
  1865 }
  1866 
  1867 int
  1868 SDL_GetTextureScaleMode(SDL_TextureID textureID, int *scaleMode)
  1869 {
  1870     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1871 
  1872     if (!texture) {
  1873         return -1;
  1874     }
  1875     if (scaleMode) {
  1876         *scaleMode = texture->scaleMode;
  1877     }
  1878     return 0;
  1879 }
  1880 
  1881 int
  1882 SDL_UpdateTexture(SDL_TextureID textureID, const SDL_Rect * rect,
  1883                   const void *pixels, int pitch)
  1884 {
  1885     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1886     SDL_Renderer *renderer;
  1887     SDL_Rect full_rect;
  1888 
  1889     if (!texture) {
  1890         return -1;
  1891     }
  1892     renderer = texture->renderer;
  1893     if (!renderer->UpdateTexture) {
  1894         SDL_Unsupported();
  1895         return -1;
  1896     }
  1897     if (!rect) {
  1898         full_rect.x = 0;
  1899         full_rect.y = 0;
  1900         full_rect.w = texture->w;
  1901         full_rect.h = texture->h;
  1902         rect = &full_rect;
  1903     }
  1904     return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
  1905 }
  1906 
  1907 int
  1908 SDL_LockTexture(SDL_TextureID textureID, const SDL_Rect * rect, int markDirty,
  1909                 void **pixels, int *pitch)
  1910 {
  1911     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1912     SDL_Renderer *renderer;
  1913     SDL_Rect full_rect;
  1914 
  1915     if (!texture) {
  1916         return -1;
  1917     }
  1918     if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
  1919         SDL_SetError("SDL_LockTexture(): texture must be streaming");
  1920         return -1;
  1921     }
  1922     renderer = texture->renderer;
  1923     if (!renderer->LockTexture) {
  1924         SDL_Unsupported();
  1925         return -1;
  1926     }
  1927     if (!rect) {
  1928         full_rect.x = 0;
  1929         full_rect.y = 0;
  1930         full_rect.w = texture->w;
  1931         full_rect.h = texture->h;
  1932         rect = &full_rect;
  1933     }
  1934     return renderer->LockTexture(renderer, texture, rect, markDirty, pixels,
  1935                                  pitch);
  1936 }
  1937 
  1938 void
  1939 SDL_UnlockTexture(SDL_TextureID textureID)
  1940 {
  1941     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1942     SDL_Renderer *renderer;
  1943 
  1944     if (!texture) {
  1945         return;
  1946     }
  1947     if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
  1948         return;
  1949     }
  1950     renderer = texture->renderer;
  1951     if (!renderer->UnlockTexture) {
  1952         return;
  1953     }
  1954     renderer->UnlockTexture(renderer, texture);
  1955 }
  1956 
  1957 void
  1958 SDL_DirtyTexture(SDL_TextureID textureID, int numrects,
  1959                  const SDL_Rect * rects)
  1960 {
  1961     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  1962     SDL_Renderer *renderer;
  1963 
  1964     if (!texture) {
  1965         return;
  1966     }
  1967     if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
  1968         return;
  1969     }
  1970     renderer = texture->renderer;
  1971     if (!renderer->DirtyTexture) {
  1972         return;
  1973     }
  1974     renderer->DirtyTexture(renderer, texture, numrects, rects);
  1975 }
  1976 
  1977 int
  1978 SDL_SetRenderDrawColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1979 {
  1980     SDL_Renderer *renderer;
  1981 
  1982     if (!_this) {
  1983         SDL_UninitializedVideo();
  1984         return -1;
  1985     }
  1986     renderer = SDL_CurrentDisplay.current_renderer;
  1987     if (!renderer) {
  1988         return -1;
  1989     }
  1990     if (!renderer->SetDrawColor) {
  1991         SDL_Unsupported();
  1992         return -1;
  1993     }
  1994     renderer->r = r;
  1995     renderer->g = g;
  1996     renderer->b = b;
  1997     renderer->a = a;
  1998     renderer->SetDrawColor(renderer);
  1999     return 0;
  2000 }
  2001 
  2002 int
  2003 SDL_GetRenderDrawColor(Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  2004 {
  2005     SDL_Renderer *renderer;
  2006 
  2007     if (!_this) {
  2008         SDL_UninitializedVideo();
  2009         return -1;
  2010     }
  2011     renderer = SDL_CurrentDisplay.current_renderer;
  2012     if (!renderer) {
  2013         return -1;
  2014     }
  2015     if (!renderer->SetDrawColor) {
  2016         SDL_Unsupported();
  2017         return -1;
  2018     }
  2019     if (r) {
  2020         *r = renderer->r;
  2021     }
  2022     if (g) {
  2023         *g = renderer->g;
  2024     }
  2025     if (b) {
  2026         *b = renderer->b;
  2027     }
  2028     if (a) {
  2029         *a = renderer->a;
  2030     }
  2031     return 0;
  2032 }
  2033 
  2034 int
  2035 SDL_SetRenderDrawBlendMode(int blendMode)
  2036 {
  2037     SDL_Renderer *renderer;
  2038 
  2039     if (!_this) {
  2040         SDL_UninitializedVideo();
  2041         return -1;
  2042     }
  2043     renderer = SDL_CurrentDisplay.current_renderer;
  2044     if (!renderer) {
  2045         return -1;
  2046     }
  2047     if (!renderer->SetDrawBlendMode) {
  2048         SDL_Unsupported();
  2049         return -1;
  2050     }
  2051     renderer->blendMode = blendMode;
  2052     renderer->SetDrawBlendMode(renderer);
  2053     return 0;
  2054 }
  2055 
  2056 int
  2057 SDL_GetRenderDrawBlendMode(int *blendMode)
  2058 {
  2059     SDL_Renderer *renderer;
  2060 
  2061     if (!_this) {
  2062         SDL_UninitializedVideo();
  2063         return -1;
  2064     }
  2065     renderer = SDL_CurrentDisplay.current_renderer;
  2066     if (!renderer) {
  2067         return -1;
  2068     }
  2069     *blendMode = renderer->blendMode;
  2070     return 0;
  2071 }
  2072 
  2073 
  2074 int
  2075 SDL_RenderFill(const SDL_Rect * rect)
  2076 {
  2077     SDL_Renderer *renderer;
  2078     SDL_Window *window;
  2079     SDL_Rect real_rect;
  2080 
  2081     if (!_this) {
  2082         SDL_UninitializedVideo();
  2083         return -1;
  2084     }
  2085     renderer = SDL_CurrentDisplay.current_renderer;
  2086     if (!renderer) {
  2087         return -1;
  2088     }
  2089     if (!renderer->RenderFill) {
  2090         SDL_Unsupported();
  2091         return -1;
  2092     }
  2093     window = SDL_GetWindowFromID(renderer->window);
  2094     real_rect.x = 0;
  2095     real_rect.y = 0;
  2096     real_rect.w = window->w;
  2097     real_rect.h = window->h;
  2098     if (rect) {
  2099         if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
  2100             return 0;
  2101         }
  2102     }
  2103     return renderer->RenderFill(renderer, &real_rect);
  2104 }
  2105 
  2106 int
  2107 SDL_RenderLine(int x1, int y1, int x2, int y2)
  2108 {
  2109     SDL_Renderer *renderer;
  2110     SDL_Window *window;
  2111     SDL_Rect real_rect;
  2112 
  2113     if (!_this) {
  2114         SDL_UninitializedVideo();
  2115         return -1;
  2116     }
  2117     renderer = SDL_CurrentDisplay.current_renderer;
  2118     if (!renderer) {
  2119         return -1;
  2120     }
  2121     if (!renderer->RenderLine) {
  2122         SDL_Unsupported();
  2123         return -1;
  2124     }
  2125 #if 0
  2126     //FIXME: Need line intersect routine
  2127     window = SDL_GetWindowFromID(renderer->window);
  2128     real_rect.x = 0;
  2129     real_rect.y = 0;
  2130     real_rect.w = window->w;
  2131     real_rect.h = window->h;
  2132     if (rect) {
  2133         if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
  2134             return 0;
  2135         }
  2136     }
  2137 #endif
  2138     return renderer->RenderLine(renderer, x1, y1, x2, y2);
  2139 }
  2140 
  2141 int
  2142 SDL_RenderCopy(SDL_TextureID textureID, const SDL_Rect * srcrect,
  2143                const SDL_Rect * dstrect)
  2144 {
  2145     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
  2146     SDL_Renderer *renderer;
  2147     SDL_Window *window;
  2148     SDL_Rect real_srcrect;
  2149     SDL_Rect real_dstrect;
  2150 
  2151     if (!texture || texture->renderer != SDL_CurrentDisplay.current_renderer) {
  2152         return -1;
  2153     }
  2154     renderer = SDL_CurrentDisplay.current_renderer;
  2155     if (!renderer) {
  2156         return -1;
  2157     }
  2158     if (!renderer->RenderCopy) {
  2159         SDL_Unsupported();
  2160         return -1;
  2161     }
  2162     window = SDL_GetWindowFromID(renderer->window);
  2163     if (srcrect) {
  2164         real_srcrect = *srcrect;
  2165     } else {
  2166         real_srcrect.x = 0;
  2167         real_srcrect.y = 0;
  2168         real_srcrect.w = texture->w;
  2169         real_srcrect.h = texture->h;
  2170     }
  2171     if (dstrect) {
  2172         real_dstrect = *dstrect;
  2173     } else {
  2174         real_dstrect.x = 0;
  2175         real_dstrect.y = 0;
  2176         real_dstrect.w = window->w;
  2177         real_dstrect.h = window->h;
  2178     }
  2179 
  2180     return renderer->RenderCopy(renderer, texture, &real_srcrect,
  2181                                 &real_dstrect);
  2182 }
  2183 
  2184 void
  2185 SDL_RenderPresent(void)
  2186 {
  2187     SDL_Renderer *renderer;
  2188 
  2189     if (!_this) {
  2190         SDL_UninitializedVideo();
  2191         return;
  2192     }
  2193     renderer = SDL_CurrentDisplay.current_renderer;
  2194     if (!renderer || !renderer->RenderPresent) {
  2195         return;
  2196     }
  2197     renderer->RenderPresent(renderer);
  2198 }
  2199 
  2200 void
  2201 SDL_DestroyTexture(SDL_TextureID textureID)
  2202 {
  2203     int hash;
  2204     SDL_Texture *prev, *texture;
  2205     SDL_Renderer *renderer;
  2206 
  2207     if (!_this) {
  2208         SDL_UninitializedVideo();
  2209         return;
  2210     }
  2211     /* Look up the texture in the hash table */
  2212     hash = (textureID % SDL_arraysize(SDL_CurrentDisplay.textures));
  2213     prev = NULL;
  2214     for (texture = SDL_CurrentDisplay.textures[hash]; texture;
  2215          prev = texture, texture = texture->next) {
  2216         if (texture->id == textureID) {
  2217             break;
  2218         }
  2219     }
  2220     if (!texture) {
  2221         return;
  2222     }
  2223     /* Unlink the texture from the list */
  2224     if (prev) {
  2225         prev->next = texture->next;
  2226     } else {
  2227         SDL_CurrentDisplay.textures[hash] = texture->next;
  2228     }
  2229 
  2230     /* Free the texture */
  2231     renderer = texture->renderer;
  2232     renderer->DestroyTexture(renderer, texture);
  2233     SDL_free(texture);
  2234 }
  2235 
  2236 void
  2237 SDL_DestroyRenderer(SDL_WindowID windowID)
  2238 {
  2239     SDL_Window *window = SDL_GetWindowFromID(windowID);
  2240     SDL_Renderer *renderer;
  2241     int i;
  2242 
  2243     if (!window) {
  2244         return;
  2245     }
  2246     renderer = window->renderer;
  2247     if (!renderer) {
  2248         return;
  2249     }
  2250     /* Free existing textures for this renderer */
  2251     for (i = 0; i < SDL_arraysize(SDL_CurrentDisplay.textures); ++i) {
  2252         SDL_Texture *texture;
  2253         SDL_Texture *prev = NULL;
  2254         SDL_Texture *next;
  2255         for (texture = SDL_CurrentDisplay.textures[i]; texture;
  2256              texture = next) {
  2257             next = texture->next;
  2258             if (texture->renderer == renderer) {
  2259                 if (prev) {
  2260                     prev->next = next;
  2261                 } else {
  2262                     SDL_CurrentDisplay.textures[i] = next;
  2263                 }
  2264                 renderer->DestroyTexture(renderer, texture);
  2265                 SDL_free(texture);
  2266             } else {
  2267                 prev = texture;
  2268             }
  2269         }
  2270     }
  2271 
  2272     /* Free the renderer instance */
  2273     renderer->DestroyRenderer(renderer);
  2274 
  2275     /* Clear references */
  2276     window->renderer = NULL;
  2277     if (SDL_CurrentDisplay.current_renderer == renderer) {
  2278         SDL_CurrentDisplay.current_renderer = NULL;
  2279     }
  2280 }
  2281 
  2282 void
  2283 SDL_VideoQuit(void)
  2284 {
  2285     int i, j;
  2286 
  2287     if (!_this) {
  2288         return;
  2289     }
  2290     /* Halt event processing before doing anything else */
  2291     SDL_StopEventLoop();
  2292 
  2293     /* Clean up the system video */
  2294     for (i = _this->num_displays; i--;) {
  2295         SDL_VideoDisplay *display = &_this->displays[i];
  2296         for (j = display->num_windows; j--;) {
  2297             SDL_DestroyWindow(display->windows[i].id);
  2298         }
  2299         if (display->windows) {
  2300             SDL_free(display->windows);
  2301             display->windows = NULL;
  2302         }
  2303         display->num_windows = 0;
  2304         if (display->render_drivers) {
  2305             SDL_free(display->render_drivers);
  2306             display->render_drivers = NULL;
  2307         }
  2308         display->num_render_drivers = 0;
  2309     }
  2310     _this->VideoQuit(_this);
  2311 
  2312     for (i = _this->num_displays; i--;) {
  2313         SDL_VideoDisplay *display = &_this->displays[i];
  2314         for (j = display->num_display_modes; j--;) {
  2315             if (display->display_modes[j].driverdata) {
  2316                 SDL_free(display->display_modes[j].driverdata);
  2317                 display->display_modes[j].driverdata = NULL;
  2318             }
  2319         }
  2320         if (display->display_modes) {
  2321             SDL_free(display->display_modes);
  2322             display->display_modes = NULL;
  2323         }
  2324         if (display->desktop_mode.driverdata) {
  2325             SDL_free(display->desktop_mode.driverdata);
  2326             display->desktop_mode.driverdata = NULL;
  2327         }
  2328         if (display->palette) {
  2329             SDL_FreePalette(display->palette);
  2330             display->palette = NULL;
  2331         }
  2332         if (display->gamma) {
  2333             SDL_free(display->gamma);
  2334             display->gamma = NULL;
  2335         }
  2336         if (display->driverdata) {
  2337             SDL_free(display->driverdata);
  2338             display->driverdata = NULL;
  2339         }
  2340     }
  2341     if (_this->displays) {
  2342         SDL_free(_this->displays);
  2343         _this->displays = NULL;
  2344     }
  2345     _this->free(_this);
  2346     _this = NULL;
  2347 }
  2348 
  2349 int
  2350 SDL_GL_LoadLibrary(const char *path)
  2351 {
  2352     int retval;
  2353 
  2354     if (!_this) {
  2355         SDL_UninitializedVideo();
  2356         return -1;
  2357     }
  2358     if (_this->GL_LoadLibrary) {
  2359         retval = _this->GL_LoadLibrary(_this, path);
  2360     } else {
  2361         SDL_SetError("No dynamic GL support in video driver");
  2362         retval = -1;
  2363     }
  2364     return (retval);
  2365 }
  2366 
  2367 void *
  2368 SDL_GL_GetProcAddress(const char *proc)
  2369 {
  2370     void *func;
  2371 
  2372     if (!_this) {
  2373         SDL_UninitializedVideo();
  2374         return NULL;
  2375     }
  2376     func = NULL;
  2377     if (_this->GL_GetProcAddress) {
  2378         if (_this->gl_config.driver_loaded) {
  2379             func = _this->GL_GetProcAddress(_this, proc);
  2380         } else {
  2381             SDL_SetError("No GL driver has been loaded");
  2382         }
  2383     } else {
  2384         SDL_SetError("No dynamic GL support in video driver");
  2385     }
  2386     return func;
  2387 }
  2388 
  2389 SDL_bool
  2390 SDL_GL_ExtensionSupported(const char *extension)
  2391 {
  2392 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES
  2393     const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
  2394     const char *extensions;
  2395     const char *start;
  2396     const char *where, *terminator;
  2397 
  2398     /* Extension names should not have spaces. */
  2399     where = SDL_strchr(extension, ' ');
  2400     if (where || *extension == '\0') {
  2401         return SDL_FALSE;
  2402     }
  2403     /* See if there's an environment variable override */
  2404     start = SDL_getenv(extension);
  2405     if (start && *start == '0') {
  2406         return SDL_FALSE;
  2407     }
  2408     /* Lookup the available extensions */
  2409     glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
  2410     if (glGetStringFunc) {
  2411         extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
  2412     } else {
  2413         extensions = NULL;
  2414     }
  2415     if (!extensions) {
  2416         return SDL_FALSE;
  2417     }
  2418     /*
  2419      * It takes a bit of care to be fool-proof about parsing the OpenGL
  2420      * extensions string. Don't be fooled by sub-strings, etc.
  2421      */
  2422 
  2423     start = extensions;
  2424 
  2425     for (;;) {
  2426         where = SDL_strstr(start, extension);
  2427         if (!where)
  2428             break;
  2429 
  2430         terminator = where + SDL_strlen(extension);
  2431         if (where == start || *(where - 1) == ' ')
  2432             if (*terminator == ' ' || *terminator == '\0')
  2433                 return SDL_TRUE;
  2434 
  2435         start = terminator;
  2436     }
  2437     return SDL_FALSE;
  2438 #else
  2439     return SDL_FALSE;
  2440 #endif
  2441 }
  2442 
  2443 int
  2444 SDL_GL_SetAttribute(SDL_GLattr attr, int value)
  2445 {
  2446 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES
  2447     int retval;
  2448 
  2449     if (!_this) {
  2450         SDL_UninitializedVideo();
  2451         return -1;
  2452     }
  2453     retval = 0;
  2454     switch (attr) {
  2455     case SDL_GL_RED_SIZE:
  2456         _this->gl_config.red_size = value;
  2457         break;
  2458     case SDL_GL_GREEN_SIZE:
  2459         _this->gl_config.green_size = value;
  2460         break;
  2461     case SDL_GL_BLUE_SIZE:
  2462         _this->gl_config.blue_size = value;
  2463         break;
  2464     case SDL_GL_ALPHA_SIZE:
  2465         _this->gl_config.alpha_size = value;
  2466         break;
  2467     case SDL_GL_DOUBLEBUFFER:
  2468         _this->gl_config.double_buffer = value;
  2469         break;
  2470     case SDL_GL_BUFFER_SIZE:
  2471         _this->gl_config.buffer_size = value;
  2472         break;
  2473     case SDL_GL_DEPTH_SIZE:
  2474         _this->gl_config.depth_size = value;
  2475         break;
  2476     case SDL_GL_STENCIL_SIZE:
  2477         _this->gl_config.stencil_size = value;
  2478         break;
  2479     case SDL_GL_ACCUM_RED_SIZE:
  2480         _this->gl_config.accum_red_size = value;
  2481         break;
  2482     case SDL_GL_ACCUM_GREEN_SIZE:
  2483         _this->gl_config.accum_green_size = value;
  2484         break;
  2485     case SDL_GL_ACCUM_BLUE_SIZE:
  2486         _this->gl_config.accum_blue_size = value;
  2487         break;
  2488     case SDL_GL_ACCUM_ALPHA_SIZE:
  2489         _this->gl_config.accum_alpha_size = value;
  2490         break;
  2491     case SDL_GL_STEREO:
  2492         _this->gl_config.stereo = value;
  2493         break;
  2494     case SDL_GL_MULTISAMPLEBUFFERS:
  2495         _this->gl_config.multisamplebuffers = value;
  2496         break;
  2497     case SDL_GL_MULTISAMPLESAMPLES:
  2498         _this->gl_config.multisamplesamples = value;
  2499         break;
  2500     case SDL_GL_ACCELERATED_VISUAL:
  2501         _this->gl_config.accelerated = value;
  2502         break;
  2503     case SDL_GL_RETAINED_BACKING:
  2504         _this->gl_config.retained_backing = value;
  2505         break;
  2506     default:
  2507         SDL_SetError("Unknown OpenGL attribute");
  2508         retval = -1;
  2509         break;
  2510     }
  2511     return retval;
  2512 #else
  2513     SDL_Unsupported();
  2514     return -1;
  2515 #endif /* SDL_VIDEO_OPENGL */
  2516 }
  2517 
  2518 int
  2519 SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
  2520 {
  2521 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES
  2522     void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
  2523     GLenum attrib = 0;
  2524 
  2525     glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
  2526     if (!glGetIntegervFunc) {
  2527         return -1;
  2528     }
  2529     switch (attr) {
  2530     case SDL_GL_RETAINED_BACKING:
  2531         *value = _this->gl_config.retained_backing;
  2532         return 0;
  2533     case SDL_GL_RED_SIZE:
  2534         attrib = GL_RED_BITS;
  2535         break;
  2536     case SDL_GL_BLUE_SIZE:
  2537         attrib = GL_BLUE_BITS;
  2538         break;
  2539     case SDL_GL_GREEN_SIZE:
  2540         attrib = GL_GREEN_BITS;
  2541         break;
  2542     case SDL_GL_ALPHA_SIZE:
  2543         attrib = GL_ALPHA_BITS;
  2544         break;
  2545     case SDL_GL_DOUBLEBUFFER:
  2546 #ifndef SDL_VIDEO_OPENGL_ES
  2547         attrib = GL_DOUBLEBUFFER;
  2548         break;
  2549 #else
  2550         /*
  2551          * I believe double buffering is the only option in OpenGL ES
  2552          * -- in any case, GL_DOUBLEBUFFER doesn't exist
  2553          */
  2554         *value = 1;
  2555         return 0;
  2556 #endif
  2557     case SDL_GL_DEPTH_SIZE:
  2558         attrib = GL_DEPTH_BITS;
  2559         break;
  2560     case SDL_GL_STENCIL_SIZE:
  2561         attrib = GL_STENCIL_BITS;
  2562         break;
  2563 #ifndef SDL_VIDEO_OPENGL_ES
  2564     case SDL_GL_ACCUM_RED_SIZE:
  2565         attrib = GL_ACCUM_RED_BITS;
  2566         break;
  2567     case SDL_GL_ACCUM_GREEN_SIZE:
  2568         attrib = GL_ACCUM_GREEN_BITS;
  2569         break;
  2570     case SDL_GL_ACCUM_BLUE_SIZE:
  2571         attrib = GL_ACCUM_BLUE_BITS;
  2572         break;
  2573     case SDL_GL_ACCUM_ALPHA_SIZE:
  2574         attrib = GL_ACCUM_ALPHA_BITS;
  2575         break;
  2576     case SDL_GL_STEREO:
  2577         attrib = GL_STEREO;
  2578         break;
  2579 #else
  2580     case SDL_GL_ACCUM_RED_SIZE:
  2581     case SDL_GL_ACCUM_GREEN_SIZE:
  2582     case SDL_GL_ACCUM_BLUE_SIZE:
  2583     case SDL_GL_ACCUM_ALPHA_SIZE:
  2584     case SDL_GL_STEREO:
  2585         /* none of these are supported in OpenGL ES */
  2586         *value = 0;
  2587         return 0;
  2588 #endif
  2589     case SDL_GL_MULTISAMPLEBUFFERS:
  2590 #ifndef SDL_VIDEO_OPENGL_ES
  2591         attrib = GL_SAMPLE_BUFFERS_ARB;
  2592 #else
  2593         attrib = GL_SAMPLE_BUFFERS;
  2594 #endif
  2595         break;
  2596     case SDL_GL_MULTISAMPLESAMPLES:
  2597 #ifndef SDL_VIDEO_OPENGL_ES
  2598         attrib = GL_SAMPLES_ARB;
  2599 #else
  2600         attrib = GL_SAMPLES;
  2601 #endif
  2602         break;
  2603     case SDL_GL_BUFFER_SIZE:
  2604         {
  2605             GLint bits = 0;
  2606             GLint component;
  2607 
  2608             /*
  2609              * there doesn't seem to be a single flag in OpenGL
  2610              * for this!
  2611              */
  2612             glGetIntegervFunc(GL_RED_BITS, &component);
  2613             bits += component;
  2614             glGetIntegervFunc(GL_GREEN_BITS, &component);
  2615             bits += component;
  2616             glGetIntegervFunc(GL_BLUE_BITS, &component);
  2617             bits += component;
  2618             glGetIntegervFunc(GL_ALPHA_BITS, &component);
  2619             bits += component;
  2620 
  2621             *value = bits;
  2622             return 0;
  2623         }
  2624     case SDL_GL_ACCELERATED_VISUAL:
  2625         {
  2626             /* FIXME: How do we get this information? */
  2627             *value = (_this->gl_config.accelerated != 0);
  2628             return 0;
  2629         }
  2630     default:
  2631         SDL_SetError("Unknown OpenGL attribute");
  2632         return -1;
  2633     }
  2634 
  2635     glGetIntegervFunc(attrib, (GLint *) value);
  2636     return 0;
  2637 #else
  2638     SDL_Unsupported();
  2639     return -1;
  2640 #endif /* SDL_VIDEO_OPENGL */
  2641 }
  2642 
  2643 SDL_GLContext
  2644 SDL_GL_CreateContext(SDL_WindowID windowID)
  2645 {
  2646     SDL_Window *window = SDL_GetWindowFromID(windowID);
  2647 
  2648     if (!window) {
  2649         return NULL;
  2650     }
  2651     if (!(window->flags & SDL_WINDOW_OPENGL)) {
  2652         SDL_SetError("The specified window isn't an OpenGL window");
  2653         return NULL;
  2654     }
  2655     return _this->GL_CreateContext(_this, window);
  2656 }
  2657 
  2658 int
  2659 SDL_GL_MakeCurrent(SDL_WindowID windowID, SDL_GLContext context)
  2660 {
  2661     SDL_Window *window = SDL_GetWindowFromID(windowID);
  2662 
  2663     if (window && !(window->flags & SDL_WINDOW_OPENGL)) {
  2664         SDL_SetError("The specified window isn't an OpenGL window");
  2665         return -1;
  2666     }
  2667     if (!context) {
  2668         window = NULL;
  2669     }
  2670     return _this->GL_MakeCurrent(_this, window, context);
  2671 }
  2672 
  2673 int
  2674 SDL_GL_SetSwapInterval(int interval)
  2675 {
  2676     if (!_this) {
  2677         SDL_UninitializedVideo();
  2678         return -1;
  2679     }
  2680     if (_this->GL_SetSwapInterval) {
  2681         return _this->GL_SetSwapInterval(_this, interval);
  2682     } else {
  2683         SDL_SetError("Setting the swap interval is not supported");
  2684         return -1;
  2685     }
  2686 }
  2687 
  2688 int
  2689 SDL_GL_GetSwapInterval(void)
  2690 {
  2691     if (!_this) {
  2692         SDL_UninitializedVideo();
  2693         return -1;
  2694     }
  2695     if (_this->GL_GetSwapInterval) {
  2696         return _this->GL_GetSwapInterval(_this);
  2697     } else {
  2698         SDL_SetError("Getting the swap interval is not supported");
  2699         return -1;
  2700     }
  2701 }
  2702 
  2703 void
  2704 SDL_GL_SwapWindow(SDL_WindowID windowID)
  2705 {
  2706     SDL_Window *window = SDL_GetWindowFromID(windowID);
  2707 
  2708     if (!window) {
  2709         return;
  2710     }
  2711     if (!(window->flags & SDL_WINDOW_OPENGL)) {
  2712         SDL_SetError("The specified window isn't an OpenGL window");
  2713         return;
  2714     }
  2715     _this->GL_SwapWindow(_this, window);
  2716 }
  2717 
  2718 void
  2719 SDL_GL_DeleteContext(SDL_GLContext context)
  2720 {
  2721     if (!_this || !context) {
  2722         return;
  2723     }
  2724     _this->GL_MakeCurrent(_this, NULL, NULL);
  2725     _this->GL_DeleteContext(_this, context);
  2726 }
  2727 
  2728 #if 0                           // FIXME
  2729 /*
  2730  * Utility function used by SDL_WM_SetIcon(); flags & 1 for color key, flags
  2731  * & 2 for alpha channel.
  2732  */
  2733 static void
  2734 CreateMaskFromColorKeyOrAlpha(SDL_Surface * icon, Uint8 * mask, int flags)
  2735 {
  2736     int x, y;
  2737     Uint32 colorkey;
  2738 #define SET_MASKBIT(icon, x, y, mask) \
  2739 	mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
  2740 
  2741     colorkey = icon->format->colorkey;
  2742     switch (icon->format->BytesPerPixel) {
  2743     case 1:
  2744         {
  2745             Uint8 *pixels;
  2746             for (y = 0; y < icon->h; ++y) {
  2747                 pixels = (Uint8 *) icon->pixels + y * icon->pitch;
  2748                 for (x = 0; x < icon->w; ++x) {
  2749                     if (*pixels++ == colorkey) {
  2750                         SET_MASKBIT(icon, x, y, mask);
  2751                     }
  2752                 }
  2753             }
  2754         }
  2755         break;
  2756 
  2757     case 2:
  2758         {
  2759             Uint16 *pixels;
  2760             for (y = 0; y < icon->h; ++y) {
  2761                 pixels = (Uint16 *) icon->pixels + y * icon->pitch / 2;
  2762                 for (x = 0; x < icon->w; ++x) {
  2763                     if ((flags & 1) && *pixels == colorkey) {
  2764                         SET_MASKBIT(icon, x, y, mask);
  2765                     } else if ((flags & 2)
  2766                                && (*pixels & icon->format->Amask) == 0) {
  2767                         SET_MASKBIT(icon, x, y, mask);
  2768                     }
  2769                     pixels++;
  2770                 }
  2771             }
  2772         }
  2773         break;
  2774 
  2775     case 4:
  2776         {
  2777             Uint32 *pixels;
  2778             for (y = 0; y < icon->h; ++y) {
  2779                 pixels = (Uint32 *) icon->pixels + y * icon->pitch / 4;
  2780                 for (x = 0; x < icon->w; ++x) {
  2781                     if ((flags & 1) && *pixels == colorkey) {
  2782                         SET_MASKBIT(icon, x, y, mask);
  2783                     } else if ((flags & 2)
  2784                                && (*pixels & icon->format->Amask) == 0) {
  2785                         SET_MASKBIT(icon, x, y, mask);
  2786                     }
  2787                     pixels++;
  2788                 }
  2789             }
  2790         }
  2791         break;
  2792     }
  2793 }
  2794 
  2795 /*
  2796  * Sets the window manager icon for the display window.
  2797  */
  2798 void
  2799 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
  2800 {
  2801     if (icon && _this->SetIcon) {
  2802         /* Generate a mask if necessary, and create the icon! */
  2803         if (mask == NULL) {
  2804             int mask_len = icon->h * (icon->w + 7) / 8;
  2805             int flags = 0;
  2806             mask = (Uint8 *) SDL_malloc(mask_len);
  2807             if (mask == NULL) {
  2808                 return;
  2809             }
  2810             SDL_memset(mask, ~0, mask_len);
  2811             if (icon->flags & SDL_SRCCOLORKEY)
  2812                 flags |= 1;
  2813             if (icon->flags & SDL_SRCALPHA)
  2814                 flags |= 2;
  2815             if (flags) {
  2816                 CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
  2817             }
  2818             _this->SetIcon(_this, icon, mask);
  2819             SDL_free(mask);
  2820         } else {
  2821             _this->SetIcon(_this, icon, mask);
  2822         }
  2823     }
  2824 }
  2825 #endif
  2826 
  2827 SDL_bool
  2828 SDL_GetWindowWMInfo(SDL_WindowID windowID, struct SDL_SysWMinfo *info)
  2829 {
  2830     SDL_Window *window = SDL_GetWindowFromID(windowID);
  2831 
  2832     if (!window || !_this->GetWindowWMInfo) {
  2833         return SDL_FALSE;
  2834     }
  2835     return (_this->GetWindowWMInfo(_this, window, info));
  2836 }
  2837 
  2838 /* vi: set ts=4 sw=4 expandtab: */