src/SDL_compat.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 09 Mar 2011 15:51:51 -0800
changeset 5460 43582fccdc0d
parent 5313 7a569d09a682
child 5466 006883d5fa51
permissions -rw-r--r--
Removed newlines from log messages
Slightly speeded up event history processing each frame
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2011 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* This file contains functions for backwards compatibility with SDL 1.2 */
    25 
    26 #include "SDL.h"
    27 #include "SDL_syswm.h"
    28 
    29 #include "video/SDL_sysvideo.h"
    30 #include "video/SDL_pixels_c.h"
    31 #include "render/SDL_yuv_sw_c.h"
    32 
    33 
    34 static SDL_Window *SDL_VideoWindow = NULL;
    35 static SDL_Surface *SDL_WindowSurface = NULL;
    36 static SDL_Surface *SDL_VideoSurface = NULL;
    37 static SDL_Surface *SDL_ShadowSurface = NULL;
    38 static SDL_Surface *SDL_PublicSurface = NULL;
    39 static SDL_GLContext *SDL_VideoContext = NULL;
    40 static Uint32 SDL_VideoFlags = 0;
    41 static SDL_Rect SDL_VideoViewport;
    42 static char *wm_title = NULL;
    43 static SDL_Surface *SDL_VideoIcon;
    44 static int SDL_enabled_UNICODE = 0;
    45 
    46 const char *
    47 SDL_AudioDriverName(char *namebuf, int maxlen)
    48 {
    49     const char *name = SDL_GetCurrentAudioDriver();
    50     if (name) {
    51         if (namebuf) {
    52             SDL_strlcpy(namebuf, name, maxlen);
    53             return namebuf;
    54         } else {
    55             return name;
    56         }
    57     }
    58     return NULL;
    59 }
    60 
    61 const char *
    62 SDL_VideoDriverName(char *namebuf, int maxlen)
    63 {
    64     const char *name = SDL_GetCurrentVideoDriver();
    65     if (name) {
    66         if (namebuf) {
    67             SDL_strlcpy(namebuf, name, maxlen);
    68             return namebuf;
    69         } else {
    70             return name;
    71         }
    72     }
    73     return NULL;
    74 }
    75 
    76 static int
    77 GetVideoDisplay()
    78 {
    79     const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
    80     if ( !variable ) {
    81         variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
    82     }
    83     if ( variable ) {
    84         return SDL_atoi(variable);
    85     } else {
    86         return 0;
    87     }
    88 }
    89 
    90 const SDL_VideoInfo *
    91 SDL_GetVideoInfo(void)
    92 {
    93     static SDL_VideoInfo info;
    94     SDL_DisplayMode mode;
    95 
    96     /* Memory leak, compatibility code, who cares? */
    97     if (!info.vfmt && SDL_GetDesktopDisplayMode(GetVideoDisplay(), &mode) == 0) {
    98         info.vfmt = SDL_AllocFormat(mode.format);
    99         info.current_w = mode.w;
   100         info.current_h = mode.h;
   101     }
   102     return &info;
   103 }
   104 
   105 int
   106 SDL_VideoModeOK(int width, int height, int bpp, Uint32 flags)
   107 {
   108     int i, actual_bpp = 0;
   109 
   110     if (!SDL_GetVideoDevice()) {
   111         return 0;
   112     }
   113 
   114     if (!(flags & SDL_FULLSCREEN)) {
   115         SDL_DisplayMode mode;
   116         SDL_GetDesktopDisplayMode(GetVideoDisplay(), &mode);
   117         return SDL_BITSPERPIXEL(mode.format);
   118     }
   119 
   120     for (i = 0; i < SDL_GetNumDisplayModes(GetVideoDisplay()); ++i) {
   121         SDL_DisplayMode mode;
   122         SDL_GetDisplayMode(GetVideoDisplay(), i, &mode);
   123         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
   124             if (!mode.format) {
   125                 return bpp;
   126             }
   127             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
   128                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
   129             }
   130         }
   131     }
   132     return actual_bpp;
   133 }
   134 
   135 SDL_Rect **
   136 SDL_ListModes(const SDL_PixelFormat * format, Uint32 flags)
   137 {
   138     int i, nmodes;
   139     SDL_Rect **modes;
   140 
   141     if (!SDL_GetVideoDevice()) {
   142         return NULL;
   143     }
   144 
   145     if (!(flags & SDL_FULLSCREEN)) {
   146         return (SDL_Rect **) (-1);
   147     }
   148 
   149     if (!format) {
   150         format = SDL_GetVideoInfo()->vfmt;
   151     }
   152 
   153     /* Memory leak, but this is a compatibility function, who cares? */
   154     nmodes = 0;
   155     modes = NULL;
   156     for (i = 0; i < SDL_GetNumDisplayModes(GetVideoDisplay()); ++i) {
   157         SDL_DisplayMode mode;
   158         int bpp;
   159 
   160         SDL_GetDisplayMode(GetVideoDisplay(), i, &mode);
   161         if (!mode.w || !mode.h) {
   162             return (SDL_Rect **) (-1);
   163         }
   164         
   165         /* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
   166         if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
   167             bpp = SDL_BITSPERPIXEL(mode.format);
   168         } else {
   169             bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
   170         }
   171 
   172         if (bpp != format->BitsPerPixel) {
   173             continue;
   174         }
   175         if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
   176             && modes[nmodes - 1]->h == mode.h) {
   177             continue;
   178         }
   179 
   180         modes = SDL_realloc(modes, (nmodes + 2) * sizeof(*modes));
   181         if (!modes) {
   182             return NULL;
   183         }
   184         modes[nmodes] = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect));
   185         if (!modes[nmodes]) {
   186             return NULL;
   187         }
   188         modes[nmodes]->x = 0;
   189         modes[nmodes]->y = 0;
   190         modes[nmodes]->w = mode.w;
   191         modes[nmodes]->h = mode.h;
   192         ++nmodes;
   193     }
   194     if (modes) {
   195         modes[nmodes] = NULL;
   196     }
   197     return modes;
   198 }
   199 
   200 static int
   201 SDL_CompatEventFilter(void *userdata, SDL_Event * event)
   202 {
   203     SDL_Event fake;
   204 
   205     switch (event->type) {
   206     case SDL_WINDOWEVENT:
   207         switch (event->window.event) {
   208         case SDL_WINDOWEVENT_EXPOSED:
   209             if (!SDL_HasEvent(SDL_VIDEOEXPOSE)) {
   210                 fake.type = SDL_VIDEOEXPOSE;
   211                 SDL_PushEvent(&fake);
   212             }
   213             break;
   214         case SDL_WINDOWEVENT_RESIZED:
   215             SDL_FlushEvent(SDL_VIDEORESIZE);
   216             /* We don't want to expose that the window width and height will
   217                be different if we don't get the desired fullscreen mode.
   218             */
   219             if (SDL_VideoWindow && !(SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN)) {
   220                 fake.type = SDL_VIDEORESIZE;
   221                 fake.resize.w = event->window.data1;
   222                 fake.resize.h = event->window.data2;
   223                 SDL_PushEvent(&fake);
   224             }
   225             break;
   226         case SDL_WINDOWEVENT_MINIMIZED:
   227             fake.type = SDL_ACTIVEEVENT;
   228             fake.active.gain = 0;
   229             fake.active.state = SDL_APPACTIVE;
   230             SDL_PushEvent(&fake);
   231             break;
   232         case SDL_WINDOWEVENT_RESTORED:
   233             fake.type = SDL_ACTIVEEVENT;
   234             fake.active.gain = 1;
   235             fake.active.state = SDL_APPACTIVE;
   236             SDL_PushEvent(&fake);
   237             break;
   238         case SDL_WINDOWEVENT_ENTER:
   239             fake.type = SDL_ACTIVEEVENT;
   240             fake.active.gain = 1;
   241             fake.active.state = SDL_APPMOUSEFOCUS;
   242             SDL_PushEvent(&fake);
   243             break;
   244         case SDL_WINDOWEVENT_LEAVE:
   245             fake.type = SDL_ACTIVEEVENT;
   246             fake.active.gain = 0;
   247             fake.active.state = SDL_APPMOUSEFOCUS;
   248             SDL_PushEvent(&fake);
   249             break;
   250         case SDL_WINDOWEVENT_FOCUS_GAINED:
   251             fake.type = SDL_ACTIVEEVENT;
   252             fake.active.gain = 1;
   253             fake.active.state = SDL_APPINPUTFOCUS;
   254             SDL_PushEvent(&fake);
   255             break;
   256         case SDL_WINDOWEVENT_FOCUS_LOST:
   257             fake.type = SDL_ACTIVEEVENT;
   258             fake.active.gain = 0;
   259             fake.active.state = SDL_APPINPUTFOCUS;
   260             SDL_PushEvent(&fake);
   261             break;
   262         case SDL_WINDOWEVENT_CLOSE:
   263             fake.type = SDL_QUIT;
   264             SDL_PushEvent(&fake);
   265             break;
   266         }
   267     case SDL_KEYDOWN:
   268     case SDL_KEYUP:
   269         {
   270             Uint32 unicode = 0;
   271             if (event->key.type == SDL_KEYDOWN && event->key.keysym.sym < 256) {
   272                 unicode = event->key.keysym.sym;
   273                 if (unicode >= 'a' && unicode <= 'z') {
   274                     int shifted = !!(event->key.keysym.mod & KMOD_SHIFT);
   275                     int capslock = !!(event->key.keysym.mod & KMOD_CAPS);
   276                     if ((shifted ^ capslock) != 0) {
   277                         unicode = SDL_toupper(unicode);
   278                     }
   279                 }
   280             }
   281             if (unicode) {
   282                 event->key.keysym.unicode = unicode;
   283             }
   284             break;
   285         }
   286     case SDL_TEXTINPUT:
   287         {
   288             /* FIXME: Generate an old style key repeat event if needed */
   289             //printf("TEXTINPUT: '%s'\n", event->text.text);
   290             break;
   291         }
   292     case SDL_MOUSEMOTION:
   293         {
   294             event->motion.x -= SDL_VideoViewport.x;
   295             event->motion.y -= SDL_VideoViewport.y;
   296             break;
   297         }
   298     case SDL_MOUSEBUTTONDOWN:
   299     case SDL_MOUSEBUTTONUP:
   300         {
   301             event->button.x -= SDL_VideoViewport.x;
   302             event->button.y -= SDL_VideoViewport.y;
   303             break;
   304         }
   305     case SDL_MOUSEWHEEL:
   306         {
   307             Uint8 button;
   308             int x, y;
   309 
   310             if (event->wheel.y == 0) {
   311                 break;
   312             }
   313 
   314             SDL_GetMouseState(&x, &y);
   315 
   316             if (event->wheel.y > 0) {
   317                 button = SDL_BUTTON_WHEELUP;
   318             } else {
   319                 button = SDL_BUTTON_WHEELDOWN;
   320             }
   321 
   322             fake.button.button = button;
   323             fake.button.x = x;
   324             fake.button.y = y;
   325             fake.button.windowID = event->wheel.windowID;
   326 
   327             fake.type = SDL_MOUSEBUTTONDOWN;
   328             fake.button.state = SDL_PRESSED;
   329             SDL_PushEvent(&fake);
   330 
   331             fake.type = SDL_MOUSEBUTTONUP;
   332             fake.button.state = SDL_RELEASED;
   333             SDL_PushEvent(&fake);
   334             break;
   335         }
   336 
   337     }
   338     return 1;
   339 }
   340 
   341 static void
   342 GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
   343 {
   344     int display = GetVideoDisplay();
   345     const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
   346     const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
   347     if (window) {
   348         if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
   349             return;
   350         }
   351         if (SDL_strcmp(window, "center") == 0) {
   352             center = window;
   353         }
   354     }
   355     if (center) {
   356         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
   357         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
   358     }
   359 }
   360 
   361 static void
   362 ClearVideoSurface()
   363 {
   364     if (SDL_ShadowSurface) {
   365         SDL_FillRect(SDL_ShadowSurface, NULL,
   366             SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
   367     }
   368     SDL_FillRect(SDL_WindowSurface, NULL, 0);
   369     SDL_UpdateWindowSurface(SDL_VideoWindow);
   370 }
   371 
   372 static void
   373 SetupScreenSaver(int flags)
   374 {
   375     const char *env;
   376     SDL_bool allow_screensaver;
   377 
   378     /* Allow environment override of screensaver disable */
   379     env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
   380     if (env) {
   381         allow_screensaver = SDL_atoi(env) ? SDL_TRUE : SDL_FALSE;
   382     } else if (flags & SDL_FULLSCREEN) {
   383         allow_screensaver = SDL_FALSE;
   384     } else {
   385         allow_screensaver = SDL_TRUE;
   386     }
   387     if (allow_screensaver) {
   388         SDL_EnableScreenSaver();
   389     } else {
   390         SDL_DisableScreenSaver();
   391     }
   392 }
   393 
   394 static int
   395 SDL_ResizeVideoMode(int width, int height, int bpp, Uint32 flags)
   396 {
   397     int w, h;
   398 
   399     /* We can't resize something we don't have... */
   400     if (!SDL_VideoSurface) {
   401         return -1;
   402     }
   403 
   404     /* We probably have to recreate the window in fullscreen mode */
   405     if (flags & SDL_FULLSCREEN) {
   406         return -1;
   407     }
   408 
   409     /* I don't think there's any change we can gracefully make in flags */
   410     if (flags != SDL_VideoFlags) {
   411         return -1;
   412     }
   413     if (bpp != SDL_VideoSurface->format->BitsPerPixel) {
   414         return -1;
   415     }
   416 
   417     /* Resize the window */
   418     SDL_GetWindowSize(SDL_VideoWindow, &w, &h);
   419     if (w != width || h != height) {
   420         SDL_SetWindowSize(SDL_VideoWindow, width, height);
   421     }
   422 
   423     /* If we're in OpenGL mode, just resize the stub surface and we're done! */
   424     if (flags & SDL_OPENGL) {
   425         SDL_VideoSurface->w = width;
   426         SDL_VideoSurface->h = height;
   427         return 0;
   428     }
   429 
   430     SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
   431     if (!SDL_WindowSurface) {
   432         return -1;
   433     }
   434     if (SDL_VideoSurface->format != SDL_WindowSurface->format) {
   435         return -1;
   436     }
   437     SDL_VideoSurface->w = width;
   438     SDL_VideoSurface->h = height;
   439     SDL_VideoSurface->pixels = SDL_WindowSurface->pixels;
   440     SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
   441     SDL_SetClipRect(SDL_VideoSurface, NULL);
   442 
   443     if (SDL_ShadowSurface) {
   444         SDL_ShadowSurface->w = width;
   445         SDL_ShadowSurface->h = height;
   446         SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
   447         SDL_ShadowSurface->pixels =
   448             SDL_realloc(SDL_ShadowSurface->pixels,
   449                         SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
   450         SDL_SetClipRect(SDL_ShadowSurface, NULL);
   451         SDL_InvalidateMap(SDL_ShadowSurface->map);
   452     } else {
   453         SDL_PublicSurface = SDL_VideoSurface;
   454     }
   455 
   456     ClearVideoSurface();
   457 
   458     return 0;
   459 }
   460 
   461 SDL_Surface *
   462 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
   463 {
   464     SDL_DisplayMode desktop_mode;
   465     int display = GetVideoDisplay();
   466     int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
   467     int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
   468     int window_w;
   469     int window_h;
   470     Uint32 window_flags;
   471     Uint32 surface_flags;
   472 
   473     if (!SDL_GetVideoDevice()) {
   474         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
   475             return NULL;
   476         }
   477     }
   478 
   479     SDL_GetDesktopDisplayMode(display, &desktop_mode);
   480 
   481     if (width == 0) {
   482         width = desktop_mode.w;
   483     }
   484     if (height == 0) {
   485         height = desktop_mode.h;
   486     }
   487     if (bpp == 0) {
   488         bpp = SDL_BITSPERPIXEL(desktop_mode.format);
   489     }
   490 
   491     /* See if we can simply resize the existing window and surface */
   492     if (SDL_ResizeVideoMode(width, height, bpp, flags) == 0) {
   493         return SDL_PublicSurface;
   494     }
   495 
   496     /* Destroy existing window */
   497     SDL_PublicSurface = NULL;
   498     if (SDL_ShadowSurface) {
   499         SDL_ShadowSurface->flags &= ~SDL_DONTFREE;
   500         SDL_FreeSurface(SDL_ShadowSurface);
   501         SDL_ShadowSurface = NULL;
   502     }
   503     if (SDL_VideoSurface) {
   504         SDL_VideoSurface->flags &= ~SDL_DONTFREE;
   505         SDL_FreeSurface(SDL_VideoSurface);
   506         SDL_VideoSurface = NULL;
   507     }
   508     if (SDL_VideoContext) {
   509         /* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
   510         SDL_GL_DeleteContext(SDL_VideoContext);
   511         SDL_VideoContext = NULL;
   512     }
   513     if (SDL_VideoWindow) {
   514         SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y);
   515         SDL_DestroyWindow(SDL_VideoWindow);
   516     }
   517 
   518     /* Set up the event filter */
   519     if (!SDL_GetEventFilter(NULL, NULL)) {
   520         SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
   521     }
   522 
   523     /* Create a new window */
   524     window_flags = SDL_WINDOW_SHOWN;
   525     if (flags & SDL_FULLSCREEN) {
   526         window_flags |= SDL_WINDOW_FULLSCREEN;
   527     }
   528     if (flags & SDL_OPENGL) {
   529         window_flags |= SDL_WINDOW_OPENGL;
   530     }
   531     if (flags & SDL_RESIZABLE) {
   532         window_flags |= SDL_WINDOW_RESIZABLE;
   533     }
   534     if (flags & SDL_NOFRAME) {
   535         window_flags |= SDL_WINDOW_BORDERLESS;
   536     }
   537     GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
   538     SDL_VideoWindow =
   539         SDL_CreateWindow(wm_title, window_x, window_y, width, height,
   540                          window_flags);
   541     if (!SDL_VideoWindow) {
   542         return NULL;
   543     }
   544     SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon);
   545 
   546     SetupScreenSaver(flags);
   547 
   548     window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
   549     surface_flags = 0;
   550     if (window_flags & SDL_WINDOW_FULLSCREEN) {
   551         surface_flags |= SDL_FULLSCREEN;
   552     }
   553     if ((window_flags & SDL_WINDOW_OPENGL) && (flags & SDL_OPENGL)) {
   554         surface_flags |= SDL_OPENGL;
   555     }
   556     if (window_flags & SDL_WINDOW_RESIZABLE) {
   557         surface_flags |= SDL_RESIZABLE;
   558     }
   559     if (window_flags & SDL_WINDOW_BORDERLESS) {
   560         surface_flags |= SDL_NOFRAME;
   561     }
   562 
   563     SDL_VideoFlags = flags;
   564 
   565     /* If we're in OpenGL mode, just create a stub surface and we're done! */
   566     if (flags & SDL_OPENGL) {
   567         SDL_VideoContext = SDL_GL_CreateContext(SDL_VideoWindow);
   568         if (!SDL_VideoContext) {
   569             return NULL;
   570         }
   571         if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) {
   572             return NULL;
   573         }
   574         SDL_VideoSurface =
   575             SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
   576         if (!SDL_VideoSurface) {
   577             return NULL;
   578         }
   579         SDL_VideoSurface->flags |= surface_flags;
   580         SDL_PublicSurface = SDL_VideoSurface;
   581         return SDL_PublicSurface;
   582     }
   583 
   584     /* Create the screen surface */
   585     SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
   586     if (!SDL_WindowSurface) {
   587         return NULL;
   588     }
   589 
   590     /* Center the public surface in the window surface */
   591     SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
   592     SDL_VideoViewport.x = (window_w - width)/2;
   593     SDL_VideoViewport.y = (window_h - height)/2;
   594     SDL_VideoViewport.w = width;
   595     SDL_VideoViewport.h = height;
   596 
   597     SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
   598     SDL_VideoSurface->flags |= surface_flags;
   599     SDL_VideoSurface->flags |= SDL_DONTFREE;
   600     SDL_FreeFormat(SDL_VideoSurface->format);
   601     SDL_VideoSurface->format = SDL_WindowSurface->format;
   602     SDL_VideoSurface->format->refcount++;
   603     SDL_VideoSurface->w = width;
   604     SDL_VideoSurface->h = height;
   605     SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
   606     SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
   607         SDL_VideoViewport.y * SDL_VideoSurface->pitch +
   608         SDL_VideoViewport.x  * SDL_VideoSurface->format->BytesPerPixel);
   609     SDL_SetClipRect(SDL_VideoSurface, NULL);
   610 
   611     /* Create a shadow surface if necessary */
   612     if ((bpp != SDL_VideoSurface->format->BitsPerPixel)
   613         && !(flags & SDL_ANYFORMAT)) {
   614         SDL_ShadowSurface =
   615             SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
   616         if (!SDL_ShadowSurface) {
   617             return NULL;
   618         }
   619         SDL_ShadowSurface->flags |= surface_flags;
   620         SDL_ShadowSurface->flags |= SDL_DONTFREE;
   621 
   622         /* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
   623         if (SDL_ShadowSurface->format->palette) {
   624             SDL_ShadowSurface->flags |= SDL_HWPALETTE;
   625             SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
   626                              SDL_ShadowSurface->format->BitsPerPixel);
   627         }
   628         SDL_FillRect(SDL_ShadowSurface, NULL,
   629             SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
   630     }
   631     SDL_PublicSurface =
   632         (SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface);
   633 
   634     ClearVideoSurface();
   635 
   636     /* We're finally done! */
   637     return SDL_PublicSurface;
   638 }
   639 
   640 SDL_Surface *
   641 SDL_GetVideoSurface(void)
   642 {
   643     return SDL_PublicSurface;
   644 }
   645 
   646 int
   647 SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value)
   648 {
   649     if (flag & SDL_SRCALPHA) {
   650         /* According to the docs, value is ignored for alpha surfaces */
   651         if (surface->format->Amask) {
   652             value = 0xFF;
   653         }
   654         SDL_SetSurfaceAlphaMod(surface, value);
   655         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
   656     } else {
   657         SDL_SetSurfaceAlphaMod(surface, 0xFF);
   658         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
   659     }
   660     SDL_SetSurfaceRLE(surface, (flag & SDL_RLEACCEL));
   661 
   662     return 0;
   663 }
   664 
   665 SDL_Surface *
   666 SDL_DisplayFormat(SDL_Surface * surface)
   667 {
   668     SDL_PixelFormat *format;
   669 
   670     if (!SDL_PublicSurface) {
   671         SDL_SetError("No video mode has been set");
   672         return NULL;
   673     }
   674     format = SDL_PublicSurface->format;
   675 
   676     /* Set the flags appropriate for copying to display surface */
   677     return SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
   678 }
   679 
   680 SDL_Surface *
   681 SDL_DisplayFormatAlpha(SDL_Surface * surface)
   682 {
   683     SDL_PixelFormat *vf;
   684     SDL_PixelFormat *format;
   685     SDL_Surface *converted;
   686     /* default to ARGB8888 */
   687     Uint32 amask = 0xff000000;
   688     Uint32 rmask = 0x00ff0000;
   689     Uint32 gmask = 0x0000ff00;
   690     Uint32 bmask = 0x000000ff;
   691 
   692     if (!SDL_PublicSurface) {
   693         SDL_SetError("No video mode has been set");
   694         return NULL;
   695     }
   696     vf = SDL_PublicSurface->format;
   697 
   698     switch (vf->BytesPerPixel) {
   699     case 2:
   700         /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
   701            For anything else (like ARGB4444) it doesn't matter
   702            since we have no special code for it anyway */
   703         if ((vf->Rmask == 0x1f) &&
   704             (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
   705             rmask = 0xff;
   706             bmask = 0xff0000;
   707         }
   708         break;
   709 
   710     case 3:
   711     case 4:
   712         /* Keep the video format, as long as the high 8 bits are
   713            unused or alpha */
   714         if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) {
   715             rmask = 0xff;
   716             bmask = 0xff0000;
   717         }
   718         break;
   719 
   720     default:
   721         /* We have no other optimised formats right now. When/if a new
   722            optimised alpha format is written, add the converter here */
   723         break;
   724     }
   725     format = SDL_AllocFormat(SDL_MasksToPixelFormatEnum(32, rmask,
   726                                                             gmask,
   727                                                             bmask,
   728                                                             amask));
   729     if (!format) {
   730         return NULL;
   731     }
   732     converted = SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
   733     SDL_FreeFormat(format);
   734     return converted;
   735 }
   736 
   737 int
   738 SDL_Flip(SDL_Surface * screen)
   739 {
   740     SDL_UpdateRect(screen, 0, 0, 0, 0);
   741     return 0;
   742 }
   743 
   744 void
   745 SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
   746 {
   747     if (screen) {
   748         SDL_Rect rect;
   749 
   750         /* Fill the rectangle */
   751         rect.x = (int) x;
   752         rect.y = (int) y;
   753         rect.w = (int) (w ? w : screen->w);
   754         rect.h = (int) (h ? h : screen->h);
   755         SDL_UpdateRects(screen, 1, &rect);
   756     }
   757 }
   758 
   759 void
   760 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
   761 {
   762     int i;
   763 
   764     if (screen == SDL_ShadowSurface) {
   765         for (i = 0; i < numrects; ++i) {
   766             SDL_LowerBlit(SDL_ShadowSurface, &rects[i], SDL_VideoSurface,
   767                           &rects[i]);
   768         }
   769 
   770         /* Fall through to video surface update */
   771         screen = SDL_VideoSurface;
   772     }
   773     if (screen == SDL_VideoSurface) {
   774         if (SDL_VideoViewport.x || SDL_VideoViewport.y) {
   775             SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
   776             SDL_Rect *stackrect;
   777             const SDL_Rect *rect;
   778             
   779             /* Offset all the rectangles before updating */
   780             for (i = 0; i < numrects; ++i) {
   781                 rect = &rects[i];
   782                 stackrect = &stackrects[i];
   783                 stackrect->x = SDL_VideoViewport.x + rect->x;
   784                 stackrect->y = SDL_VideoViewport.y + rect->y;
   785                 stackrect->w = rect->w;
   786                 stackrect->h = rect->h;
   787             }
   788             SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, stackrects, numrects);
   789             SDL_stack_free(stackrects);
   790         } else {
   791             SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, rects, numrects);
   792         }
   793     }
   794 }
   795 
   796 void
   797 SDL_WM_SetCaption(const char *title, const char *icon)
   798 {
   799     if (wm_title) {
   800         SDL_free(wm_title);
   801     }
   802     if (title) {
   803         wm_title = SDL_strdup(title);
   804     } else {
   805         wm_title = NULL;
   806     }
   807     SDL_SetWindowTitle(SDL_VideoWindow, wm_title);
   808 }
   809 
   810 void
   811 SDL_WM_GetCaption(const char **title, const char **icon)
   812 {
   813     if (title) {
   814         *title = wm_title;
   815     }
   816     if (icon) {
   817         *icon = "";
   818     }
   819 }
   820 
   821 void
   822 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
   823 {
   824     SDL_VideoIcon = icon;
   825 }
   826 
   827 int
   828 SDL_WM_IconifyWindow(void)
   829 {
   830     SDL_MinimizeWindow(SDL_VideoWindow);
   831     return 0;
   832 }
   833 
   834 int
   835 SDL_WM_ToggleFullScreen(SDL_Surface * surface)
   836 {
   837     int length;
   838     void *pixels;
   839     Uint8 *src, *dst;
   840     int row;
   841     int window_w;
   842     int window_h;
   843 
   844     if (!SDL_PublicSurface) {
   845         SDL_SetError("SDL_SetVideoMode() hasn't been called");
   846         return 0;
   847     }
   848 
   849     /* Copy the old bits out */
   850     length = SDL_PublicSurface->w * SDL_PublicSurface->format->BytesPerPixel;
   851     pixels = SDL_malloc(SDL_PublicSurface->h * length);
   852     if (pixels) {
   853         src = (Uint8*)SDL_PublicSurface->pixels;
   854         dst = (Uint8*)pixels;
   855         for (row = 0; row < SDL_PublicSurface->h; ++row) {
   856             SDL_memcpy(dst, src, length);
   857             src += SDL_PublicSurface->pitch;
   858             dst += length;
   859         }
   860     }
   861 
   862     /* Do the physical mode switch */
   863     if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) {
   864         if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) {
   865             return 0;
   866         }
   867         SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
   868     } else {
   869         if (SDL_SetWindowFullscreen(SDL_VideoWindow, 1) < 0) {
   870             return 0;
   871         }
   872         SDL_PublicSurface->flags |= SDL_FULLSCREEN;
   873     }
   874 
   875     /* Recreate the screen surface */
   876     SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
   877     if (!SDL_WindowSurface) {
   878         /* We're totally hosed... */
   879         return 0;
   880     }
   881 
   882     /* Center the public surface in the window surface */
   883     SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
   884     SDL_VideoViewport.x = (window_w - SDL_VideoSurface->w)/2;
   885     SDL_VideoViewport.y = (window_h - SDL_VideoSurface->h)/2;
   886     SDL_VideoViewport.w = SDL_VideoSurface->w;
   887     SDL_VideoViewport.h = SDL_VideoSurface->h;
   888 
   889     /* Do some shuffling behind the application's back if format changes */
   890     if (SDL_VideoSurface->format->format != SDL_WindowSurface->format->format) {
   891         if (SDL_ShadowSurface) {
   892             if (SDL_ShadowSurface->format->format == SDL_WindowSurface->format->format) {
   893                 /* Whee!  We don't need a shadow surface anymore! */
   894                 SDL_VideoSurface->flags &= ~SDL_DONTFREE;
   895                 SDL_FreeSurface(SDL_VideoSurface);
   896                 SDL_free(SDL_ShadowSurface->pixels);
   897                 SDL_VideoSurface = SDL_ShadowSurface;
   898                 SDL_VideoSurface->flags |= SDL_PREALLOC;
   899                 SDL_ShadowSurface = NULL;
   900             } else {
   901                 /* No problem, just change the video surface format */
   902                 SDL_FreeFormat(SDL_VideoSurface->format);
   903                 SDL_VideoSurface->format = SDL_WindowSurface->format;
   904                 SDL_VideoSurface->format->refcount++;
   905                 SDL_InvalidateMap(SDL_ShadowSurface->map);
   906             }
   907         } else {
   908             /* We can make the video surface the shadow surface */
   909             SDL_ShadowSurface = SDL_VideoSurface;
   910             SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
   911             SDL_ShadowSurface->pixels = SDL_malloc(SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
   912             if (!SDL_ShadowSurface->pixels) {
   913                 /* Uh oh, we're hosed */
   914                 SDL_ShadowSurface = NULL;
   915                 return 0;
   916             }
   917             SDL_ShadowSurface->flags &= ~SDL_PREALLOC;
   918 
   919             SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
   920             SDL_VideoSurface->flags = SDL_ShadowSurface->flags;
   921             SDL_VideoSurface->flags |= SDL_PREALLOC;
   922             SDL_FreeFormat(SDL_VideoSurface->format);
   923             SDL_VideoSurface->format = SDL_WindowSurface->format;
   924             SDL_VideoSurface->format->refcount++;
   925             SDL_VideoSurface->w = SDL_ShadowSurface->w;
   926             SDL_VideoSurface->h = SDL_ShadowSurface->h;
   927         }
   928     }
   929 
   930     /* Update the video surface */
   931     SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
   932     SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
   933         SDL_VideoViewport.y * SDL_VideoSurface->pitch +
   934         SDL_VideoViewport.x  * SDL_VideoSurface->format->BytesPerPixel);
   935     SDL_SetClipRect(SDL_VideoSurface, NULL);
   936 
   937     /* Copy the old bits back */
   938     if (pixels) {
   939         src = (Uint8*)pixels;
   940         dst = (Uint8*)SDL_PublicSurface->pixels;
   941         for (row = 0; row < SDL_PublicSurface->h; ++row) {
   942             SDL_memcpy(dst, src, length);
   943             src += length;
   944             dst += SDL_PublicSurface->pitch;
   945         }
   946         SDL_Flip(SDL_PublicSurface);
   947         SDL_free(pixels);
   948     }
   949 
   950     /* We're done! */
   951     return 1;
   952 }
   953 
   954 SDL_GrabMode
   955 SDL_WM_GrabInput(SDL_GrabMode mode)
   956 {
   957     if (mode != SDL_GRAB_QUERY) {
   958         SDL_SetWindowGrab(SDL_VideoWindow, mode);
   959     }
   960     return (SDL_GrabMode) SDL_GetWindowGrab(SDL_VideoWindow);
   961 }
   962 
   963 void
   964 SDL_WarpMouse(Uint16 x, Uint16 y)
   965 {
   966     SDL_WarpMouseInWindow(SDL_VideoWindow, x, y);
   967 }
   968 
   969 Uint8
   970 SDL_GetAppState(void)
   971 {
   972     Uint8 state = 0;
   973     Uint32 flags = 0;
   974 
   975     flags = SDL_GetWindowFlags(SDL_VideoWindow);
   976     if ((flags & SDL_WINDOW_SHOWN) && !(flags & SDL_WINDOW_MINIMIZED)) {
   977         state |= SDL_APPACTIVE;
   978     }
   979     if (flags & SDL_WINDOW_INPUT_FOCUS) {
   980         state |= SDL_APPINPUTFOCUS;
   981     }
   982     if (flags & SDL_WINDOW_MOUSE_FOCUS) {
   983         state |= SDL_APPMOUSEFOCUS;
   984     }
   985     return state;
   986 }
   987 
   988 const SDL_version *
   989 SDL_Linked_Version(void)
   990 {
   991     static SDL_version version;
   992     SDL_VERSION(&version);
   993     return &version;
   994 }
   995 
   996 int
   997 SDL_SetPalette(SDL_Surface * surface, int flags, const SDL_Color * colors,
   998                int firstcolor, int ncolors)
   999 {
  1000     return SDL_SetColors(surface, colors, firstcolor, ncolors);
  1001 }
  1002 
  1003 int
  1004 SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor,
  1005               int ncolors)
  1006 {
  1007     if (SDL_SetPaletteColors
  1008         (surface->format->palette, colors, firstcolor, ncolors) == 0) {
  1009         return 1;
  1010     } else {
  1011         return 0;
  1012     }
  1013 }
  1014 
  1015 int
  1016 SDL_GetWMInfo(SDL_SysWMinfo * info)
  1017 {
  1018     return SDL_GetWindowWMInfo(SDL_VideoWindow, info);
  1019 }
  1020 
  1021 #if 0
  1022 void
  1023 SDL_MoveCursor(int x, int y)
  1024 {
  1025     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1026 
  1027     /* Erase and update the current mouse position */
  1028     if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
  1029         /* Erase and redraw mouse cursor in new position */
  1030         SDL_LockCursor();
  1031         SDL_EraseCursor(SDL_VideoSurface);
  1032         SDL_cursor->area.x = (x - SDL_cursor->hot_x);
  1033         SDL_cursor->area.y = (y - SDL_cursor->hot_y);
  1034         SDL_DrawCursor(SDL_VideoSurface);
  1035         SDL_UnlockCursor();
  1036     } else if (_this->MoveWMCursor) {
  1037         _this->MoveWMCursor(_this, x, y);
  1038     }
  1039 }
  1040 
  1041 /* Keep track of the current cursor colors */
  1042 static int palette_changed = 1;
  1043 static Uint8 pixels8[2];
  1044 
  1045 void
  1046 SDL_CursorPaletteChanged(void)
  1047 {
  1048     palette_changed = 1;
  1049 }
  1050 
  1051 void
  1052 SDL_MouseRect(SDL_Rect * area)
  1053 {
  1054     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1055     int clip_diff;
  1056 
  1057     *area = SDL_cursor->area;
  1058     if (area->x < 0) {
  1059         area->w += area->x;
  1060         area->x = 0;
  1061     }
  1062     if (area->y < 0) {
  1063         area->h += area->y;
  1064         area->y = 0;
  1065     }
  1066     clip_diff = (area->x + area->w) - SDL_VideoSurface->w;
  1067     if (clip_diff > 0) {
  1068         area->w = area->w < clip_diff ? 0 : area->w - clip_diff;
  1069     }
  1070     clip_diff = (area->y + area->h) - SDL_VideoSurface->h;
  1071     if (clip_diff > 0) {
  1072         area->h = area->h < clip_diff ? 0 : area->h - clip_diff;
  1073     }
  1074 }
  1075 
  1076 static void
  1077 SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area)
  1078 {
  1079     const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
  1080     int i, w, h;
  1081     Uint8 *data, datab;
  1082     Uint8 *mask, maskb;
  1083 
  1084     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  1085     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  1086     switch (screen->format->BytesPerPixel) {
  1087 
  1088     case 1:
  1089         {
  1090             Uint8 *dst;
  1091             int dstskip;
  1092 
  1093             if (palette_changed) {
  1094                 pixels8[0] =
  1095                     (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  1096                 pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  1097                 palette_changed = 0;
  1098             }
  1099             dst = (Uint8 *) screen->pixels +
  1100                 (SDL_cursor->area.y + area->y) * screen->pitch +
  1101                 SDL_cursor->area.x;
  1102             dstskip = screen->pitch - area->w;
  1103 
  1104             for (h = area->h; h; h--) {
  1105                 for (w = area->w / 8; w; w--) {
  1106                     maskb = *mask++;
  1107                     datab = *data++;
  1108                     for (i = 0; i < 8; ++i) {
  1109                         if (maskb & 0x80) {
  1110                             *dst = pixels8[datab >> 7];
  1111                         }
  1112                         maskb <<= 1;
  1113                         datab <<= 1;
  1114                         dst++;
  1115                     }
  1116                 }
  1117                 dst += dstskip;
  1118             }
  1119         }
  1120         break;
  1121 
  1122     case 2:
  1123         {
  1124             Uint16 *dst;
  1125             int dstskip;
  1126 
  1127             dst = (Uint16 *) screen->pixels +
  1128                 (SDL_cursor->area.y + area->y) * screen->pitch / 2 +
  1129                 SDL_cursor->area.x;
  1130             dstskip = (screen->pitch / 2) - area->w;
  1131 
  1132             for (h = area->h; h; h--) {
  1133                 for (w = area->w / 8; w; w--) {
  1134                     maskb = *mask++;
  1135                     datab = *data++;
  1136                     for (i = 0; i < 8; ++i) {
  1137                         if (maskb & 0x80) {
  1138                             *dst = (Uint16) pixels[datab >> 7];
  1139                         }
  1140                         maskb <<= 1;
  1141                         datab <<= 1;
  1142                         dst++;
  1143                     }
  1144                 }
  1145                 dst += dstskip;
  1146             }
  1147         }
  1148         break;
  1149 
  1150     case 3:
  1151         {
  1152             Uint8 *dst;
  1153             int dstskip;
  1154 
  1155             dst = (Uint8 *) screen->pixels +
  1156                 (SDL_cursor->area.y + area->y) * screen->pitch +
  1157                 SDL_cursor->area.x * 3;
  1158             dstskip = screen->pitch - area->w * 3;
  1159 
  1160             for (h = area->h; h; h--) {
  1161                 for (w = area->w / 8; w; w--) {
  1162                     maskb = *mask++;
  1163                     datab = *data++;
  1164                     for (i = 0; i < 8; ++i) {
  1165                         if (maskb & 0x80) {
  1166                             SDL_memset(dst, pixels[datab >> 7], 3);
  1167                         }
  1168                         maskb <<= 1;
  1169                         datab <<= 1;
  1170                         dst += 3;
  1171                     }
  1172                 }
  1173                 dst += dstskip;
  1174             }
  1175         }
  1176         break;
  1177 
  1178     case 4:
  1179         {
  1180             Uint32 *dst;
  1181             int dstskip;
  1182 
  1183             dst = (Uint32 *) screen->pixels +
  1184                 (SDL_cursor->area.y + area->y) * screen->pitch / 4 +
  1185                 SDL_cursor->area.x;
  1186             dstskip = (screen->pitch / 4) - area->w;
  1187 
  1188             for (h = area->h; h; h--) {
  1189                 for (w = area->w / 8; w; w--) {
  1190                     maskb = *mask++;
  1191                     datab = *data++;
  1192                     for (i = 0; i < 8; ++i) {
  1193                         if (maskb & 0x80) {
  1194                             *dst = pixels[datab >> 7];
  1195                         }
  1196                         maskb <<= 1;
  1197                         datab <<= 1;
  1198                         dst++;
  1199                     }
  1200                 }
  1201                 dst += dstskip;
  1202             }
  1203         }
  1204         break;
  1205     }
  1206 }
  1207 
  1208 static void
  1209 SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area)
  1210 {
  1211     const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
  1212     int h;
  1213     int x, minx, maxx;
  1214     Uint8 *data, datab = 0;
  1215     Uint8 *mask, maskb = 0;
  1216     Uint8 *dst;
  1217     int dstbpp, dstskip;
  1218 
  1219     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  1220     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  1221     dstbpp = screen->format->BytesPerPixel;
  1222     dst = (Uint8 *) screen->pixels +
  1223         (SDL_cursor->area.y + area->y) * screen->pitch +
  1224         SDL_cursor->area.x * dstbpp;
  1225     dstskip = screen->pitch - SDL_cursor->area.w * dstbpp;
  1226 
  1227     minx = area->x;
  1228     maxx = area->x + area->w;
  1229     if (screen->format->BytesPerPixel == 1) {
  1230         if (palette_changed) {
  1231             pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  1232             pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  1233             palette_changed = 0;
  1234         }
  1235         for (h = area->h; h; h--) {
  1236             for (x = 0; x < SDL_cursor->area.w; ++x) {
  1237                 if ((x % 8) == 0) {
  1238                     maskb = *mask++;
  1239                     datab = *data++;
  1240                 }
  1241                 if ((x >= minx) && (x < maxx)) {
  1242                     if (maskb & 0x80) {
  1243                         SDL_memset(dst, pixels8[datab >> 7], dstbpp);
  1244                     }
  1245                 }
  1246                 maskb <<= 1;
  1247                 datab <<= 1;
  1248                 dst += dstbpp;
  1249             }
  1250             dst += dstskip;
  1251         }
  1252     } else {
  1253         for (h = area->h; h; h--) {
  1254             for (x = 0; x < SDL_cursor->area.w; ++x) {
  1255                 if ((x % 8) == 0) {
  1256                     maskb = *mask++;
  1257                     datab = *data++;
  1258                 }
  1259                 if ((x >= minx) && (x < maxx)) {
  1260                     if (maskb & 0x80) {
  1261                         SDL_memset(dst, pixels[datab >> 7], dstbpp);
  1262                     }
  1263                 }
  1264                 maskb <<= 1;
  1265                 datab <<= 1;
  1266                 dst += dstbpp;
  1267             }
  1268             dst += dstskip;
  1269         }
  1270     }
  1271 }
  1272 
  1273 /* This handles the ugly work of converting the saved cursor background from
  1274    the pixel format of the shadow surface to that of the video surface.
  1275    This is only necessary when blitting from a shadow surface of a different
  1276    pixel format than the video surface, and using a software rendered cursor.
  1277 */
  1278 static void
  1279 SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h)
  1280 {
  1281     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1282     SDL_BlitInfo info;
  1283     SDL_loblit RunBlit;
  1284 
  1285     /* Make sure we can steal the blit mapping */
  1286     if (screen->map->dst != SDL_VideoSurface) {
  1287         return;
  1288     }
  1289 
  1290     /* Set up the blit information */
  1291     info.s_pixels = SDL_cursor->save[1];
  1292     info.s_width = w;
  1293     info.s_height = h;
  1294     info.s_skip = 0;
  1295     info.d_pixels = SDL_cursor->save[0];
  1296     info.d_width = w;
  1297     info.d_height = h;
  1298     info.d_skip = 0;
  1299     info.aux_data = screen->map->sw_data->aux_data;
  1300     info.src = screen->format;
  1301     info.table = screen->map->table;
  1302     info.dst = SDL_VideoSurface->format;
  1303     RunBlit = screen->map->sw_data->blit;
  1304 
  1305     /* Run the actual software blit */
  1306     RunBlit(&info);
  1307 }
  1308 
  1309 void
  1310 SDL_DrawCursorNoLock(SDL_Surface * screen)
  1311 {
  1312     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1313     SDL_Rect area;
  1314 
  1315     /* Get the mouse rectangle, clipped to the screen */
  1316     SDL_MouseRect(&area);
  1317     if ((area.w == 0) || (area.h == 0)) {
  1318         return;
  1319     }
  1320 
  1321     /* Copy mouse background */
  1322     {
  1323         int w, h, screenbpp;
  1324         Uint8 *src, *dst;
  1325 
  1326         /* Set up the copy pointers */
  1327         screenbpp = screen->format->BytesPerPixel;
  1328         if ((screen == SDL_VideoSurface) ||
  1329             FORMAT_EQUAL(screen->format, SDL_VideoSurface->format)) {
  1330             dst = SDL_cursor->save[0];
  1331         } else {
  1332             dst = SDL_cursor->save[1];
  1333         }
  1334         src = (Uint8 *) screen->pixels + area.y * screen->pitch +
  1335             area.x * screenbpp;
  1336 
  1337         /* Perform the copy */
  1338         w = area.w * screenbpp;
  1339         h = area.h;
  1340         while (h--) {
  1341             SDL_memcpy(dst, src, w);
  1342             dst += w;
  1343             src += screen->pitch;
  1344         }
  1345     }
  1346 
  1347     /* Draw the mouse cursor */
  1348     area.x -= SDL_cursor->area.x;
  1349     area.y -= SDL_cursor->area.y;
  1350     if ((area.x == 0) && (area.w == SDL_cursor->area.w)) {
  1351         SDL_DrawCursorFast(screen, &area);
  1352     } else {
  1353         SDL_DrawCursorSlow(screen, &area);
  1354     }
  1355 }
  1356 
  1357 void
  1358 SDL_DrawCursor(SDL_Surface * screen)
  1359 {
  1360     /* Lock the screen if necessary */
  1361     if (screen == NULL) {
  1362         return;
  1363     }
  1364     if (SDL_MUSTLOCK(screen)) {
  1365         if (SDL_LockSurface(screen) < 0) {
  1366             return;
  1367         }
  1368     }
  1369 
  1370     SDL_DrawCursorNoLock(screen);
  1371 
  1372     /* Unlock the screen and update if necessary */
  1373     if (SDL_MUSTLOCK(screen)) {
  1374         SDL_UnlockSurface(screen);
  1375     }
  1376     if (screen->flags & SDL_SCREEN_SURFACE) {
  1377         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1378         SDL_Window *window;
  1379         SDL_Rect area;
  1380 
  1381         window = SDL_GetWindowFromSurface(screen);
  1382         if (!window) {
  1383             return;
  1384         }
  1385 
  1386         SDL_MouseRect(&area);
  1387 
  1388         if (_this->UpdateWindowSurface) {
  1389             _this->UpdateWindowSurface(_this, window, 1, &area);
  1390         }
  1391     }
  1392 }
  1393 
  1394 void
  1395 SDL_EraseCursorNoLock(SDL_Surface * screen)
  1396 {
  1397     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1398     SDL_Window *window;
  1399     SDL_Rect area;
  1400 
  1401     /* Get the window associated with the surface */
  1402     window = SDL_GetWindowFromSurface(screen);
  1403     if (!window || !window->surface) {
  1404         return;
  1405     }
  1406 
  1407     /* Get the mouse rectangle, clipped to the screen */
  1408     SDL_MouseRect(&area);
  1409     if ((area.w == 0) || (area.h == 0)) {
  1410         return;
  1411     }
  1412 
  1413     /* Copy mouse background */
  1414     {
  1415         int w, h, screenbpp;
  1416         Uint8 *src, *dst;
  1417 
  1418         /* Set up the copy pointers */
  1419         screenbpp = screen->format->BytesPerPixel;
  1420         if ((screen->flags & SDL_SCREEN_SURFACE) ||
  1421             FORMAT_EQUAL(screen->format, window->surface->format)) {
  1422             src = SDL_cursor->save[0];
  1423         } else {
  1424             src = SDL_cursor->save[1];
  1425         }
  1426         dst = (Uint8 *) screen->pixels + area.y * screen->pitch +
  1427             area.x * screenbpp;
  1428 
  1429         /* Perform the copy */
  1430         w = area.w * screenbpp;
  1431         h = area.h;
  1432         while (h--) {
  1433             SDL_memcpy(dst, src, w);
  1434             src += w;
  1435             dst += screen->pitch;
  1436         }
  1437 
  1438         /* Perform pixel conversion on cursor background */
  1439         if (src > SDL_cursor->save[1]) {
  1440             SDL_ConvertCursorSave(screen, area.w, area.h);
  1441         }
  1442     }
  1443 }
  1444 
  1445 void
  1446 SDL_EraseCursor(SDL_Surface * screen)
  1447 {
  1448     /* Lock the screen if necessary */
  1449     if (screen == NULL) {
  1450         return;
  1451     }
  1452     if (SDL_MUSTLOCK(screen)) {
  1453         if (SDL_LockSurface(screen) < 0) {
  1454             return;
  1455         }
  1456     }
  1457 
  1458     SDL_EraseCursorNoLock(screen);
  1459 
  1460     /* Unlock the screen and update if necessary */
  1461     if (SDL_MUSTLOCK(screen)) {
  1462         SDL_UnlockSurface(screen);
  1463     }
  1464     if (screen->flags & SDL_SCREEN_SURFACE) {
  1465         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1466         SDL_Window *window;
  1467         SDL_Rect area;
  1468 
  1469         window = SDL_GetWindowFromSurface(screen);
  1470         if (!window) {
  1471             return;
  1472         }
  1473 
  1474         SDL_MouseRect(&area);
  1475 
  1476         if (_this->UpdateWindowSurface) {
  1477             _this->UpdateWindowSurface(_this, window, 1, &area);
  1478         }
  1479     }
  1480 }
  1481 
  1482 /* Reset the cursor on video mode change
  1483    FIXME:  Keep track of all cursors, and reset them all.
  1484  */
  1485 void
  1486 SDL_ResetCursor(void)
  1487 {
  1488     int savelen;
  1489 
  1490     if (SDL_cursor) {
  1491         savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h;
  1492         SDL_cursor->area.x = 0;
  1493         SDL_cursor->area.y = 0;
  1494         SDL_memset(SDL_cursor->save[0], 0, savelen);
  1495     }
  1496 }
  1497 #endif
  1498 
  1499 struct private_yuvhwdata
  1500 {
  1501     SDL_SW_YUVTexture *texture;
  1502     SDL_Surface *display;
  1503     Uint32 display_format;
  1504 };
  1505 
  1506 SDL_Overlay *
  1507 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
  1508 {
  1509     SDL_Overlay *overlay;
  1510     Uint32 texture_format;
  1511     SDL_SW_YUVTexture *texture;
  1512 
  1513     if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
  1514         SDL_SetError("YUV overlays are not supported in OpenGL mode");
  1515         return NULL;
  1516     }
  1517 
  1518     if (display != SDL_PublicSurface) {
  1519         SDL_SetError("YUV display is only supported on the screen surface");
  1520         return NULL;
  1521     }
  1522 
  1523     switch (format) {
  1524     case SDL_YV12_OVERLAY:
  1525         texture_format = SDL_PIXELFORMAT_YV12;
  1526         break;
  1527     case SDL_IYUV_OVERLAY:
  1528         texture_format = SDL_PIXELFORMAT_IYUV;
  1529         break;
  1530     case SDL_YUY2_OVERLAY:
  1531         texture_format = SDL_PIXELFORMAT_YUY2;
  1532         break;
  1533     case SDL_UYVY_OVERLAY:
  1534         texture_format = SDL_PIXELFORMAT_UYVY;
  1535         break;
  1536     case SDL_YVYU_OVERLAY:
  1537         texture_format = SDL_PIXELFORMAT_YVYU;
  1538         break;
  1539     default:
  1540         SDL_SetError("Unknown YUV format");
  1541         return NULL;
  1542     }
  1543 
  1544     overlay = (SDL_Overlay *) SDL_malloc(sizeof(*overlay));
  1545     if (!overlay) {
  1546         SDL_OutOfMemory();
  1547         return NULL;
  1548     }
  1549     SDL_zerop(overlay);
  1550 
  1551     overlay->hwdata =
  1552         (struct private_yuvhwdata *) SDL_malloc(sizeof(*overlay->hwdata));
  1553     if (!overlay->hwdata) {
  1554         SDL_free(overlay);
  1555         SDL_OutOfMemory();
  1556         return NULL;
  1557     }
  1558 
  1559     texture = SDL_SW_CreateYUVTexture(texture_format, w, h);
  1560     if (!texture) {
  1561         SDL_free(overlay->hwdata);
  1562         SDL_free(overlay);
  1563         return NULL;
  1564     }
  1565     overlay->hwdata->texture = texture;
  1566     overlay->hwdata->display = NULL;
  1567     overlay->hwdata->display_format = SDL_PIXELFORMAT_UNKNOWN;
  1568 
  1569     overlay->format = format;
  1570     overlay->w = w;
  1571     overlay->h = h;
  1572     if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
  1573         overlay->planes = 3;
  1574     } else {
  1575         overlay->planes = 1;
  1576     }
  1577     overlay->pitches = texture->pitches;
  1578     overlay->pixels = texture->planes;
  1579 
  1580     return overlay;
  1581 }
  1582 
  1583 int
  1584 SDL_LockYUVOverlay(SDL_Overlay * overlay)
  1585 {
  1586     SDL_Rect rect;
  1587     void *pixels;
  1588     int pitch;
  1589 
  1590     if (!overlay) {
  1591         SDL_SetError("Passed a NULL overlay");
  1592         return -1;
  1593     }
  1594 
  1595     rect.x = 0;
  1596     rect.y = 0;
  1597     rect.w = overlay->w;
  1598     rect.h = overlay->h;
  1599 
  1600     if (SDL_SW_LockYUVTexture(overlay->hwdata->texture, &rect, &pixels, &pitch) < 0) {
  1601         return -1;
  1602     }
  1603 
  1604     overlay->pixels[0] = (Uint8 *) pixels;
  1605     overlay->pitches[0] = pitch;
  1606     switch (overlay->format) {
  1607     case SDL_YV12_OVERLAY:
  1608     case SDL_IYUV_OVERLAY:
  1609         overlay->pitches[1] = pitch / 2;
  1610         overlay->pitches[2] = pitch / 2;
  1611         overlay->pixels[1] =
  1612             overlay->pixels[0] + overlay->pitches[0] * overlay->h;
  1613         overlay->pixels[2] =
  1614             overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
  1615         break;
  1616     case SDL_YUY2_OVERLAY:
  1617     case SDL_UYVY_OVERLAY:
  1618     case SDL_YVYU_OVERLAY:
  1619         break;
  1620     }
  1621     return 0;
  1622 }
  1623 
  1624 void
  1625 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
  1626 {
  1627     if (!overlay) {
  1628         return;
  1629     }
  1630 
  1631     SDL_SW_UnlockYUVTexture(overlay->hwdata->texture);
  1632 }
  1633 
  1634 int
  1635 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
  1636 {
  1637     SDL_Surface *display;
  1638     SDL_Rect src_rect;
  1639     SDL_Rect dst_rect;
  1640     void *pixels;
  1641 
  1642     if (!overlay || !dstrect) {
  1643         SDL_SetError("Passed a NULL overlay or dstrect");
  1644         return -1;
  1645     }
  1646 
  1647     display = overlay->hwdata->display;
  1648     if (display != SDL_VideoSurface) {
  1649         overlay->hwdata->display = display = SDL_VideoSurface;
  1650         overlay->hwdata->display_format = SDL_MasksToPixelFormatEnum(
  1651                                                 display->format->BitsPerPixel,
  1652                                                 display->format->Rmask,
  1653                                                 display->format->Gmask,
  1654                                                 display->format->Bmask,
  1655                                                 display->format->Amask);
  1656     }
  1657 
  1658     src_rect.x = 0;
  1659     src_rect.y = 0;
  1660     src_rect.w = overlay->w;
  1661     src_rect.h = overlay->h;
  1662 
  1663     if (!SDL_IntersectRect(&display->clip_rect, dstrect, &dst_rect)) {
  1664         return 0;
  1665     }
  1666      
  1667     pixels = (void *)((Uint8 *)display->pixels +
  1668                         dst_rect.y * display->pitch +
  1669                         dst_rect.x * display->format->BytesPerPixel);
  1670 
  1671     if (SDL_SW_CopyYUVToRGB(overlay->hwdata->texture, &src_rect,
  1672                             overlay->hwdata->display_format,
  1673                             dst_rect.w, dst_rect.h,
  1674                             pixels, display->pitch) < 0) {
  1675         return -1;
  1676     }
  1677     SDL_UpdateWindowSurface(SDL_VideoWindow);
  1678     return 0;
  1679 }
  1680 
  1681 void
  1682 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
  1683 {
  1684     if (!overlay) {
  1685         return;
  1686     }
  1687     if (overlay->hwdata) {
  1688         if (overlay->hwdata->texture) {
  1689             SDL_SW_DestroyYUVTexture(overlay->hwdata->texture);
  1690         }
  1691         SDL_free(overlay->hwdata);
  1692     }
  1693     SDL_free(overlay);
  1694 }
  1695 
  1696 void
  1697 SDL_GL_SwapBuffers(void)
  1698 {
  1699     SDL_GL_SwapWindow(SDL_VideoWindow);
  1700 }
  1701 
  1702 int
  1703 SDL_SetGamma(float red, float green, float blue)
  1704 {
  1705     SDL_Unsupported();
  1706     return -1;
  1707 }
  1708 
  1709 int
  1710 SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green, const Uint16 * blue)
  1711 {
  1712     SDL_Unsupported();
  1713     return -1;
  1714 }
  1715 
  1716 int
  1717 SDL_GetGammaRamp(Uint16 * red, Uint16 * green, Uint16 * blue)
  1718 {
  1719     SDL_Unsupported();
  1720     return -1;
  1721 }
  1722 
  1723 int
  1724 SDL_EnableKeyRepeat(int delay, int interval)
  1725 {
  1726     return 0;
  1727 }
  1728 
  1729 void
  1730 SDL_GetKeyRepeat(int *delay, int *interval)
  1731 {
  1732     if (delay) {
  1733         *delay = SDL_DEFAULT_REPEAT_DELAY;
  1734     }
  1735     if (interval) {
  1736         *interval = SDL_DEFAULT_REPEAT_INTERVAL;
  1737     }
  1738 }
  1739 
  1740 int
  1741 SDL_EnableUNICODE(int enable)
  1742 {
  1743     int previous = SDL_enabled_UNICODE;
  1744 
  1745     switch (enable) {
  1746     case 1:
  1747         SDL_enabled_UNICODE = 1;
  1748         SDL_StartTextInput();
  1749         break;
  1750     case 0:
  1751         SDL_enabled_UNICODE = 0;
  1752         SDL_StopTextInput();
  1753         break;
  1754     }
  1755     return previous;
  1756 }
  1757 
  1758 static Uint32
  1759 SDL_SetTimerCallback(Uint32 interval, void* param)
  1760 {
  1761     return ((SDL_OldTimerCallback)param)(interval);
  1762 }
  1763 
  1764 int
  1765 SDL_SetTimer(Uint32 interval, SDL_OldTimerCallback callback)
  1766 {
  1767     static SDL_TimerID compat_timer;
  1768 
  1769     if (compat_timer) {
  1770         SDL_RemoveTimer(compat_timer);
  1771         compat_timer = 0;
  1772     }
  1773 
  1774     if (interval && callback) {
  1775         compat_timer = SDL_AddTimer(interval, SDL_SetTimerCallback, callback);
  1776         if (!compat_timer) {
  1777             return -1;
  1778         }
  1779     }
  1780     return 0;
  1781 }
  1782 
  1783 int
  1784 SDL_putenv(const char *_var)
  1785 {
  1786     char *ptr = NULL;
  1787     char *var = SDL_strdup(_var);
  1788     if (var == NULL) {
  1789         return -1;  /* we don't set errno. */
  1790     }
  1791 
  1792     ptr = SDL_strchr(var, '=');
  1793     if (ptr == NULL) {
  1794         SDL_free(var);
  1795         return -1;
  1796     }
  1797 
  1798     *ptr = '\0';  /* split the string into name and value. */
  1799     SDL_setenv(var, ptr + 1, 1);
  1800     SDL_free(var);
  1801     return 0;
  1802 }
  1803 
  1804 /* vi: set ts=4 sw=4 expandtab: */