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