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