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