src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 11 Apr 2013 21:27:04 -0400
changeset 26 34c2ae82780a
parent 25 2dfd8573dba0
child 27 4b3e208d2c10
permissions -rw-r--r--
Implemented SDL_CreateThread().
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 /* This file contains functions for backwards compatibility with SDL 1.2 */
    23 
    24 #include "SDL.h"
    25 
    26 #if !SDL_VERSION_ATLEAST(2,0,0)
    27 #error You need to compile against SDL 2.0 headers.
    28 #endif
    29 
    30 #include "SDL_syswm.h"
    31 
    32 #include <stdarg.h>
    33 
    34 //#include "video/SDL_sysvideo.h"
    35 //#include "video/SDL_pixels_c.h"
    36 //#include "render/SDL_yuv_sw_c.h"
    37 
    38 // !!! IMPLEMENT_ME SDL_ConvertSurface
    39 // !!! IMPLEMENT_ME SDL_EventState
    40 // !!! IMPLEMENT_ME SDL_GL_GetAttribute
    41 // !!! IMPLEMENT_ME SDL_GL_Lock
    42 // !!! IMPLEMENT_ME SDL_GL_SetAttribute
    43 // !!! IMPLEMENT_ME SDL_GL_Unlock
    44 // !!! IMPLEMENT_ME SDL_GL_UpdateRects
    45 // !!! IMPLEMENT_ME SDL_GetKeyName
    46 // !!! IMPLEMENT_ME SDL_GetKeyState
    47 // !!! IMPLEMENT_ME SDL_GetModState
    48 // !!! IMPLEMENT_ME SDL_GetMouseState
    49 // !!! IMPLEMENT_ME SDL_GetRelativeMouseState
    50 // !!! IMPLEMENT_ME SDL_LockSurface
    51 // !!! IMPLEMENT_ME SDL_LowerBlit
    52 // !!! IMPLEMENT_ME SDL_SetColorKey
    53 // !!! IMPLEMENT_ME SDL_SetModState
    54 // !!! IMPLEMENT_ME SDL_SoftStretch
    55 // !!! IMPLEMENT_ME SDL_UnlockSurface
    56 // !!! IMPLEMENT_ME SDL_UpperBlit
    57 // !!! IMPLEMENT_ME SDL_WaitEvent
    58 // !!! IMPLEMENT_ME X11_KeyToUnicode
    59 
    60 
    61 #define SDL20_SYM(rc,fn,params,args,ret) \
    62     typedef rc (*SDL20_##fn##_t) params; \
    63     static SDL20_##fn##_t SDL20_##fn = NULL;
    64 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
    65     SDL20_SYM(rc,fn,params,args,ret)
    66 #include "SDL20_syms.h"
    67 #undef SDL20_SYM_PASSTHROUGH
    68 #undef SDL20_SYM
    69 
    70 typedef void (*SDL20_SetError_t)(const char *fmt, ...);
    71 static SDL20_SetError_t SDL20_SetError = NULL;
    72 
    73 
    74 
    75 #define SDL12_INIT_TIMER       0x00000001
    76 #define SDL12_INIT_AUDIO       0x00000010
    77 #define SDL12_INIT_VIDEO       0x00000020
    78 #define SDL12_INIT_CDROM       0x00000100
    79 #define SDL12_INIT_JOYSTICK    0x00000200
    80 #define SDL12_INIT_NOPARACHUTE 0x00100000
    81 #define SDL12_INIT_EVENTTHREAD 0x01000000
    82 #define SDL12_INIT_EVERYTHING  0x0000FFFF
    83 
    84 typedef struct SDL12_Palette
    85 {
    86     int       ncolors;
    87     SDL_Color *colors;
    88 } SDL12_Palette;
    89 
    90 typedef struct SDL12_PixelFormat
    91 {
    92     SDL12_Palette *palette;
    93     Uint8 BitsPerPixel;
    94     Uint8 BytesPerPixel;
    95     Uint8 Rloss;
    96     Uint8 Gloss;
    97     Uint8 Bloss;
    98     Uint8 Aloss;
    99     Uint8 Rshift;
   100     Uint8 Gshift;
   101     Uint8 Bshift;
   102     Uint8 Ashift;
   103     Uint32 Rmask;
   104     Uint32 Gmask;
   105     Uint32 Bmask;
   106     Uint32 Amask;
   107     Uint32 colorkey;
   108     Uint8 alpha;
   109 } SDL12_PixelFormat;
   110 
   111 typedef struct SDL12_Surface
   112 {
   113     Uint32 flags;
   114     SDL12_PixelFormat *format;
   115     int w;
   116     int h;
   117     Uint16 pitch;
   118     void *pixels;
   119     int offset;
   120     SDL_Surface *hwdata; /* the real SDL 1.2 has an opaque pointer to a platform-specific thing here. */
   121     SDL_Rect clip_rect;
   122     Uint32 unused1;
   123     Uint32 locked;
   124     void *blitmap;
   125     unsigned int format_version;
   126     int refcount;
   127 } SDL12_Surface;
   128 
   129 typedef struct
   130 {
   131     Uint32 hw_available :1;
   132     Uint32 wm_available :1;
   133     Uint32 UnusedBits1  :6;
   134     Uint32 UnusedBits2  :1;
   135     Uint32 blit_hw      :1;
   136     Uint32 blit_hw_CC   :1;
   137     Uint32 blit_hw_A    :1;
   138     Uint32 blit_sw      :1;
   139     Uint32 blit_sw_CC   :1;
   140     Uint32 blit_sw_A    :1;
   141     Uint32 blit_fill    :1;
   142     Uint32 UnusedBits3  :16;
   143     Uint32 video_mem;
   144     SDL_PixelFormat *vfmt;
   145     int current_w;
   146     int current_h;
   147 } SDL12_VideoInfo;
   148 
   149 
   150 #define SDL12_HWSURFACE 0x00000001
   151 #define SDL12_ASYNCBLIT 0x00000004
   152 #define SDL12_ANYFORMAT 0x10000000
   153 #define SDL12_HWPALETTE 0x20000000
   154 #define SDL12_DOUBLEBUF 0x40000000
   155 #define SDL12_FULLSCREEN 0x80000000
   156 #define SDL12_OPENGL 0x00000002
   157 #define SDL12_OPENGLBLIT 0x0000000A
   158 #define SDL12_RESIZABLE 0x00000010
   159 #define SDL12_NOFRAME 0x00000020
   160 #define SDL12_HWACCEL 0x00000100
   161 #define SDL12_SRCCOLORKEY 0x00001000
   162 #define SDL12_RLEACCELOK 0x00002000
   163 #define SDL12_RLEACCEL 0x00004000
   164 #define SDL12_SRCALPHA 0x00010000
   165 #define SDL12_PREALLOC 0x01000000
   166 
   167 typedef int (SDLCALL *SDL12_EventFilter)(const SDL12_Event *event12);
   168 static int EventFilter20to12(void *data, SDL_Event *event20);
   169 
   170 typedef enum
   171 {
   172     SDL12_NOEVENT = 0,
   173     SDL12_ACTIVEEVENT,
   174     SDL12_KEYDOWN,
   175     SDL12_KEYUP,
   176     SDL12_MOUSEMOTION,
   177     SDL12_MOUSEBUTTONDOWN,
   178     SDL12_MOUSEBUTTONUP,
   179     SDL12_JOYAXISMOTION,
   180     SDL12_JOYBALLMOTION,
   181     SDL12_JOYHATMOTION,
   182     SDL12_JOYBUTTONDOWN,
   183     SDL12_JOYBUTTONUP,
   184     SDL12_QUIT,
   185     SDL12_SYSWMEVENT,
   186     SDL12_EVENT_RESERVEDA,
   187     SDL12_EVENT_RESERVEDB,
   188     SDL12_VIDEORESIZE,
   189     SDL12_VIDEOEXPOSE,
   190     SDL12_USEREVENT = 24,
   191     SDL12_NUMEVENTS = 32
   192 } SDL12_EventType;
   193 
   194 typedef struct
   195 {
   196     Uint8 type;
   197     Uint8 gain;
   198     Uint8 state;
   199 } SDL12_ActiveEvent;
   200 
   201 typedef struct
   202 {
   203     Uint8 type;
   204     Uint8 which;
   205     Uint8 state;
   206     SDL12_keysym keysym;
   207 } SDL12_KeyboardEvent;
   208 
   209 typedef struct
   210 {
   211     Uint8 type;
   212     Uint8 which;
   213     Uint8 state;
   214     Uint16 x, y;
   215     Sint16 xrel;
   216     Sint16 yrel;
   217 } SDL12_MouseMotionEvent;
   218 
   219 typedef struct
   220 {
   221     Uint8 type;
   222     Uint8 which;
   223     Uint8 button;
   224     Uint8 state;
   225     Uint16 x, y;
   226 } SDL12_MouseButtonEvent;
   227 
   228 typedef struct
   229 {
   230     Uint8 type;
   231     Uint8 which;
   232     Uint8 axis;
   233     Sint16 value;
   234 } SDL12_JoyAxisEvent;
   235 
   236 typedef struct
   237 {
   238     Uint8 type;
   239     Uint8 which;
   240     Uint8 ball;
   241     Sint16 xrel;
   242     Sint16 yrel;
   243 } SDL12_JoyBallEvent;
   244 
   245 typedef struct
   246 {
   247     Uint8 type;
   248     Uint8 which;
   249     Uint8 hat;
   250     Uint8 value;
   251 } SDL12_JoyHatEvent;
   252 
   253 typedef struct
   254 {
   255     Uint8 type;
   256     Uint8 which;
   257     Uint8 button;
   258     Uint8 state;
   259 } SDL12_JoyButtonEvent;
   260 
   261 typedef struct
   262 {
   263     Uint8 type;
   264     int w;
   265     int h;
   266 } SDL12_ResizeEvent;
   267 
   268 typedef struct
   269 {
   270     Uint8 type;
   271 } SDL12_ExposeEvent;
   272 
   273 typedef struct
   274 {
   275     Uint8 type;
   276 } SDL12_QuitEvent;
   277 
   278 typedef struct
   279 {
   280     Uint8 type;
   281     int code;
   282     void *data1;
   283     void *data2;
   284 } SDL12_UserEvent;
   285 
   286 typedef struct
   287 {
   288     Uint8 type;
   289     void *msg;
   290 } SDL12_SysWMEvent;
   291 
   292 typedef union
   293 {
   294     Uint8 type;
   295     SDL12_ActiveEvent active;
   296     SDL12_KeyboardEvent key;
   297     SDL12_MouseMotionEvent motion;
   298     SDL12_MouseButtonEvent button;
   299     SDL12_JoyAxisEvent jaxis;
   300     SDL12_JoyBallEvent jball;
   301     SDL12_JoyHatEvent jhat;
   302     SDL12_JoyButtonEvent jbutton;
   303     SDL12_ResizeEvent resize;
   304     SDL12_ExposeEvent expose;
   305     SDL12_QuitEvent quit;
   306     SDL12_UserEvent user;
   307     SDL12_SysWMEvent syswm;
   308 } SDL12_Event;
   309 
   310 typedef struct
   311 `{
   312     SDL_Rect area;
   313     Sint16 hot_x;
   314     Sint16 hot_y;
   315     Uint8 *data;
   316     Uint8 *mask;
   317     Uint8 *save[2];
   318     SDL_Cursor *wm_cursor;  /* the real SDL 1.2 has an opaque pointer to a platform-specific cursor here. */
   319 } SDL12_Cursor;
   320 
   321 
   322 static SDL12_VideoInfo VideoInfo;
   323 static SDL_Window *VideoWindow20 = NULL;
   324 static SDL12_Surface *WindowSurface = NULL;
   325 static SDL12_Surface *VideoSurface = NULL;
   326 static SDL12_Surface *ShadowSurface = NULL;
   327 static SDL12_Surface *PublicSurface = NULL;
   328 static SDL_GLContext *VideoContext = NULL;
   329 static Uint32 VideoFlags = 0;
   330 static SDL_Rect VideoViewport;
   331 static char *WindowTitle = NULL;
   332 static char *WindowIconTitle = NULL;
   333 static SDL_Surface *VideoIcon;
   334 static int EnabledUnicode = 0;
   335 static int VideoDisplayIndex = 0;
   336 static int CDRomInit = 0;
   337 static SDL12_EventFilter EventFilter12 = NULL;
   338 static SDL12_Cursor *CurrentCursor = NULL;
   339 
   340 
   341 // !!! FIXME: need a mutex for the event queue.
   342 #define SDL12_MAXEVENTS 128
   343 typedef struct EventQueueType
   344 {
   345     SDL12_Event event12;
   346     struct EventQueueType *next;
   347 } EventQueueType;
   348 
   349 static EventQueueType EventQueuePool[SDL12_MAXEVENTS];
   350 static EventQueueType *EventQueueHead = NULL;
   351 static EventQueueType *EventQueueTail = NULL;
   352 static EventQueueType *EventQueueAvailable = NULL;
   353 
   354 /* Obviously we can't use SDL_LoadObject() to load SDL2.  :)  */
   355 #if defined(_WINDOWS)
   356     #define WIN32_LEAN_AND_MEAN 1
   357     #include <windows.h>
   358     #define SDL20_LIBNAME "SDL2.dll"
   359     static HANDLE Loaded_SDL20 = NULL;
   360     #define LoadSDL20Library() ((Loaded_SDL20 = LoadLibraryA(SDL20_LIBNAME)) != NULL)
   361     #define LookupSDL20Sym(sym) GetProcAddress(Loaded_SDL20, sym)
   362     #define CloseSDL20Library() { { if (Loaded_SDL20) { FreeLibrary(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   363 #elif defined(unix) || defined(__APPLE__)
   364     #include <dlfcn.h>
   365     #ifdef __APPLE__
   366     #define SDL20_LIBNAME "libSDL2.dylib"
   367     #else
   368     #define SDL20_LIBNAME "libSDL2-2.0.so.0"
   369     #endif
   370     static void *Loaded_SDL20 = NULL;
   371     #define LoadSDL20Library() ((Loaded_SDL20 = dlopen(SDL20_LIBNAME, RTLD_LOCAL)) != NULL)
   372     #define LookupSDL20Sym(sym) dlsym(Loaded_SDL20, sym)
   373     #define CloseSDL20Library() { if (Loaded_SDL20) { dlclose(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   374 #else
   375     #error Please define your platform.
   376 #endif
   377 
   378 static void *
   379 LoadSDL20Symbol(const char *fn, int *okay)
   380 {
   381     void *retval = NULL;
   382     if (*okay)  /* only bother trying if we haven't previously failed. */
   383     {
   384         retval = LookupSDL20Sym(fn);
   385         if (retval == NULL)
   386             *okay = 0;
   387     }
   388     return retval;
   389 }
   390 
   391 static void
   392 UnloadSDL20(void)
   393 {
   394     #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = NULL;
   395     #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) SDL20_##fn = NULL;
   396     #include "SDL20_syms.h"
   397     #undef SDL20_SYM_PASSTHROUGH
   398     #undef SDL20_SYM
   399     SDL20_SetError = NULL;
   400     CloseSDL20Library();
   401 }
   402 
   403 static int
   404 LoadSDL20(void)
   405 {
   406     int okay = 1;
   407     if (!Loaded_SDL20)
   408     {
   409         okay = LoadSDL20Library();
   410         #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = (SDL20_##fn##_t) LoadSDL20Symbol("SDL_" #fn, &okay);
   411         #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) SDL20_SYM(rc,fn,params,args,ret)
   412         #include "SDL20_syms.h"
   413         #undef SDL20_SYM_PASSTHROUGH
   414         #undef SDL20_SYM
   415         SDL20_SetError = (SDL20_SetError_t) LoadSDL20Symbol("SDL_SetError", &okay);
   416         if (!okay)
   417             UnloadSDL20();
   418     }
   419     return okay;
   420 }
   421 
   422 
   423 static int
   424 GetVideoDisplay()
   425 {
   426     // !!! FIXME: cache this value during SDL_Init() so it doesn't change.
   427     const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
   428     if ( !variable ) {
   429         variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
   430     }
   431     if ( variable ) {
   432         return SDL_atoi(variable);
   433     } else {
   434         return 0;
   435     }
   436 }
   437 
   438 static int
   439 DoSDLInit(const int justsubs, Uint32 sdl12flags)
   440 {
   441     Uint32 sdl20flags = 0;
   442     int rc;
   443 
   444     if (!LoadSDL20())
   445         return -1;
   446 
   447     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   448     SETFLAG(TIMER);
   449     SETFLAG(AUDIO);
   450     SETFLAG(VIDEO);
   451     SETFLAG(JOYSTICK);
   452     SETFLAG(NOPARACHUTE);
   453     #undef SETFLAG
   454 
   455     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   456     if (sdl12flags & SDL12_INIT_CDROM)
   457         CDRomInit = 1;
   458 
   459     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   460 
   461     rc = justsubs ? SDL20_InitSubSystem(sdl20flags) : SDL20_Init(sdl20flags);
   462     if ((rc == 0) && (sdl20flags & SDL_INIT_VIDEO))
   463     {
   464         int i;
   465         for (i = 0; i < SDL12_MAXEVENTS-1; i++)
   466             EventQueuePool[i].next = &EventQueuePool[i+1];
   467         EventQueuePool[SDL12_MAXEVENTS-1].next = NULL;
   468         EventQueueHead = EventQueueTail = NULL;
   469         EventQueueAvailable = EventQueuePool;
   470 
   471         SDL20_SetEventFilter(EventFilter20to12, NULL);
   472         VideoDisplayIndex = GetVideoDisplay();
   473     }
   474 
   475     return rc;
   476 }
   477 
   478 int
   479 SDL_InitSubSystem(Uint32 sdl12flags)
   480 {
   481     return DoSDLInit(1, sdl12flags);
   482 }
   483 
   484 int
   485 SDL_Init(Uint32 sdl12flags)
   486 {
   487     return DoSDLInit(0, sdl12flags);
   488 }
   489 
   490 Uint32
   491 SDL_WasInit(Uint32 sdl12flags)
   492 {
   493     // !!! FIXME: this is cut and pasted several places.
   494     Uint32 sdl20flags = 0;
   495     Uint32 extraflags = 0;
   496 
   497     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   498     SETFLAG(TIMER);
   499     SETFLAG(AUDIO);
   500     SETFLAG(VIDEO);
   501     SETFLAG(JOYSTICK);
   502     SETFLAG(NOPARACHUTE);
   503     #undef SETFLAG
   504 
   505     if ((sdl12flags & SDL12_INIT_CDROM) && (CDRomInit))
   506         extraflags |= SDL12_INIT_CDROM;
   507 
   508     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   509 
   510     // !!! FIXME: convert back to 1.2
   511     return SDL20_WasInit(sdl20flags) | extraflags;
   512 }
   513 
   514 void
   515 SDL_QuitSubSystem(Uint32 sdl12flags)
   516 {
   517     Uint32 sdl20flags = 0;
   518 
   519     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   520     SETFLAG(TIMER);
   521     SETFLAG(AUDIO);
   522     SETFLAG(VIDEO);
   523     SETFLAG(JOYSTICK);
   524     SETFLAG(NOPARACHUTE);
   525     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   526     #undef SETFLAG
   527 
   528     if (sdl12flags & SDL12_INIT_CDROM)
   529         CDRomInit = 0;
   530 
   531     // !!! FIXME: reset a bunch of other global variables too.
   532     if (sdl12flags & SDL12_INIT_VIDEO) {
   533         EventFilter12 = NULL;
   534         EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   535         CurrentCursor = NULL;
   536         SDL20_FreeFormat(VideoInfo.vfmt);
   537         SDL_zero(VideoInfo);
   538     }
   539 
   540     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   541     SDL20_QuitSubSystem(sdl20flags);
   542 
   543     // !!! FIXME: UnloadSDL20() ?
   544 }
   545 
   546 void
   547 SDL_Quit(void)
   548 {
   549     // !!! FIXME: reset a bunch of other global variables too.
   550     EventFilter12 = NULL;
   551     EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   552     CurrentCursor = NULL;
   553     SDL20_FreeFormat(VideoInfo.vfmt);
   554     SDL_zero(VideoInfo);
   555     CDRomInit = 0;
   556     SDL20_Quit();
   557     UnloadSDL20();
   558 }
   559 
   560 void
   561 SDL_SetError(const char *fmt, ...)
   562 {
   563     char *str = NULL;
   564     va_list ap;
   565     va_start(ap, fmt);
   566     vasprintf(&str, fmt, ap);
   567     va_end(ap);
   568     if (!str)
   569         SDL20_OutOfMemory();
   570     else
   571     {
   572         SDL20_SetError("%s", str);
   573         free(str);
   574     }
   575 }
   576 
   577 const char *
   578 SDL_GetError(void)
   579 {
   580     if (!Loaded_SDL20)
   581     {
   582         static const char noload_errstr[] = "Failed to load SDL 2.0 shared library";
   583         return noload_errstr;
   584     }
   585     return SDL20_GetError();
   586 }
   587 
   588 
   589 static const char *
   590 GetDriverName(const char *name, char *namebuf, int maxlen)
   591 {
   592     if (name) {
   593         if (namebuf) {
   594             SDL20_strlcpy(namebuf, name, maxlen);
   595             return namebuf;
   596         } else {
   597             return name;
   598         }
   599     }
   600     return NULL;
   601 }
   602 
   603 const char *
   604 SDL_AudioDriverName(char *namebuf, int maxlen)
   605 {
   606     return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
   607 }
   608 
   609 const char *
   610 SDL_VideoDriverName(char *namebuf, int maxlen)
   611 {
   612     return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
   613 }
   614 
   615 static int
   616 EventFilter20to12(void *data, SDL_Event *event20)
   617 {
   618     const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
   619     SDL12_Event event12;
   620 
   621     SDL_assert(data == NULL);  /* currently unused. */
   622 
   623     SDL_zero(event12);
   624 
   625     switch (event20->type)
   626     {
   627         case SDL_QUIT:
   628             event12->type = SDL12_QUIT;
   629             break;
   630 
   631         case SDL_WINDOWEVENT:
   632             switch (event20->window.event)
   633             {
   634                 case SDL_WINDOWEVENT_CLOSE:
   635                     event12->type = SDL12_QUIT;
   636                     break;
   637 
   638                 case SDL_WINDOWEVENT_SHOWN:
   639                 case SDL_WINDOWEVENT_EXPOSED:
   640                     event12->type = SDL12_VIDEOEXPOSE;
   641                     break;
   642 
   643                 case SDL_WINDOWEVENT_RESIZED:
   644                 case SDL_WINDOWEVENT_SIZE_CHANGED:  // !!! FIXME: what's the difference between RESIZED and SIZE_CHANGED?
   645                     event12->type = SDL12_VIDEORESIZE;
   646                     event12->resize.w = event20->window.data1;
   647                     event12->resize.h = event20->window.data2;
   648                     break;
   649 
   650                 case SDL_WINDOWEVENT_MINIMIZED:
   651                     event12->type = SDL_ACTIVEEVENT;
   652                     event12->active.gain = 0;
   653                     event12->active.state = SDL_APPACTIVE;
   654                     break;
   655 
   656                 case SDL_WINDOWEVENT_RESTORED:
   657                     event12->type = SDL_ACTIVEEVENT;
   658                     event12->active.gain = 1;
   659                     event12->active.state = SDL_APPACTIVE;
   660                     break;
   661 
   662                 case SDL_WINDOWEVENT_ENTER:
   663                     event12->type = SDL_ACTIVEEVENT;
   664                     event12->active.gain = 1;
   665                     event12->active.state = SDL_APPMOUSEFOCUS;
   666                     break;
   667 
   668                 case SDL_WINDOWEVENT_LEAVE:
   669                     event12->type = SDL_ACTIVEEVENT;
   670                     event12->active.gain = 0;
   671                     event12->active.state = SDL_APPMOUSEFOCUS;
   672                     break;
   673 
   674                 case SDL_WINDOWEVENT_FOCUS_GAINED:
   675                     event12->type = SDL_ACTIVEEVENT;
   676                     event12->active.gain = 1;
   677                     event12->active.state = SDL_APPINPUTFOCUS;
   678                     break;
   679 
   680                 case SDL_WINDOWEVENT_FOCUS_LOST:
   681                     event12->type = SDL_ACTIVEEVENT;
   682                     event12->active.gain = 0;
   683                     event12->active.state = SDL_APPINPUTFOCUS;
   684                     break;
   685             }
   686             break;
   687 
   688         // !!! FIXME: this is sort of a mess to convert.
   689         //case SDL_SYSWMEVENT:
   690 
   691         // !!! FIXME: write me
   692         case SDL_KEYDOWN:
   693         case SDL_KEYUP:
   694             return 0;
   695 
   696         // !!! FIXME: write me
   697         case SDL_TEXTEDITING:
   698         case SDL_TEXTINPUT:
   699             return 0;
   700 
   701         case SDL_MOUSEMOTION:
   702         	event12->type = SDL12_MOUSEMOTION;
   703             event12->motion.which = (Uint8) event20->motion.which;
   704             event12->motion.state = event20->motion.state;
   705             event12->motion.x = (Uint16) event20->motion.x;
   706             event12->motion.y = (Uint16) event20->motion.y;
   707             event12->motion.xrel = (Sint16) event20->motion.xrel;
   708             event12->motion.yrel = (Sint16) event20->motion.yrel;
   709             break;
   710 
   711         case SDL_MOUSEBUTTONDOWN:
   712         	event12->type = SDL12_MOUSEBUTTONDOWN;
   713             event12->button.which = (Uint8) event20->button.which;
   714             event12->button.button = event20->button.button;
   715             event12->button.state = event20->button.state;
   716             event12->button.x = (Uint16) event20->button.x;
   717             event12->button.y = (Uint16) event20->button.y;
   718             break;
   719 
   720         case SDL_MOUSEBUTTONUP:
   721         	event12->type = SDL12_MOUSEBUTTONUP;
   722             event12->button.which = (Uint8) event20->button.which;
   723             event12->button.button = event20->button.button;
   724             event12->button.state = event20->button.state;
   725             event12->button.x = (Uint16) event20->button.x;
   726             event12->button.y = (Uint16) event20->button.y;
   727             break;
   728 
   729         case SDL_MOUSEWHEEL:
   730             return 0;  // !!! FIXME
   731         	//event12->type = SDL12_MOUSEBUTTONDOWN;
   732             //check app filter, push event
   733         	//event12->type = SDL12_MOUSEBUTTONUP;
   734             break;
   735 
   736         case SDL_JOYAXISMOTION:
   737             event12->type = SDL12_JOYAXISMOTION;
   738             event12->jaxis.which = (Uint8) event20->jaxis.which;
   739             event12->jaxis.axis = event20->jaxis.axis;
   740             event12->jaxis.value = event20->jaxis.value;
   741             break;
   742 
   743         case SDL_JOYBALLMOTION:
   744             event12->type = SDL12_JOYBALLMOTION;
   745             event12->jball.which = (Uint8) event20->jball.which;
   746             event12->jball.ball = event20->jball.ball;
   747             event12->jball.xrel = event20->jball.xrel;
   748             event12->jball.yrel = event20->jball.yrel;
   749             break;
   750 
   751         case SDL_JOYHATMOTION:
   752             event12->type = SDL12_JOYHATMOTION;
   753             event12->jhat.which = (Uint8) event20->jhat.which;
   754             event12->jhat.hat = event20->jhat.hat;
   755             event12->jhat.value = event20->jhat.xrel;
   756             break;
   757 
   758         case SDL_JOYBUTTONDOWN:
   759             event12->type = SDL12_JOYBUTTONDOWN;
   760             event12->jbutton.which = (Uint8) event20->jbutton.which;
   761             event12->jbutton.button = event20->jbutton.button;
   762             event12->jbutton.state = event20->jbutton.state;
   763             break;
   764 
   765         case SDL_JOYBUTTONUP:
   766             event12->type = SDL12_JOYBUTTONUP;
   767             event12->jbutton.which = (Uint8) event20->jbutton.which;
   768             event12->jbutton.button = event20->jbutton.button;
   769             event12->jbutton.state = event20->jbutton.state;
   770             break;
   771 
   772         //case SDL_JOYDEVICEADDED:
   773         //case SDL_JOYDEVICEREMOVED:
   774 	    //case SDL_CONTROLLERAXISMOTION:
   775 	    //case SDL_CONTROLLERBUTTONDOWN:
   776 	    //case SDL_CONTROLLERBUTTONUP:
   777 	    //case SDL_CONTROLLERDEVICEADDED:
   778 	    //case SDL_CONTROLLERDEVICEREMOVED:
   779 	    //case SDL_CONTROLLERDEVICEREMAPPED:
   780         //case SDL_FINGERDOWN:
   781         //case SDL_FINGERUP:
   782         //case SDL_FINGERMOTION:
   783         //case SDL_DOLLARGESTURE:
   784         //case SDL_DOLLARRECORD:
   785         //case SDL_MULTIGESTURE:
   786         //case SDL_CLIPBOARDUPDATE:
   787         //case SDL_DROPFILE:
   788 
   789         default:
   790             return 0;  /* drop everything else. */
   791     }
   792 
   793     if ((!EventFilter12) || (EventFilter12(&event12)))
   794         SDL_PushEvent(&event12);
   795 
   796     return 0;  /* always drop it from the 2.0 event queue. */
   797 }
   798 
   799 int
   800 SDL_PollEvent(SDL12_Event *event12)
   801 {
   802     EventQueueType *next;
   803 
   804     SDL20_PumpEvents();  /* this will run our filter and build our 1.2 queue. */
   805 
   806     if (EventQueueHead == NULL)
   807         return 0;  /* no events at the moment. */
   808 
   809     SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
   810     next = EventQueueHead->next;
   811     EventQueueHead->next = EventQueueAvailable;
   812     EventQueueAvailable = EventQueueHead;
   813     EventQueueHead = next;
   814     return 1;
   815 }
   816 
   817 int
   818 SDL_PushEvent(SDL12_Event *event12)
   819 {
   820     EventQueueType *item = EventQueueAvailable;
   821     if (item == NULL)
   822         return -1;  /* no space available at the moment. */
   823 
   824     EventQueueAvailable = item->next;
   825     if (EventQueueTail)
   826         EventQueueTail->next = item;
   827     else
   828         EventQueueHead = EventQueueTail = item;
   829     item->next = NULL;
   830 
   831     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
   832     return 0;
   833 }
   834 
   835 int
   836 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
   837 {
   838     int i;
   839 
   840     if (action == SDL_ADDEVENT)
   841     {
   842         for (i = 0; i < numevents; i++)
   843         {
   844             if (SDL_PushEvent(&events12[i]) == -1)
   845                 break;  /* out of space for more events. */
   846         }
   847         return i;
   848     }
   849     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
   850     {
   851         const int isGet = (action == SDL_GETEVENT);
   852         EventQueueType *prev = NULL;
   853         EventQueueType *item = EventQueueHead;
   854         EventQueueType *next = NULL;
   855         int chosen = 0;
   856         while (chosen < numevents)
   857         {
   858             EventQueueType *nextPrev = item;
   859             if (!item)
   860                 break;  /* no more events at the moment. */
   861 
   862             next = item->next;  /* copy, since we might overwrite item->next */
   863 
   864             if (mask & (1<<event12->type))
   865             {
   866                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
   867                 if (isGet)  /* remove from list? */
   868                 {
   869                     if (prev != NULL)
   870                         prev->next = next;
   871                     if (item == EventQueueHead)
   872                         EventQueueHead = next;
   873                     if (item == EventQueueTail)
   874                         EventQueueTail = prev;
   875 
   876                     /* put it back in the free pool. */
   877                     item->next = EventQueueAvailable;
   878                     EventQueueAvailable = item;
   879                     nextPrev = prev;  /* previous item doesn't change. */
   880                 }
   881             }
   882 
   883             item = next;
   884             prev = nextPrev;
   885         }
   886         return chosen;
   887     }
   888 
   889     return 0;
   890 }
   891 
   892 void
   893 SDL_SetEventFilter(SDL12_EventFilter filter12)
   894 {
   895     /* We always have a filter installed, but will call the app's too. */
   896     EventFilter12 = filter12;
   897 }
   898 
   899 SDL12_EventFilter
   900 SDL_GetEventFilter(void)
   901 {
   902     return EventFilter12;
   903 }
   904 
   905 
   906 SDL12_Surface *
   907 Surface20to12(SDL_Surface *surface20)
   908 {
   909     SDL12_Surface *surface12 = NULL;
   910     SDL12_Palette *palette12 = NULL;
   911     SDL12_PixelFormat *format12 = NULL;
   912     UInt32 flags = 0;
   913 
   914     if (!surface20)
   915         return NULL;
   916 
   917     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
   918     if (!surface12)
   919         goto failed;
   920 
   921     palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
   922     if (!palette12)
   923         goto failed;
   924 
   925     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
   926     if (!format12)
   927         goto failed;
   928 
   929     SDL_zerop(palette12);
   930     palette12->ncolors = surface20->palette->ncolors;
   931     palette12->colors = surface20->palette->colors;
   932 
   933     SDL_zerop(format12);
   934     format12->palette = palette12;
   935     format12->BitsPerPixel = surface20->format->BitsPerPixel;
   936     format12->BytesPerPixel = surface20->format->BytesPerPixel;
   937     format12->Rloss = surface20->format->Rloss;
   938     format12->Gloss = surface20->format->Gloss;
   939     format12->Bloss = surface20->format->Bloss;
   940     format12->Aloss = surface20->format->Aloss;
   941     format12->Rshift = surface20->format->Rshift;
   942     format12->Gshift = surface20->format->Gshift;
   943     format12->Bshift = surface20->format->Bshift;
   944     format12->Ashift = surface20->format->Ashift;
   945     format12->Rmask = surface20->format->Rmask;
   946     format12->Gmask = surface20->format->Gmask;
   947     format12->Bmask = surface20->format->Bmask;
   948     format12->Amask = surface20->format->Amask;
   949     /* !!! FIXME: format12->colorkey; */
   950     /* !!! FIXME: format12->alpha; */
   951 
   952     SDL_zerop(surface12);
   953     flags = surface20->flags;
   954     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
   955     MAPSURFACEFLAGS(PREALLOC);
   956     MAPSURFACEFLAGS(RLEACCEL);
   957     MAPSURFACEFLAGS(DONTFREE);
   958     #undef MAPSURFACEFLAGS
   959     assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
   960 
   961     surface12->format = format12;
   962     surface12->w = surface20->w;
   963     surface12->h = surface20->h;
   964     surface12->pitch = (Uint16) surface20->pitch;  /* !!! FIXME: make sure this fits in a Uint16 */
   965     surface12->pixels = surface20->pixels;
   966     surface12->offset = 0;
   967     surface12->hwdata = surface20;
   968     SDL20_memcpy(&surface12->clip_rect, &surface20->clip_rect, sizeof (SDL_Rect));
   969     surface12->refcount = surface20->refcount;
   970 
   971     return surface12;
   972 
   973 failed:
   974     SDL20_free(surface12);
   975     SDL20_free(palette12);
   976     SDL20_free(format12);
   977     return NULL;
   978 }
   979 
   980 SDL12_Surface *
   981 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
   982 {
   983     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
   984     SDL12_Surface *surface12 = Surface20to12(surface20);
   985     if (!surface12) {
   986         SDL20_FreeSurface(surface20);
   987         return NULL;
   988     }
   989 
   990     assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
   991     return surface12;
   992 }
   993 
   994 SDL12_Surface *
   995 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
   996 {
   997     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, Rmask, Gmask, Bmask, Amask);
   998     SDL12_Surface *surface12 = Surface20to12(surface20);
   999     if (!surface12) {
  1000         SDL20_FreeSurface(surface20);
  1001         return NULL;
  1002     }
  1003 
  1004     assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  1005     return surface12;
  1006 }
  1007 
  1008 void SDL_FreeSurface(SDL12_Surface *surface12)
  1009 {
  1010     if (surface12) {
  1011         SDL20_FreeSurface(surface12->hwdata);
  1012         if (surface12->format) {
  1013             SDL20_free(surface12->format->palette);
  1014             SDL20_free(surface12->format);
  1015         }
  1016         SDL20_free(surface12);
  1017     }
  1018 }
  1019 
  1020 void
  1021 SDL_GetClipRect(SDL12_Surface *surface12, SDL_Rect *rect)
  1022 {
  1023     if (surface12 && rect)
  1024 	    SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL_Rect));
  1025 }
  1026 
  1027 SDL_bool
  1028 SDL_SetClipRect(SDL12_Surface *surface12, const SDL_Rect *rect)
  1029 {
  1030     SDL_bool retval = SDL_FALSE;
  1031     if (surface12)
  1032     {
  1033         retval = SDL20_SetClipRect(surface12->hwdata, rect);
  1034         SDL20_GetClipRect(surface12->hwdata, &surface12->clip_rect);
  1035     }
  1036     return retval;
  1037 }
  1038 
  1039 int
  1040 SDL_FillRect(SDL12_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1041 {
  1042     const SDL_Rect orig_dstrect = *dstrect;
  1043     const int retval = SDL20_FillRect(dst->hwdata, orig_dstrect, color);
  1044     if (retval != -1)
  1045     {
  1046         if (dstrect)  /* 1.2 stores the clip intersection in dstrect */
  1047             SDL20_IntersectRect(orig_dstrect, &dst->clip_rect, dstrect);
  1048     }
  1049     return retval;
  1050 }
  1051 
  1052 
  1053 static SDL_PixelFormat *
  1054 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, SDL12_PixelFormat *format12)
  1055 {
  1056     palette20->ncolors = format12->palette->ncolors;
  1057     palette20->colors = format12->palette->colors;
  1058     palette20->version = 1;
  1059     palette20->refcount = 1;
  1060     format20->format = SDL_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1061     format20->palette = palette20;
  1062     format20->BitsPerPixel = format12->BitsPerPixel;
  1063     format20->BytesPerPixel = format12->BytesPerPixel;
  1064     format20->Rmask = format12->Rmask;
  1065     format20->Gmask = format12->Gmask;
  1066     format20->Bmask = format12->Bmask;
  1067     format20->Amask = format12->Amask;
  1068     format20->Rloss = format12->Rloss;
  1069     format20->Gloss = format12->Gloss;
  1070     format20->Bloss = format12->Bloss;
  1071     format20->Aloss = format12->Aloss;
  1072     format20->Rshift = format12->Rshift;
  1073     format20->Gshift = format12->Gshift;
  1074     format20->Bshift = format12->Bshift;
  1075     format20->Ashift = format12->Ashift;
  1076     format20->refcount = 1;
  1077     format20->next = NULL;
  1078     return format20;
  1079 }
  1080 
  1081 Uint32
  1082 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  1083 {
  1084     /* This is probably way slower than apps expect. */
  1085     SDL_PixelFormat format20;
  1086     SDL_Palette palette20;
  1087     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1088 }
  1089 
  1090 Uint32
  1091 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1092 {
  1093     /* This is probably way slower than apps expect. */
  1094     SDL_PixelFormat format20;
  1095     SDL_Palette palette20;
  1096     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1097 }
  1098 
  1099 void
  1100 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  1101 {
  1102     /* This is probably way slower than apps expect. */
  1103     SDL_PixelFormat format20;
  1104     SDL_Palette palette20;
  1105     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1106 }
  1107 
  1108 void
  1109 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1110 {
  1111     /* This is probably way slower than apps expect. */
  1112     SDL_PixelFormat format20;
  1113     SDL_Palette palette20;
  1114     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1115 }
  1116 
  1117 const SDL12_VideoInfo *
  1118 SDL_GetVideoInfo(void)
  1119 {
  1120     SDL_DisplayMode mode;
  1121 
  1122     if (!VideoInfo.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1123         VideoInfo.vfmt = SDL20_AllocFormat(mode.format);
  1124         VideoInfo.current_w = mode.w;
  1125         VideoInfo.current_h = mode.h;
  1126         // !!! FIXME
  1127         //VideoInfo.wm_available = 1;
  1128         //VideoInfo.video_mem = 1024 * 256;
  1129     }
  1130     return &VideoInfo;
  1131 }
  1132 
  1133 int
  1134 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  1135 {
  1136     int i, nummodes, actual_bpp = 0;
  1137 
  1138     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1139         return 0;
  1140     }
  1141 
  1142     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  1143         SDL_DisplayMode mode;
  1144         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  1145         return SDL_BITSPERPIXEL(mode.format);
  1146     }
  1147 
  1148     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1149     for (i = 0; i < nummodes; ++i) {
  1150         SDL_DisplayMode mode;
  1151         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1152         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  1153             if (!mode.format) {
  1154                 return bpp;
  1155             }
  1156             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  1157                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  1158             }
  1159         }
  1160     }
  1161     return actual_bpp;
  1162 }
  1163 
  1164 SDL_Rect **
  1165 SDL_ListModes(const SDL12_PixelFormat *format, Uint32 flags)
  1166 {
  1167     int i, nmodes;
  1168     SDL_Rect **modes;
  1169 
  1170     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1171         return NULL;
  1172     }
  1173 
  1174     if (!(flags & SDL12_FULLSCREEN)) {
  1175         return (SDL_Rect **) (-1);
  1176     }
  1177 
  1178     if (!format) {
  1179         format = VideoInfo.vfmt;
  1180     }
  1181 
  1182     /* !!! FIXME: Memory leak */
  1183     nmodes = 0;
  1184     modes = NULL;
  1185     for (i = 0; i < SDL20_GetNumDisplayModes(VideoDisplayIndex); ++i) {
  1186         SDL_DisplayMode mode;
  1187         int bpp;
  1188 
  1189         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1190         if (!mode.w || !mode.h) {
  1191             return (SDL_Rect **) (-1);
  1192         }
  1193         
  1194         /* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
  1195         if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
  1196             bpp = SDL_BITSPERPIXEL(mode.format);
  1197         } else {
  1198             bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
  1199         }
  1200 
  1201         if (bpp != format->BitsPerPixel) {
  1202             continue;
  1203         }
  1204         if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
  1205             && modes[nmodes - 1]->h == mode.h) {
  1206             continue;
  1207         }
  1208 
  1209         modes = SDL20_realloc(modes, (nmodes + 2) * sizeof(*modes));
  1210         if (!modes) {
  1211             return NULL;
  1212         }
  1213         modes[nmodes] = (SDL_Rect *) SDL20_malloc(sizeof(SDL_Rect));
  1214         if (!modes[nmodes]) {
  1215             return NULL;
  1216         }
  1217         modes[nmodes]->x = 0;
  1218         modes[nmodes]->y = 0;
  1219         modes[nmodes]->w = mode.w;
  1220         modes[nmodes]->h = mode.h;
  1221         ++nmodes;
  1222     }
  1223     if (modes) {
  1224         modes[nmodes] = NULL;
  1225     }
  1226     return modes;
  1227 }
  1228 
  1229 
  1230 SDL12_Cursor *
  1231 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  1232 {
  1233     const size_t datasize = h * (w / 8);
  1234     SDL_Cursor *cursor20 = NULL;
  1235     SDL12_Cursor *retval = NULL;
  1236 
  1237     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  1238     if (!retval)
  1239         goto outofmem;
  1240 
  1241     SDL_zerop(retval);
  1242 
  1243     retval->data = (Uint8 *) SDL20_malloc(datasize);
  1244     if (!retval->data);
  1245         goto outofmem;
  1246 
  1247     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  1248     if (!retval->mask);
  1249         goto outofmem;
  1250 
  1251     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  1252     if (!cursor20)
  1253         goto failed;
  1254 
  1255     retval->area.w = w;
  1256     retval->area.h = h;
  1257     retval->hot_x = hot_x;
  1258     retval->hot_y = hot_y;
  1259     retval->wm_cursor = cursor20;
  1260     /* we always leave retval->save as null pointers. */
  1261 
  1262     SDL20_memcpy(retval->data, data, datasize);
  1263     SDL20_memcpy(retval->mask, mask, datasize);
  1264 
  1265     return retval;
  1266 
  1267 outofmem:
  1268     SDL_OutOfMemory();
  1269 
  1270 failed:
  1271     SDL_FreeCursor(retval);
  1272     return NULL;
  1273 }
  1274 
  1275 void
  1276 SDL_SetCursor(SDL12_Cursor *cursor)
  1277 {
  1278     CurrentCursor = cursor;
  1279     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  1280 }
  1281 
  1282 SDL12_Cursor *
  1283 SDL_GetCursor(void)
  1284 {
  1285     return CurrentCursor;
  1286 }
  1287 
  1288 void
  1289 SDL_FreeCursor(SDL12_Cursor *cursor)
  1290 {
  1291     if (retval)
  1292     {
  1293         if (retval->wm_cursor)
  1294             SDL20_FreeCursor(cursor);
  1295         SDL20_free(retval->data);
  1296         SDL20_free(retval->mask);
  1297         SDL20_free(retval);
  1298     }
  1299 }
  1300 
  1301 
  1302 static void
  1303 GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
  1304 {
  1305     int display = VideoDisplayIndex;
  1306     const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
  1307     const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
  1308     if (window) {
  1309         if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
  1310             return;
  1311         }
  1312         if (SDL_strcmp(window, "center") == 0) {
  1313             center = window;
  1314         }
  1315     }
  1316     if (center) {
  1317         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1318         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1319     }
  1320 }
  1321 
  1322 static void
  1323 ClearVideoSurface()
  1324 {
  1325     if (ShadowSurface) {
  1326         SDL20_FillRect(ShadowSurface, NULL,
  1327             SDL20_MapRGB(ShadowSurface->format, 0, 0, 0));
  1328     }
  1329     SDL20_FillRect(WindowSurface, NULL, 0);
  1330     SDL20_UpdateWindowSurface(VideoWindow20);
  1331 }
  1332 
  1333 static void
  1334 SetupScreenSaver(int flags12)
  1335 {
  1336     const char *env;
  1337     SDL_bool allow_screensaver;
  1338 
  1339     /* Allow environment override of screensaver disable */
  1340     env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  1341     if (env) {
  1342         allow_screensaver = SDL_atoi(env) ? SDL_TRUE : SDL_FALSE;
  1343     } else if (flags12 & SDL12_FULLSCREEN) {
  1344         allow_screensaver = SDL_FALSE;
  1345     } else {
  1346         allow_screensaver = SDL_TRUE;
  1347     }
  1348     if (allow_screensaver) {
  1349         SDL20_EnableScreenSaver();
  1350     } else {
  1351         SDL20_DisableScreenSaver();
  1352     }
  1353 }
  1354 
  1355 static int
  1356 ResizeVideoMode(int width, int height, int bpp, Uint32 flags12)
  1357 {
  1358     int w, h;
  1359 
  1360     /* We can't resize something we don't have... */
  1361     if (!VideoSurface) {
  1362         return -1;
  1363     }
  1364 
  1365     /* We probably have to recreate the window in fullscreen mode */
  1366     if (flags12 & SDL12_FULLSCREEN) {
  1367         return -1;
  1368     }
  1369 
  1370     /* I don't think there's any change we can gracefully make in flags */
  1371     if (flags12 != VideoFlags) {
  1372         return -1;
  1373     }
  1374     if (bpp != VideoSurface->format->BitsPerPixel) {
  1375         return -1;
  1376     }
  1377 
  1378     /* Resize the window */
  1379     SDL20_GetWindowSize(VideoWindow20, &w, &h);
  1380     if (w != width || h != height) {
  1381         SDL20_SetWindowSize(VideoWindow20, width, height);
  1382     }
  1383 
  1384     /* If we're in OpenGL mode, just resize the stub surface and we're done! */
  1385     if (flags12 & SDL12_OPENGL) {
  1386         VideoSurface->w = width;
  1387         VideoSurface->h = height;
  1388         return 0;
  1389     }
  1390 
  1391     WindowSurface = SDL20_GetWindowSurface(VideoWindow20);
  1392     if (!WindowSurface) {
  1393         return -1;
  1394     }
  1395     if (VideoSurface->format != WindowSurface->format) {
  1396         return -1;
  1397     }
  1398     VideoSurface->w = width;
  1399     VideoSurface->h = height;
  1400     VideoSurface->pixels = WindowSurface->pixels;
  1401     VideoSurface->pitch = WindowSurface->pitch;
  1402     SDL20_SetClipRect(VideoSurface, NULL);
  1403 
  1404     if (ShadowSurface) {
  1405         ShadowSurface->w = width;
  1406         ShadowSurface->h = height;
  1407         ShadowSurface->pitch = SDL20_CalculatePitch(ShadowSurface);
  1408         ShadowSurface->pixels =
  1409             SDL20_realloc(ShadowSurface->pixels,
  1410                         ShadowSurface->h * ShadowSurface->pitch);
  1411         SDL20_SetClipRect(ShadowSurface, NULL);
  1412         SDL20_InvalidateMap(ShadowSurface->map);
  1413     } else {
  1414         PublicSurface = VideoSurface;
  1415     }
  1416 
  1417     ClearVideoSurface();
  1418 
  1419     return 0;
  1420 }
  1421 
  1422 SDL_Surface *
  1423 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  1424 {
  1425     SDL_DisplayMode desktop_mode;
  1426     int display = VideoDisplayIndex;
  1427     int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
  1428     int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
  1429     int window_w;
  1430     int window_h;
  1431     Uint32 window_flags20;
  1432     Uint32 surface_flags12;
  1433 
  1434     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1435         if (SDL_Init(SDL12_INIT_VIDEO | SDL12_INIT_NOPARACHUTE) < 0) {
  1436             return NULL;
  1437         }
  1438     }
  1439 
  1440     SDL20_GetDesktopDisplayMode(display, &desktop_mode);
  1441 
  1442     if (width == 0) {
  1443         width = desktop_mode.w;
  1444     }
  1445     if (height == 0) {
  1446         height = desktop_mode.h;
  1447     }
  1448     if (bpp == 0) {
  1449         bpp = SDL_BITSPERPIXEL(desktop_mode.format);
  1450     }
  1451 
  1452     /* See if we can simply resize the existing window and surface */
  1453     if (ResizeVideoMode(width, height, bpp, flags12) == 0) {
  1454         return PublicSurface;
  1455     }
  1456 
  1457     /* Destroy existing window */
  1458     PublicSurface = NULL;
  1459     if (ShadowSurface) {
  1460         ShadowSurface->flags &= ~SDL_DONTFREE;
  1461         SDL20_FreeSurface(ShadowSurface);
  1462         ShadowSurface = NULL;
  1463     }
  1464     if (VideoSurface) {
  1465         VideoSurface->flags &= ~SDL_DONTFREE;
  1466         SDL20_FreeSurface(VideoSurface);
  1467         VideoSurface = NULL;
  1468     }
  1469     if (VideoContext) {
  1470         /* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
  1471         SDL20_GL_DeleteContext(VideoContext);
  1472         VideoContext = NULL;
  1473     }
  1474     if (VideoWindow20) {
  1475         SDL20_GetWindowPosition(VideoWindow20, &window_x, &window_y);
  1476         SDL20_DestroyWindow(VideoWindow20);
  1477     }
  1478 
  1479     /* Create a new window */
  1480     window_flags20 = SDL_WINDOW_SHOWN;
  1481     if (flags12 & SDL12_FULLSCREEN) {
  1482         window_flags20 |= SDL_WINDOW_FULLSCREEN;
  1483     }
  1484     if (flags12 & SDL12_OPENGL) {
  1485         window_flags20 |= SDL_WINDOW_OPENGL;
  1486     }
  1487     if (flags12 & SDL12_RESIZABLE) {
  1488         window_flags20 |= SDL_WINDOW_RESIZABLE;
  1489     }
  1490     if (flags12 & SDL12_NOFRAME) {
  1491         window_flags20 |= SDL_WINDOW_BORDERLESS;
  1492     }
  1493     GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
  1494     VideoWindow20 =
  1495         SDL20_CreateWindow(WindowTitle, window_x, window_y, width, height,
  1496                          window_flags20);
  1497     if (!VideoWindow20) {
  1498         return NULL;
  1499     }
  1500     SDL20_SetWindowIcon(VideoWindow20, VideoIcon);
  1501 
  1502     SetupScreenSaver(flags12);
  1503 
  1504     window_flags20 = SDL_GetWindowFlags(VideoWindow20);
  1505     surface_flags12 = 0;
  1506     if (window_flags20 & SDL_WINDOW_FULLSCREEN) {
  1507         surface_flags12 |= SDL_FULLSCREEN;
  1508     }
  1509     if ((window_flags & SDL_WINDOW_OPENGL) && (flags12 & SDL_OPENGL)) {
  1510         surface_flags12 |= SDL_OPENGL;
  1511     }
  1512     if (window_flags & SDL_WINDOW_RESIZABLE) {
  1513         surface_flags12 |= SDL_RESIZABLE;
  1514     }
  1515     if (window_flags & SDL_WINDOW_BORDERLESS) {
  1516         surface_flags12 |= SDL_NOFRAME;
  1517     }
  1518 
  1519     VideoFlags = flags12;
  1520 
  1521     /* If we're in OpenGL mode, just create a stub surface and we're done! */
  1522     if (flags12 & SDL_OPENGL) {
  1523         VideoContext = SDL_GL_CreateContext(VideoWindow20);
  1524         if (!VideoContext) {
  1525             return NULL;
  1526         }
  1527         if (SDL_GL_MakeCurrent(VideoWindow20, VideoContext) < 0) {
  1528             return NULL;
  1529         }
  1530         VideoSurface =
  1531             SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
  1532         if (!VideoSurface) {
  1533             return NULL;
  1534         }
  1535         VideoSurface->flags |= surface_flags12;
  1536         PublicSurface = VideoSurface;
  1537         return PublicSurface;
  1538     }
  1539 
  1540     /* Create the screen surface */
  1541     WindowSurface = SDL_GetWindowSurface(VideoWindow20);
  1542     if (!WindowSurface) {
  1543         return NULL;
  1544     }
  1545 
  1546     /* Center the public surface in the window surface */
  1547     SDL_GetWindowSize(VideoWindow20, &window_w, &window_h);
  1548     VideoViewport.x = (window_w - width)/2;
  1549     VideoViewport.y = (window_h - height)/2;
  1550     VideoViewport.w = width;
  1551     VideoViewport.h = height;
  1552 
  1553     VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
  1554     VideoSurface->flags |= surface_flags12;
  1555     VideoSurface->flags |= SDL12_DONTFREE;
  1556     SDL_FreeFormat(VideoSurface->format);
  1557     VideoSurface->format = WindowSurface->format;
  1558     VideoSurface->format->refcount++;
  1559     VideoSurface->w = width;
  1560     VideoSurface->h = height;
  1561     VideoSurface->pitch = WindowSurface->pitch;
  1562     VideoSurface->pixels = (void *)((Uint8 *)WindowSurface->pixels +
  1563         VideoViewport.y * VideoSurface->pitch +
  1564         VideoViewport.x  * VideoSurface->format->BytesPerPixel);
  1565     SDL_SetClipRect(VideoSurface, NULL);
  1566 
  1567     /* Create a shadow surface if necessary */
  1568     if ((bpp != VideoSurface->format->BitsPerPixel)
  1569         && !(flags12 & SDL12_ANYFORMAT)) {
  1570         ShadowSurface =
  1571             SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
  1572         if (!ShadowSurface) {
  1573             return NULL;
  1574         }
  1575         ShadowSurface->flags |= surface_flags12;
  1576         ShadowSurface->flags |= SDL12_DONTFREE;
  1577 
  1578         /* 8-bit ShadowSurface surfaces report that they have exclusive palette */
  1579         if (ShadowSurface->format->palette) {
  1580             ShadowSurface->flags |= SDL12_HWPALETTE;
  1581             SDL_DitherColors(ShadowSurface->format->palette->colors,
  1582                              ShadowSurface->format->BitsPerPixel);
  1583         }
  1584         SDL_FillRect(ShadowSurface, NULL,
  1585             SDL_MapRGB(ShadowSurface->format, 0, 0, 0));
  1586     }
  1587     PublicSurface =
  1588         (ShadowSurface ? ShadowSurface : VideoSurface);
  1589 
  1590     ClearVideoSurface();
  1591 
  1592     /* We're finally done! */
  1593     return PublicSurface;
  1594 }
  1595 
  1596 SDL_Surface *
  1597 SDL_GetVideoSurface(void)
  1598 {
  1599     return PublicSurface;
  1600 }
  1601 
  1602 int
  1603 SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value)
  1604 {
  1605     if (flag & SDL_SRCALPHA) {
  1606         /* According to the docs, value is ignored for alpha surfaces */
  1607         if (surface->format->Amask) {
  1608             value = 0xFF;
  1609         }
  1610         SDL_SetSurfaceAlphaMod(surface, value);
  1611         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
  1612     } else {
  1613         SDL_SetSurfaceAlphaMod(surface, 0xFF);
  1614         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
  1615     }
  1616     SDL_SetSurfaceRLE(surface, (flag & SDL_RLEACCEL));
  1617 
  1618     return 0;
  1619 }
  1620 
  1621 SDL12_Surface *
  1622 SDL_DisplayFormat(SDL12_Surface *surface12)
  1623 {
  1624     SDL12_PixelFormat *format;
  1625 
  1626     if (!PublicSurface) {
  1627         SDL20_SetError("No video mode has been set");
  1628         return NULL;
  1629     }
  1630     format = PublicSurface->format;
  1631 
  1632     /* Set the flags appropriate for copying to display surface */
  1633     return SDL_ConvertSurface(surface, format, SDL12_RLEACCEL);
  1634 }
  1635 
  1636 SDL12_Surface *
  1637 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  1638 {
  1639     SDL_PixelFormat *vf;
  1640     SDL_PixelFormat *format;
  1641     SDL_Surface *converted;
  1642     /* default to ARGB8888 */
  1643     Uint32 amask = 0xff000000;
  1644     Uint32 rmask = 0x00ff0000;
  1645     Uint32 gmask = 0x0000ff00;
  1646     Uint32 bmask = 0x000000ff;
  1647 
  1648     if (!PublicSurface) {
  1649         SDL_SetError("No video mode has been set");
  1650         return NULL;
  1651     }
  1652     vf = PublicSurface->format;
  1653 
  1654     switch (vf->BytesPerPixel) {
  1655     case 2:
  1656         /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
  1657            For anything else (like ARGB4444) it doesn't matter
  1658            since we have no special code for it anyway */
  1659         if ((vf->Rmask == 0x1f) &&
  1660             (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
  1661             rmask = 0xff;
  1662             bmask = 0xff0000;
  1663         }
  1664         break;
  1665 
  1666     case 3:
  1667     case 4:
  1668         /* Keep the video format, as long as the high 8 bits are
  1669            unused or alpha */
  1670         if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) {
  1671             rmask = 0xff;
  1672             bmask = 0xff0000;
  1673         }
  1674         break;
  1675 
  1676     default:
  1677         /* We have no other optimised formats right now. When/if a new
  1678            optimised alpha format is written, add the converter here */
  1679         break;
  1680     }
  1681     format = SDL_AllocFormat(SDL_MasksToPixelFormatEnum(32, rmask,
  1682                                                             gmask,
  1683                                                             bmask,
  1684                                                             amask));
  1685     if (!format) {
  1686         return NULL;
  1687     }
  1688     converted = SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
  1689     SDL_FreeFormat(format);
  1690     return converted;
  1691 }
  1692 
  1693 int
  1694 SDL_Flip(SDL_Surface * screen)
  1695 {
  1696     SDL_UpdateRect(screen, 0, 0, 0, 0);
  1697     return 0;
  1698 }
  1699 
  1700 void
  1701 SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  1702 {
  1703     if (screen) {
  1704         SDL_Rect rect;
  1705 
  1706         /* Fill the rectangle */
  1707         rect.x = (int) x;
  1708         rect.y = (int) y;
  1709         rect.w = (int) (w ? w : screen->w);
  1710         rect.h = (int) (h ? h : screen->h);
  1711         SDL_UpdateRects(screen, 1, &rect);
  1712     }
  1713 }
  1714 
  1715 void
  1716 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
  1717 {
  1718     int i;
  1719 
  1720     if (screen == ShadowSurface) {
  1721         for (i = 0; i < numrects; ++i) {
  1722             SDL_BlitSurface(ShadowSurface, &rects[i], VideoSurface,
  1723                             &rects[i]);
  1724         }
  1725 
  1726         /* Fall through to video surface update */
  1727         screen = VideoSurface;
  1728     }
  1729     if (screen == VideoSurface) {
  1730         if (VideoViewport.x || VideoViewport.y) {
  1731             SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
  1732             SDL_Rect *stackrect;
  1733             const SDL_Rect *rect;
  1734             
  1735             /* Offset all the rectangles before updating */
  1736             for (i = 0; i < numrects; ++i) {
  1737                 rect = &rects[i];
  1738                 stackrect = &stackrects[i];
  1739                 stackrect->x = VideoViewport.x + rect->x;
  1740                 stackrect->y = VideoViewport.y + rect->y;
  1741                 stackrect->w = rect->w;
  1742                 stackrect->h = rect->h;
  1743             }
  1744             SDL_UpdateWindowSurfaceRects(VideoWindow20, stackrects, numrects);
  1745             SDL_stack_free(stackrects);
  1746         } else {
  1747             SDL_UpdateWindowSurfaceRects(VideoWindow20, rects, numrects);
  1748         }
  1749     }
  1750 }
  1751 
  1752 void
  1753 SDL_WM_SetCaption(const char *title, const char *icon)
  1754 {
  1755     if (WindowTitle) {
  1756         SDL_free(WindowTitle);
  1757     }
  1758     if (WindowIconTitle) {
  1759         SDL_free(WindowIconTitle);
  1760     }
  1761     WindowTitle = title ? SDL_strdup(title) : NULL;
  1762     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  1763     SDL_SetWindowTitle(VideoWindow20, WindowTitle);
  1764 }
  1765 
  1766 void
  1767 SDL_WM_GetCaption(const char **title, const char **icon)
  1768 {
  1769     if (title) {
  1770         *title = WindowTitle;
  1771     }
  1772     if (icon) {
  1773         *icon = WindowIconTitle;
  1774     }
  1775 }
  1776 
  1777 void
  1778 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
  1779 {
  1780     // !!! FIXME: free previous icon?
  1781     VideoIcon = icon;
  1782     ++VideoIcon->refcount;
  1783 }
  1784 
  1785 int
  1786 SDL_WM_IconifyWindow(void)
  1787 {
  1788     SDL_MinimizeWindow(VideoWindow20);
  1789     return 0;
  1790 }
  1791 
  1792 int
  1793 SDL_WM_ToggleFullScreen(SDL_Surface * surface)
  1794 {
  1795     int length;
  1796     void *pixels;
  1797     Uint8 *src, *dst;
  1798     int row;
  1799     int window_w;
  1800     int window_h;
  1801 
  1802     if (!PublicSurface) {
  1803         SDL_SetError("SDL_SetVideoMode() hasn't been called");
  1804         return 0;
  1805     }
  1806 
  1807     /* Copy the old bits out */
  1808     length = PublicSurface->w * PublicSurface->format->BytesPerPixel;
  1809     pixels = SDL_malloc(PublicSurface->h * length);
  1810     if (pixels && PublicSurface->pixels) {
  1811         src = (Uint8*)PublicSurface->pixels;
  1812         dst = (Uint8*)pixels;
  1813         for (row = 0; row < PublicSurface->h; ++row) {
  1814             SDL_memcpy(dst, src, length);
  1815             src += PublicSurface->pitch;
  1816             dst += length;
  1817         }
  1818     }
  1819 
  1820     /* Do the physical mode switch */
  1821     if (SDL_GetWindowFlags(VideoWindow20) & SDL_WINDOW_FULLSCREEN) {
  1822         if (SDL_SetWindowFullscreen(VideoWindow20, 0) < 0) {
  1823             return 0;
  1824         }
  1825         PublicSurface->flags &= ~SDL_FULLSCREEN;
  1826     } else {
  1827         if (SDL_SetWindowFullscreen(VideoWindow20, 1) < 0) {
  1828             return 0;
  1829         }
  1830         PublicSurface->flags |= SDL_FULLSCREEN;
  1831     }
  1832 
  1833     /* Recreate the screen surface */
  1834     WindowSurface = SDL_GetWindowSurface(VideoWindow20);
  1835     if (!WindowSurface) {
  1836         /* We're totally hosed... */
  1837         return 0;
  1838     }
  1839 
  1840     /* Center the public surface in the window surface */
  1841     SDL_GetWindowSize(VideoWindow20, &window_w, &window_h);
  1842     VideoViewport.x = (window_w - VideoSurface->w)/2;
  1843     VideoViewport.y = (window_h - VideoSurface->h)/2;
  1844     VideoViewport.w = VideoSurface->w;
  1845     VideoViewport.h = VideoSurface->h;
  1846 
  1847     /* Do some shuffling behind the application's back if format changes */
  1848     if (VideoSurface->format->format != WindowSurface->format->format) {
  1849         if (ShadowSurface) {
  1850             if (ShadowSurface->format->format == WindowSurface->format->format) {
  1851                 /* Whee!  We don't need a shadow surface anymore! */
  1852                 VideoSurface->flags &= ~SDL_DONTFREE;
  1853                 SDL_FreeSurface(VideoSurface);
  1854                 SDL_free(ShadowSurface->pixels);
  1855                 VideoSurface = ShadowSurface;
  1856                 VideoSurface->flags |= SDL_PREALLOC;
  1857                 ShadowSurface = NULL;
  1858             } else {
  1859                 /* No problem, just change the video surface format */
  1860                 SDL_FreeFormat(VideoSurface->format);
  1861                 VideoSurface->format = WindowSurface->format;
  1862                 VideoSurface->format->refcount++;
  1863                 SDL_InvalidateMap(ShadowSurface->map);
  1864             }
  1865         } else {
  1866             /* We can make the video surface the shadow surface */
  1867             ShadowSurface = VideoSurface;
  1868             ShadowSurface->pitch = SDL_CalculatePitch(ShadowSurface);
  1869             ShadowSurface->pixels = SDL_malloc(ShadowSurface->h * ShadowSurface->pitch);
  1870             if (!ShadowSurface->pixels) {
  1871                 /* Uh oh, we're hosed */
  1872                 ShadowSurface = NULL;
  1873                 return 0;
  1874             }
  1875             ShadowSurface->flags &= ~SDL_PREALLOC;
  1876 
  1877             VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
  1878             VideoSurface->flags = ShadowSurface->flags;
  1879             VideoSurface->flags |= SDL_PREALLOC;
  1880             SDL_FreeFormat(VideoSurface->format);
  1881             VideoSurface->format = WindowSurface->format;
  1882             VideoSurface->format->refcount++;
  1883             VideoSurface->w = ShadowSurface->w;
  1884             VideoSurface->h = ShadowSurface->h;
  1885         }
  1886     }
  1887 
  1888     /* Update the video surface */
  1889     VideoSurface->pitch = WindowSurface->pitch;
  1890     VideoSurface->pixels = (void *)((Uint8 *)WindowSurface->pixels +
  1891         VideoViewport.y * VideoSurface->pitch +
  1892         VideoViewport.x  * VideoSurface->format->BytesPerPixel);
  1893     SDL_SetClipRect(VideoSurface, NULL);
  1894 
  1895     /* Copy the old bits back */
  1896     if (pixels) {
  1897         src = (Uint8*)pixels;
  1898         dst = (Uint8*)PublicSurface->pixels;
  1899         for (row = 0; row < PublicSurface->h; ++row) {
  1900             SDL_memcpy(dst, src, length);
  1901             src += length;
  1902             dst += PublicSurface->pitch;
  1903         }
  1904         SDL_Flip(PublicSurface);
  1905         SDL_free(pixels);
  1906     }
  1907 
  1908     /* We're done! */
  1909     return 1;
  1910 }
  1911 
  1912 SDL_GrabMode
  1913 SDL_WM_GrabInput(SDL_GrabMode mode)
  1914 {
  1915     if (mode != SDL_GRAB_QUERY) {
  1916         SDL_SetWindowGrab(VideoWindow20, mode);
  1917     }
  1918     return (SDL_GrabMode) SDL_GetWindowGrab(VideoWindow20);
  1919 }
  1920 
  1921 void
  1922 SDL_WarpMouse(Uint16 x, Uint16 y)
  1923 {
  1924     SDL_WarpMouseInWindow(VideoWindow20, x, y);
  1925 }
  1926 
  1927 Uint8
  1928 SDL_GetAppState(void)
  1929 {
  1930     Uint8 state = 0;
  1931     Uint32 flags = 0;
  1932 
  1933     flags = SDL_GetWindowFlags(VideoWindow20);
  1934     if ((flags & SDL_WINDOW_SHOWN) && !(flags & SDL_WINDOW_MINIMIZED)) {
  1935         state |= SDL_APPACTIVE;
  1936     }
  1937     if (flags & SDL_WINDOW_INPUT_FOCUS) {
  1938         state |= SDL_APPINPUTFOCUS;
  1939     }
  1940     if (flags & SDL_WINDOW_MOUSE_FOCUS) {
  1941         state |= SDL_APPMOUSEFOCUS;
  1942     }
  1943     return state;
  1944 }
  1945 
  1946 const SDL_version *
  1947 SDL_Linked_Version(void)
  1948 {
  1949     static SDL_version version;
  1950     SDL_VERSION(&version);
  1951     return &version;
  1952 }
  1953 
  1954 int
  1955 SDL_SetPalette(SDL_Surface * surface, int flags, const SDL_Color * colors,
  1956                int firstcolor, int ncolors)
  1957 {
  1958     return SDL_SetColors(surface, colors, firstcolor, ncolors);
  1959 }
  1960 
  1961 int
  1962 SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor,
  1963               int ncolors)
  1964 {
  1965     if (SDL_SetPaletteColors
  1966         (surface->format->palette, colors, firstcolor, ncolors) == 0) {
  1967         return 1;
  1968     } else {
  1969         return 0;
  1970     }
  1971 }
  1972 
  1973 int
  1974 SDL_GetWMInfo(SDL_SysWMinfo * info)
  1975 {
  1976     return SDL_GetWindowWMInfo(VideoWindow20, info);
  1977 }
  1978 
  1979 #if 0
  1980 void
  1981 SDL_MoveCursor(int x, int y)
  1982 {
  1983     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1984 
  1985     /* Erase and update the current mouse position */
  1986     if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
  1987         /* Erase and redraw mouse cursor in new position */
  1988         SDL_LockCursor();
  1989         SDL_EraseCursor(VideoSurface);
  1990         SDL_cursor->area.x = (x - SDL_cursor->hot_x);
  1991         SDL_cursor->area.y = (y - SDL_cursor->hot_y);
  1992         SDL_DrawCursor(VideoSurface);
  1993         SDL_UnlockCursor();
  1994     } else if (_this->MoveWMCursor) {
  1995         _this->MoveWMCursor(_this, x, y);
  1996     }
  1997 }
  1998 
  1999 /* Keep track of the current cursor colors */
  2000 static int palette_changed = 1;
  2001 static Uint8 pixels8[2];
  2002 
  2003 void
  2004 SDL_CursorPaletteChanged(void)
  2005 {
  2006     palette_changed = 1;
  2007 }
  2008 
  2009 void
  2010 SDL_MouseRect(SDL_Rect * area)
  2011 {
  2012     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2013     int clip_diff;
  2014 
  2015     *area = SDL_cursor->area;
  2016     if (area->x < 0) {
  2017         area->w += area->x;
  2018         area->x = 0;
  2019     }
  2020     if (area->y < 0) {
  2021         area->h += area->y;
  2022         area->y = 0;
  2023     }
  2024     clip_diff = (area->x + area->w) - VideoSurface->w;
  2025     if (clip_diff > 0) {
  2026         area->w = area->w < clip_diff ? 0 : area->w - clip_diff;
  2027     }
  2028     clip_diff = (area->y + area->h) - VideoSurface->h;
  2029     if (clip_diff > 0) {
  2030         area->h = area->h < clip_diff ? 0 : area->h - clip_diff;
  2031     }
  2032 }
  2033 
  2034 static void
  2035 SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area)
  2036 {
  2037     const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
  2038     int i, w, h;
  2039     Uint8 *data, datab;
  2040     Uint8 *mask, maskb;
  2041 
  2042     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  2043     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  2044     switch (screen->format->BytesPerPixel) {
  2045 
  2046     case 1:
  2047         {
  2048             Uint8 *dst;
  2049             int dstskip;
  2050 
  2051             if (palette_changed) {
  2052                 pixels8[0] =
  2053                     (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  2054                 pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  2055                 palette_changed = 0;
  2056             }
  2057             dst = (Uint8 *) screen->pixels +
  2058                 (SDL_cursor->area.y + area->y) * screen->pitch +
  2059                 SDL_cursor->area.x;
  2060             dstskip = screen->pitch - area->w;
  2061 
  2062             for (h = area->h; h; h--) {
  2063                 for (w = area->w / 8; w; w--) {
  2064                     maskb = *mask++;
  2065                     datab = *data++;
  2066                     for (i = 0; i < 8; ++i) {
  2067                         if (maskb & 0x80) {
  2068                             *dst = pixels8[datab >> 7];
  2069                         }
  2070                         maskb <<= 1;
  2071                         datab <<= 1;
  2072                         dst++;
  2073                     }
  2074                 }
  2075                 dst += dstskip;
  2076             }
  2077         }
  2078         break;
  2079 
  2080     case 2:
  2081         {
  2082             Uint16 *dst;
  2083             int dstskip;
  2084 
  2085             dst = (Uint16 *) screen->pixels +
  2086                 (SDL_cursor->area.y + area->y) * screen->pitch / 2 +
  2087                 SDL_cursor->area.x;
  2088             dstskip = (screen->pitch / 2) - area->w;
  2089 
  2090             for (h = area->h; h; h--) {
  2091                 for (w = area->w / 8; w; w--) {
  2092                     maskb = *mask++;
  2093                     datab = *data++;
  2094                     for (i = 0; i < 8; ++i) {
  2095                         if (maskb & 0x80) {
  2096                             *dst = (Uint16) pixels[datab >> 7];
  2097                         }
  2098                         maskb <<= 1;
  2099                         datab <<= 1;
  2100                         dst++;
  2101                     }
  2102                 }
  2103                 dst += dstskip;
  2104             }
  2105         }
  2106         break;
  2107 
  2108     case 3:
  2109         {
  2110             Uint8 *dst;
  2111             int dstskip;
  2112 
  2113             dst = (Uint8 *) screen->pixels +
  2114                 (SDL_cursor->area.y + area->y) * screen->pitch +
  2115                 SDL_cursor->area.x * 3;
  2116             dstskip = screen->pitch - area->w * 3;
  2117 
  2118             for (h = area->h; h; h--) {
  2119                 for (w = area->w / 8; w; w--) {
  2120                     maskb = *mask++;
  2121                     datab = *data++;
  2122                     for (i = 0; i < 8; ++i) {
  2123                         if (maskb & 0x80) {
  2124                             SDL_memset(dst, pixels[datab >> 7], 3);
  2125                         }
  2126                         maskb <<= 1;
  2127                         datab <<= 1;
  2128                         dst += 3;
  2129                     }
  2130                 }
  2131                 dst += dstskip;
  2132             }
  2133         }
  2134         break;
  2135 
  2136     case 4:
  2137         {
  2138             Uint32 *dst;
  2139             int dstskip;
  2140 
  2141             dst = (Uint32 *) screen->pixels +
  2142                 (SDL_cursor->area.y + area->y) * screen->pitch / 4 +
  2143                 SDL_cursor->area.x;
  2144             dstskip = (screen->pitch / 4) - area->w;
  2145 
  2146             for (h = area->h; h; h--) {
  2147                 for (w = area->w / 8; w; w--) {
  2148                     maskb = *mask++;
  2149                     datab = *data++;
  2150                     for (i = 0; i < 8; ++i) {
  2151                         if (maskb & 0x80) {
  2152                             *dst = pixels[datab >> 7];
  2153                         }
  2154                         maskb <<= 1;
  2155                         datab <<= 1;
  2156                         dst++;
  2157                     }
  2158                 }
  2159                 dst += dstskip;
  2160             }
  2161         }
  2162         break;
  2163     }
  2164 }
  2165 
  2166 static void
  2167 SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area)
  2168 {
  2169     const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
  2170     int h;
  2171     int x, minx, maxx;
  2172     Uint8 *data, datab = 0;
  2173     Uint8 *mask, maskb = 0;
  2174     Uint8 *dst;
  2175     int dstbpp, dstskip;
  2176 
  2177     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  2178     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  2179     dstbpp = screen->format->BytesPerPixel;
  2180     dst = (Uint8 *) screen->pixels +
  2181         (SDL_cursor->area.y + area->y) * screen->pitch +
  2182         SDL_cursor->area.x * dstbpp;
  2183     dstskip = screen->pitch - SDL_cursor->area.w * dstbpp;
  2184 
  2185     minx = area->x;
  2186     maxx = area->x + area->w;
  2187     if (screen->format->BytesPerPixel == 1) {
  2188         if (palette_changed) {
  2189             pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  2190             pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  2191             palette_changed = 0;
  2192         }
  2193         for (h = area->h; h; h--) {
  2194             for (x = 0; x < SDL_cursor->area.w; ++x) {
  2195                 if ((x % 8) == 0) {
  2196                     maskb = *mask++;
  2197                     datab = *data++;
  2198                 }
  2199                 if ((x >= minx) && (x < maxx)) {
  2200                     if (maskb & 0x80) {
  2201                         SDL_memset(dst, pixels8[datab >> 7], dstbpp);
  2202                     }
  2203                 }
  2204                 maskb <<= 1;
  2205                 datab <<= 1;
  2206                 dst += dstbpp;
  2207             }
  2208             dst += dstskip;
  2209         }
  2210     } else {
  2211         for (h = area->h; h; h--) {
  2212             for (x = 0; x < SDL_cursor->area.w; ++x) {
  2213                 if ((x % 8) == 0) {
  2214                     maskb = *mask++;
  2215                     datab = *data++;
  2216                 }
  2217                 if ((x >= minx) && (x < maxx)) {
  2218                     if (maskb & 0x80) {
  2219                         SDL_memset(dst, pixels[datab >> 7], dstbpp);
  2220                     }
  2221                 }
  2222                 maskb <<= 1;
  2223                 datab <<= 1;
  2224                 dst += dstbpp;
  2225             }
  2226             dst += dstskip;
  2227         }
  2228     }
  2229 }
  2230 
  2231 /* This handles the ugly work of converting the saved cursor background from
  2232    the pixel format of the shadow surface to that of the video surface.
  2233    This is only necessary when blitting from a shadow surface of a different
  2234    pixel format than the video surface, and using a software rendered cursor.
  2235 */
  2236 static void
  2237 SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h)
  2238 {
  2239     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2240     SDL_BlitInfo info;
  2241     SDL_loblit RunBlit;
  2242 
  2243     /* Make sure we can steal the blit mapping */
  2244     if (screen->map->dst != VideoSurface) {
  2245         return;
  2246     }
  2247 
  2248     /* Set up the blit information */
  2249     info.s_pixels = SDL_cursor->save[1];
  2250     info.s_width = w;
  2251     info.s_height = h;
  2252     info.s_skip = 0;
  2253     info.d_pixels = SDL_cursor->save[0];
  2254     info.d_width = w;
  2255     info.d_height = h;
  2256     info.d_skip = 0;
  2257     info.aux_data = screen->map->sw_data->aux_data;
  2258     info.src = screen->format;
  2259     info.table = screen->map->table;
  2260     info.dst = VideoSurface->format;
  2261     RunBlit = screen->map->sw_data->blit;
  2262 
  2263     /* Run the actual software blit */
  2264     RunBlit(&info);
  2265 }
  2266 
  2267 void
  2268 SDL_DrawCursorNoLock(SDL_Surface * screen)
  2269 {
  2270     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2271     SDL_Rect area;
  2272 
  2273     /* Get the mouse rectangle, clipped to the screen */
  2274     SDL_MouseRect(&area);
  2275     if ((area.w == 0) || (area.h == 0)) {
  2276         return;
  2277     }
  2278 
  2279     /* Copy mouse background */
  2280     {
  2281         int w, h, screenbpp;
  2282         Uint8 *src, *dst;
  2283 
  2284         /* Set up the copy pointers */
  2285         screenbpp = screen->format->BytesPerPixel;
  2286         if ((screen == VideoSurface) ||
  2287             FORMAT_EQUAL(screen->format, VideoSurface->format)) {
  2288             dst = SDL_cursor->save[0];
  2289         } else {
  2290             dst = SDL_cursor->save[1];
  2291         }
  2292         src = (Uint8 *) screen->pixels + area.y * screen->pitch +
  2293             area.x * screenbpp;
  2294 
  2295         /* Perform the copy */
  2296         w = area.w * screenbpp;
  2297         h = area.h;
  2298         while (h--) {
  2299             SDL_memcpy(dst, src, w);
  2300             dst += w;
  2301             src += screen->pitch;
  2302         }
  2303     }
  2304 
  2305     /* Draw the mouse cursor */
  2306     area.x -= SDL_cursor->area.x;
  2307     area.y -= SDL_cursor->area.y;
  2308     if ((area.x == 0) && (area.w == SDL_cursor->area.w)) {
  2309         SDL_DrawCursorFast(screen, &area);
  2310     } else {
  2311         SDL_DrawCursorSlow(screen, &area);
  2312     }
  2313 }
  2314 
  2315 void
  2316 SDL_DrawCursor(SDL_Surface * screen)
  2317 {
  2318     /* Lock the screen if necessary */
  2319     if (screen == NULL) {
  2320         return;
  2321     }
  2322     if (SDL_MUSTLOCK(screen)) {
  2323         if (SDL_LockSurface(screen) < 0) {
  2324             return;
  2325         }
  2326     }
  2327 
  2328     SDL_DrawCursorNoLock(screen);
  2329 
  2330     /* Unlock the screen and update if necessary */
  2331     if (SDL_MUSTLOCK(screen)) {
  2332         SDL_UnlockSurface(screen);
  2333     }
  2334     if (screen->flags & SDL_SCREEN_SURFACE) {
  2335         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2336         SDL_Window *window;
  2337         SDL_Rect area;
  2338 
  2339         window = SDL_GetWindowFromSurface(screen);
  2340         if (!window) {
  2341             return;
  2342         }
  2343 
  2344         SDL_MouseRect(&area);
  2345 
  2346         if (_this->UpdateWindowSurface) {
  2347             _this->UpdateWindowSurface(_this, window, 1, &area);
  2348         }
  2349     }
  2350 }
  2351 
  2352 void
  2353 SDL_EraseCursorNoLock(SDL_Surface * screen)
  2354 {
  2355     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2356     SDL_Window *window;
  2357     SDL_Rect area;
  2358 
  2359     /* Get the window associated with the surface */
  2360     window = SDL_GetWindowFromSurface(screen);
  2361     if (!window || !window->surface) {
  2362         return;
  2363     }
  2364 
  2365     /* Get the mouse rectangle, clipped to the screen */
  2366     SDL_MouseRect(&area);
  2367     if ((area.w == 0) || (area.h == 0)) {
  2368         return;
  2369     }
  2370 
  2371     /* Copy mouse background */
  2372     {
  2373         int w, h, screenbpp;
  2374         Uint8 *src, *dst;
  2375 
  2376         /* Set up the copy pointers */
  2377         screenbpp = screen->format->BytesPerPixel;
  2378         if ((screen->flags & SDL_SCREEN_SURFACE) ||
  2379             FORMAT_EQUAL(screen->format, window->surface->format)) {
  2380             src = SDL_cursor->save[0];
  2381         } else {
  2382             src = SDL_cursor->save[1];
  2383         }
  2384         dst = (Uint8 *) screen->pixels + area.y * screen->pitch +
  2385             area.x * screenbpp;
  2386 
  2387         /* Perform the copy */
  2388         w = area.w * screenbpp;
  2389         h = area.h;
  2390         while (h--) {
  2391             SDL_memcpy(dst, src, w);
  2392             src += w;
  2393             dst += screen->pitch;
  2394         }
  2395 
  2396         /* Perform pixel conversion on cursor background */
  2397         if (src > SDL_cursor->save[1]) {
  2398             SDL_ConvertCursorSave(screen, area.w, area.h);
  2399         }
  2400     }
  2401 }
  2402 
  2403 void
  2404 SDL_EraseCursor(SDL_Surface * screen)
  2405 {
  2406     /* Lock the screen if necessary */
  2407     if (screen == NULL) {
  2408         return;
  2409     }
  2410     if (SDL_MUSTLOCK(screen)) {
  2411         if (SDL_LockSurface(screen) < 0) {
  2412             return;
  2413         }
  2414     }
  2415 
  2416     SDL_EraseCursorNoLock(screen);
  2417 
  2418     /* Unlock the screen and update if necessary */
  2419     if (SDL_MUSTLOCK(screen)) {
  2420         SDL_UnlockSurface(screen);
  2421     }
  2422     if (screen->flags & SDL_SCREEN_SURFACE) {
  2423         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2424         SDL_Window *window;
  2425         SDL_Rect area;
  2426 
  2427         window = SDL_GetWindowFromSurface(screen);
  2428         if (!window) {
  2429             return;
  2430         }
  2431 
  2432         SDL_MouseRect(&area);
  2433 
  2434         if (_this->UpdateWindowSurface) {
  2435             _this->UpdateWindowSurface(_this, window, 1, &area);
  2436         }
  2437     }
  2438 }
  2439 
  2440 /* Reset the cursor on video mode change
  2441    FIXME:  Keep track of all cursors, and reset them all.
  2442  */
  2443 void
  2444 SDL_ResetCursor(void)
  2445 {
  2446     int savelen;
  2447 
  2448     if (SDL_cursor) {
  2449         savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h;
  2450         SDL_cursor->area.x = 0;
  2451         SDL_cursor->area.y = 0;
  2452         SDL_memset(SDL_cursor->save[0], 0, savelen);
  2453     }
  2454 }
  2455 #endif
  2456 
  2457 struct private_yuvhwdata
  2458 {
  2459     SDL_SW_YUVTexture *texture;
  2460     SDL_Surface *display;
  2461     Uint32 display_format;
  2462 };
  2463 
  2464 SDL_Overlay *
  2465 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
  2466 {
  2467     SDL_Overlay *overlay;
  2468     Uint32 texture_format;
  2469     SDL_SW_YUVTexture *texture;
  2470 
  2471     if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
  2472         SDL_SetError("YUV overlays are not supported in OpenGL mode");
  2473         return NULL;
  2474     }
  2475 
  2476     if (display != PublicSurface) {
  2477         SDL_SetError("YUV display is only supported on the screen surface");
  2478         return NULL;
  2479     }
  2480 
  2481     switch (format) {
  2482     case SDL_YV12_OVERLAY:
  2483         texture_format = SDL_PIXELFORMAT_YV12;
  2484         break;
  2485     case SDL_IYUV_OVERLAY:
  2486         texture_format = SDL_PIXELFORMAT_IYUV;
  2487         break;
  2488     case SDL_YUY2_OVERLAY:
  2489         texture_format = SDL_PIXELFORMAT_YUY2;
  2490         break;
  2491     case SDL_UYVY_OVERLAY:
  2492         texture_format = SDL_PIXELFORMAT_UYVY;
  2493         break;
  2494     case SDL_YVYU_OVERLAY:
  2495         texture_format = SDL_PIXELFORMAT_YVYU;
  2496         break;
  2497     default:
  2498         SDL_SetError("Unknown YUV format");
  2499         return NULL;
  2500     }
  2501 
  2502     overlay = (SDL_Overlay *) SDL_malloc(sizeof(*overlay));
  2503     if (!overlay) {
  2504         SDL_OutOfMemory();
  2505         return NULL;
  2506     }
  2507     SDL_zerop(overlay);
  2508 
  2509     overlay->hwdata =
  2510         (struct private_yuvhwdata *) SDL_malloc(sizeof(*overlay->hwdata));
  2511     if (!overlay->hwdata) {
  2512         SDL_free(overlay);
  2513         SDL_OutOfMemory();
  2514         return NULL;
  2515     }
  2516 
  2517     texture = SDL_SW_CreateYUVTexture(texture_format, w, h);
  2518     if (!texture) {
  2519         SDL_free(overlay->hwdata);
  2520         SDL_free(overlay);
  2521         return NULL;
  2522     }
  2523     overlay->hwdata->texture = texture;
  2524     overlay->hwdata->display = NULL;
  2525     overlay->hwdata->display_format = SDL_PIXELFORMAT_UNKNOWN;
  2526 
  2527     overlay->format = format;
  2528     overlay->w = w;
  2529     overlay->h = h;
  2530     if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
  2531         overlay->planes = 3;
  2532     } else {
  2533         overlay->planes = 1;
  2534     }
  2535     overlay->pitches = texture->pitches;
  2536     overlay->pixels = texture->planes;
  2537 
  2538     return overlay;
  2539 }
  2540 
  2541 int
  2542 SDL_LockYUVOverlay(SDL_Overlay * overlay)
  2543 {
  2544     SDL_Rect rect;
  2545     void *pixels;
  2546     int pitch;
  2547 
  2548     if (!overlay) {
  2549         SDL_SetError("Passed a NULL overlay");
  2550         return -1;
  2551     }
  2552 
  2553     rect.x = 0;
  2554     rect.y = 0;
  2555     rect.w = overlay->w;
  2556     rect.h = overlay->h;
  2557 
  2558     if (SDL_SW_LockYUVTexture(overlay->hwdata->texture, &rect, &pixels, &pitch) < 0) {
  2559         return -1;
  2560     }
  2561 
  2562     overlay->pixels[0] = (Uint8 *) pixels;
  2563     overlay->pitches[0] = pitch;
  2564     switch (overlay->format) {
  2565     case SDL_YV12_OVERLAY:
  2566     case SDL_IYUV_OVERLAY:
  2567         overlay->pitches[1] = pitch / 2;
  2568         overlay->pitches[2] = pitch / 2;
  2569         overlay->pixels[1] =
  2570             overlay->pixels[0] + overlay->pitches[0] * overlay->h;
  2571         overlay->pixels[2] =
  2572             overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
  2573         break;
  2574     case SDL_YUY2_OVERLAY:
  2575     case SDL_UYVY_OVERLAY:
  2576     case SDL_YVYU_OVERLAY:
  2577         break;
  2578     }
  2579     return 0;
  2580 }
  2581 
  2582 void
  2583 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
  2584 {
  2585     if (!overlay) {
  2586         return;
  2587     }
  2588 
  2589     SDL_SW_UnlockYUVTexture(overlay->hwdata->texture);
  2590 }
  2591 
  2592 int
  2593 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
  2594 {
  2595     SDL_Surface *display;
  2596     SDL_Rect src_rect;
  2597     SDL_Rect dst_rect;
  2598     void *pixels;
  2599 
  2600     if (!overlay || !dstrect) {
  2601         SDL_SetError("Passed a NULL overlay or dstrect");
  2602         return -1;
  2603     }
  2604 
  2605     display = overlay->hwdata->display;
  2606     if (display != VideoSurface) {
  2607         overlay->hwdata->display = display = VideoSurface;
  2608         overlay->hwdata->display_format = SDL_MasksToPixelFormatEnum(
  2609                                                 display->format->BitsPerPixel,
  2610                                                 display->format->Rmask,
  2611                                                 display->format->Gmask,
  2612                                                 display->format->Bmask,
  2613                                                 display->format->Amask);
  2614     }
  2615 
  2616     src_rect.x = 0;
  2617     src_rect.y = 0;
  2618     src_rect.w = overlay->w;
  2619     src_rect.h = overlay->h;
  2620 
  2621     if (!SDL_IntersectRect(&display->clip_rect, dstrect, &dst_rect)) {
  2622         return 0;
  2623     }
  2624      
  2625     pixels = (void *)((Uint8 *)display->pixels +
  2626                         dst_rect.y * display->pitch +
  2627                         dst_rect.x * display->format->BytesPerPixel);
  2628 
  2629     if (SDL_SW_CopyYUVToRGB(overlay->hwdata->texture, &src_rect,
  2630                             overlay->hwdata->display_format,
  2631                             dst_rect.w, dst_rect.h,
  2632                             pixels, display->pitch) < 0) {
  2633         return -1;
  2634     }
  2635     SDL_UpdateWindowSurface(VideoWindow20);
  2636     return 0;
  2637 }
  2638 
  2639 void
  2640 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
  2641 {
  2642     if (!overlay) {
  2643         return;
  2644     }
  2645     if (overlay->hwdata) {
  2646         if (overlay->hwdata->texture) {
  2647             SDL_SW_DestroyYUVTexture(overlay->hwdata->texture);
  2648         }
  2649         SDL_free(overlay->hwdata);
  2650     }
  2651     SDL_free(overlay);
  2652 }
  2653 
  2654 void
  2655 SDL_GL_SwapBuffers(void)
  2656 {
  2657     SDL_GL_SwapWindow(VideoWindow20);
  2658 }
  2659 
  2660 int
  2661 SDL_SetGamma(float red, float green, float blue)
  2662 {
  2663     Uint16 red_ramp[256];
  2664     Uint16 green_ramp[256];
  2665     Uint16 blue_ramp[256];
  2666 
  2667     SDL_CalculateGammaRamp(red, red_ramp);
  2668     if (green == red) {
  2669         SDL_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2670     } else {
  2671         SDL_CalculateGammaRamp(green, green_ramp);
  2672     }
  2673     if (blue == red) {
  2674         SDL_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2675     } else {
  2676         SDL_CalculateGammaRamp(blue, blue_ramp);
  2677     }
  2678     return SDL_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2679 }
  2680 
  2681 int
  2682 SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green, const Uint16 * blue)
  2683 {
  2684     return SDL_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2685 }
  2686 
  2687 int
  2688 SDL_GetGammaRamp(Uint16 * red, Uint16 * green, Uint16 * blue)
  2689 {
  2690     return SDL_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  2691 }
  2692 
  2693 int
  2694 SDL_EnableKeyRepeat(int delay, int interval)
  2695 {
  2696     return 0;
  2697 }
  2698 
  2699 void
  2700 SDL_GetKeyRepeat(int *delay, int *interval)
  2701 {
  2702     if (delay) {
  2703         *delay = SDL_DEFAULT_REPEAT_DELAY;
  2704     }
  2705     if (interval) {
  2706         *interval = SDL_DEFAULT_REPEAT_INTERVAL;
  2707     }
  2708 }
  2709 
  2710 
  2711 
  2712 
  2713 int
  2714 SDL_EnableUNICODE(int enable)
  2715 {
  2716     int previous = EnabledUnicode;
  2717 
  2718     switch (enable) {
  2719     case 1:
  2720         EnabledUnicode = 1;
  2721         SDL_StartTextInput();
  2722         break;
  2723     case 0:
  2724         EnabledUnicode = 0;
  2725         SDL_StopTextInput();
  2726         break;
  2727     }
  2728     return previous;
  2729 }
  2730 
  2731 static Uint32
  2732 SDL_SetTimerCallback(Uint32 interval, void* param)
  2733 {
  2734     return ((SDL_OldTimerCallback)param)(interval);
  2735 }
  2736 
  2737 int
  2738 SDL_SetTimer(Uint32 interval, SDL_OldTimerCallback callback)
  2739 {
  2740     static SDL_TimerID compat_timer;
  2741 
  2742     if (compat_timer) {
  2743         SDL20_RemoveTimer(compat_timer);
  2744         compat_timer = 0;
  2745     }
  2746 
  2747     if (interval && callback) {
  2748         compat_timer = SDL20_AddTimer(interval, SDL_SetTimerCallback, callback);
  2749         if (!compat_timer) {
  2750             return -1;
  2751         }
  2752     }
  2753     return 0;
  2754 }
  2755 
  2756 int
  2757 SDL_putenv(const char *_var)
  2758 {
  2759     char *ptr = NULL;
  2760     char *var = SDL_strdup(_var);
  2761     if (var == NULL) {
  2762         return -1;  /* we don't set errno. */
  2763     }
  2764 
  2765     ptr = SDL_strchr(var, '=');
  2766     if (ptr == NULL) {
  2767         SDL_free(var);
  2768         return -1;
  2769     }
  2770 
  2771     *ptr = '\0';  /* split the string into name and value. */
  2772     SDL_setenv(var, ptr + 1, 1);
  2773     SDL_free(var);
  2774     return 0;
  2775 }
  2776 
  2777 
  2778 
  2779 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2780 
  2781 typedef void *SDL12_CD;  /* close enough.  :) */
  2782 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2783 
  2784 static int
  2785 CDUnsupported(void)
  2786 {
  2787     SDL_SetError("CD interface is unsupported");
  2788     return -1;
  2789 }
  2790 
  2791 int
  2792 SDL_CDNumDrives(void)
  2793 {
  2794     return 0;  /* !!! FIXME: should return -1 without SDL_INIT_CDROM */
  2795 }
  2796 
  2797 const char *SDL_CDName(int drive) { CDUnsupported(); return NULL; }
  2798 SDL12_CD * SDL_CDOpen(int drive) { CDUnsupported(); return NULL; }
  2799 SDL12_CDstatus SDL_CDStatus(SDL_CD *cdrom) { return CDUnsupported(); }
  2800 int SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return CDUnsupported(); }
  2801 int SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return CDUnsupported(); }
  2802 int SDL_CDPause(SDL12_CD *cdrom) { return CDUnsupported(); }
  2803 int SDL_CDResume(SDL12_CD *cdrom) { return CDUnsupported(); }
  2804 int SDL_CDStop(SDL12_CD *cdrom) { return CDUnsupported(); }
  2805 int SDL_CDEject(SDL12_CD *cdrom) { return CDUnsupported(); }
  2806 void SDL_CDClose(SDL12_CD *cdrom) {}
  2807 
  2808 
  2809 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  2810 SDL_Thread *
  2811 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  2812 {
  2813     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  2814 }
  2815 #else
  2816 SDL_Thread *
  2817 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  2818 {
  2819     return SDL20_CreateThread(fn, NULL, data);
  2820 }
  2821 #endif
  2822 
  2823 
  2824 /* !!! FIXME: Removed from 2.0; do nothing. We can't even report failure. */
  2825 void SDL_KillThread(SDL_Thread *thread) {}
  2826 
  2827 /* This changed from an opaque pointer to an int in 2.0. */
  2828 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2829 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2830 
  2831 SDL12_TimerID
  2832 SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param)
  2833 {
  2834     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2835 }
  2836 
  2837 SDL_bool
  2838 SDL_RemoveTimer(SDL12_TimerID id)
  2839 {
  2840     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  2841 }
  2842 
  2843 
  2844 typedef struct SDL12_RWops {
  2845     int (SDLCALL *seek)(struct SDL_RWops *context, int offset, int whence);
  2846     int (SDLCALL *read)(struct SDL_RWops *context, void *ptr, int size, int maxnum);
  2847     int (SDLCALL *write)(struct SDL_RWops *context, const void *ptr, int size, int num);
  2848     int (SDLCALL *close)(struct SDL_RWops *context);
  2849     Uint32 type;
  2850     void *padding[8];
  2851     SDL_RWops *rwops20;
  2852 } SDL12_RWops;
  2853 
  2854 
  2855 SDL12_RWops *
  2856 SDL_AllocRW(void)
  2857 {
  2858     SDL12_RWops *rwops = (SDL12_RWops *) SDL_malloc(sizeof (SDL12_RWops));
  2859     if (!rwops)
  2860         SDL20_OutOfMemory();
  2861     return rwops;
  2862 }
  2863 
  2864 void
  2865 SDL_FreeRW(SDL12_RWops *rwops12)
  2866 {
  2867     SDL_free(rwops12);
  2868 }
  2869 
  2870 static int SDLCALL
  2871 RWops12to20_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  2872 {
  2873     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  2874 }
  2875 
  2876 static int SDLCALL
  2877 RWops12to20_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  2878 {
  2879     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  2880 }
  2881 
  2882 static int SDLCALL
  2883 RWops12to20_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  2884 {
  2885     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  2886 }
  2887 
  2888 static int SDLCALL
  2889 RWops12to20_close(struct SDL12_RWops *rwops12)
  2890 {
  2891     int rc = 0;
  2892     if (rwops12)
  2893     {
  2894         rc = rwops12->rwops20->close(rwops12->rwops20);
  2895         if (rc == 0)
  2896             SDL_FreeRW(rwops12);
  2897     }
  2898     return rc;
  2899 }
  2900 
  2901 static SDL12_RWops *
  2902 RWops12to20(SDL12_RWops *rwops12, SDL_RWops *rwops20)
  2903 {
  2904     if (!rwops20)
  2905     {
  2906         SDL_FreeRW(rwops12);
  2907         return NULL;
  2908     }
  2909     SDL_zerop(rwops12);
  2910     rwops12->type = rwops20->type;
  2911     rwops12->rwops20 = rwops20;
  2912     rwops12->seek = RWops12to20_seek;
  2913     rwops12->read = RWops12to20_read;
  2914     rwops12->write = RWops12to20_write;
  2915     rwops12->close = RWops12to20_close;
  2916     return rwops12;
  2917 }
  2918 
  2919 SDL12_RWops *
  2920 SDL_RWFromFile(const char *file, const char *mode)
  2921 {
  2922     SDL12_RWops *rwops12 = SDL_AllocRW();
  2923     return rwops12 ? RWops12to20(rwops12, SDL20_RWFromFile(file, mode)) : NULL;
  2924 }
  2925 
  2926 SDL12_RWops *
  2927 SDL_RWFromFP(FILE *io, int autoclose)
  2928 {
  2929     SDL12_RWops *rwops12 = SDL_AllocRW();
  2930     return rwops12 ? RWops12to20(rwops12, SDL20_RWFromFP(io, autoclose)) : NULL;
  2931 }
  2932 
  2933 SDL12_RWops *
  2934 SDL_RWFromMem(void *mem, int size)
  2935 {
  2936     SDL12_RWops *rwops12 = SDL_AllocRW();
  2937     return rwops12 ? RWops12to20(rwops12, SDL20_RWFromMem(mem, size)) : NULL;
  2938 }
  2939 
  2940 SDL12_RWops *
  2941 SDL_RWFromConstMem(const void *mem, int size)
  2942 {
  2943     SDL12_RWops *rwops12 = SDL_AllocRW();
  2944     return rwops12 ? RWops12to20(rwops12, SDL20_RWFromConstMem(mem, size)) : NULL;
  2945 }
  2946 
  2947 #define READ_AND_BYTESWAP(endian, bits) \
  2948     Uint##bits SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  2949         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  2950         return SDL_Swap##endian##bits(val); \
  2951     }
  2952 
  2953 READ_AND_BYTESWAP(LE,16)
  2954 READ_AND_BYTESWAP(BE,16)
  2955 READ_AND_BYTESWAP(LE,32)
  2956 READ_AND_BYTESWAP(BE,32)
  2957 READ_AND_BYTESWAP(LE,64)
  2958 READ_AND_BYTESWAP(BE,64)
  2959 #undef READ_AND_BYTESWAP
  2960 
  2961 #define BYTESWAP_AND_WRITE(endian, bits) \
  2962     int SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##endian##bits val) { \
  2963         val = SDL_Swap##endian##bits(val); \
  2964         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  2965     }
  2966 BYTESWAP_AND_WRITE(LE,16)
  2967 BYTESWAP_AND_WRITE(BE,16)
  2968 BYTESWAP_AND_WRITE(LE,32)
  2969 BYTESWAP_AND_WRITE(BE,32)
  2970 BYTESWAP_AND_WRITE(LE,64)
  2971 BYTESWAP_AND_WRITE(BE,64)
  2972 #undef BYTESWAP_AND_WRITE
  2973 
  2974 /* Things that _should_ be binary compatible pass right through... */
  2975 #define SDL20_SYM(rc,fn,params,args,ret)
  2976 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
  2977     rc SDL_##fn params { ret SDL20_##fn args; }
  2978 #include "SDL20_syms.h"
  2979 #undef SDL20_SYM_PASSTHROUGH
  2980 #undef SDL20_SYM
  2981 
  2982 
  2983 static Sint64 SDLCALL
  2984 RWops20to12_size(struct SDL_RWops *rwops20)
  2985 {
  2986     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2987     int size = rwops20->hidden.unknown.data2;
  2988     int pos;
  2989 
  2990     if (size != -1)
  2991         return size;
  2992 
  2993     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  2994     if (pos == -1)
  2995         return -1;
  2996 
  2997     size = (Sint64) rwops->seek(rwops12, 0, SEEK_END);
  2998     if (size == -1)
  2999         return -1;
  3000 
  3001     rwops->seek(rwops12, pos, SEEK_SET);  /* !!! FIXME: and if this fails? */
  3002     rwops20->hidden.unknown.data2 = size;
  3003     return size;
  3004 }
  3005 
  3006 static Sint64
  3007 RWops20to12_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  3008 {
  3009     /* !!! FIXME: fail if (offset) is too big */
  3010     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3011     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  3012 }
  3013 
  3014 static size_t SDLCALL
  3015 RWops20to12_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  3016 {
  3017     /* !!! FIXME: fail if (size) or (maxnum) is too big */
  3018     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3019     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  3020 }
  3021 
  3022 static size_t SDLCALL
  3023 RWops20to12_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  3024 {
  3025     /* !!! FIXME: fail if (size) or (maxnum) is too big */
  3026     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3027     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  3028 }
  3029 
  3030 static int SDLCALL
  3031 RWops20to12_close(struct SDL_RWops *rwops20)
  3032 {
  3033     int rc = 0;
  3034     if (rwops20)
  3035     {
  3036         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3037         rc = rwops12->close(rwops12);
  3038         if (rc == 0)
  3039             SDL20_FreeRW(rwops20);
  3040     }
  3041     return rc;
  3042 }
  3043 
  3044 static SDL12_RWops *
  3045 RWops20to12(SDL12_RWops *rwops12)
  3046 {
  3047     SDL20_RWops *rwops20;
  3048 
  3049     if (!rwops12)
  3050         return NULL;
  3051 
  3052     rwops20 = SDL20_AllocRW();
  3053     if (!rwops20)
  3054         return NULL;
  3055 
  3056     SDL_zerop(rwops20);
  3057     rwops20->type = rwops12->type;
  3058     rwops20->hidden.unknown.data1 = rwops12;
  3059     rwops20->hidden.unknown.data2 = -1;  /* cached size of stream */
  3060     rwops20->size = RWops20to12_size;
  3061     rwops20->seek = RWops20to12_seek;
  3062     rwops20->read = RWops20to12_read;
  3063     rwops20->write = RWops20to12_write;
  3064     rwops20->close = RWops20to12_close;
  3065     return rwops20;
  3066 }
  3067 
  3068 SDL12_Surface *
  3069 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  3070 {
  3071     SDL_RWops *rwops20 = RWops20to12(rwops12);
  3072     SDL_Surface *retval = SDL20_LoadBMP_RW(rwops20, freerwops12);
  3073     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3074         SDL20_FreeRW(rwops20);
  3075     // !!! FIXME: wrap surface.
  3076     return retval;
  3077 }
  3078 
  3079 int
  3080 SDL_SaveBMP_RW(SDL12_Surface *surface, SDL12_RWops *rwops12, int freerwops12)
  3081 {
  3082     // !!! FIXME: wrap surface.
  3083     SDL_RWops *rwops20 = RWops20to12(rwops12);
  3084     const int retval = SDL20_SaveBMP_RW(surface, rwops20, freerwops12);
  3085     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3086         SDL20_FreeRW(rwops20);
  3087     return retval;
  3088 }
  3089 
  3090 SDL_AudioSpec *
  3091 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  3092                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  3093 {
  3094     SDL_RWops *rwops20 = RWops20to12(rwops12);
  3095     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  3096     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3097         SDL20_FreeRW(rwops20);
  3098     return retval;
  3099 }
  3100 
  3101 /* vi: set ts=4 sw=4 expandtab: */