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