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