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