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