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