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