src/SDL_compat.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 31 Oct 2011 05:56:58 -0400
changeset 6044 35448a5ea044
parent 5941 e4e18a80be61
child 6138 4c64952a58fb
permissions -rw-r--r--
Lots of fixes importing SDL source wholesale into a new iOS project
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2011 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 #include "SDL_config.h"
    22 
    23 /* This file contains functions for backwards compatibility with SDL 1.2 */
    24 
    25 #include "SDL.h"
    26 #include "SDL_syswm.h"
    27 
    28 #include "video/SDL_sysvideo.h"
    29 #include "video/SDL_pixels_c.h"
    30 #include "render/SDL_yuv_sw_c.h"
    31 
    32 
    33 static SDL_Window *SDL_VideoWindow = NULL;
    34 static SDL_Surface *SDL_WindowSurface = NULL;
    35 static SDL_Surface *SDL_VideoSurface = NULL;
    36 static SDL_Surface *SDL_ShadowSurface = NULL;
    37 static SDL_Surface *SDL_PublicSurface = NULL;
    38 static SDL_GLContext *SDL_VideoContext = NULL;
    39 static Uint32 SDL_VideoFlags = 0;
    40 static SDL_Rect SDL_VideoViewport;
    41 static char *wm_title = NULL;
    42 static SDL_Surface *SDL_VideoIcon;
    43 static int SDL_enabled_UNICODE = 0;
    44 
    45 const char *
    46 SDL_AudioDriverName(char *namebuf, int maxlen)
    47 {
    48     const char *name = SDL_GetCurrentAudioDriver();
    49     if (name) {
    50         if (namebuf) {
    51             SDL_strlcpy(namebuf, name, maxlen);
    52             return namebuf;
    53         } else {
    54             return name;
    55         }
    56     }
    57     return NULL;
    58 }
    59 
    60 const char *
    61 SDL_VideoDriverName(char *namebuf, int maxlen)
    62 {
    63     const char *name = SDL_GetCurrentVideoDriver();
    64     if (name) {
    65         if (namebuf) {
    66             SDL_strlcpy(namebuf, name, maxlen);
    67             return namebuf;
    68         } else {
    69             return name;
    70         }
    71     }
    72     return NULL;
    73 }
    74 
    75 static int
    76 GetVideoDisplay()
    77 {
    78     const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
    79     if ( !variable ) {
    80         variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
    81     }
    82     if ( variable ) {
    83         return SDL_atoi(variable);
    84     } else {
    85         return 0;
    86     }
    87 }
    88 
    89 const SDL_VideoInfo *
    90 SDL_GetVideoInfo(void)
    91 {
    92     static SDL_VideoInfo info;
    93     SDL_DisplayMode mode;
    94 
    95     /* Memory leak, compatibility code, who cares? */
    96     if (!info.vfmt && SDL_GetDesktopDisplayMode(GetVideoDisplay(), &mode) == 0) {
    97         info.vfmt = SDL_AllocFormat(mode.format);
    98         info.current_w = mode.w;
    99         info.current_h = mode.h;
   100     }
   101     return &info;
   102 }
   103 
   104 int
   105 SDL_VideoModeOK(int width, int height, int bpp, Uint32 flags)
   106 {
   107     int i, actual_bpp = 0;
   108 
   109     if (!SDL_GetVideoDevice()) {
   110         return 0;
   111     }
   112 
   113     if (!(flags & SDL_FULLSCREEN)) {
   114         SDL_DisplayMode mode;
   115         SDL_GetDesktopDisplayMode(GetVideoDisplay(), &mode);
   116         return SDL_BITSPERPIXEL(mode.format);
   117     }
   118 
   119     for (i = 0; i < SDL_GetNumDisplayModes(GetVideoDisplay()); ++i) {
   120         SDL_DisplayMode mode;
   121         SDL_GetDisplayMode(GetVideoDisplay(), i, &mode);
   122         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
   123             if (!mode.format) {
   124                 return bpp;
   125             }
   126             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
   127                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
   128             }
   129         }
   130     }
   131     return actual_bpp;
   132 }
   133 
   134 SDL_Rect **
   135 SDL_ListModes(const SDL_PixelFormat * format, Uint32 flags)
   136 {
   137     int i, nmodes;
   138     SDL_Rect **modes;
   139 
   140     if (!SDL_GetVideoDevice()) {
   141         return NULL;
   142     }
   143 
   144     if (!(flags & SDL_FULLSCREEN)) {
   145         return (SDL_Rect **) (-1);
   146     }
   147 
   148     if (!format) {
   149         format = SDL_GetVideoInfo()->vfmt;
   150     }
   151 
   152     /* Memory leak, but this is a compatibility function, who cares? */
   153     nmodes = 0;
   154     modes = NULL;
   155     for (i = 0; i < SDL_GetNumDisplayModes(GetVideoDisplay()); ++i) {
   156         SDL_DisplayMode mode;
   157         int bpp;
   158 
   159         SDL_GetDisplayMode(GetVideoDisplay(), i, &mode);
   160         if (!mode.w || !mode.h) {
   161             return (SDL_Rect **) (-1);
   162         }
   163         
   164         /* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
   165         if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
   166             bpp = SDL_BITSPERPIXEL(mode.format);
   167         } else {
   168             bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
   169         }
   170 
   171         if (bpp != format->BitsPerPixel) {
   172             continue;
   173         }
   174         if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
   175             && modes[nmodes - 1]->h == mode.h) {
   176             continue;
   177         }
   178 
   179         modes = SDL_realloc(modes, (nmodes + 2) * sizeof(*modes));
   180         if (!modes) {
   181             return NULL;
   182         }
   183         modes[nmodes] = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect));
   184         if (!modes[nmodes]) {
   185             return NULL;
   186         }
   187         modes[nmodes]->x = 0;
   188         modes[nmodes]->y = 0;
   189         modes[nmodes]->w = mode.w;
   190         modes[nmodes]->h = mode.h;
   191         ++nmodes;
   192     }
   193     if (modes) {
   194         modes[nmodes] = NULL;
   195     }
   196     return modes;
   197 }
   198 
   199 static int
   200 SDL_CompatEventFilter(void *userdata, SDL_Event * event)
   201 {
   202     SDL_Event fake;
   203 
   204     switch (event->type) {
   205     case SDL_WINDOWEVENT:
   206         switch (event->window.event) {
   207         case SDL_WINDOWEVENT_EXPOSED:
   208             if (!SDL_HasEvent(SDL_VIDEOEXPOSE)) {
   209                 fake.type = SDL_VIDEOEXPOSE;
   210                 SDL_PushEvent(&fake);
   211             }
   212             break;
   213         case SDL_WINDOWEVENT_RESIZED:
   214             SDL_FlushEvent(SDL_VIDEORESIZE);
   215             /* We don't want to expose that the window width and height will
   216                be different if we don't get the desired fullscreen mode.
   217             */
   218             if (SDL_VideoWindow && !(SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN)) {
   219                 fake.type = SDL_VIDEORESIZE;
   220                 fake.resize.w = event->window.data1;
   221                 fake.resize.h = event->window.data2;
   222                 SDL_PushEvent(&fake);
   223             }
   224             break;
   225         case SDL_WINDOWEVENT_MINIMIZED:
   226             fake.type = SDL_ACTIVEEVENT;
   227             fake.active.gain = 0;
   228             fake.active.state = SDL_APPACTIVE;
   229             SDL_PushEvent(&fake);
   230             break;
   231         case SDL_WINDOWEVENT_RESTORED:
   232             fake.type = SDL_ACTIVEEVENT;
   233             fake.active.gain = 1;
   234             fake.active.state = SDL_APPACTIVE;
   235             SDL_PushEvent(&fake);
   236             break;
   237         case SDL_WINDOWEVENT_ENTER:
   238             fake.type = SDL_ACTIVEEVENT;
   239             fake.active.gain = 1;
   240             fake.active.state = SDL_APPMOUSEFOCUS;
   241             SDL_PushEvent(&fake);
   242             break;
   243         case SDL_WINDOWEVENT_LEAVE:
   244             fake.type = SDL_ACTIVEEVENT;
   245             fake.active.gain = 0;
   246             fake.active.state = SDL_APPMOUSEFOCUS;
   247             SDL_PushEvent(&fake);
   248             break;
   249         case SDL_WINDOWEVENT_FOCUS_GAINED:
   250             fake.type = SDL_ACTIVEEVENT;
   251             fake.active.gain = 1;
   252             fake.active.state = SDL_APPINPUTFOCUS;
   253             SDL_PushEvent(&fake);
   254             break;
   255         case SDL_WINDOWEVENT_FOCUS_LOST:
   256             fake.type = SDL_ACTIVEEVENT;
   257             fake.active.gain = 0;
   258             fake.active.state = SDL_APPINPUTFOCUS;
   259             SDL_PushEvent(&fake);
   260             break;
   261         case SDL_WINDOWEVENT_CLOSE:
   262             fake.type = SDL_QUIT;
   263             SDL_PushEvent(&fake);
   264             break;
   265         }
   266     case SDL_KEYDOWN:
   267     case SDL_KEYUP:
   268         {
   269             Uint32 unicode = 0;
   270             if (event->key.type == SDL_KEYDOWN && event->key.keysym.sym < 256) {
   271                 unicode = event->key.keysym.sym;
   272                 if (unicode >= 'a' && unicode <= 'z') {
   273                     int shifted = !!(event->key.keysym.mod & KMOD_SHIFT);
   274                     int capslock = !!(event->key.keysym.mod & KMOD_CAPS);
   275                     if ((shifted ^ capslock) != 0) {
   276                         unicode = SDL_toupper(unicode);
   277                     }
   278                 }
   279             }
   280             if (unicode) {
   281                 event->key.keysym.unicode = unicode;
   282             }
   283             break;
   284         }
   285     case SDL_TEXTINPUT:
   286         {
   287             /* FIXME: Generate an old style key repeat event if needed */
   288             //printf("TEXTINPUT: '%s'\n", event->text.text);
   289             break;
   290         }
   291     case SDL_MOUSEMOTION:
   292         {
   293             event->motion.x -= SDL_VideoViewport.x;
   294             event->motion.y -= SDL_VideoViewport.y;
   295             break;
   296         }
   297     case SDL_MOUSEBUTTONDOWN:
   298     case SDL_MOUSEBUTTONUP:
   299         {
   300             event->button.x -= SDL_VideoViewport.x;
   301             event->button.y -= SDL_VideoViewport.y;
   302             break;
   303         }
   304     case SDL_MOUSEWHEEL:
   305         {
   306             Uint8 button;
   307             int x, y;
   308 
   309             if (event->wheel.y == 0) {
   310                 break;
   311             }
   312 
   313             SDL_GetMouseState(&x, &y);
   314 
   315             if (event->wheel.y > 0) {
   316                 button = SDL_BUTTON_WHEELUP;
   317             } else {
   318                 button = SDL_BUTTON_WHEELDOWN;
   319             }
   320 
   321             fake.button.button = button;
   322             fake.button.x = x;
   323             fake.button.y = y;
   324             fake.button.windowID = event->wheel.windowID;
   325 
   326             fake.type = SDL_MOUSEBUTTONDOWN;
   327             fake.button.state = SDL_PRESSED;
   328             SDL_PushEvent(&fake);
   329 
   330             fake.type = SDL_MOUSEBUTTONUP;
   331             fake.button.state = SDL_RELEASED;
   332             SDL_PushEvent(&fake);
   333             break;
   334         }
   335 
   336     }
   337     return 1;
   338 }
   339 
   340 static void
   341 GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
   342 {
   343     int display = GetVideoDisplay();
   344     const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
   345     const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
   346     if (window) {
   347         if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
   348             return;
   349         }
   350         if (SDL_strcmp(window, "center") == 0) {
   351             center = window;
   352         }
   353     }
   354     if (center) {
   355         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
   356         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
   357     }
   358 }
   359 
   360 static void
   361 ClearVideoSurface()
   362 {
   363     if (SDL_ShadowSurface) {
   364         SDL_FillRect(SDL_ShadowSurface, NULL,
   365             SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
   366     }
   367     SDL_FillRect(SDL_WindowSurface, NULL, 0);
   368     SDL_UpdateWindowSurface(SDL_VideoWindow);
   369 }
   370 
   371 static void
   372 SetupScreenSaver(int flags)
   373 {
   374     const char *env;
   375     SDL_bool allow_screensaver;
   376 
   377     /* Allow environment override of screensaver disable */
   378     env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
   379     if (env) {
   380         allow_screensaver = SDL_atoi(env) ? SDL_TRUE : SDL_FALSE;
   381     } else if (flags & SDL_FULLSCREEN) {
   382         allow_screensaver = SDL_FALSE;
   383     } else {
   384         allow_screensaver = SDL_TRUE;
   385     }
   386     if (allow_screensaver) {
   387         SDL_EnableScreenSaver();
   388     } else {
   389         SDL_DisableScreenSaver();
   390     }
   391 }
   392 
   393 static int
   394 SDL_ResizeVideoMode(int width, int height, int bpp, Uint32 flags)
   395 {
   396     int w, h;
   397 
   398     /* We can't resize something we don't have... */
   399     if (!SDL_VideoSurface) {
   400         return -1;
   401     }
   402 
   403     /* We probably have to recreate the window in fullscreen mode */
   404     if (flags & SDL_FULLSCREEN) {
   405         return -1;
   406     }
   407 
   408     /* I don't think there's any change we can gracefully make in flags */
   409     if (flags != SDL_VideoFlags) {
   410         return -1;
   411     }
   412     if (bpp != SDL_VideoSurface->format->BitsPerPixel) {
   413         return -1;
   414     }
   415 
   416     /* Resize the window */
   417     SDL_GetWindowSize(SDL_VideoWindow, &w, &h);
   418     if (w != width || h != height) {
   419         SDL_SetWindowSize(SDL_VideoWindow, width, height);
   420     }
   421 
   422     /* If we're in OpenGL mode, just resize the stub surface and we're done! */
   423     if (flags & SDL_OPENGL) {
   424         SDL_VideoSurface->w = width;
   425         SDL_VideoSurface->h = height;
   426         return 0;
   427     }
   428 
   429     SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
   430     if (!SDL_WindowSurface) {
   431         return -1;
   432     }
   433     if (SDL_VideoSurface->format != SDL_WindowSurface->format) {
   434         return -1;
   435     }
   436     SDL_VideoSurface->w = width;
   437     SDL_VideoSurface->h = height;
   438     SDL_VideoSurface->pixels = SDL_WindowSurface->pixels;
   439     SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
   440     SDL_SetClipRect(SDL_VideoSurface, NULL);
   441 
   442     if (SDL_ShadowSurface) {
   443         SDL_ShadowSurface->w = width;
   444         SDL_ShadowSurface->h = height;
   445         SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
   446         SDL_ShadowSurface->pixels =
   447             SDL_realloc(SDL_ShadowSurface->pixels,
   448                         SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
   449         SDL_SetClipRect(SDL_ShadowSurface, NULL);
   450         SDL_InvalidateMap(SDL_ShadowSurface->map);
   451     } else {
   452         SDL_PublicSurface = SDL_VideoSurface;
   453     }
   454 
   455     ClearVideoSurface();
   456 
   457     return 0;
   458 }
   459 
   460 SDL_Surface *
   461 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
   462 {
   463     SDL_DisplayMode desktop_mode;
   464     int display = GetVideoDisplay();
   465     int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
   466     int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
   467     int window_w;
   468     int window_h;
   469     Uint32 window_flags;
   470     Uint32 surface_flags;
   471 
   472     if (!SDL_GetVideoDevice()) {
   473         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
   474             return NULL;
   475         }
   476     }
   477 
   478     SDL_GetDesktopDisplayMode(display, &desktop_mode);
   479 
   480     if (width == 0) {
   481         width = desktop_mode.w;
   482     }
   483     if (height == 0) {
   484         height = desktop_mode.h;
   485     }
   486     if (bpp == 0) {
   487         bpp = SDL_BITSPERPIXEL(desktop_mode.format);
   488     }
   489 
   490     /* See if we can simply resize the existing window and surface */
   491     if (SDL_ResizeVideoMode(width, height, bpp, flags) == 0) {
   492         return SDL_PublicSurface;
   493     }
   494 
   495     /* Destroy existing window */
   496     SDL_PublicSurface = NULL;
   497     if (SDL_ShadowSurface) {
   498         SDL_ShadowSurface->flags &= ~SDL_DONTFREE;
   499         SDL_FreeSurface(SDL_ShadowSurface);
   500         SDL_ShadowSurface = NULL;
   501     }
   502     if (SDL_VideoSurface) {
   503         SDL_VideoSurface->flags &= ~SDL_DONTFREE;
   504         SDL_FreeSurface(SDL_VideoSurface);
   505         SDL_VideoSurface = NULL;
   506     }
   507     if (SDL_VideoContext) {
   508         /* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
   509         SDL_GL_DeleteContext(SDL_VideoContext);
   510         SDL_VideoContext = NULL;
   511     }
   512     if (SDL_VideoWindow) {
   513         SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y);
   514         SDL_DestroyWindow(SDL_VideoWindow);
   515     }
   516 
   517     /* Set up the event filter */
   518     if (!SDL_GetEventFilter(NULL, NULL)) {
   519         SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
   520     }
   521 
   522     /* Create a new window */
   523     window_flags = SDL_WINDOW_SHOWN;
   524     if (flags & SDL_FULLSCREEN) {
   525         window_flags |= SDL_WINDOW_FULLSCREEN;
   526     }
   527     if (flags & SDL_OPENGL) {
   528         window_flags |= SDL_WINDOW_OPENGL;
   529     }
   530     if (flags & SDL_RESIZABLE) {
   531         window_flags |= SDL_WINDOW_RESIZABLE;
   532     }
   533     if (flags & SDL_NOFRAME) {
   534         window_flags |= SDL_WINDOW_BORDERLESS;
   535     }
   536     GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
   537     SDL_VideoWindow =
   538         SDL_CreateWindow(wm_title, window_x, window_y, width, height,
   539                          window_flags);
   540     if (!SDL_VideoWindow) {
   541         return NULL;
   542     }
   543     SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon);
   544 
   545     SetupScreenSaver(flags);
   546 
   547     window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
   548     surface_flags = 0;
   549     if (window_flags & SDL_WINDOW_FULLSCREEN) {
   550         surface_flags |= SDL_FULLSCREEN;
   551     }
   552     if ((window_flags & SDL_WINDOW_OPENGL) && (flags & SDL_OPENGL)) {
   553         surface_flags |= SDL_OPENGL;
   554     }
   555     if (window_flags & SDL_WINDOW_RESIZABLE) {
   556         surface_flags |= SDL_RESIZABLE;
   557     }
   558     if (window_flags & SDL_WINDOW_BORDERLESS) {
   559         surface_flags |= SDL_NOFRAME;
   560     }
   561 
   562     SDL_VideoFlags = flags;
   563 
   564     /* If we're in OpenGL mode, just create a stub surface and we're done! */
   565     if (flags & SDL_OPENGL) {
   566         SDL_VideoContext = SDL_GL_CreateContext(SDL_VideoWindow);
   567         if (!SDL_VideoContext) {
   568             return NULL;
   569         }
   570         if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) {
   571             return NULL;
   572         }
   573         SDL_VideoSurface =
   574             SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
   575         if (!SDL_VideoSurface) {
   576             return NULL;
   577         }
   578         SDL_VideoSurface->flags |= surface_flags;
   579         SDL_PublicSurface = SDL_VideoSurface;
   580         return SDL_PublicSurface;
   581     }
   582 
   583     /* Create the screen surface */
   584     SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
   585     if (!SDL_WindowSurface) {
   586         return NULL;
   587     }
   588 
   589     /* Center the public surface in the window surface */
   590     SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
   591     SDL_VideoViewport.x = (window_w - width)/2;
   592     SDL_VideoViewport.y = (window_h - height)/2;
   593     SDL_VideoViewport.w = width;
   594     SDL_VideoViewport.h = height;
   595 
   596     SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
   597     SDL_VideoSurface->flags |= surface_flags;
   598     SDL_VideoSurface->flags |= SDL_DONTFREE;
   599     SDL_FreeFormat(SDL_VideoSurface->format);
   600     SDL_VideoSurface->format = SDL_WindowSurface->format;
   601     SDL_VideoSurface->format->refcount++;
   602     SDL_VideoSurface->w = width;
   603     SDL_VideoSurface->h = height;
   604     SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
   605     SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
   606         SDL_VideoViewport.y * SDL_VideoSurface->pitch +
   607         SDL_VideoViewport.x  * SDL_VideoSurface->format->BytesPerPixel);
   608     SDL_SetClipRect(SDL_VideoSurface, NULL);
   609 
   610     /* Create a shadow surface if necessary */
   611     if ((bpp != SDL_VideoSurface->format->BitsPerPixel)
   612         && !(flags & SDL_ANYFORMAT)) {
   613         SDL_ShadowSurface =
   614             SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
   615         if (!SDL_ShadowSurface) {
   616             return NULL;
   617         }
   618         SDL_ShadowSurface->flags |= surface_flags;
   619         SDL_ShadowSurface->flags |= SDL_DONTFREE;
   620 
   621         /* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
   622         if (SDL_ShadowSurface->format->palette) {
   623             SDL_ShadowSurface->flags |= SDL_HWPALETTE;
   624             SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
   625                              SDL_ShadowSurface->format->BitsPerPixel);
   626         }
   627         SDL_FillRect(SDL_ShadowSurface, NULL,
   628             SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
   629     }
   630     SDL_PublicSurface =
   631         (SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface);
   632 
   633     ClearVideoSurface();
   634 
   635     /* We're finally done! */
   636     return SDL_PublicSurface;
   637 }
   638 
   639 SDL_Surface *
   640 SDL_GetVideoSurface(void)
   641 {
   642     return SDL_PublicSurface;
   643 }
   644 
   645 int
   646 SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value)
   647 {
   648     if (flag & SDL_SRCALPHA) {
   649         /* According to the docs, value is ignored for alpha surfaces */
   650         if (surface->format->Amask) {
   651             value = 0xFF;
   652         }
   653         SDL_SetSurfaceAlphaMod(surface, value);
   654         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
   655     } else {
   656         SDL_SetSurfaceAlphaMod(surface, 0xFF);
   657         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
   658     }
   659     SDL_SetSurfaceRLE(surface, (flag & SDL_RLEACCEL));
   660 
   661     return 0;
   662 }
   663 
   664 SDL_Surface *
   665 SDL_DisplayFormat(SDL_Surface * surface)
   666 {
   667     SDL_PixelFormat *format;
   668 
   669     if (!SDL_PublicSurface) {
   670         SDL_SetError("No video mode has been set");
   671         return NULL;
   672     }
   673     format = SDL_PublicSurface->format;
   674 
   675     /* Set the flags appropriate for copying to display surface */
   676     return SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
   677 }
   678 
   679 SDL_Surface *
   680 SDL_DisplayFormatAlpha(SDL_Surface * surface)
   681 {
   682     SDL_PixelFormat *vf;
   683     SDL_PixelFormat *format;
   684     SDL_Surface *converted;
   685     /* default to ARGB8888 */
   686     Uint32 amask = 0xff000000;
   687     Uint32 rmask = 0x00ff0000;
   688     Uint32 gmask = 0x0000ff00;
   689     Uint32 bmask = 0x000000ff;
   690 
   691     if (!SDL_PublicSurface) {
   692         SDL_SetError("No video mode has been set");
   693         return NULL;
   694     }
   695     vf = SDL_PublicSurface->format;
   696 
   697     switch (vf->BytesPerPixel) {
   698     case 2:
   699         /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
   700            For anything else (like ARGB4444) it doesn't matter
   701            since we have no special code for it anyway */
   702         if ((vf->Rmask == 0x1f) &&
   703             (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
   704             rmask = 0xff;
   705             bmask = 0xff0000;
   706         }
   707         break;
   708 
   709     case 3:
   710     case 4:
   711         /* Keep the video format, as long as the high 8 bits are
   712            unused or alpha */
   713         if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) {
   714             rmask = 0xff;
   715             bmask = 0xff0000;
   716         }
   717         break;
   718 
   719     default:
   720         /* We have no other optimised formats right now. When/if a new
   721            optimised alpha format is written, add the converter here */
   722         break;
   723     }
   724     format = SDL_AllocFormat(SDL_MasksToPixelFormatEnum(32, rmask,
   725                                                             gmask,
   726                                                             bmask,
   727                                                             amask));
   728     if (!format) {
   729         return NULL;
   730     }
   731     converted = SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
   732     SDL_FreeFormat(format);
   733     return converted;
   734 }
   735 
   736 int
   737 SDL_Flip(SDL_Surface * screen)
   738 {
   739     SDL_UpdateRect(screen, 0, 0, 0, 0);
   740     return 0;
   741 }
   742 
   743 void
   744 SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
   745 {
   746     if (screen) {
   747         SDL_Rect rect;
   748 
   749         /* Fill the rectangle */
   750         rect.x = (int) x;
   751         rect.y = (int) y;
   752         rect.w = (int) (w ? w : screen->w);
   753         rect.h = (int) (h ? h : screen->h);
   754         SDL_UpdateRects(screen, 1, &rect);
   755     }
   756 }
   757 
   758 void
   759 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
   760 {
   761     int i;
   762 
   763     if (screen == SDL_ShadowSurface) {
   764         for (i = 0; i < numrects; ++i) {
   765             SDL_BlitSurface(SDL_ShadowSurface, &rects[i], SDL_VideoSurface,
   766                             &rects[i]);
   767         }
   768 
   769         /* Fall through to video surface update */
   770         screen = SDL_VideoSurface;
   771     }
   772     if (screen == SDL_VideoSurface) {
   773         if (SDL_VideoViewport.x || SDL_VideoViewport.y) {
   774             SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
   775             SDL_Rect *stackrect;
   776             const SDL_Rect *rect;
   777             
   778             /* Offset all the rectangles before updating */
   779             for (i = 0; i < numrects; ++i) {
   780                 rect = &rects[i];
   781                 stackrect = &stackrects[i];
   782                 stackrect->x = SDL_VideoViewport.x + rect->x;
   783                 stackrect->y = SDL_VideoViewport.y + rect->y;
   784                 stackrect->w = rect->w;
   785                 stackrect->h = rect->h;
   786             }
   787             SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, stackrects, numrects);
   788             SDL_stack_free(stackrects);
   789         } else {
   790             SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, rects, numrects);
   791         }
   792     }
   793 }
   794 
   795 void
   796 SDL_WM_SetCaption(const char *title, const char *icon)
   797 {
   798     if (wm_title) {
   799         SDL_free(wm_title);
   800     }
   801     if (title) {
   802         wm_title = SDL_strdup(title);
   803     } else {
   804         wm_title = NULL;
   805     }
   806     SDL_SetWindowTitle(SDL_VideoWindow, wm_title);
   807 }
   808 
   809 void
   810 SDL_WM_GetCaption(const char **title, const char **icon)
   811 {
   812     if (title) {
   813         *title = wm_title;
   814     }
   815     if (icon) {
   816         *icon = "";
   817     }
   818 }
   819 
   820 void
   821 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
   822 {
   823     SDL_VideoIcon = icon;
   824     ++SDL_VideoIcon->refcount;
   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 && SDL_PublicSurface->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     Uint16 red_ramp[256];
  1706     Uint16 green_ramp[256];
  1707     Uint16 blue_ramp[256];
  1708 
  1709     SDL_CalculateGammaRamp(red, red_ramp);
  1710     if (green == red) {
  1711         SDL_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  1712     } else {
  1713         SDL_CalculateGammaRamp(green, green_ramp);
  1714     }
  1715     if (blue == red) {
  1716         SDL_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  1717     } else {
  1718         SDL_CalculateGammaRamp(blue, blue_ramp);
  1719     }
  1720     return SDL_SetWindowGammaRamp(SDL_VideoWindow, red_ramp, green_ramp, blue_ramp);
  1721 }
  1722 
  1723 int
  1724 SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green, const Uint16 * blue)
  1725 {
  1726     return SDL_SetWindowGammaRamp(SDL_VideoWindow, red, green, blue);
  1727 }
  1728 
  1729 int
  1730 SDL_GetGammaRamp(Uint16 * red, Uint16 * green, Uint16 * blue)
  1731 {
  1732     return SDL_GetWindowGammaRamp(SDL_VideoWindow, red, green, blue);
  1733 }
  1734 
  1735 int
  1736 SDL_EnableKeyRepeat(int delay, int interval)
  1737 {
  1738     return 0;
  1739 }
  1740 
  1741 void
  1742 SDL_GetKeyRepeat(int *delay, int *interval)
  1743 {
  1744     if (delay) {
  1745         *delay = SDL_DEFAULT_REPEAT_DELAY;
  1746     }
  1747     if (interval) {
  1748         *interval = SDL_DEFAULT_REPEAT_INTERVAL;
  1749     }
  1750 }
  1751 
  1752 int
  1753 SDL_EnableUNICODE(int enable)
  1754 {
  1755     int previous = SDL_enabled_UNICODE;
  1756 
  1757     switch (enable) {
  1758     case 1:
  1759         SDL_enabled_UNICODE = 1;
  1760         SDL_StartTextInput();
  1761         break;
  1762     case 0:
  1763         SDL_enabled_UNICODE = 0;
  1764         SDL_StopTextInput();
  1765         break;
  1766     }
  1767     return previous;
  1768 }
  1769 
  1770 static Uint32
  1771 SDL_SetTimerCallback(Uint32 interval, void* param)
  1772 {
  1773     return ((SDL_OldTimerCallback)param)(interval);
  1774 }
  1775 
  1776 int
  1777 SDL_SetTimer(Uint32 interval, SDL_OldTimerCallback callback)
  1778 {
  1779     static SDL_TimerID compat_timer;
  1780 
  1781     if (compat_timer) {
  1782         SDL_RemoveTimer(compat_timer);
  1783         compat_timer = 0;
  1784     }
  1785 
  1786     if (interval && callback) {
  1787         compat_timer = SDL_AddTimer(interval, SDL_SetTimerCallback, callback);
  1788         if (!compat_timer) {
  1789             return -1;
  1790         }
  1791     }
  1792     return 0;
  1793 }
  1794 
  1795 int
  1796 SDL_putenv(const char *_var)
  1797 {
  1798     char *ptr = NULL;
  1799     char *var = SDL_strdup(_var);
  1800     if (var == NULL) {
  1801         return -1;  /* we don't set errno. */
  1802     }
  1803 
  1804     ptr = SDL_strchr(var, '=');
  1805     if (ptr == NULL) {
  1806         SDL_free(var);
  1807         return -1;
  1808     }
  1809 
  1810     *ptr = '\0';  /* split the string into name and value. */
  1811     SDL_setenv(var, ptr + 1, 1);
  1812     SDL_free(var);
  1813     return 0;
  1814 }
  1815 
  1816 /* vi: set ts=4 sw=4 expandtab: */