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