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