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