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