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