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