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