src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Sat, 26 Jul 2014 00:55:20 -0400
changeset 40 9f165553c592
parent 39 354ef2d7f999
child 41 f9d92daf587f
permissions -rw-r--r--
Fail unconditionally on SDL_INIT_EVENTTHREAD for now.
     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_InitSubSubsystem(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     // !!! FIXME: UnloadSDL20() ?
   742 }
   743 
   744 DECLSPEC void SDLCALL
   745 SDL_Quit(void)
   746 {
   747     // !!! FIXME: reset a bunch of other global variables too.
   748     EventFilter12 = NULL;
   749     EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   750     CurrentCursor = NULL;
   751     SDL20_FreeFormat(VideoInfo.vfmt);
   752     SDL20_zero(VideoInfo);
   753     CDRomInit = 0;
   754     SDL20_Quit();
   755     UnloadSDL20();
   756 }
   757 
   758 DECLSPEC void SDLCALL
   759 SDL_SetError(const char *fmt, ...)
   760 {
   761     char ch;
   762     char *str = NULL;
   763     size_t len = 0;
   764     va_list ap;
   765     va_start(ap, fmt);
   766     len = SDL20_vsnprintf(&ch, 1, fmt, ap);
   767     va_end(ap);
   768 
   769     str = (char *) SDL20_malloc(len + 1);
   770     if (!str)
   771         SDL20_OutOfMemory();
   772     else
   773     {
   774         va_start(ap, fmt);
   775         SDL20_vsnprintf(str, len + 1, fmt, ap);
   776         va_end(ap);
   777         SDL20_SetError("%s", str);
   778         SDL20_free(str);
   779     }
   780 }
   781 
   782 DECLSPEC const char * SDLCALL
   783 SDL_GetError(void)
   784 {
   785     if (!Loaded_SDL20)
   786     {
   787         static const char noload_errstr[] = "Failed to load SDL 2.0 shared library";
   788         return noload_errstr;
   789     }
   790     return SDL20_GetError();
   791 }
   792 
   793 
   794 static const char *
   795 GetDriverName(const char *name, char *namebuf, int maxlen)
   796 {
   797     if (name) {
   798         if (namebuf) {
   799             SDL20_strlcpy(namebuf, name, maxlen);
   800             return namebuf;
   801         } else {
   802             return name;
   803         }
   804     }
   805     return NULL;
   806 }
   807 
   808 DECLSPEC const char * SDLCALL
   809 SDL_AudioDriverName(char *namebuf, int maxlen)
   810 {
   811     return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
   812 }
   813 
   814 DECLSPEC const char * SDLCALL
   815 SDL_VideoDriverName(char *namebuf, int maxlen)
   816 {
   817     return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
   818 }
   819 
   820 DECLSPEC int SDLCALL
   821 SDL_PollEvent(SDL12_Event *event12)
   822 {
   823     EventQueueType *next;
   824 
   825     SDL20_PumpEvents();  /* this will run our filter and build our 1.2 queue. */
   826 
   827     if (EventQueueHead == NULL)
   828         return 0;  /* no events at the moment. */
   829 
   830     SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
   831     next = EventQueueHead->next;
   832     EventQueueHead->next = EventQueueAvailable;
   833     EventQueueAvailable = EventQueueHead;
   834     EventQueueHead = next;
   835     return 1;
   836 }
   837 
   838 DECLSPEC int SDLCALL
   839 SDL_PushEvent(SDL12_Event *event12)
   840 {
   841     EventQueueType *item = EventQueueAvailable;
   842     if (item == NULL)
   843         return -1;  /* no space available at the moment. */
   844 
   845     EventQueueAvailable = item->next;
   846     if (EventQueueTail)
   847         EventQueueTail->next = item;
   848     else
   849         EventQueueHead = EventQueueTail = item;
   850     item->next = NULL;
   851 
   852     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
   853     return 0;
   854 }
   855 
   856 DECLSPEC int SDLCALL
   857 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
   858 {
   859     if (action == SDL_ADDEVENT)
   860     {
   861         int i;
   862         for (i = 0; i < numevents; i++)
   863         {
   864             if (SDL_PushEvent(&events12[i]) == -1)
   865                 break;  /* out of space for more events. */
   866         }
   867         return i;
   868     }
   869     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
   870     {
   871         const SDL_bool isGet = (action == SDL_GETEVENT);
   872         EventQueueType *prev = NULL;
   873         EventQueueType *item = EventQueueHead;
   874         EventQueueType *next = NULL;
   875         int chosen = 0;
   876         while (chosen < numevents)
   877         {
   878             EventQueueType *nextPrev = item;
   879             if (!item)
   880                 break;  /* no more events at the moment. */
   881 
   882             next = item->next;  /* copy, since we might overwrite item->next */
   883 
   884             if (mask & (1<<item->event12.type))
   885             {
   886                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
   887                 if (isGet)  /* remove from list? */
   888                 {
   889                     if (prev != NULL)
   890                         prev->next = next;
   891                     if (item == EventQueueHead)
   892                         EventQueueHead = next;
   893                     if (item == EventQueueTail)
   894                         EventQueueTail = prev;
   895 
   896                     /* put it back in the free pool. */
   897                     item->next = EventQueueAvailable;
   898                     EventQueueAvailable = item;
   899                     nextPrev = prev;  /* previous item doesn't change. */
   900                 }
   901             }
   902 
   903             item = next;
   904             prev = nextPrev;
   905         }
   906         return chosen;
   907     }
   908 
   909     return 0;
   910 }
   911 
   912 DECLSPEC int SDLCALL
   913 SDL_WaitEvent(SDL12_Event *event12)
   914 {
   915     /* In 1.2, this only fails (-1) if you haven't SDL_Init()'d. */
   916     while (!SDL_PollEvent(event12))
   917         SDL_Delay(10);
   918     return 1;
   919 }
   920 
   921 static SDL_bool
   922 PushEventIfNotFiltered(SDL12_Event *event12)
   923 {
   924     if (event12->type != SDL12_NOEVENT)
   925     {
   926         if (EventStates[event12->type] != SDL_IGNORE)
   927         {
   928             if ((!EventFilter12) || (EventFilter12(event12)))
   929                 return (SDL_PushEvent(event12) == 0);
   930         }
   931     }
   932     return SDL_FALSE;
   933 }
   934 
   935 DECLSPEC Uint8 SDLCALL
   936 SDL_EventState(Uint8 type, int state)
   937 {
   938     /* the values of "state" match between 1.2 and 2.0 */
   939     const Uint8 retval = EventStates[type];
   940     SDL12_Event e;
   941 
   942     if (state != SDL_QUERY)
   943         EventStates[type] = state;
   944     if (state == SDL_IGNORE)  /* drop existing events of this type. */
   945         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
   946 
   947     return retval;
   948 }
   949 
   950 DECLSPEC Uint8 SDLCALL
   951 SDL_GetMouseState(int *x, int *y)
   952 {
   953     const Uint32 state20 = SDL20_GetMouseState(x, y);
   954     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
   955 
   956     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
   957     if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
   958         retval |= (1<<5);
   959     if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
   960         retval |= (1<<6);
   961 
   962     return retval;
   963 }
   964 
   965 static int
   966 EventFilter20to12(void *data, SDL_Event *event20)
   967 {
   968     const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
   969     SDL12_Event event12;
   970     int x, y;
   971 
   972     SDL_assert(data == NULL);  /* currently unused. */
   973 
   974     SDL20_zero(event12);
   975 
   976     switch (event20->type)
   977     {
   978         case SDL_QUIT:
   979             event12.type = SDL12_QUIT;
   980             break;
   981 
   982         case SDL_WINDOWEVENT:
   983             switch (event20->window.event)
   984             {
   985                 case SDL_WINDOWEVENT_CLOSE:
   986                     event12.type = SDL12_QUIT;
   987                     break;
   988 
   989                 case SDL_WINDOWEVENT_SHOWN:
   990                 case SDL_WINDOWEVENT_EXPOSED:
   991                     event12.type = SDL12_VIDEOEXPOSE;
   992                     break;
   993 
   994                 case SDL_WINDOWEVENT_RESIZED:
   995                 case SDL_WINDOWEVENT_SIZE_CHANGED:  // !!! FIXME: what's the difference between RESIZED and SIZE_CHANGED?
   996                     event12.type = SDL12_VIDEORESIZE;
   997                     event12.resize.w = event20->window.data1;
   998                     event12.resize.h = event20->window.data2;
   999                     break;
  1000 
  1001                 case SDL_WINDOWEVENT_MINIMIZED:
  1002                     event12.type = SDL12_ACTIVEEVENT;
  1003                     event12.active.gain = 0;
  1004                     event12.active.state = SDL12_APPACTIVE;
  1005                     break;
  1006 
  1007                 case SDL_WINDOWEVENT_RESTORED:
  1008                     event12.type = SDL12_ACTIVEEVENT;
  1009                     event12.active.gain = 1;
  1010                     event12.active.state = SDL12_APPACTIVE;
  1011                     break;
  1012 
  1013                 case SDL_WINDOWEVENT_ENTER:
  1014                     event12.type = SDL12_ACTIVEEVENT;
  1015                     event12.active.gain = 1;
  1016                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1017                     break;
  1018 
  1019                 case SDL_WINDOWEVENT_LEAVE:
  1020                     event12.type = SDL12_ACTIVEEVENT;
  1021                     event12.active.gain = 0;
  1022                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1023                     break;
  1024 
  1025                 case SDL_WINDOWEVENT_FOCUS_GAINED:
  1026                     event12.type = SDL12_ACTIVEEVENT;
  1027                     event12.active.gain = 1;
  1028                     event12.active.state = SDL12_APPINPUTFOCUS;
  1029                     break;
  1030 
  1031                 case SDL_WINDOWEVENT_FOCUS_LOST:
  1032                     event12.type = SDL12_ACTIVEEVENT;
  1033                     event12.active.gain = 0;
  1034                     event12.active.state = SDL12_APPINPUTFOCUS;
  1035                     break;
  1036             }
  1037             break;
  1038 
  1039         // !!! FIXME: this is sort of a mess to convert.
  1040         //case SDL_SYSWMEVENT:
  1041 
  1042         // !!! FIXME: write me
  1043         case SDL_KEYDOWN:
  1044         case SDL_KEYUP:
  1045             return 0;
  1046 
  1047         // !!! FIXME: write me
  1048         case SDL_TEXTEDITING:
  1049         case SDL_TEXTINPUT:
  1050             return 0;
  1051 
  1052         case SDL_MOUSEMOTION:
  1053         	event12.type = SDL12_MOUSEMOTION;
  1054             event12.motion.which = (Uint8) event20->motion.which;
  1055             event12.motion.state = event20->motion.state;
  1056             event12.motion.x = (Uint16) event20->motion.x;
  1057             event12.motion.y = (Uint16) event20->motion.y;
  1058             event12.motion.xrel = (Sint16) event20->motion.xrel;
  1059             event12.motion.yrel = (Sint16) event20->motion.yrel;
  1060             break;
  1061 
  1062         case SDL_MOUSEBUTTONDOWN:
  1063         	event12.type = SDL12_MOUSEBUTTONDOWN;
  1064             event12.button.which = (Uint8) event20->button.which;
  1065             event12.button.button = event20->button.button;
  1066             event12.button.state = event20->button.state;
  1067             event12.button.x = (Uint16) event20->button.x;
  1068             event12.button.y = (Uint16) event20->button.y;
  1069             break;
  1070 
  1071         case SDL_MOUSEBUTTONUP:
  1072         	event12.type = SDL12_MOUSEBUTTONUP;
  1073             event12.button.which = (Uint8) event20->button.which;
  1074             event12.button.button = event20->button.button;
  1075             event12.button.state = event20->button.state;
  1076             event12.button.x = (Uint16) event20->button.x;
  1077             event12.button.y = (Uint16) event20->button.y;
  1078             break;
  1079 
  1080         case SDL_MOUSEWHEEL:
  1081             if (event20->wheel.y == 0)
  1082                 break;  /* don't support horizontal wheels in 1.2. */
  1083 
  1084             event12.type = SDL12_MOUSEBUTTONDOWN;
  1085             event12.button.which = (Uint8) event20->wheel.which;
  1086             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
  1087             event12.button.state = SDL_GetMouseState(&x, &y);
  1088             event12.button.x = (Uint16) x;
  1089             event12.button.y = (Uint16) y;
  1090             PushEventIfNotFiltered(&event12);
  1091 
  1092             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
  1093             break;
  1094 
  1095         case SDL_JOYAXISMOTION:
  1096             event12.type = SDL12_JOYAXISMOTION;
  1097             event12.jaxis.which = (Uint8) event20->jaxis.which;
  1098             event12.jaxis.axis = event20->jaxis.axis;
  1099             event12.jaxis.value = event20->jaxis.value;
  1100             break;
  1101 
  1102         case SDL_JOYBALLMOTION:
  1103             event12.type = SDL12_JOYBALLMOTION;
  1104             event12.jball.which = (Uint8) event20->jball.which;
  1105             event12.jball.ball = event20->jball.ball;
  1106             event12.jball.xrel = event20->jball.xrel;
  1107             event12.jball.yrel = event20->jball.yrel;
  1108             break;
  1109 
  1110         case SDL_JOYHATMOTION:
  1111             event12.type = SDL12_JOYHATMOTION;
  1112             event12.jhat.which = (Uint8) event20->jhat.which;
  1113             event12.jhat.hat = event20->jhat.hat;
  1114             event12.jhat.value = event20->jhat.value;
  1115             break;
  1116 
  1117         case SDL_JOYBUTTONDOWN:
  1118             event12.type = SDL12_JOYBUTTONDOWN;
  1119             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1120             event12.jbutton.button = event20->jbutton.button;
  1121             event12.jbutton.state = event20->jbutton.state;
  1122             break;
  1123 
  1124         case SDL_JOYBUTTONUP:
  1125             event12.type = SDL12_JOYBUTTONUP;
  1126             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1127             event12.jbutton.button = event20->jbutton.button;
  1128             event12.jbutton.state = event20->jbutton.state;
  1129             break;
  1130 
  1131         //case SDL_JOYDEVICEADDED:
  1132         //case SDL_JOYDEVICEREMOVED:
  1133 	    //case SDL_CONTROLLERAXISMOTION:
  1134 	    //case SDL_CONTROLLERBUTTONDOWN:
  1135 	    //case SDL_CONTROLLERBUTTONUP:
  1136 	    //case SDL_CONTROLLERDEVICEADDED:
  1137 	    //case SDL_CONTROLLERDEVICEREMOVED:
  1138 	    //case SDL_CONTROLLERDEVICEREMAPPED:
  1139         //case SDL_FINGERDOWN:
  1140         //case SDL_FINGERUP:
  1141         //case SDL_FINGERMOTION:
  1142         //case SDL_DOLLARGESTURE:
  1143         //case SDL_DOLLARRECORD:
  1144         //case SDL_MULTIGESTURE:
  1145         //case SDL_CLIPBOARDUPDATE:
  1146         //case SDL_DROPFILE:
  1147 
  1148         default:
  1149             return 0;  /* drop everything else. */
  1150     }
  1151 
  1152     PushEventIfNotFiltered(&event12);
  1153 
  1154     return 0;  /* always drop it from the 2.0 event queue. */
  1155 }
  1156 
  1157 DECLSPEC void SDLCALL
  1158 SDL_SetEventFilter(SDL12_EventFilter filter12)
  1159 {
  1160     /* We always have a filter installed, but will call the app's too. */
  1161     EventFilter12 = filter12;
  1162 }
  1163 
  1164 DECLSPEC SDL12_EventFilter SDLCALL
  1165 SDL_GetEventFilter(void)
  1166 {
  1167     return EventFilter12;
  1168 }
  1169 
  1170 
  1171 static SDL12_Surface *
  1172 Surface20to12(SDL_Surface *surface20)
  1173 {
  1174     SDL12_Surface *surface12 = NULL;
  1175     SDL12_Palette *palette12 = NULL;
  1176     SDL12_PixelFormat *format12 = NULL;
  1177     Uint32 flags = 0;
  1178 
  1179     if (!surface20)
  1180         return NULL;
  1181 
  1182     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
  1183     if (!surface12)
  1184         goto failed;
  1185 
  1186     palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
  1187     if (!palette12)
  1188         goto failed;
  1189 
  1190     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  1191     if (!format12)
  1192         goto failed;
  1193 
  1194     SDL20_zerop(palette12);
  1195     palette12->ncolors = surface20->format->palette->ncolors;
  1196     palette12->colors = surface20->format->palette->colors;
  1197 
  1198     SDL20_zerop(format12);
  1199     format12->palette = palette12;
  1200     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  1201     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  1202     format12->Rloss = surface20->format->Rloss;
  1203     format12->Gloss = surface20->format->Gloss;
  1204     format12->Bloss = surface20->format->Bloss;
  1205     format12->Aloss = surface20->format->Aloss;
  1206     format12->Rshift = surface20->format->Rshift;
  1207     format12->Gshift = surface20->format->Gshift;
  1208     format12->Bshift = surface20->format->Bshift;
  1209     format12->Ashift = surface20->format->Ashift;
  1210     format12->Rmask = surface20->format->Rmask;
  1211     format12->Gmask = surface20->format->Gmask;
  1212     format12->Bmask = surface20->format->Bmask;
  1213     format12->Amask = surface20->format->Amask;
  1214     /* !!! FIXME: format12->colorkey; */
  1215     /* !!! FIXME: format12->alpha; */
  1216 
  1217     SDL20_zerop(surface12);
  1218     flags = surface20->flags;
  1219     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  1220     MAPSURFACEFLAGS(PREALLOC);
  1221     MAPSURFACEFLAGS(RLEACCEL);
  1222     /*MAPSURFACEFLAGS(DONTFREE);*/
  1223     #undef MAPSURFACEFLAGS
  1224     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  1225 
  1226     surface12->format = format12;
  1227     surface12->w = surface20->w;
  1228     surface12->h = surface20->h;
  1229     surface12->pitch = (Uint16) surface20->pitch;  /* !!! FIXME: make sure this fits in a Uint16 */
  1230     surface12->pixels = surface20->pixels;
  1231     surface12->offset = 0;
  1232     surface12->surface20 = surface20;
  1233     SDL20_memcpy(&surface12->clip_rect, &surface20->clip_rect, sizeof (SDL_Rect));
  1234     surface12->refcount = surface20->refcount;
  1235 
  1236     return surface12;
  1237 
  1238 failed:
  1239     SDL20_free(surface12);
  1240     SDL20_free(palette12);
  1241     SDL20_free(format12);
  1242     return NULL;
  1243 }
  1244 
  1245 DECLSPEC SDL12_Surface * SDLCALL
  1246 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1247 {
  1248     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  1249     SDL12_Surface *surface12 = Surface20to12(surface20);
  1250     if (!surface12) {
  1251         SDL20_FreeSurface(surface20);
  1252         return NULL;
  1253     }
  1254 
  1255     SDL_assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  1256     return surface12;
  1257 }
  1258 
  1259 DECLSPEC SDL12_Surface * SDLCALL
  1260 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1261 {
  1262     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  1263     SDL12_Surface *surface12 = Surface20to12(surface20);
  1264     if (!surface12) {
  1265         SDL20_FreeSurface(surface20);
  1266         return NULL;
  1267     }
  1268 
  1269     SDL_assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  1270     return surface12;
  1271 }
  1272 
  1273 DECLSPEC void SDLCALL
  1274 SDL_FreeSurface(SDL12_Surface *surface12)
  1275 {
  1276     if (surface12) {
  1277         SDL20_FreeSurface(surface12->surface20);
  1278         if (surface12->format) {
  1279             SDL20_free(surface12->format->palette);
  1280             SDL20_free(surface12->format);
  1281         }
  1282         SDL20_free(surface12);
  1283     }
  1284 }
  1285 
  1286 DECLSPEC void SDLCALL
  1287 SDL_GetClipRect(SDL12_Surface *surface12, SDL_Rect *rect)
  1288 {
  1289     if (surface12 && rect)
  1290 	    SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL_Rect));
  1291 }
  1292 
  1293 DECLSPEC SDL_bool SDLCALL
  1294 SDL_SetClipRect(SDL12_Surface *surface12, const SDL_Rect *rect)
  1295 {
  1296     SDL_bool retval = SDL_FALSE;
  1297     if (surface12)
  1298     {
  1299         retval = SDL20_SetClipRect(surface12->surface20, rect);
  1300         SDL20_GetClipRect(surface12->surface20, &surface12->clip_rect);
  1301     }
  1302     return retval;
  1303 }
  1304 
  1305 DECLSPEC int SDLCALL
  1306 SDL_FillRect(SDL12_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1307 {
  1308     const SDL_Rect orig_dstrect = *dstrect;
  1309     const int retval = SDL20_FillRect(dst->surface20, &orig_dstrect, color);
  1310     if (retval != -1)
  1311     {
  1312         if (dstrect)  /* 1.2 stores the clip intersection in dstrect */
  1313             SDL20_IntersectRect(&orig_dstrect, &dst->clip_rect, dstrect);
  1314     }
  1315     return retval;
  1316 }
  1317 
  1318 
  1319 static SDL_PixelFormat *
  1320 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  1321 {
  1322     palette20->ncolors = format12->palette->ncolors;
  1323     palette20->colors = format12->palette->colors;
  1324     palette20->version = 1;
  1325     palette20->refcount = 1;
  1326     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1327     format20->palette = palette20;
  1328     format20->BitsPerPixel = format12->BitsPerPixel;
  1329     format20->BytesPerPixel = format12->BytesPerPixel;
  1330     format20->Rmask = format12->Rmask;
  1331     format20->Gmask = format12->Gmask;
  1332     format20->Bmask = format12->Bmask;
  1333     format20->Amask = format12->Amask;
  1334     format20->Rloss = format12->Rloss;
  1335     format20->Gloss = format12->Gloss;
  1336     format20->Bloss = format12->Bloss;
  1337     format20->Aloss = format12->Aloss;
  1338     format20->Rshift = format12->Rshift;
  1339     format20->Gshift = format12->Gshift;
  1340     format20->Bshift = format12->Bshift;
  1341     format20->Ashift = format12->Ashift;
  1342     format20->refcount = 1;
  1343     format20->next = NULL;
  1344     return format20;
  1345 }
  1346 
  1347 DECLSPEC Uint32 SDLCALL
  1348 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  1349 {
  1350     /* This is probably way slower than apps expect. */
  1351     SDL_PixelFormat format20;
  1352     SDL_Palette palette20;
  1353     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1354 }
  1355 
  1356 DECLSPEC Uint32 SDLCALL
  1357 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1358 {
  1359     /* This is probably way slower than apps expect. */
  1360     SDL_PixelFormat format20;
  1361     SDL_Palette palette20;
  1362     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1363 }
  1364 
  1365 DECLSPEC void SDLCALL
  1366 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  1367 {
  1368     /* This is probably way slower than apps expect. */
  1369     SDL_PixelFormat format20;
  1370     SDL_Palette palette20;
  1371     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1372 }
  1373 
  1374 DECLSPEC void SDLCALL
  1375 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1376 {
  1377     /* This is probably way slower than apps expect. */
  1378     SDL_PixelFormat format20;
  1379     SDL_Palette palette20;
  1380     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1381 }
  1382 
  1383 DECLSPEC const SDL12_VideoInfo * SDLCALL
  1384 SDL_GetVideoInfo(void)
  1385 {
  1386     SDL_DisplayMode mode;
  1387 
  1388     // !!! FIXME: calculate this in Init12Video(), then this just does: return VideoInfo.vfmt ? &VideoInfo : NULL;
  1389 
  1390     if (!VideoInfo.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1391         VideoInfo.vfmt = SDL20_AllocFormat(mode.format);
  1392         VideoInfo.current_w = mode.w;
  1393         VideoInfo.current_h = mode.h;
  1394         // !!! FIXME
  1395         //VideoInfo.wm_available = 1;
  1396         //VideoInfo.video_mem = 1024 * 256;
  1397     }
  1398     return &VideoInfo;
  1399 }
  1400 
  1401 DECLSPEC int SDLCALL
  1402 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  1403 {
  1404     int i, nummodes, actual_bpp = 0;
  1405 
  1406     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1407         return 0;
  1408     }
  1409 
  1410     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  1411         SDL_DisplayMode mode;
  1412         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  1413         return SDL_BITSPERPIXEL(mode.format);
  1414     }
  1415 
  1416     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1417     for (i = 0; i < nummodes; ++i) {
  1418         SDL_DisplayMode mode;
  1419         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1420         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  1421             if (!mode.format) {
  1422                 return bpp;
  1423             }
  1424             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  1425                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  1426             }
  1427         }
  1428     }
  1429     return actual_bpp;
  1430 }
  1431 
  1432 DECLSPEC SDL_Rect ** SDLCALL
  1433 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
  1434 {
  1435     Uint32 fmt;
  1436     int i;
  1437 
  1438     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1439         return NULL;
  1440     }
  1441 
  1442     if ((!format12) && (!VideoInfo.vfmt)) {
  1443         SDL20_SetError("No pixel format specified");
  1444         return NULL;
  1445     }
  1446 
  1447     if (!(flags & SDL12_FULLSCREEN)) {
  1448         return (SDL_Rect **) (-1);  /* any resolution is fine. */
  1449     }
  1450 
  1451     if (format12) {
  1452         fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1453     } else {
  1454         fmt = VideoInfo.vfmt->format;
  1455     }
  1456 
  1457     for (i = 0; i < VideoModesCount; i++) {
  1458         VideoModeList *modes = &VideoModes[i];
  1459         if (modes->format == fmt) {
  1460             return modes->modes;
  1461         }
  1462     }
  1463 
  1464     SDL20_SetError("No modes support requested pixel format");
  1465     return NULL;
  1466 }
  1467 
  1468 DECLSPEC void SDLCALL
  1469 SDL_FreeCursor(SDL12_Cursor *cursor12)
  1470 {
  1471     if (cursor12)
  1472     {
  1473         if (cursor12->wm_cursor)
  1474             SDL20_FreeCursor(cursor12->wm_cursor);
  1475         SDL20_free(cursor12->data);
  1476         SDL20_free(cursor12->mask);
  1477         SDL20_free(cursor12);
  1478     }
  1479 }
  1480 
  1481 DECLSPEC SDL12_Cursor * SDLCALL
  1482 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  1483 {
  1484     const size_t datasize = h * (w / 8);
  1485     SDL_Cursor *cursor20 = NULL;
  1486     SDL12_Cursor *retval = NULL;
  1487 
  1488     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  1489     if (!retval)
  1490         goto outofmem;
  1491 
  1492     SDL20_zerop(retval);
  1493 
  1494     retval->data = (Uint8 *) SDL20_malloc(datasize);
  1495     if (!retval->data)
  1496         goto outofmem;
  1497 
  1498     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  1499     if (!retval->mask)
  1500         goto outofmem;
  1501 
  1502     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  1503     if (!cursor20)
  1504         goto failed;
  1505 
  1506     retval->area.w = w;
  1507     retval->area.h = h;
  1508     retval->hot_x = hot_x;
  1509     retval->hot_y = hot_y;
  1510     retval->wm_cursor = cursor20;
  1511     /* we always leave retval->save as null pointers. */
  1512 
  1513     SDL20_memcpy(retval->data, data, datasize);
  1514     SDL20_memcpy(retval->mask, mask, datasize);
  1515 
  1516     return retval;
  1517 
  1518 outofmem:
  1519     SDL20_OutOfMemory();
  1520 
  1521 failed:
  1522     SDL_FreeCursor(retval);
  1523     return NULL;
  1524 }
  1525 
  1526 DECLSPEC void SDLCALL
  1527 SDL_SetCursor(SDL12_Cursor *cursor)
  1528 {
  1529     CurrentCursor = cursor;
  1530     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  1531 }
  1532 
  1533 DECLSPEC SDL12_Cursor * SDLCALL
  1534 SDL_GetCursor(void)
  1535 {
  1536     return CurrentCursor;
  1537 }
  1538 
  1539 static void
  1540 GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
  1541 {
  1542     int display = VideoDisplayIndex;
  1543     const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
  1544     const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
  1545     if (window) {
  1546         if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
  1547             return;
  1548         }
  1549         if (SDL_strcmp(window, "center") == 0) {
  1550             center = window;
  1551         }
  1552     }
  1553     if (center) {
  1554         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1555         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1556     }
  1557 }
  1558 
  1559 #if SANITY_CHECK_THIS_CODE
  1560 static void
  1561 ClearVideoSurface()
  1562 {
  1563     if (ShadowSurface) {
  1564         SDL20_FillRect(ShadowSurface, NULL,
  1565             SDL20_MapRGB(ShadowSurface->format, 0, 0, 0));
  1566     }
  1567     SDL20_FillRect(WindowSurface, NULL, 0);
  1568     SDL20_UpdateWindowSurface(VideoWindow20);
  1569 }
  1570 #endif
  1571 
  1572 static void
  1573 SetupScreenSaver(int flags12)
  1574 {
  1575     const char *env;
  1576     SDL_bool allow_screensaver;
  1577 
  1578     /* Allow environment override of screensaver disable */
  1579     env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  1580     if (env) {
  1581         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  1582     } else if (flags12 & SDL12_FULLSCREEN) {
  1583         allow_screensaver = SDL_FALSE;
  1584     } else {
  1585         allow_screensaver = SDL_TRUE;
  1586     }
  1587     if (allow_screensaver) {
  1588         SDL20_EnableScreenSaver();
  1589     } else {
  1590         SDL20_DisableScreenSaver();
  1591     }
  1592 }
  1593 
  1594 #if SANITY_CHECK_THIS_CODE
  1595 static int
  1596 ResizeVideoMode(int width, int height, int bpp, Uint32 flags12)
  1597 {
  1598     int w, h;
  1599 
  1600     /* We can't resize something we don't have... */
  1601     if (!VideoSurface) {
  1602         return -1;
  1603     }
  1604 
  1605     /* We probably have to recreate the window in fullscreen mode */
  1606     if (flags12 & SDL12_FULLSCREEN) {
  1607         return -1;
  1608     }
  1609 
  1610     /* I don't think there's any change we can gracefully make in flags */
  1611     if (flags12 != VideoFlags) {
  1612         return -1;
  1613     }
  1614     if (bpp != VideoSurface->format->BitsPerPixel) {
  1615         return -1;
  1616     }
  1617 
  1618     /* Resize the window */
  1619     SDL20_GetWindowSize(VideoWindow20, &w, &h);
  1620     if (w != width || h != height) {
  1621         SDL20_SetWindowSize(VideoWindow20, width, height);
  1622     }
  1623 
  1624     /* If we're in OpenGL mode, just resize the stub surface and we're done! */
  1625     if (flags12 & SDL12_OPENGL) {
  1626         VideoSurface->w = width;
  1627         VideoSurface->h = height;
  1628         return 0;
  1629     }
  1630 
  1631     WindowSurface = SDL20_GetWindowSurface(VideoWindow20);
  1632     if (!WindowSurface) {
  1633         return -1;
  1634     }
  1635     if (VideoSurface->format != WindowSurface->format) {
  1636         return -1;
  1637     }
  1638     VideoSurface->w = width;
  1639     VideoSurface->h = height;
  1640     VideoSurface->pixels = WindowSurface->pixels;
  1641     VideoSurface->pitch = WindowSurface->pitch;
  1642     SDL20_SetClipRect(VideoSurface, NULL);
  1643 
  1644     if (ShadowSurface) {
  1645         ShadowSurface->w = width;
  1646         ShadowSurface->h = height;
  1647         ShadowSurface->pitch = SDL20_CalculatePitch(ShadowSurface);
  1648         ShadowSurface->pixels =
  1649             SDL20_realloc(ShadowSurface->pixels,
  1650                         ShadowSurface->h * ShadowSurface->pitch);
  1651         SDL20_SetClipRect(ShadowSurface, NULL);
  1652         SDL20_InvalidateMap(ShadowSurface->map);
  1653     } else {
  1654         PublicSurface = VideoSurface;
  1655     }
  1656 
  1657     ClearVideoSurface();
  1658 
  1659     return 0;
  1660 }
  1661 
  1662 DECLSPEC SDL12_Surface * SDLCALL
  1663 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  1664 {
  1665     SDL_DisplayMode desktop_mode;
  1666     int display = VideoDisplayIndex;
  1667     int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
  1668     int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
  1669     int window_w;
  1670     int window_h;
  1671     Uint32 window_flags20;
  1672     Uint32 surface_flags12;
  1673 
  1674     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1675         if (SDL_Init(SDL12_INIT_VIDEO | SDL12_INIT_NOPARACHUTE) < 0) {
  1676             return NULL;
  1677         }
  1678     }
  1679 
  1680     SDL20_GetDesktopDisplayMode(display, &desktop_mode);
  1681 
  1682     if (width == 0) {
  1683         width = desktop_mode.w;
  1684     }
  1685     if (height == 0) {
  1686         height = desktop_mode.h;
  1687     }
  1688     if (bpp == 0) {
  1689         bpp = SDL_BITSPERPIXEL(desktop_mode.format);
  1690     }
  1691 
  1692     /* See if we can simply resize the existing window and surface */
  1693     if (ResizeVideoMode(width, height, bpp, flags12) == 0) {
  1694         return PublicSurface;
  1695     }
  1696 
  1697     /* Destroy existing window */
  1698     PublicSurface = NULL;
  1699     if (ShadowSurface) {
  1700         ShadowSurface->flags &= ~SDL_DONTFREE;
  1701         SDL20_FreeSurface(ShadowSurface);
  1702         ShadowSurface = NULL;
  1703     }
  1704     if (VideoSurface) {
  1705         VideoSurface->flags &= ~SDL_DONTFREE;
  1706         SDL20_FreeSurface(VideoSurface);
  1707         VideoSurface = NULL;
  1708     }
  1709     if (VideoContext) {
  1710         /* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
  1711         SDL20_GL_DeleteContext(VideoContext);
  1712         VideoContext = NULL;
  1713     }
  1714     if (VideoWindow20) {
  1715         SDL20_GetWindowPosition(VideoWindow20, &window_x, &window_y);
  1716         SDL20_DestroyWindow(VideoWindow20);
  1717     }
  1718 
  1719     /* Create a new window */
  1720     window_flags20 = SDL_WINDOW_SHOWN;
  1721     if (flags12 & SDL12_FULLSCREEN) {
  1722         window_flags20 |= SDL_WINDOW_FULLSCREEN;
  1723     }
  1724     if (flags12 & SDL12_OPENGL) {
  1725         window_flags20 |= SDL_WINDOW_OPENGL;
  1726     }
  1727     if (flags12 & SDL12_RESIZABLE) {
  1728         window_flags20 |= SDL_WINDOW_RESIZABLE;
  1729     }
  1730     if (flags12 & SDL12_NOFRAME) {
  1731         window_flags20 |= SDL_WINDOW_BORDERLESS;
  1732     }
  1733     GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
  1734     VideoWindow20 =
  1735         SDL20_CreateWindow(WindowTitle, window_x, window_y, width, height,
  1736                          window_flags20);
  1737     if (!VideoWindow20) {
  1738         return NULL;
  1739     }
  1740     SDL20_SetWindowIcon(VideoWindow20, VideoIcon);
  1741 
  1742     SetupScreenSaver(flags12);
  1743 
  1744     window_flags20 = SDL20_GetWindowFlags(VideoWindow20);
  1745     surface_flags12 = 0;
  1746     if (window_flags20 & SDL_WINDOW_FULLSCREEN) {
  1747         surface_flags12 |= SDL_FULLSCREEN;
  1748     }
  1749     if ((window_flags & SDL_WINDOW_OPENGL) && (flags12 & SDL_OPENGL)) {
  1750         surface_flags12 |= SDL_OPENGL;
  1751     }
  1752     if (window_flags & SDL_WINDOW_RESIZABLE) {
  1753         surface_flags12 |= SDL_RESIZABLE;
  1754     }
  1755     if (window_flags & SDL_WINDOW_BORDERLESS) {
  1756         surface_flags12 |= SDL_NOFRAME;
  1757     }
  1758 
  1759     VideoFlags = flags12;
  1760 
  1761     /* If we're in OpenGL mode, just create a stub surface and we're done! */
  1762     if (flags12 & SDL_OPENGL) {
  1763 
  1764         VideoContext = SDL_GL_CreateContext(VideoWindow20);
  1765         if (!VideoContext) {
  1766             return NULL;
  1767         }
  1768         if (SDL_GL_MakeCurrent(VideoWindow20, VideoContext) < 0) {
  1769             return NULL;
  1770         }
  1771 
  1772         SDL20_GL_SetSwapInterval(SwapInterval);  /* don't care if this fails. */
  1773 
  1774         VideoSurface =
  1775             SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
  1776         if (!VideoSurface) {
  1777             return NULL;
  1778         }
  1779         VideoSurface->flags |= surface_flags12;
  1780         PublicSurface = VideoSurface;
  1781         return PublicSurface;
  1782     }
  1783 
  1784     /* Create the screen surface */
  1785     WindowSurface = SDL_GetWindowSurface(VideoWindow20);
  1786     if (!WindowSurface) {
  1787         return NULL;
  1788     }
  1789 
  1790     /* Center the public surface in the window surface */
  1791     SDL_GetWindowSize(VideoWindow20, &window_w, &window_h);
  1792     VideoViewport.x = (window_w - width)/2;
  1793     VideoViewport.y = (window_h - height)/2;
  1794     VideoViewport.w = width;
  1795     VideoViewport.h = height;
  1796 
  1797     VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
  1798     VideoSurface->flags |= surface_flags12;
  1799     VideoSurface->flags |= SDL12_DONTFREE;
  1800     SDL_FreeFormat(VideoSurface->format);
  1801     VideoSurface->format = WindowSurface->format;
  1802     VideoSurface->format->refcount++;
  1803     VideoSurface->w = width;
  1804     VideoSurface->h = height;
  1805     VideoSurface->pitch = WindowSurface->pitch;
  1806     VideoSurface->pixels = (void *)((Uint8 *)WindowSurface->pixels +
  1807         VideoViewport.y * VideoSurface->pitch +
  1808         VideoViewport.x  * VideoSurface->format->BytesPerPixel);
  1809     SDL_SetClipRect(VideoSurface, NULL);
  1810 
  1811     /* Create a shadow surface if necessary */
  1812     if ((bpp != VideoSurface->format->BitsPerPixel)
  1813         && !(flags12 & SDL12_ANYFORMAT)) {
  1814         ShadowSurface =
  1815             SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
  1816         if (!ShadowSurface) {
  1817             return NULL;
  1818         }
  1819         ShadowSurface->flags |= surface_flags12;
  1820         ShadowSurface->flags |= SDL12_DONTFREE;
  1821 
  1822         /* 8-bit ShadowSurface surfaces report that they have exclusive palette */
  1823         if (ShadowSurface->format->palette) {
  1824             ShadowSurface->flags |= SDL12_HWPALETTE;
  1825             SDL_DitherColors(ShadowSurface->format->palette->colors,
  1826                              ShadowSurface->format->BitsPerPixel);
  1827         }
  1828         SDL_FillRect(ShadowSurface, NULL,
  1829             SDL_MapRGB(ShadowSurface->format, 0, 0, 0));
  1830     }
  1831     PublicSurface =
  1832         (ShadowSurface ? ShadowSurface : VideoSurface);
  1833 
  1834     ClearVideoSurface();
  1835 
  1836     /* We're finally done! */
  1837     return PublicSurface;
  1838 }
  1839 
  1840 DECLSPEC SDL12_Surface * SDLCALL
  1841 SDL_GetVideoSurface(void)
  1842 {
  1843     return PublicSurface;
  1844 }
  1845 
  1846 DECLSPEC int SDLCALL
  1847 SDL_SetAlpha(SDL12_Surface * surface, Uint32 flag, Uint8 value)
  1848 {
  1849     if (flag & SDL_SRCALPHA) {
  1850         /* According to the docs, value is ignored for alpha surfaces */
  1851         if (surface->format->Amask) {
  1852             value = 0xFF;
  1853         }
  1854         SDL_SetSurfaceAlphaMod(surface, value);
  1855         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
  1856     } else {
  1857         SDL_SetSurfaceAlphaMod(surface, 0xFF);
  1858         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
  1859     }
  1860     SDL_SetSurfaceRLE(surface, (flag & SDL_RLEACCEL));
  1861 
  1862     return 0;
  1863 }
  1864 
  1865 DECLSPEC SDL12_Surface * SDLCALL
  1866 SDL_DisplayFormat(SDL12_Surface *surface12)
  1867 {
  1868     SDL12_PixelFormat *format;
  1869 
  1870     if (!PublicSurface) {
  1871         SDL20_SetError("No video mode has been set");
  1872         return NULL;
  1873     }
  1874     format = PublicSurface->format;
  1875 
  1876     /* Set the flags appropriate for copying to display surface */
  1877     return SDL_ConvertSurface(surface, format, SDL12_RLEACCEL);
  1878 }
  1879 
  1880 DECLSPEC SDL12_Surface * SDLCALL
  1881 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  1882 {
  1883     SDL_PixelFormat *vf;
  1884     SDL_PixelFormat *format;
  1885     SDL_Surface *converted;
  1886     /* default to ARGB8888 */
  1887     Uint32 amask = 0xff000000;
  1888     Uint32 rmask = 0x00ff0000;
  1889     Uint32 gmask = 0x0000ff00;
  1890     Uint32 bmask = 0x000000ff;
  1891 
  1892     if (!PublicSurface) {
  1893         SDL20_SetError("No video mode has been set");
  1894         return NULL;
  1895     }
  1896     vf = PublicSurface->format;
  1897 
  1898     switch (vf->BytesPerPixel) {
  1899     case 2:
  1900         /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
  1901            For anything else (like ARGB4444) it doesn't matter
  1902            since we have no special code for it anyway */
  1903         if ((vf->Rmask == 0x1f) &&
  1904             (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
  1905             rmask = 0xff;
  1906             bmask = 0xff0000;
  1907         }
  1908         break;
  1909 
  1910     case 3:
  1911     case 4:
  1912         /* Keep the video format, as long as the high 8 bits are
  1913            unused or alpha */
  1914         if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) {
  1915             rmask = 0xff;
  1916             bmask = 0xff0000;
  1917         }
  1918         break;
  1919 
  1920     default:
  1921         /* We have no other optimised formats right now. When/if a new
  1922            optimised alpha format is written, add the converter here */
  1923         break;
  1924     }
  1925     format = SDL_AllocFormat(SDL_MasksToPixelFormatEnum(32, rmask,
  1926                                                             gmask,
  1927                                                             bmask,
  1928                                                             amask));
  1929     if (!format) {
  1930         return NULL;
  1931     }
  1932     converted = SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
  1933     SDL_FreeFormat(format);
  1934     return converted;
  1935 }
  1936 
  1937 DECLSPEC void SDLCALL
  1938 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
  1939 {
  1940     int i;
  1941 
  1942     if (screen == ShadowSurface) {
  1943         for (i = 0; i < numrects; ++i) {
  1944             SDL_BlitSurface(ShadowSurface, &rects[i], VideoSurface,
  1945                             &rects[i]);
  1946         }
  1947 
  1948         /* Fall through to video surface update */
  1949         screen = VideoSurface;
  1950     }
  1951     if (screen == VideoSurface) {
  1952         if (VideoViewport.x || VideoViewport.y) {
  1953             SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
  1954             SDL_Rect *stackrect;
  1955             const SDL_Rect *rect;
  1956             
  1957             /* Offset all the rectangles before updating */
  1958             for (i = 0; i < numrects; ++i) {
  1959                 rect = &rects[i];
  1960                 stackrect = &stackrects[i];
  1961                 stackrect->x = VideoViewport.x + rect->x;
  1962                 stackrect->y = VideoViewport.y + rect->y;
  1963                 stackrect->w = rect->w;
  1964                 stackrect->h = rect->h;
  1965             }
  1966             SDL_UpdateWindowSurfaceRects(VideoWindow20, stackrects, numrects);
  1967             SDL_stack_free(stackrects);
  1968         } else {
  1969             SDL_UpdateWindowSurfaceRects(VideoWindow20, rects, numrects);
  1970         }
  1971     }
  1972 }
  1973 #endif
  1974 
  1975 DECLSPEC void SDLCALL
  1976 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  1977 {
  1978     if (screen12) {
  1979         SDL_Rect rect;
  1980         rect.x = (int) x;
  1981         rect.y = (int) y;
  1982         rect.w = (int) (w ? w : screen12->w);
  1983         rect.h = (int) (h ? h : screen12->h);
  1984         SDL_UpdateRects(screen12, 1, &rect);
  1985     }
  1986 }
  1987 
  1988 DECLSPEC int SDLCALL
  1989 SDL_Flip(SDL12_Surface *screen12)
  1990 {
  1991     SDL_UpdateRect(screen12, 0, 0, 0, 0);
  1992     return 0;
  1993 }
  1994 
  1995 DECLSPEC void SDLCALL
  1996 SDL_WM_SetCaption(const char *title, const char *icon)
  1997 {
  1998     if (WindowTitle) {
  1999         SDL20_free(WindowTitle);
  2000     }
  2001     if (WindowIconTitle) {
  2002         SDL20_free(WindowIconTitle);
  2003     }
  2004     WindowTitle = title ? SDL_strdup(title) : NULL;
  2005     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  2006     SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  2007 }
  2008 
  2009 DECLSPEC void SDLCALL
  2010 SDL_WM_GetCaption(const char **title, const char **icon)
  2011 {
  2012     if (title) {
  2013         *title = WindowTitle;
  2014     }
  2015     if (icon) {
  2016         *icon = WindowIconTitle;
  2017     }
  2018 }
  2019 
  2020 #if SANITY_CHECK_THIS_CODE
  2021 DECLSPEC void SDLCALL
  2022 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
  2023 {
  2024     // !!! FIXME: free previous icon?
  2025     VideoIcon = icon;
  2026     ++VideoIcon->refcount;
  2027 }
  2028 #endif
  2029 
  2030 DECLSPEC int SDLCALL
  2031 SDL_WM_IconifyWindow(void)
  2032 {
  2033     SDL20_MinimizeWindow(VideoWindow20);
  2034     return 0;
  2035 }
  2036 
  2037 #if SANITY_CHECK_THIS_CODE
  2038 DECLSPEC int SDLCALL
  2039 SDL_WM_ToggleFullScreen(SDL_Surface *surface)
  2040 {
  2041     int length;
  2042     void *pixels;
  2043     Uint8 *src, *dst;
  2044     int row;
  2045     int window_w;
  2046     int window_h;
  2047 
  2048     if (!PublicSurface) {
  2049         SDL20_SetError("SDL_SetVideoMode() hasn't been called");
  2050         return 0;
  2051     }
  2052 
  2053     /* Copy the old bits out */
  2054     length = PublicSurface->w * PublicSurface->format->BytesPerPixel;
  2055     pixels = SDL20_malloc(PublicSurface->h * length);
  2056     if (pixels && PublicSurface->pixels) {
  2057         src = (Uint8*)PublicSurface->pixels;
  2058         dst = (Uint8*)pixels;
  2059         for (row = 0; row < PublicSurface->h; ++row) {
  2060             SDL_memcpy(dst, src, length);
  2061             src += PublicSurface->pitch;
  2062             dst += length;
  2063         }
  2064     }
  2065 
  2066     /* Do the physical mode switch */
  2067     if (SDL20_GetWindowFlags(VideoWindow20) & SDL_WINDOW_FULLSCREEN) {
  2068         if (SDL20_SetWindowFullscreen(VideoWindow20, 0) < 0) {
  2069             return 0;
  2070         }
  2071         PublicSurface->flags &= ~SDL_FULLSCREEN;
  2072     } else {
  2073         if (SDL20_SetWindowFullscreen(VideoWindow20, 1) < 0) {
  2074             return 0;
  2075         }
  2076         PublicSurface->flags |= SDL_FULLSCREEN;
  2077     }
  2078 
  2079     /* Recreate the screen surface */
  2080     WindowSurface = SDL20_GetWindowSurface(VideoWindow20);
  2081     if (!WindowSurface) {
  2082         /* We're totally hosed... */
  2083         return 0;
  2084     }
  2085 
  2086     /* Center the public surface in the window surface */
  2087     SDL_GetWindowSize(VideoWindow20, &window_w, &window_h);
  2088     VideoViewport.x = (window_w - VideoSurface->w)/2;
  2089     VideoViewport.y = (window_h - VideoSurface->h)/2;
  2090     VideoViewport.w = VideoSurface->w;
  2091     VideoViewport.h = VideoSurface->h;
  2092 
  2093     /* Do some shuffling behind the application's back if format changes */
  2094     if (VideoSurface->format->format != WindowSurface->format->format) {
  2095         if (ShadowSurface) {
  2096             if (ShadowSurface->format->format == WindowSurface->format->format) {
  2097                 /* Whee!  We don't need a shadow surface anymore! */
  2098                 VideoSurface->flags &= ~SDL_DONTFREE;
  2099                 SDL_FreeSurface(VideoSurface);
  2100                 SDL20_free(ShadowSurface->pixels);
  2101                 VideoSurface = ShadowSurface;
  2102                 VideoSurface->flags |= SDL_PREALLOC;
  2103                 ShadowSurface = NULL;
  2104             } else {
  2105                 /* No problem, just change the video surface format */
  2106                 SDL_FreeFormat(VideoSurface->format);
  2107                 VideoSurface->format = WindowSurface->format;
  2108                 VideoSurface->format->refcount++;
  2109                 SDL_InvalidateMap(ShadowSurface->map);
  2110             }
  2111         } else {
  2112             /* We can make the video surface the shadow surface */
  2113             ShadowSurface = VideoSurface;
  2114             ShadowSurface->pitch = SDL_CalculatePitch(ShadowSurface);
  2115             ShadowSurface->pixels = SDL20_malloc(ShadowSurface->h * ShadowSurface->pitch);
  2116             if (!ShadowSurface->pixels) {
  2117                 /* Uh oh, we're hosed */
  2118                 ShadowSurface = NULL;
  2119                 return 0;
  2120             }
  2121             ShadowSurface->flags &= ~SDL_PREALLOC;
  2122 
  2123             VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
  2124             VideoSurface->flags = ShadowSurface->flags;
  2125             VideoSurface->flags |= SDL_PREALLOC;
  2126             SDL_FreeFormat(VideoSurface->format);
  2127             VideoSurface->format = WindowSurface->format;
  2128             VideoSurface->format->refcount++;
  2129             VideoSurface->w = ShadowSurface->w;
  2130             VideoSurface->h = ShadowSurface->h;
  2131         }
  2132     }
  2133 
  2134     /* Update the video surface */
  2135     VideoSurface->pitch = WindowSurface->pitch;
  2136     VideoSurface->pixels = (void *)((Uint8 *)WindowSurface->pixels +
  2137         VideoViewport.y * VideoSurface->pitch +
  2138         VideoViewport.x  * VideoSurface->format->BytesPerPixel);
  2139     SDL_SetClipRect(VideoSurface, NULL);
  2140 
  2141     /* Copy the old bits back */
  2142     if (pixels) {
  2143         src = (Uint8*)pixels;
  2144         dst = (Uint8*)PublicSurface->pixels;
  2145         for (row = 0; row < PublicSurface->h; ++row) {
  2146             SDL_memcpy(dst, src, length);
  2147             src += length;
  2148             dst += PublicSurface->pitch;
  2149         }
  2150         SDL_Flip(PublicSurface);
  2151         SDL20_free(pixels);
  2152     }
  2153 
  2154     /* We're done! */
  2155     return 1;
  2156 }
  2157 #endif
  2158 
  2159 typedef enum
  2160 {
  2161     SDL12_GRAB_QUERY = -1,
  2162     SDL12_GRAB_OFF = 0,
  2163     SDL12_GRAB_ON = 1
  2164 } SDL12_GrabMode;
  2165 
  2166 DECLSPEC SDL12_GrabMode SDLCALL
  2167 SDL_WM_GrabInput(SDL12_GrabMode mode)
  2168 {
  2169     if (mode != SDL12_GRAB_QUERY) {
  2170         SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
  2171     }
  2172     return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  2173 }
  2174 
  2175 DECLSPEC void SDLCALL
  2176 SDL_WarpMouse(Uint16 x, Uint16 y)
  2177 {
  2178     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  2179 }
  2180 
  2181 DECLSPEC Uint8 SDLCALL
  2182 SDL_GetAppState(void)
  2183 {
  2184     Uint8 state12 = 0;
  2185     Uint32 flags20 = 0;
  2186 
  2187     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  2188     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  2189         state12 |= SDL12_APPACTIVE;
  2190     }
  2191     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  2192         state12 |= SDL12_APPINPUTFOCUS;
  2193     }
  2194     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  2195         state12 |= SDL12_APPMOUSEFOCUS;
  2196     }
  2197     return state12;
  2198 }
  2199 
  2200 #if SANITY_CHECK_THIS_CODE
  2201 DECLSPEC int SDLCALL
  2202 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
  2203                int firstcolor, int ncolors)
  2204 {
  2205     return SDL_SetColors(surface12, colors, firstcolor, ncolors);
  2206 }
  2207 
  2208 DECLSPEC int SDLCALL
  2209 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
  2210               int ncolors)
  2211 {
  2212     if (SDL20_SetPaletteColors
  2213         (surface->format->palette, colors, firstcolor, ncolors) == 0) {
  2214         return 1;
  2215     } else {
  2216         return 0;
  2217     }
  2218 }
  2219 
  2220 DECLSPEC int SDLCALL
  2221 SDL_GetWMInfo(SDL_SysWMinfo * info)
  2222 {
  2223     return SDL_GetWindowWMInfo(VideoWindow20, info);
  2224 }
  2225 
  2226 struct private_yuvhwdata
  2227 {
  2228     SDL_SW_YUVTexture *texture;
  2229     SDL_Surface *display;
  2230     Uint32 display_format;
  2231 };
  2232 
  2233 DECLSPEC SDL_Overlay * SDLCALL
  2234 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
  2235 {
  2236     SDL_Overlay *overlay;
  2237     Uint32 texture_format;
  2238     SDL_SW_YUVTexture *texture;
  2239 
  2240     if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
  2241         SDL20_SetError("YUV overlays are not supported in OpenGL mode");
  2242         return NULL;
  2243     }
  2244 
  2245     if (display != PublicSurface) {
  2246         SDL20_SetError("YUV display is only supported on the screen surface");
  2247         return NULL;
  2248     }
  2249 
  2250     switch (format) {
  2251     case SDL_YV12_OVERLAY:
  2252         texture_format = SDL_PIXELFORMAT_YV12;
  2253         break;
  2254     case SDL_IYUV_OVERLAY:
  2255         texture_format = SDL_PIXELFORMAT_IYUV;
  2256         break;
  2257     case SDL_YUY2_OVERLAY:
  2258         texture_format = SDL_PIXELFORMAT_YUY2;
  2259         break;
  2260     case SDL_UYVY_OVERLAY:
  2261         texture_format = SDL_PIXELFORMAT_UYVY;
  2262         break;
  2263     case SDL_YVYU_OVERLAY:
  2264         texture_format = SDL_PIXELFORMAT_YVYU;
  2265         break;
  2266     default:
  2267         SDL20_SetError("Unknown YUV format");
  2268         return NULL;
  2269     }
  2270 
  2271     overlay = (SDL_Overlay *) SDL20_malloc(sizeof(*overlay));
  2272     if (!overlay) {
  2273         SDL20_OutOfMemory();
  2274         return NULL;
  2275     }
  2276     SDL20_zerop(overlay);
  2277 
  2278     overlay->hwdata =
  2279         (struct private_yuvhwdata *) SDL20_malloc(sizeof(*overlay->hwdata));
  2280     if (!overlay->hwdata) {
  2281         SDL20_free(overlay);
  2282         SDL20_OutOfMemory();
  2283         return NULL;
  2284     }
  2285 
  2286     texture = SDL_SW_CreateYUVTexture(texture_format, w, h);
  2287     if (!texture) {
  2288         SDL20_free(overlay->hwdata);
  2289         SDL20_free(overlay);
  2290         return NULL;
  2291     }
  2292     overlay->hwdata->texture = texture;
  2293     overlay->hwdata->display = NULL;
  2294     overlay->hwdata->display_format = SDL_PIXELFORMAT_UNKNOWN;
  2295 
  2296     overlay->format = format;
  2297     overlay->w = w;
  2298     overlay->h = h;
  2299     if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
  2300         overlay->planes = 3;
  2301     } else {
  2302         overlay->planes = 1;
  2303     }
  2304     overlay->pitches = texture->pitches;
  2305     overlay->pixels = texture->planes;
  2306 
  2307     return overlay;
  2308 }
  2309 
  2310 DECLSPEC int SDLCALL
  2311 SDL_LockYUVOverlay(SDL_Overlay * overlay)
  2312 {
  2313     SDL_Rect rect;
  2314     void *pixels;
  2315     int pitch;
  2316 
  2317     if (!overlay) {
  2318         return SDL20_SetError("Passed a NULL overlay");
  2319     }
  2320 
  2321     rect.x = 0;
  2322     rect.y = 0;
  2323     rect.w = overlay->w;
  2324     rect.h = overlay->h;
  2325 
  2326     if (SDL_SW_LockYUVTexture(overlay->hwdata->texture, &rect, &pixels, &pitch) < 0) {
  2327         return -1;
  2328     }
  2329 
  2330     overlay->pixels[0] = (Uint8 *) pixels;
  2331     overlay->pitches[0] = pitch;
  2332     switch (overlay->format) {
  2333     case SDL_YV12_OVERLAY:
  2334     case SDL_IYUV_OVERLAY:
  2335         overlay->pitches[1] = pitch / 2;
  2336         overlay->pitches[2] = pitch / 2;
  2337         overlay->pixels[1] =
  2338             overlay->pixels[0] + overlay->pitches[0] * overlay->h;
  2339         overlay->pixels[2] =
  2340             overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
  2341         break;
  2342     case SDL_YUY2_OVERLAY:
  2343     case SDL_UYVY_OVERLAY:
  2344     case SDL_YVYU_OVERLAY:
  2345         break;
  2346     }
  2347     return 0;
  2348 }
  2349 
  2350 DECLSPEC void SDLCALL
  2351 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
  2352 {
  2353     if (!overlay) {
  2354         return;
  2355     }
  2356 
  2357     SDL_SW_UnlockYUVTexture(overlay->hwdata->texture);
  2358 }
  2359 
  2360 DECLSPEC int SDLCALL
  2361 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
  2362 {
  2363     SDL_Surface *display;
  2364     SDL_Rect src_rect;
  2365     SDL_Rect dst_rect;
  2366     void *pixels;
  2367 
  2368     if (!overlay || !dstrect) {
  2369         return SDL20_SetError("Passed a NULL overlay or dstrect");
  2370     }
  2371 
  2372     display = overlay->hwdata->display;
  2373     if (display != VideoSurface) {
  2374         overlay->hwdata->display = display = VideoSurface;
  2375         overlay->hwdata->display_format = SDL_MasksToPixelFormatEnum(
  2376                                                 display->format->BitsPerPixel,
  2377                                                 display->format->Rmask,
  2378                                                 display->format->Gmask,
  2379                                                 display->format->Bmask,
  2380                                                 display->format->Amask);
  2381     }
  2382 
  2383     src_rect.x = 0;
  2384     src_rect.y = 0;
  2385     src_rect.w = overlay->w;
  2386     src_rect.h = overlay->h;
  2387 
  2388     if (!SDL_IntersectRect(&display->clip_rect, dstrect, &dst_rect)) {
  2389         return 0;
  2390     }
  2391      
  2392     pixels = (void *)((Uint8 *)display->pixels +
  2393                         dst_rect.y * display->pitch +
  2394                         dst_rect.x * display->format->BytesPerPixel);
  2395 
  2396     if (SDL_SW_CopyYUVToRGB(overlay->hwdata->texture, &src_rect,
  2397                             overlay->hwdata->display_format,
  2398                             dst_rect.w, dst_rect.h,
  2399                             pixels, display->pitch) < 0) {
  2400         return -1;
  2401     }
  2402     SDL_UpdateWindowSurface(VideoWindow20);
  2403     return 0;
  2404 }
  2405 
  2406 DECLSPEC void SDLCALL
  2407 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
  2408 {
  2409     if (!overlay) {
  2410         return;
  2411     }
  2412     if (overlay->hwdata) {
  2413         if (overlay->hwdata->texture) {
  2414             SDL_SW_DestroyYUVTexture(overlay->hwdata->texture);
  2415         }
  2416         SDL20_free(overlay->hwdata);
  2417     }
  2418     SDL20_free(overlay);
  2419 }
  2420 #endif
  2421 
  2422 DECLSPEC int SDLCALL
  2423 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  2424 {
  2425     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2426         return SDL20_SetError("Unknown GL attribute");
  2427 
  2428     /* swap control was moved out of this API, everything else lines up. */
  2429     if (attr == SDL12_GL_SWAP_CONTROL)
  2430     {
  2431         SwapInterval = value;
  2432         return 0;
  2433     }
  2434 
  2435     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  2436 }
  2437 
  2438 DECLSPEC int SDLCALL
  2439 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  2440 {
  2441     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2442         return SDL20_SetError("Unknown GL attribute");
  2443 
  2444     /* swap control was moved out of this API, everything else lines up. */
  2445     if (attr == SDL12_GL_SWAP_CONTROL)
  2446     {
  2447         *value = SDL20_GL_GetSwapInterval();
  2448         return 0;
  2449     }
  2450 
  2451     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  2452 }
  2453 
  2454 
  2455 DECLSPEC void SDLCALL
  2456 SDL_GL_SwapBuffers(void)
  2457 {
  2458     if (VideoWindow20)
  2459         SDL20_GL_SwapWindow(VideoWindow20);
  2460 }
  2461 
  2462 DECLSPEC int SDLCALL
  2463 SDL_SetGamma(float red, float green, float blue)
  2464 {
  2465     Uint16 red_ramp[256];
  2466     Uint16 green_ramp[256];
  2467     Uint16 blue_ramp[256];
  2468 
  2469     SDL20_CalculateGammaRamp(red, red_ramp);
  2470     if (green == red) {
  2471         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2472     } else {
  2473         SDL20_CalculateGammaRamp(green, green_ramp);
  2474     }
  2475     if (blue == red) {
  2476         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2477     } else if (blue == green) {
  2478         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  2479     } else {
  2480         SDL20_CalculateGammaRamp(blue, blue_ramp);
  2481     }
  2482     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2483 }
  2484 
  2485 DECLSPEC int SDLCALL
  2486 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  2487 {
  2488     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2489 }
  2490 
  2491 DECLSPEC int SDLCALL
  2492 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  2493 {
  2494     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  2495 }
  2496 
  2497 DECLSPEC int SDLCALL
  2498 SDL_EnableKeyRepeat(int delay, int interval)
  2499 {
  2500     return 0;
  2501 }
  2502 
  2503 DECLSPEC void SDLCALL
  2504 SDL_GetKeyRepeat(int *delay, int *interval)
  2505 {
  2506     if (delay) {
  2507         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  2508     }
  2509     if (interval) {
  2510         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  2511     }
  2512 }
  2513 
  2514 #if SANITY_CHECK_THIS_CODE
  2515 DECLSPEC int SDLCALL
  2516 SDL_EnableUNICODE(int enable)
  2517 {
  2518     int previous = EnabledUnicode;
  2519 
  2520     switch (enable) {
  2521     case 1:
  2522         EnabledUnicode = 1;
  2523         SDL20_StartTextInput();
  2524         break;
  2525     case 0:
  2526         EnabledUnicode = 0;
  2527         SDL20_StopTextInput();
  2528         break;
  2529     }
  2530     return previous;
  2531 }
  2532 #endif
  2533 
  2534 static Uint32
  2535 SetTimerOld_Callback(Uint32 interval, void* param)
  2536 {
  2537     return ((SDL12_TimerCallback)param)(interval);
  2538 }
  2539 
  2540 DECLSPEC int SDLCALL
  2541 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  2542 {
  2543     static SDL_TimerID compat_timer;
  2544 
  2545     if (compat_timer) {
  2546         SDL20_RemoveTimer(compat_timer);
  2547         compat_timer = 0;
  2548     }
  2549 
  2550     if (interval && callback) {
  2551         compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
  2552         if (!compat_timer) {
  2553             return -1;
  2554         }
  2555     }
  2556     return 0;
  2557 }
  2558 
  2559 DECLSPEC int SDLCALL
  2560 SDL_putenv(const char *_var)
  2561 {
  2562     char *ptr = NULL;
  2563     char *var = SDL20_strdup(_var);
  2564     if (var == NULL) {
  2565         return -1;  /* we don't set errno. */
  2566     }
  2567 
  2568     ptr = SDL20_strchr(var, '=');
  2569     if (ptr == NULL) {
  2570         SDL20_free(var);
  2571         return -1;
  2572     }
  2573 
  2574     *ptr = '\0';  /* split the string into name and value. */
  2575     SDL20_setenv(var, ptr + 1, 1);
  2576     SDL20_free(var);
  2577     return 0;
  2578 }
  2579 
  2580 
  2581 
  2582 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2583 
  2584 typedef void *SDL12_CD;  /* close enough.  :) */
  2585 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2586 
  2587 DECLSPEC int SDLCALL
  2588 SDL_CDNumDrives(void)
  2589 {
  2590     return 0;  /* !!! FIXME: should return -1 without SDL_INIT_CDROM */
  2591 }
  2592 
  2593 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  2594 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  2595 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2596 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  2597 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  2598 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2599 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2600 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2601 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2602 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
  2603 
  2604 
  2605 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  2606 DECLSPEC SDL_Thread * SDLCALL
  2607 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  2608 {
  2609     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  2610 }
  2611 #else
  2612 DECLSPEC SDL_Thread * SDLCALL
  2613 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  2614 {
  2615     return SDL20_CreateThread(fn, NULL, data);
  2616 }
  2617 #endif
  2618 
  2619 
  2620 /* !!! FIXME: Removed from 2.0; do nothing. We can't even report failure. */
  2621 DECLSPEC void SDLCALL SDL_KillThread(SDL_Thread *thread) {}
  2622 
  2623 /* This changed from an opaque pointer to an int in 2.0. */
  2624 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2625 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2626 
  2627 
  2628 DECLSPEC SDL12_TimerID SDLCALL
  2629 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  2630 {
  2631     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2632 }
  2633 
  2634 DECLSPEC SDL_bool SDLCALL
  2635 SDL_RemoveTimer(SDL12_TimerID id)
  2636 {
  2637     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  2638 }
  2639 
  2640 
  2641 typedef struct SDL12_RWops {
  2642     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  2643     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  2644     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  2645     int (SDLCALL *close)(struct SDL12_RWops *context);
  2646     Uint32 type;
  2647     void *padding[8];
  2648     SDL_RWops *rwops20;
  2649 } SDL12_RWops;
  2650 
  2651 
  2652 DECLSPEC SDL12_RWops * SDLCALL
  2653 SDL_AllocRW(void)
  2654 {
  2655     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  2656     if (!rwops)
  2657         SDL20_OutOfMemory();
  2658     return rwops;
  2659 }
  2660 
  2661 DECLSPEC void SDLCALL
  2662 SDL_FreeRW(SDL12_RWops *rwops12)
  2663 {
  2664     SDL20_free(rwops12);
  2665 }
  2666 
  2667 static int SDLCALL
  2668 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  2669 {
  2670     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  2671 }
  2672 
  2673 static int SDLCALL
  2674 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  2675 {
  2676     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  2677 }
  2678 
  2679 static int SDLCALL
  2680 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  2681 {
  2682     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  2683 }
  2684 
  2685 static int SDLCALL
  2686 RWops20to12_close(struct SDL12_RWops *rwops12)
  2687 {
  2688     int rc = 0;
  2689     if (rwops12)
  2690     {
  2691         rc = rwops12->rwops20->close(rwops12->rwops20);
  2692         if (rc == 0)
  2693             SDL_FreeRW(rwops12);
  2694     }
  2695     return rc;
  2696 }
  2697 
  2698 static SDL12_RWops *
  2699 RWops20to12(SDL_RWops *rwops20)
  2700 {
  2701     SDL12_RWops *rwops12;
  2702 
  2703     if (!rwops20)
  2704         return NULL;
  2705 
  2706     rwops12 = SDL_AllocRW();
  2707     if (!rwops12)
  2708         return NULL;
  2709 
  2710     SDL20_zerop(rwops12);
  2711     rwops12->type = rwops20->type;
  2712     rwops12->rwops20 = rwops20;
  2713     rwops12->seek = RWops20to12_seek;
  2714     rwops12->read = RWops20to12_read;
  2715     rwops12->write = RWops20to12_write;
  2716     rwops12->close = RWops20to12_close;
  2717 
  2718     return rwops12;
  2719 }
  2720 
  2721 DECLSPEC SDL12_RWops * SDLCALL
  2722 SDL_RWFromFile(const char *file, const char *mode)
  2723 {
  2724     return RWops20to12(SDL20_RWFromFile(file, mode));
  2725 }
  2726 
  2727 DECLSPEC SDL12_RWops * SDLCALL
  2728 SDL_RWFromFP(FILE *io, int autoclose)
  2729 {
  2730     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  2731 }
  2732 
  2733 DECLSPEC SDL12_RWops * SDLCALL
  2734 SDL_RWFromMem(void *mem, int size)
  2735 {
  2736     return RWops20to12(SDL20_RWFromMem(mem, size));
  2737 }
  2738 
  2739 DECLSPEC SDL12_RWops * SDLCALL
  2740 SDL_RWFromConstMem(const void *mem, int size)
  2741 {
  2742     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  2743 }
  2744 
  2745 #define READ_AND_BYTESWAP(endian, bits) \
  2746     DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  2747         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  2748         return SDL_Swap##endian##bits(val); \
  2749     }
  2750 
  2751 READ_AND_BYTESWAP(LE,16)
  2752 READ_AND_BYTESWAP(BE,16)
  2753 READ_AND_BYTESWAP(LE,32)
  2754 READ_AND_BYTESWAP(BE,32)
  2755 READ_AND_BYTESWAP(LE,64)
  2756 READ_AND_BYTESWAP(BE,64)
  2757 #undef READ_AND_BYTESWAP
  2758 
  2759 #define BYTESWAP_AND_WRITE(endian, bits) \
  2760     DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  2761         val = SDL_Swap##endian##bits(val); \
  2762         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  2763     }
  2764 BYTESWAP_AND_WRITE(LE,16)
  2765 BYTESWAP_AND_WRITE(BE,16)
  2766 BYTESWAP_AND_WRITE(LE,32)
  2767 BYTESWAP_AND_WRITE(BE,32)
  2768 BYTESWAP_AND_WRITE(LE,64)
  2769 BYTESWAP_AND_WRITE(BE,64)
  2770 #undef BYTESWAP_AND_WRITE
  2771 
  2772 
  2773 static Sint64 SDLCALL
  2774 RWops12to20_size(struct SDL_RWops *rwops20)
  2775 {
  2776     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2777     int size = rwops20->hidden.unknown.data2;
  2778     int pos;
  2779 
  2780     if (size != -1)
  2781         return size;
  2782 
  2783     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  2784     if (pos == -1)
  2785         return -1;
  2786 
  2787     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  2788     if (size == -1)
  2789         return -1;
  2790 
  2791     rwops12->seek(rwops12, pos, SEEK_SET);  /* !!! FIXME: and if this fails? */
  2792     rwops20->hidden.unknown.data2 = size;
  2793     return size;
  2794 }
  2795 
  2796 static Sint64 SDLCALL
  2797 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  2798 {
  2799     /* !!! FIXME: fail if (offset) is too big */
  2800     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2801     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  2802 }
  2803 
  2804 static size_t SDLCALL
  2805 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  2806 {
  2807     /* !!! FIXME: fail if (size) or (maxnum) is too big */
  2808     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2809     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  2810 }
  2811 
  2812 static size_t SDLCALL
  2813 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  2814 {
  2815     /* !!! FIXME: fail if (size) or (maxnum) is too big */
  2816     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2817     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  2818 }
  2819 
  2820 static int SDLCALL
  2821 RWops12to20_close(struct SDL_RWops *rwops20)
  2822 {
  2823     int rc = 0;
  2824     if (rwops20)
  2825     {
  2826         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2827         rc = rwops12->close(rwops12);
  2828         if (rc == 0)
  2829             SDL20_FreeRW(rwops20);
  2830     }
  2831     return rc;
  2832 }
  2833 
  2834 static SDL_RWops *
  2835 RWops12to20(SDL12_RWops *rwops12)
  2836 {
  2837     SDL_RWops *rwops20;
  2838 
  2839     if (!rwops12)
  2840         return NULL;
  2841 
  2842     rwops20 = SDL20_AllocRW();
  2843     if (!rwops20)
  2844         return NULL;
  2845 
  2846     SDL20_zerop(rwops20);
  2847     rwops20->type = rwops12->type;
  2848     rwops20->hidden.unknown.data1 = rwops12;
  2849     rwops20->hidden.unknown.data2 = -1;  /* cached size of stream */
  2850     rwops20->size = RWops12to20_size;
  2851     rwops20->seek = RWops12to20_seek;
  2852     rwops20->read = RWops12to20_read;
  2853     rwops20->write = RWops12to20_write;
  2854     rwops20->close = RWops12to20_close;
  2855     return rwops20;
  2856 }
  2857 
  2858 DECLSPEC SDL12_Surface * SDLCALL
  2859 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  2860 {
  2861     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2862     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  2863     SDL12_Surface *surface12 = Surface20to12(surface20);
  2864     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2865         SDL20_FreeRW(rwops20);
  2866     if ((!surface12) && (surface20))
  2867         SDL20_FreeSurface(surface20);
  2868     return surface12;
  2869 }
  2870 
  2871 DECLSPEC int SDLCALL
  2872 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  2873 {
  2874     // !!! FIXME: wrap surface.
  2875     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2876     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  2877     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2878         SDL20_FreeRW(rwops20);
  2879     return retval;
  2880 }
  2881 
  2882 DECLSPEC SDL_AudioSpec * SDLCALL
  2883 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  2884                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  2885 {
  2886     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2887     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  2888     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2889         SDL20_FreeRW(rwops20);
  2890     return retval;
  2891 }
  2892 
  2893 /* vi: set ts=4 sw=4 expandtab: */