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