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