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