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