src/SDL_compat.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 05 Aug 2006 17:09:42 +0000
changeset 1965 a788656ca29a
parent 1936 83946ee0ff1f
child 1967 01e29c3e9a29
permissions -rw-r--r--
SDL constants are all uppercase.
     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(SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_LOCAL,
   473                               width, height);
   474     }
   475     if (!SDL_VideoTexture) {
   476         return NULL;
   477     }
   478 
   479     /* Create the screen surface */
   480     SDL_VideoSurface = SDL_CreateRGBSurfaceFromTexture(SDL_VideoTexture);
   481     if (!SDL_VideoSurface) {
   482         return NULL;
   483     }
   484     SDL_VideoSurface->flags |= surface_flags;
   485 
   486     /* Set a default screen palette */
   487     if (SDL_VideoSurface->format->palette) {
   488         SDL_VideoSurface->flags |= SDL_HWPALETTE;
   489         SDL_DitherColors(SDL_VideoSurface->format->palette->colors,
   490                          SDL_VideoSurface->format->BitsPerPixel);
   491         SDL_AddPaletteWatch(SDL_VideoSurface->format->palette,
   492                             SDL_VideoPaletteChanged, NULL);
   493         SDL_SetPaletteColors(SDL_VideoSurface->format->palette,
   494                              SDL_VideoSurface->format->palette->colors, 0,
   495                              SDL_VideoSurface->format->palette->ncolors);
   496     }
   497 
   498     /* Create a shadow surface if necessary */
   499     if (((bpp != SDL_VideoSurface->format->BitsPerPixel)
   500          && !(flags & SDL_ANYFORMAT))
   501         || ((SDL_VideoSurface->flags & SDL_HWSURFACE)
   502             && !(flags & SDL_HWSURFACE))) {
   503         if ((bpp == SDL_VideoSurface->format->BitsPerPixel)
   504             || (flags & SDL_ANYFORMAT)) {
   505             SDL_ShadowSurface =
   506                 SDL_CreateRGBSurface(0, width, height,
   507                                      SDL_VideoSurface->format->BitsPerPixel,
   508                                      SDL_VideoSurface->format->Rmask,
   509                                      SDL_VideoSurface->format->Gmask,
   510                                      SDL_VideoSurface->format->Bmask,
   511                                      SDL_VideoSurface->format->Amask);
   512         } else {
   513             SDL_ShadowSurface =
   514                 SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
   515         }
   516         if (!SDL_ShadowSurface) {
   517             return NULL;
   518         }
   519         SDL_ShadowSurface->flags |= surface_flags;
   520 
   521         /* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
   522         if (SDL_ShadowSurface->format->palette) {
   523             SDL_ShadowSurface->flags |= SDL_HWPALETTE;
   524             if (SDL_VideoSurface->format->palette) {
   525                 SDL_SetSurfacePalette(SDL_ShadowSurface,
   526                                       SDL_VideoSurface->format->palette);
   527             } else {
   528                 SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
   529                                  SDL_ShadowSurface->format->BitsPerPixel);
   530             }
   531         }
   532     }
   533     SDL_PublicSurface =
   534         (SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface);
   535 
   536     /* Clear the surface for display */
   537     SDL_FillRect(SDL_PublicSurface, NULL, 0);
   538     SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
   539 
   540     /* We're finally done! */
   541     return SDL_PublicSurface;
   542 }
   543 
   544 SDL_Surface *
   545 SDL_GetVideoSurface(void)
   546 {
   547     return SDL_PublicSurface;
   548 }
   549 
   550 SDL_Surface *
   551 SDL_DisplayFormat(SDL_Surface * surface)
   552 {
   553     Uint32 flags;
   554 
   555     if (!SDL_PublicSurface) {
   556         SDL_SetError("No video mode has been set");
   557         return NULL;
   558     }
   559 
   560     /* Set the flags appropriate for copying to display surface */
   561     flags = SDL_SWSURFACE;
   562 #ifdef AUTORLE_DISPLAYFORMAT
   563     flags |= (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA));
   564     flags |= SDL_RLEACCELOK;
   565 #else
   566     flags |=
   567         surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_RLEACCELOK);
   568 #endif
   569     return SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags);
   570 }
   571 
   572 SDL_Surface *
   573 SDL_DisplayFormatAlpha(SDL_Surface * surface)
   574 {
   575     SDL_PixelFormat *vf;
   576     SDL_PixelFormat *format;
   577     SDL_Surface *converted;
   578     Uint32 flags;
   579     /* default to ARGB8888 */
   580     Uint32 amask = 0xff000000;
   581     Uint32 rmask = 0x00ff0000;
   582     Uint32 gmask = 0x0000ff00;
   583     Uint32 bmask = 0x000000ff;
   584 
   585     if (!SDL_PublicSurface) {
   586         SDL_SetError("No video mode has been set");
   587         return NULL;
   588     }
   589     vf = SDL_PublicSurface->format;
   590 
   591     switch (vf->BytesPerPixel) {
   592     case 2:
   593         /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
   594            For anything else (like ARGB4444) it doesn't matter
   595            since we have no special code for it anyway */
   596         if ((vf->Rmask == 0x1f) &&
   597             (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
   598             rmask = 0xff;
   599             bmask = 0xff0000;
   600         }
   601         break;
   602 
   603     case 3:
   604     case 4:
   605         /* Keep the video format, as long as the high 8 bits are
   606            unused or alpha */
   607         if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) {
   608             rmask = 0xff;
   609             bmask = 0xff0000;
   610         }
   611         break;
   612 
   613     default:
   614         /* We have no other optimised formats right now. When/if a new
   615            optimised alpha format is written, add the converter here */
   616         break;
   617     }
   618     format = SDL_AllocFormat(32, rmask, gmask, bmask, amask);
   619     flags = SDL_PublicSurface->flags & SDL_HWSURFACE;
   620     flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
   621     converted = SDL_ConvertSurface(surface, format, flags);
   622     SDL_FreeFormat(format);
   623     return converted;
   624 }
   625 
   626 int
   627 SDL_Flip(SDL_Surface * screen)
   628 {
   629     SDL_UpdateRect(screen, 0, 0, 0, 0);
   630     return 0;
   631 }
   632 
   633 void
   634 SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
   635 {
   636     if (screen) {
   637         SDL_Rect rect;
   638 
   639         /* Fill the rectangle */
   640         rect.x = (int) x;
   641         rect.y = (int) y;
   642         rect.w = (int) (w ? w : screen->w);
   643         rect.h = (int) (h ? h : screen->h);
   644         SDL_UpdateRects(screen, 1, &rect);
   645     }
   646 }
   647 void
   648 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
   649 {
   650     int i;
   651 
   652     if (screen == SDL_ShadowSurface) {
   653         for (i = 0; i < numrects; ++i) {
   654             SDL_LowerBlit(SDL_ShadowSurface, &rects[i], SDL_VideoSurface,
   655                           &rects[i]);
   656         }
   657 
   658         /* Fall through to video surface update */
   659         screen = SDL_VideoSurface;
   660     }
   661     if (screen == SDL_VideoSurface) {
   662         if (SDL_VideoRendererInfo.flags & SDL_RENDERER_PRESENTCOPY) {
   663             for (i = 0; i < numrects; ++i) {
   664                 SDL_RenderCopy(SDL_VideoTexture, &rects[i], &rects[i],
   665                                SDL_TEXTUREBLENDMODE_NONE,
   666                                SDL_TEXTURESCALEMODE_NONE);
   667             }
   668         } else {
   669             SDL_Rect rect;
   670             rect.x = 0;
   671             rect.y = 0;
   672             rect.w = screen->w;
   673             rect.h = screen->h;
   674             SDL_RenderCopy(SDL_VideoTexture, &rect, &rect,
   675                            SDL_TEXTUREBLENDMODE_NONE,
   676                            SDL_TEXTURESCALEMODE_NONE);
   677         }
   678         SDL_RenderPresent();
   679     }
   680 }
   681 
   682 void
   683 SDL_WM_SetCaption(const char *title, const char *icon)
   684 {
   685     if (wm_title) {
   686         SDL_free(wm_title);
   687     } else {
   688         wm_title = SDL_strdup(title);
   689     }
   690     SDL_SetWindowTitle(SDL_VideoWindow, wm_title);
   691 }
   692 
   693 void
   694 SDL_WM_GetCaption(char **title, char **icon)
   695 {
   696     if (title) {
   697         *title = wm_title;
   698     }
   699     if (icon) {
   700         *icon = "";
   701     }
   702 }
   703 
   704 void
   705 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
   706 {
   707     /* FIXME */
   708 }
   709 
   710 int
   711 SDL_WM_IconifyWindow(void)
   712 {
   713     SDL_MinimizeWindow(SDL_VideoWindow);
   714     return 0;
   715 }
   716 
   717 int
   718 SDL_WM_ToggleFullScreen(SDL_Surface * surface)
   719 {
   720     if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) {
   721         if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) {
   722             return 0;
   723         }
   724         SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
   725     } else {
   726         if (SDL_SetWindowFullscreen(SDL_VideoWindow, 1) < 0) {
   727             return 0;
   728         }
   729         SDL_PublicSurface->flags |= SDL_FULLSCREEN;
   730     }
   731     return 1;
   732 }
   733 
   734 SDL_GrabMode
   735 SDL_WM_GrabInput(SDL_GrabMode mode)
   736 {
   737     if (mode != SDL_GRAB_QUERY) {
   738         SDL_SetWindowGrab(SDL_VideoWindow, mode);
   739     }
   740     return (SDL_GrabMode) SDL_GetWindowGrab(SDL_VideoWindow);
   741 }
   742 
   743 void
   744 SDL_WarpMouse(Uint16 x, Uint16 y)
   745 {
   746     SDL_WarpMouseInWindow(SDL_VideoWindow, x, y);
   747 }
   748 
   749 Uint8
   750 SDL_GetAppState(void)
   751 {
   752     Uint8 state = 0;
   753     Uint32 flags = 0;
   754 
   755     flags = SDL_GetWindowFlags(SDL_VideoWindow);
   756     if ((flags & SDL_WINDOW_SHOWN) && !(flags & SDL_WINDOW_MINIMIZED)) {
   757         state |= SDL_APPACTIVE;
   758     }
   759     if (flags & SDL_WINDOW_INPUT_FOCUS) {
   760         state |= SDL_APPINPUTFOCUS;
   761     }
   762     if (flags & SDL_WINDOW_MOUSE_FOCUS) {
   763         state |= SDL_APPMOUSEFOCUS;
   764     }
   765     return state;
   766 }
   767 
   768 const SDL_version *
   769 SDL_Linked_Version(void)
   770 {
   771     static SDL_version version;
   772     SDL_VERSION(&version);
   773     return &version;
   774 }
   775 
   776 int
   777 SDL_SetPalette(SDL_Surface * surface, int flags, const SDL_Color * colors,
   778                int firstcolor, int ncolors)
   779 {
   780     return SDL_SetColors(surface, colors, firstcolor, ncolors);
   781 }
   782 
   783 int
   784 SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor,
   785               int ncolors)
   786 {
   787     if (SDL_SetPaletteColors
   788         (surface->format->palette, colors, firstcolor, ncolors) == 0) {
   789         return 1;
   790     } else {
   791         return 0;
   792     }
   793 }
   794 
   795 int
   796 SDL_GetWMInfo(SDL_SysWMinfo * info)
   797 {
   798     return SDL_GetWindowWMInfo(SDL_VideoWindow, info);
   799 }
   800 
   801 #if 0
   802 void
   803 SDL_MoveCursor(int x, int y)
   804 {
   805     SDL_VideoDevice *_this = SDL_GetVideoDevice();
   806 
   807     /* Erase and update the current mouse position */
   808     if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
   809         /* Erase and redraw mouse cursor in new position */
   810         SDL_LockCursor();
   811         SDL_EraseCursor(SDL_VideoSurface);
   812         SDL_cursor->area.x = (x - SDL_cursor->hot_x);
   813         SDL_cursor->area.y = (y - SDL_cursor->hot_y);
   814         SDL_DrawCursor(SDL_VideoSurface);
   815         SDL_UnlockCursor();
   816     } else if (_this->MoveWMCursor) {
   817         _this->MoveWMCursor(_this, x, y);
   818     }
   819 }
   820 
   821 /* Keep track of the current cursor colors */
   822 static int palette_changed = 1;
   823 static Uint8 pixels8[2];
   824 
   825 void
   826 SDL_CursorPaletteChanged(void)
   827 {
   828     palette_changed = 1;
   829 }
   830 
   831 void
   832 SDL_MouseRect(SDL_Rect * area)
   833 {
   834     SDL_VideoDevice *_this = SDL_GetVideoDevice();
   835     int clip_diff;
   836 
   837     *area = SDL_cursor->area;
   838     if (area->x < 0) {
   839         area->w += area->x;
   840         area->x = 0;
   841     }
   842     if (area->y < 0) {
   843         area->h += area->y;
   844         area->y = 0;
   845     }
   846     clip_diff = (area->x + area->w) - SDL_VideoSurface->w;
   847     if (clip_diff > 0) {
   848         area->w = area->w < clip_diff ? 0 : area->w - clip_diff;
   849     }
   850     clip_diff = (area->y + area->h) - SDL_VideoSurface->h;
   851     if (clip_diff > 0) {
   852         area->h = area->h < clip_diff ? 0 : area->h - clip_diff;
   853     }
   854 }
   855 
   856 static void
   857 SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area)
   858 {
   859     const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
   860     int i, w, h;
   861     Uint8 *data, datab;
   862     Uint8 *mask, maskb;
   863 
   864     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
   865     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
   866     switch (screen->format->BytesPerPixel) {
   867 
   868     case 1:
   869         {
   870             Uint8 *dst;
   871             int dstskip;
   872 
   873             if (palette_changed) {
   874                 pixels8[0] =
   875                     (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
   876                 pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
   877                 palette_changed = 0;
   878             }
   879             dst = (Uint8 *) screen->pixels +
   880                 (SDL_cursor->area.y + area->y) * screen->pitch +
   881                 SDL_cursor->area.x;
   882             dstskip = screen->pitch - area->w;
   883 
   884             for (h = area->h; h; h--) {
   885                 for (w = area->w / 8; w; w--) {
   886                     maskb = *mask++;
   887                     datab = *data++;
   888                     for (i = 0; i < 8; ++i) {
   889                         if (maskb & 0x80) {
   890                             *dst = pixels8[datab >> 7];
   891                         }
   892                         maskb <<= 1;
   893                         datab <<= 1;
   894                         dst++;
   895                     }
   896                 }
   897                 dst += dstskip;
   898             }
   899         }
   900         break;
   901 
   902     case 2:
   903         {
   904             Uint16 *dst;
   905             int dstskip;
   906 
   907             dst = (Uint16 *) screen->pixels +
   908                 (SDL_cursor->area.y + area->y) * screen->pitch / 2 +
   909                 SDL_cursor->area.x;
   910             dstskip = (screen->pitch / 2) - area->w;
   911 
   912             for (h = area->h; h; h--) {
   913                 for (w = area->w / 8; w; w--) {
   914                     maskb = *mask++;
   915                     datab = *data++;
   916                     for (i = 0; i < 8; ++i) {
   917                         if (maskb & 0x80) {
   918                             *dst = (Uint16) pixels[datab >> 7];
   919                         }
   920                         maskb <<= 1;
   921                         datab <<= 1;
   922                         dst++;
   923                     }
   924                 }
   925                 dst += dstskip;
   926             }
   927         }
   928         break;
   929 
   930     case 3:
   931         {
   932             Uint8 *dst;
   933             int dstskip;
   934 
   935             dst = (Uint8 *) screen->pixels +
   936                 (SDL_cursor->area.y + area->y) * screen->pitch +
   937                 SDL_cursor->area.x * 3;
   938             dstskip = screen->pitch - area->w * 3;
   939 
   940             for (h = area->h; h; h--) {
   941                 for (w = area->w / 8; w; w--) {
   942                     maskb = *mask++;
   943                     datab = *data++;
   944                     for (i = 0; i < 8; ++i) {
   945                         if (maskb & 0x80) {
   946                             SDL_memset(dst, pixels[datab >> 7], 3);
   947                         }
   948                         maskb <<= 1;
   949                         datab <<= 1;
   950                         dst += 3;
   951                     }
   952                 }
   953                 dst += dstskip;
   954             }
   955         }
   956         break;
   957 
   958     case 4:
   959         {
   960             Uint32 *dst;
   961             int dstskip;
   962 
   963             dst = (Uint32 *) screen->pixels +
   964                 (SDL_cursor->area.y + area->y) * screen->pitch / 4 +
   965                 SDL_cursor->area.x;
   966             dstskip = (screen->pitch / 4) - area->w;
   967 
   968             for (h = area->h; h; h--) {
   969                 for (w = area->w / 8; w; w--) {
   970                     maskb = *mask++;
   971                     datab = *data++;
   972                     for (i = 0; i < 8; ++i) {
   973                         if (maskb & 0x80) {
   974                             *dst = pixels[datab >> 7];
   975                         }
   976                         maskb <<= 1;
   977                         datab <<= 1;
   978                         dst++;
   979                     }
   980                 }
   981                 dst += dstskip;
   982             }
   983         }
   984         break;
   985     }
   986 }
   987 
   988 static void
   989 SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area)
   990 {
   991     const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
   992     int h;
   993     int x, minx, maxx;
   994     Uint8 *data, datab = 0;
   995     Uint8 *mask, maskb = 0;
   996     Uint8 *dst;
   997     int dstbpp, dstskip;
   998 
   999     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  1000     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  1001     dstbpp = screen->format->BytesPerPixel;
  1002     dst = (Uint8 *) screen->pixels +
  1003         (SDL_cursor->area.y + area->y) * screen->pitch +
  1004         SDL_cursor->area.x * dstbpp;
  1005     dstskip = screen->pitch - SDL_cursor->area.w * dstbpp;
  1006 
  1007     minx = area->x;
  1008     maxx = area->x + area->w;
  1009     if (screen->format->BytesPerPixel == 1) {
  1010         if (palette_changed) {
  1011             pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  1012             pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  1013             palette_changed = 0;
  1014         }
  1015         for (h = area->h; h; h--) {
  1016             for (x = 0; x < SDL_cursor->area.w; ++x) {
  1017                 if ((x % 8) == 0) {
  1018                     maskb = *mask++;
  1019                     datab = *data++;
  1020                 }
  1021                 if ((x >= minx) && (x < maxx)) {
  1022                     if (maskb & 0x80) {
  1023                         SDL_memset(dst, pixels8[datab >> 7], dstbpp);
  1024                     }
  1025                 }
  1026                 maskb <<= 1;
  1027                 datab <<= 1;
  1028                 dst += dstbpp;
  1029             }
  1030             dst += dstskip;
  1031         }
  1032     } else {
  1033         for (h = area->h; h; h--) {
  1034             for (x = 0; x < SDL_cursor->area.w; ++x) {
  1035                 if ((x % 8) == 0) {
  1036                     maskb = *mask++;
  1037                     datab = *data++;
  1038                 }
  1039                 if ((x >= minx) && (x < maxx)) {
  1040                     if (maskb & 0x80) {
  1041                         SDL_memset(dst, pixels[datab >> 7], dstbpp);
  1042                     }
  1043                 }
  1044                 maskb <<= 1;
  1045                 datab <<= 1;
  1046                 dst += dstbpp;
  1047             }
  1048             dst += dstskip;
  1049         }
  1050     }
  1051 }
  1052 
  1053 /* This handles the ugly work of converting the saved cursor background from
  1054    the pixel format of the shadow surface to that of the video surface.
  1055    This is only necessary when blitting from a shadow surface of a different
  1056    pixel format than the video surface, and using a software rendered cursor.
  1057 */
  1058 static void
  1059 SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h)
  1060 {
  1061     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1062     SDL_BlitInfo info;
  1063     SDL_loblit RunBlit;
  1064 
  1065     /* Make sure we can steal the blit mapping */
  1066     if (screen->map->dst != SDL_VideoSurface) {
  1067         return;
  1068     }
  1069 
  1070     /* Set up the blit information */
  1071     info.s_pixels = SDL_cursor->save[1];
  1072     info.s_width = w;
  1073     info.s_height = h;
  1074     info.s_skip = 0;
  1075     info.d_pixels = SDL_cursor->save[0];
  1076     info.d_width = w;
  1077     info.d_height = h;
  1078     info.d_skip = 0;
  1079     info.aux_data = screen->map->sw_data->aux_data;
  1080     info.src = screen->format;
  1081     info.table = screen->map->table;
  1082     info.dst = SDL_VideoSurface->format;
  1083     RunBlit = screen->map->sw_data->blit;
  1084 
  1085     /* Run the actual software blit */
  1086     RunBlit(&info);
  1087 }
  1088 
  1089 void
  1090 SDL_DrawCursorNoLock(SDL_Surface * screen)
  1091 {
  1092     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1093     SDL_Rect area;
  1094 
  1095     /* Get the mouse rectangle, clipped to the screen */
  1096     SDL_MouseRect(&area);
  1097     if ((area.w == 0) || (area.h == 0)) {
  1098         return;
  1099     }
  1100 
  1101     /* Copy mouse background */
  1102     {
  1103         int w, h, screenbpp;
  1104         Uint8 *src, *dst;
  1105 
  1106         /* Set up the copy pointers */
  1107         screenbpp = screen->format->BytesPerPixel;
  1108         if ((screen == SDL_VideoSurface) ||
  1109             FORMAT_EQUAL(screen->format, SDL_VideoSurface->format)) {
  1110             dst = SDL_cursor->save[0];
  1111         } else {
  1112             dst = SDL_cursor->save[1];
  1113         }
  1114         src = (Uint8 *) screen->pixels + area.y * screen->pitch +
  1115             area.x * screenbpp;
  1116 
  1117         /* Perform the copy */
  1118         w = area.w * screenbpp;
  1119         h = area.h;
  1120         while (h--) {
  1121             SDL_memcpy(dst, src, w);
  1122             dst += w;
  1123             src += screen->pitch;
  1124         }
  1125     }
  1126 
  1127     /* Draw the mouse cursor */
  1128     area.x -= SDL_cursor->area.x;
  1129     area.y -= SDL_cursor->area.y;
  1130     if ((area.x == 0) && (area.w == SDL_cursor->area.w)) {
  1131         SDL_DrawCursorFast(screen, &area);
  1132     } else {
  1133         SDL_DrawCursorSlow(screen, &area);
  1134     }
  1135 }
  1136 
  1137 void
  1138 SDL_DrawCursor(SDL_Surface * screen)
  1139 {
  1140     /* Lock the screen if necessary */
  1141     if (screen == NULL) {
  1142         return;
  1143     }
  1144     if (SDL_MUSTLOCK(screen)) {
  1145         if (SDL_LockSurface(screen) < 0) {
  1146             return;
  1147         }
  1148     }
  1149 
  1150     SDL_DrawCursorNoLock(screen);
  1151 
  1152     /* Unlock the screen and update if necessary */
  1153     if (SDL_MUSTLOCK(screen)) {
  1154         SDL_UnlockSurface(screen);
  1155     }
  1156     if ((screen->flags & SDL_SCREEN_SURFACE) &&
  1157         !(screen->flags & SDL_HWSURFACE)) {
  1158         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1159         SDL_Window *window;
  1160         SDL_Rect area;
  1161 
  1162         window = SDL_GetWindowFromSurface(screen);
  1163         if (!window) {
  1164             return;
  1165         }
  1166 
  1167         SDL_MouseRect(&area);
  1168 
  1169         if (_this->UpdateWindowSurface) {
  1170             _this->UpdateWindowSurface(_this, window, 1, &area);
  1171         }
  1172     }
  1173 }
  1174 
  1175 void
  1176 SDL_EraseCursorNoLock(SDL_Surface * screen)
  1177 {
  1178     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1179     SDL_Window *window;
  1180     SDL_Rect area;
  1181 
  1182     /* Get the window associated with the surface */
  1183     window = SDL_GetWindowFromSurface(screen);
  1184     if (!window || !window->surface) {
  1185         return;
  1186     }
  1187 
  1188     /* Get the mouse rectangle, clipped to the screen */
  1189     SDL_MouseRect(&area);
  1190     if ((area.w == 0) || (area.h == 0)) {
  1191         return;
  1192     }
  1193 
  1194     /* Copy mouse background */
  1195     {
  1196         int w, h, screenbpp;
  1197         Uint8 *src, *dst;
  1198 
  1199         /* Set up the copy pointers */
  1200         screenbpp = screen->format->BytesPerPixel;
  1201         if ((screen->flags & SDL_SCREEN_SURFACE) ||
  1202             FORMAT_EQUAL(screen->format, window->surface->format)) {
  1203             src = SDL_cursor->save[0];
  1204         } else {
  1205             src = SDL_cursor->save[1];
  1206         }
  1207         dst = (Uint8 *) screen->pixels + area.y * screen->pitch +
  1208             area.x * screenbpp;
  1209 
  1210         /* Perform the copy */
  1211         w = area.w * screenbpp;
  1212         h = area.h;
  1213         while (h--) {
  1214             SDL_memcpy(dst, src, w);
  1215             src += w;
  1216             dst += screen->pitch;
  1217         }
  1218 
  1219         /* Perform pixel conversion on cursor background */
  1220         if (src > SDL_cursor->save[1]) {
  1221             SDL_ConvertCursorSave(screen, area.w, area.h);
  1222         }
  1223     }
  1224 }
  1225 
  1226 void
  1227 SDL_EraseCursor(SDL_Surface * screen)
  1228 {
  1229     /* Lock the screen if necessary */
  1230     if (screen == NULL) {
  1231         return;
  1232     }
  1233     if (SDL_MUSTLOCK(screen)) {
  1234         if (SDL_LockSurface(screen) < 0) {
  1235             return;
  1236         }
  1237     }
  1238 
  1239     SDL_EraseCursorNoLock(screen);
  1240 
  1241     /* Unlock the screen and update if necessary */
  1242     if (SDL_MUSTLOCK(screen)) {
  1243         SDL_UnlockSurface(screen);
  1244     }
  1245     if ((screen->flags & SDL_SCREEN_SURFACE) &&
  1246         !(screen->flags & SDL_HWSURFACE)) {
  1247         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1248         SDL_Window *window;
  1249         SDL_Rect area;
  1250 
  1251         window = SDL_GetWindowFromSurface(screen);
  1252         if (!window) {
  1253             return;
  1254         }
  1255 
  1256         SDL_MouseRect(&area);
  1257 
  1258         if (_this->UpdateWindowSurface) {
  1259             _this->UpdateWindowSurface(_this, window, 1, &area);
  1260         }
  1261     }
  1262 }
  1263 
  1264 /* Reset the cursor on video mode change
  1265    FIXME:  Keep track of all cursors, and reset them all.
  1266  */
  1267 void
  1268 SDL_ResetCursor(void)
  1269 {
  1270     int savelen;
  1271 
  1272     if (SDL_cursor) {
  1273         savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h;
  1274         SDL_cursor->area.x = 0;
  1275         SDL_cursor->area.y = 0;
  1276         SDL_memset(SDL_cursor->save[0], 0, savelen);
  1277     }
  1278 }
  1279 #endif
  1280 
  1281 struct private_yuvhwdata
  1282 {
  1283     Uint16 pitches[3];
  1284     Uint8 *planes[3];
  1285 
  1286     SDL_TextureID textureID;
  1287 };
  1288 
  1289 SDL_Overlay *
  1290 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
  1291 {
  1292     SDL_Overlay *overlay;
  1293     Uint32 texture_format;
  1294 
  1295     if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
  1296         SDL_SetError("YUV overlays are not supported in OpenGL mode");
  1297         return NULL;
  1298     }
  1299 
  1300     if (display != SDL_PublicSurface) {
  1301         SDL_SetError("YUV display is only supported on the screen surface");
  1302         return NULL;
  1303     }
  1304 
  1305     switch (format) {
  1306     case SDL_YV12_OVERLAY:
  1307         texture_format = SDL_PIXELFORMAT_YV12;
  1308         break;
  1309     case SDL_IYUV_OVERLAY:
  1310         texture_format = SDL_PIXELFORMAT_IYUV;
  1311         break;
  1312     case SDL_YUY2_OVERLAY:
  1313         texture_format = SDL_PIXELFORMAT_YUY2;
  1314         break;
  1315     case SDL_UYVY_OVERLAY:
  1316         texture_format = SDL_PIXELFORMAT_UYVY;
  1317         break;
  1318     case SDL_YVYU_OVERLAY:
  1319         texture_format = SDL_PIXELFORMAT_YVYU;
  1320         break;
  1321     default:
  1322         SDL_SetError("Unknown YUV format");
  1323         return NULL;
  1324     }
  1325 
  1326     overlay = (SDL_Overlay *) SDL_malloc(sizeof(*overlay));
  1327     if (!overlay) {
  1328         SDL_OutOfMemory();
  1329         return NULL;
  1330     }
  1331     SDL_zerop(overlay);
  1332 
  1333     overlay->hwdata =
  1334         (struct private_yuvhwdata *) SDL_malloc(sizeof(*overlay->hwdata));
  1335     if (!overlay->hwdata) {
  1336         SDL_free(overlay);
  1337         SDL_OutOfMemory();
  1338         return NULL;
  1339     }
  1340 
  1341     overlay->format = format;
  1342     overlay->w = w;
  1343     overlay->h = h;
  1344     if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
  1345         overlay->planes = 3;
  1346     } else {
  1347         overlay->planes = 1;
  1348     }
  1349     overlay->pitches = overlay->hwdata->pitches;
  1350     overlay->pixels = overlay->hwdata->planes;
  1351 
  1352     switch (format) {
  1353     case SDL_YV12_OVERLAY:
  1354     case SDL_IYUV_OVERLAY:
  1355         overlay->pitches[0] = overlay->w;
  1356         overlay->pitches[1] = overlay->w / 2;
  1357         overlay->pitches[2] = overlay->w / 2;
  1358         break;
  1359     case SDL_YUY2_OVERLAY:
  1360     case SDL_UYVY_OVERLAY:
  1361     case SDL_YVYU_OVERLAY:
  1362         overlay->pitches[0] = overlay->w * 2;
  1363         break;
  1364     }
  1365 
  1366     overlay->hwdata->textureID =
  1367         SDL_CreateTexture(texture_format, SDL_TEXTUREACCESS_LOCAL, w, h);
  1368     if (!overlay->hwdata->textureID) {
  1369         SDL_FreeYUVOverlay(overlay);
  1370         return NULL;
  1371     }
  1372 
  1373     return overlay;
  1374 }
  1375 
  1376 int
  1377 SDL_LockYUVOverlay(SDL_Overlay * overlay)
  1378 {
  1379     void *pixels;
  1380     int pitch;
  1381     if (SDL_LockTexture(overlay->hwdata->textureID, NULL, 1, &pixels, &pitch)
  1382         < 0) {
  1383         return -1;
  1384     }
  1385     switch (overlay->format) {
  1386     case SDL_YV12_OVERLAY:
  1387     case SDL_IYUV_OVERLAY:
  1388         overlay->pixels[0] = (Uint8 *) pixels;
  1389         overlay->pixels[1] =
  1390             overlay->pixels[0] + overlay->pitches[0] * overlay->h;
  1391         overlay->pixels[2] =
  1392             overlay->pixels[1] + overlay->pitches[1] * overlay->h;
  1393         break;
  1394     case SDL_YUY2_OVERLAY:
  1395     case SDL_UYVY_OVERLAY:
  1396     case SDL_YVYU_OVERLAY:
  1397         overlay->pixels[0] = (Uint8 *) pixels;
  1398         break;
  1399     }
  1400     return 0;
  1401 }
  1402 
  1403 void
  1404 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
  1405 {
  1406     SDL_UnlockTexture(overlay->hwdata->textureID);
  1407 }
  1408 
  1409 int
  1410 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
  1411 {
  1412     if (SDL_RenderCopy(overlay->hwdata->textureID, NULL, dstrect,
  1413                        SDL_TEXTUREBLENDMODE_NONE,
  1414                        SDL_TEXTURESCALEMODE_FAST) < 0) {
  1415         return -1;
  1416     }
  1417     SDL_RenderPresent();
  1418     return 0;
  1419 }
  1420 
  1421 void
  1422 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
  1423 {
  1424     if (overlay) {
  1425         if (overlay->hwdata) {
  1426             if (overlay->hwdata->textureID) {
  1427                 SDL_DestroyTexture(overlay->hwdata->textureID);
  1428             }
  1429             SDL_free(overlay->hwdata);
  1430         }
  1431         SDL_free(overlay);
  1432     }
  1433 }
  1434 
  1435 void
  1436 SDL_GL_SwapBuffers(void)
  1437 {
  1438     SDL_GL_SwapWindow(SDL_VideoWindow);
  1439 }
  1440 
  1441 /* vi: set ts=4 sw=4 expandtab: */