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