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