src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 31 Mar 2013 22:19:24 -0400
changeset 18 221a624a97fb
parent 17 473158daa1de
child 19 bb548168a73b
permissions -rw-r--r--
A bunch of work on the event subsystem.

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