src/SDL_compat.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 15 Jun 2006 07:07:07 +0000
branchSDL-1.3
changeset 1681 80a5e6a4e1e2
parent 1680 9488fca10677
child 1682 7ae8018b2e5d
permissions -rw-r--r--
Working on paletted display and texture support (two different issues)
     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         SDL_SetDisplayPalette(SDL_VideoSurface->format->palette->colors, 0,
   670                               SDL_VideoSurface->format->palette->ncolors);
   671     }
   672 
   673     return gotall;
   674 }
   675 
   676 int
   677 SDL_GetWMInfo(SDL_SysWMinfo * info)
   678 {
   679     return SDL_GetWindowWMInfo(SDL_VideoWindow, info);
   680 }
   681 
   682 #if 0
   683 void
   684 SDL_MoveCursor(int x, int y)
   685 {
   686     SDL_VideoDevice *_this = SDL_GetVideoDevice();
   687 
   688     /* Erase and update the current mouse position */
   689     if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
   690         /* Erase and redraw mouse cursor in new position */
   691         SDL_LockCursor();
   692         SDL_EraseCursor(SDL_VideoSurface);
   693         SDL_cursor->area.x = (x - SDL_cursor->hot_x);
   694         SDL_cursor->area.y = (y - SDL_cursor->hot_y);
   695         SDL_DrawCursor(SDL_VideoSurface);
   696         SDL_UnlockCursor();
   697     } else if (_this->MoveWMCursor) {
   698         _this->MoveWMCursor(_this, x, y);
   699     }
   700 }
   701 
   702 /* Keep track of the current cursor colors */
   703 static int palette_changed = 1;
   704 static Uint8 pixels8[2];
   705 
   706 void
   707 SDL_CursorPaletteChanged(void)
   708 {
   709     palette_changed = 1;
   710 }
   711 
   712 void
   713 SDL_MouseRect(SDL_Rect * area)
   714 {
   715     SDL_VideoDevice *_this = SDL_GetVideoDevice();
   716     int clip_diff;
   717 
   718     *area = SDL_cursor->area;
   719     if (area->x < 0) {
   720         area->w += area->x;
   721         area->x = 0;
   722     }
   723     if (area->y < 0) {
   724         area->h += area->y;
   725         area->y = 0;
   726     }
   727     clip_diff = (area->x + area->w) - SDL_VideoSurface->w;
   728     if (clip_diff > 0) {
   729         area->w = area->w < clip_diff ? 0 : area->w - clip_diff;
   730     }
   731     clip_diff = (area->y + area->h) - SDL_VideoSurface->h;
   732     if (clip_diff > 0) {
   733         area->h = area->h < clip_diff ? 0 : area->h - clip_diff;
   734     }
   735 }
   736 
   737 static void
   738 SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area)
   739 {
   740     const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
   741     int i, w, h;
   742     Uint8 *data, datab;
   743     Uint8 *mask, maskb;
   744 
   745     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
   746     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
   747     switch (screen->format->BytesPerPixel) {
   748 
   749     case 1:
   750         {
   751             Uint8 *dst;
   752             int dstskip;
   753 
   754             if (palette_changed) {
   755                 pixels8[0] =
   756                     (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
   757                 pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
   758                 palette_changed = 0;
   759             }
   760             dst = (Uint8 *) screen->pixels +
   761                 (SDL_cursor->area.y + area->y) * screen->pitch +
   762                 SDL_cursor->area.x;
   763             dstskip = screen->pitch - area->w;
   764 
   765             for (h = area->h; h; h--) {
   766                 for (w = area->w / 8; w; w--) {
   767                     maskb = *mask++;
   768                     datab = *data++;
   769                     for (i = 0; i < 8; ++i) {
   770                         if (maskb & 0x80) {
   771                             *dst = pixels8[datab >> 7];
   772                         }
   773                         maskb <<= 1;
   774                         datab <<= 1;
   775                         dst++;
   776                     }
   777                 }
   778                 dst += dstskip;
   779             }
   780         }
   781         break;
   782 
   783     case 2:
   784         {
   785             Uint16 *dst;
   786             int dstskip;
   787 
   788             dst = (Uint16 *) screen->pixels +
   789                 (SDL_cursor->area.y + area->y) * screen->pitch / 2 +
   790                 SDL_cursor->area.x;
   791             dstskip = (screen->pitch / 2) - area->w;
   792 
   793             for (h = area->h; h; h--) {
   794                 for (w = area->w / 8; w; w--) {
   795                     maskb = *mask++;
   796                     datab = *data++;
   797                     for (i = 0; i < 8; ++i) {
   798                         if (maskb & 0x80) {
   799                             *dst = (Uint16) pixels[datab >> 7];
   800                         }
   801                         maskb <<= 1;
   802                         datab <<= 1;
   803                         dst++;
   804                     }
   805                 }
   806                 dst += dstskip;
   807             }
   808         }
   809         break;
   810 
   811     case 3:
   812         {
   813             Uint8 *dst;
   814             int dstskip;
   815 
   816             dst = (Uint8 *) screen->pixels +
   817                 (SDL_cursor->area.y + area->y) * screen->pitch +
   818                 SDL_cursor->area.x * 3;
   819             dstskip = screen->pitch - area->w * 3;
   820 
   821             for (h = area->h; h; h--) {
   822                 for (w = area->w / 8; w; w--) {
   823                     maskb = *mask++;
   824                     datab = *data++;
   825                     for (i = 0; i < 8; ++i) {
   826                         if (maskb & 0x80) {
   827                             SDL_memset(dst, pixels[datab >> 7], 3);
   828                         }
   829                         maskb <<= 1;
   830                         datab <<= 1;
   831                         dst += 3;
   832                     }
   833                 }
   834                 dst += dstskip;
   835             }
   836         }
   837         break;
   838 
   839     case 4:
   840         {
   841             Uint32 *dst;
   842             int dstskip;
   843 
   844             dst = (Uint32 *) screen->pixels +
   845                 (SDL_cursor->area.y + area->y) * screen->pitch / 4 +
   846                 SDL_cursor->area.x;
   847             dstskip = (screen->pitch / 4) - area->w;
   848 
   849             for (h = area->h; h; h--) {
   850                 for (w = area->w / 8; w; w--) {
   851                     maskb = *mask++;
   852                     datab = *data++;
   853                     for (i = 0; i < 8; ++i) {
   854                         if (maskb & 0x80) {
   855                             *dst = pixels[datab >> 7];
   856                         }
   857                         maskb <<= 1;
   858                         datab <<= 1;
   859                         dst++;
   860                     }
   861                 }
   862                 dst += dstskip;
   863             }
   864         }
   865         break;
   866     }
   867 }
   868 
   869 static void
   870 SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area)
   871 {
   872     const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
   873     int h;
   874     int x, minx, maxx;
   875     Uint8 *data, datab = 0;
   876     Uint8 *mask, maskb = 0;
   877     Uint8 *dst;
   878     int dstbpp, dstskip;
   879 
   880     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
   881     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
   882     dstbpp = screen->format->BytesPerPixel;
   883     dst = (Uint8 *) screen->pixels +
   884         (SDL_cursor->area.y + area->y) * screen->pitch +
   885         SDL_cursor->area.x * dstbpp;
   886     dstskip = screen->pitch - SDL_cursor->area.w * dstbpp;
   887 
   888     minx = area->x;
   889     maxx = area->x + area->w;
   890     if (screen->format->BytesPerPixel == 1) {
   891         if (palette_changed) {
   892             pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
   893             pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
   894             palette_changed = 0;
   895         }
   896         for (h = area->h; h; h--) {
   897             for (x = 0; x < SDL_cursor->area.w; ++x) {
   898                 if ((x % 8) == 0) {
   899                     maskb = *mask++;
   900                     datab = *data++;
   901                 }
   902                 if ((x >= minx) && (x < maxx)) {
   903                     if (maskb & 0x80) {
   904                         SDL_memset(dst, pixels8[datab >> 7], dstbpp);
   905                     }
   906                 }
   907                 maskb <<= 1;
   908                 datab <<= 1;
   909                 dst += dstbpp;
   910             }
   911             dst += dstskip;
   912         }
   913     } else {
   914         for (h = area->h; h; h--) {
   915             for (x = 0; x < SDL_cursor->area.w; ++x) {
   916                 if ((x % 8) == 0) {
   917                     maskb = *mask++;
   918                     datab = *data++;
   919                 }
   920                 if ((x >= minx) && (x < maxx)) {
   921                     if (maskb & 0x80) {
   922                         SDL_memset(dst, pixels[datab >> 7], dstbpp);
   923                     }
   924                 }
   925                 maskb <<= 1;
   926                 datab <<= 1;
   927                 dst += dstbpp;
   928             }
   929             dst += dstskip;
   930         }
   931     }
   932 }
   933 
   934 /* This handles the ugly work of converting the saved cursor background from
   935    the pixel format of the shadow surface to that of the video surface.
   936    This is only necessary when blitting from a shadow surface of a different
   937    pixel format than the video surface, and using a software rendered cursor.
   938 */
   939 static void
   940 SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h)
   941 {
   942     SDL_VideoDevice *_this = SDL_GetVideoDevice();
   943     SDL_BlitInfo info;
   944     SDL_loblit RunBlit;
   945 
   946     /* Make sure we can steal the blit mapping */
   947     if (screen->map->dst != SDL_VideoSurface) {
   948         return;
   949     }
   950 
   951     /* Set up the blit information */
   952     info.s_pixels = SDL_cursor->save[1];
   953     info.s_width = w;
   954     info.s_height = h;
   955     info.s_skip = 0;
   956     info.d_pixels = SDL_cursor->save[0];
   957     info.d_width = w;
   958     info.d_height = h;
   959     info.d_skip = 0;
   960     info.aux_data = screen->map->sw_data->aux_data;
   961     info.src = screen->format;
   962     info.table = screen->map->table;
   963     info.dst = SDL_VideoSurface->format;
   964     RunBlit = screen->map->sw_data->blit;
   965 
   966     /* Run the actual software blit */
   967     RunBlit(&info);
   968 }
   969 
   970 void
   971 SDL_DrawCursorNoLock(SDL_Surface * screen)
   972 {
   973     SDL_VideoDevice *_this = SDL_GetVideoDevice();
   974     SDL_Rect area;
   975 
   976     /* Get the mouse rectangle, clipped to the screen */
   977     SDL_MouseRect(&area);
   978     if ((area.w == 0) || (area.h == 0)) {
   979         return;
   980     }
   981 
   982     /* Copy mouse background */
   983     {
   984         int w, h, screenbpp;
   985         Uint8 *src, *dst;
   986 
   987         /* Set up the copy pointers */
   988         screenbpp = screen->format->BytesPerPixel;
   989         if ((screen == SDL_VideoSurface) ||
   990             FORMAT_EQUAL(screen->format, SDL_VideoSurface->format)) {
   991             dst = SDL_cursor->save[0];
   992         } else {
   993             dst = SDL_cursor->save[1];
   994         }
   995         src = (Uint8 *) screen->pixels + area.y * screen->pitch +
   996             area.x * screenbpp;
   997 
   998         /* Perform the copy */
   999         w = area.w * screenbpp;
  1000         h = area.h;
  1001         while (h--) {
  1002             SDL_memcpy(dst, src, w);
  1003             dst += w;
  1004             src += screen->pitch;
  1005         }
  1006     }
  1007 
  1008     /* Draw the mouse cursor */
  1009     area.x -= SDL_cursor->area.x;
  1010     area.y -= SDL_cursor->area.y;
  1011     if ((area.x == 0) && (area.w == SDL_cursor->area.w)) {
  1012         SDL_DrawCursorFast(screen, &area);
  1013     } else {
  1014         SDL_DrawCursorSlow(screen, &area);
  1015     }
  1016 }
  1017 
  1018 void
  1019 SDL_DrawCursor(SDL_Surface * screen)
  1020 {
  1021     /* Lock the screen if necessary */
  1022     if (screen == NULL) {
  1023         return;
  1024     }
  1025     if (SDL_MUSTLOCK(screen)) {
  1026         if (SDL_LockSurface(screen) < 0) {
  1027             return;
  1028         }
  1029     }
  1030 
  1031     SDL_DrawCursorNoLock(screen);
  1032 
  1033     /* Unlock the screen and update if necessary */
  1034     if (SDL_MUSTLOCK(screen)) {
  1035         SDL_UnlockSurface(screen);
  1036     }
  1037     if ((screen->flags & SDL_SCREEN_SURFACE) &&
  1038         !(screen->flags & SDL_HWSURFACE)) {
  1039         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1040         SDL_Window *window;
  1041         SDL_Rect area;
  1042 
  1043         window = SDL_GetWindowFromSurface(screen);
  1044         if (!window) {
  1045             return;
  1046         }
  1047 
  1048         SDL_MouseRect(&area);
  1049 
  1050         if (_this->UpdateWindowSurface) {
  1051             _this->UpdateWindowSurface(_this, window, 1, &area);
  1052         }
  1053     }
  1054 }
  1055 
  1056 void
  1057 SDL_EraseCursorNoLock(SDL_Surface * screen)
  1058 {
  1059     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1060     SDL_Window *window;
  1061     SDL_Rect area;
  1062 
  1063     /* Get the window associated with the surface */
  1064     window = SDL_GetWindowFromSurface(screen);
  1065     if (!window || !window->surface) {
  1066         return;
  1067     }
  1068 
  1069     /* Get the mouse rectangle, clipped to the screen */
  1070     SDL_MouseRect(&area);
  1071     if ((area.w == 0) || (area.h == 0)) {
  1072         return;
  1073     }
  1074 
  1075     /* Copy mouse background */
  1076     {
  1077         int w, h, screenbpp;
  1078         Uint8 *src, *dst;
  1079 
  1080         /* Set up the copy pointers */
  1081         screenbpp = screen->format->BytesPerPixel;
  1082         if ((screen->flags & SDL_SCREEN_SURFACE) ||
  1083             FORMAT_EQUAL(screen->format, window->surface->format)) {
  1084             src = SDL_cursor->save[0];
  1085         } else {
  1086             src = SDL_cursor->save[1];
  1087         }
  1088         dst = (Uint8 *) screen->pixels + area.y * screen->pitch +
  1089             area.x * screenbpp;
  1090 
  1091         /* Perform the copy */
  1092         w = area.w * screenbpp;
  1093         h = area.h;
  1094         while (h--) {
  1095             SDL_memcpy(dst, src, w);
  1096             src += w;
  1097             dst += screen->pitch;
  1098         }
  1099 
  1100         /* Perform pixel conversion on cursor background */
  1101         if (src > SDL_cursor->save[1]) {
  1102             SDL_ConvertCursorSave(screen, area.w, area.h);
  1103         }
  1104     }
  1105 }
  1106 
  1107 void
  1108 SDL_EraseCursor(SDL_Surface * screen)
  1109 {
  1110     /* Lock the screen if necessary */
  1111     if (screen == NULL) {
  1112         return;
  1113     }
  1114     if (SDL_MUSTLOCK(screen)) {
  1115         if (SDL_LockSurface(screen) < 0) {
  1116             return;
  1117         }
  1118     }
  1119 
  1120     SDL_EraseCursorNoLock(screen);
  1121 
  1122     /* Unlock the screen and update if necessary */
  1123     if (SDL_MUSTLOCK(screen)) {
  1124         SDL_UnlockSurface(screen);
  1125     }
  1126     if ((screen->flags & SDL_SCREEN_SURFACE) &&
  1127         !(screen->flags & SDL_HWSURFACE)) {
  1128         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1129         SDL_Window *window;
  1130         SDL_Rect area;
  1131 
  1132         window = SDL_GetWindowFromSurface(screen);
  1133         if (!window) {
  1134             return;
  1135         }
  1136 
  1137         SDL_MouseRect(&area);
  1138 
  1139         if (_this->UpdateWindowSurface) {
  1140             _this->UpdateWindowSurface(_this, window, 1, &area);
  1141         }
  1142     }
  1143 }
  1144 
  1145 /* Reset the cursor on video mode change
  1146    FIXME:  Keep track of all cursors, and reset them all.
  1147  */
  1148 void
  1149 SDL_ResetCursor(void)
  1150 {
  1151     int savelen;
  1152 
  1153     if (SDL_cursor) {
  1154         savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h;
  1155         SDL_cursor->area.x = 0;
  1156         SDL_cursor->area.y = 0;
  1157         SDL_memset(SDL_cursor->save[0], 0, savelen);
  1158     }
  1159 }
  1160 
  1161 SDL_Overlay *
  1162 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
  1163 {
  1164     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1165     SDL_Window *window;
  1166     const char *yuv_hwaccel;
  1167     SDL_Overlay *overlay;
  1168 
  1169     window = SDL_GetWindowFromSurface(display);
  1170     if (window && (window->flags & SDL_WINDOW_OPENGL)) {
  1171         SDL_SetError("YUV overlays are not supported in OpenGL mode");
  1172         return NULL;
  1173     }
  1174 
  1175     /* Display directly on video surface, if possible */
  1176     if (SDL_getenv("SDL_VIDEO_YUV_DIRECT")) {
  1177         if (window &&
  1178             ((window->surface->format->BytesPerPixel == 2) ||
  1179              (window->surface->format->BytesPerPixel == 4))) {
  1180             display = window->surface;
  1181         }
  1182     }
  1183     overlay = NULL;
  1184     yuv_hwaccel = SDL_getenv("SDL_VIDEO_YUV_HWACCEL");
  1185     if (((display->flags & SDL_SCREEN_SURFACE) && _this->CreateYUVOverlay) &&
  1186         (!yuv_hwaccel || (SDL_atoi(yuv_hwaccel) > 0))) {
  1187         overlay = _this->CreateYUVOverlay(_this, w, h, format, display);
  1188     }
  1189     /* If hardware YUV overlay failed ... */
  1190     if (overlay == NULL) {
  1191         overlay = SDL_CreateYUV_SW(_this, w, h, format, display);
  1192     }
  1193     return overlay;
  1194 }
  1195 
  1196 int
  1197 SDL_LockYUVOverlay(SDL_Overlay * overlay)
  1198 {
  1199     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1200     return overlay->hwfuncs->Lock(_this, overlay);
  1201 }
  1202 
  1203 void
  1204 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
  1205 {
  1206     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1207     overlay->hwfuncs->Unlock(_this, overlay);
  1208 }
  1209 
  1210 int
  1211 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
  1212 {
  1213     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1214     SDL_Rect src, dst;
  1215     int srcx, srcy, srcw, srch;
  1216     int dstx, dsty, dstw, dsth;
  1217 
  1218     /* Clip the rectangle to the screen area */
  1219     srcx = 0;
  1220     srcy = 0;
  1221     srcw = overlay->w;
  1222     srch = overlay->h;
  1223     dstx = dstrect->x;
  1224     dsty = dstrect->y;
  1225     dstw = dstrect->w;
  1226     dsth = dstrect->h;
  1227     if (dstx < 0) {
  1228         srcw += (dstx * overlay->w) / dstrect->w;
  1229         dstw += dstx;
  1230         srcx -= (dstx * overlay->w) / dstrect->w;
  1231         dstx = 0;
  1232     }
  1233     if ((dstx + dstw) > SDL_VideoSurface->w) {
  1234         int extra = (dstx + dstw - SDL_VideoSurface->w);
  1235         srcw -= (extra * overlay->w) / dstrect->w;
  1236         dstw -= extra;
  1237     }
  1238     if (dsty < 0) {
  1239         srch += (dsty * overlay->h) / dstrect->h;
  1240         dsth += dsty;
  1241         srcy -= (dsty * overlay->h) / dstrect->h;
  1242         dsty = 0;
  1243     }
  1244     if ((dsty + dsth) > SDL_VideoSurface->h) {
  1245         int extra = (dsty + dsth - SDL_VideoSurface->h);
  1246         srch -= (extra * overlay->h) / dstrect->h;
  1247         dsth -= extra;
  1248     }
  1249     if (srcw <= 0 || srch <= 0 || srch <= 0 || dsth <= 0) {
  1250         return 0;
  1251     }
  1252     /* Ugh, I can't wait for SDL_Rect to be int values */
  1253     src.x = srcx;
  1254     src.y = srcy;
  1255     src.w = srcw;
  1256     src.h = srch;
  1257     dst.x = dstx;
  1258     dst.y = dsty;
  1259     dst.w = dstw;
  1260     dst.h = dsth;
  1261     return overlay->hwfuncs->Display(_this, overlay, &src, &dst);
  1262 }
  1263 
  1264 void
  1265 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
  1266 {
  1267     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  1268     if (overlay) {
  1269         if (overlay->hwfuncs) {
  1270             overlay->hwfuncs->FreeHW(_this, overlay);
  1271         }
  1272         SDL_free(overlay);
  1273     }
  1274 }
  1275 #endif
  1276 
  1277 /* vi: set ts=4 sw=4 expandtab: */