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