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