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