Subversion Repositories Kolibri OS

Rev

Rev 8218 | Rev 9769 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 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.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.     Sam Lantinga
  20.     slouken@devolution.com
  21. */
  22.  
  23.  
  24. /* The high-level video driver subsystem */
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29.  
  30. #include "SDL.h"
  31. #include "SDL_error.h"
  32. #include "SDL_video.h"
  33. #include "SDL_events.h"
  34. #include "SDL_mutex.h"
  35. #include "SDL_sysvideo.h"
  36. #include "SDL_sysevents.h"
  37. #include "SDL_blit.h"
  38. #include "SDL_pixels_c.h"
  39. #include "SDL_events_c.h"
  40. #include "SDL_cursor_c.h"
  41.  
  42. /* Available video drivers */
  43. static VideoBootStrap *bootstrap[] = {
  44. #ifdef ENABLE_X11
  45.         &X11_bootstrap,
  46. #endif
  47. #ifdef ENABLE_DGA
  48.         &DGA_bootstrap,
  49. #endif
  50. #ifdef ENABLE_NANOX
  51.         &NX_bootstrap,
  52. #endif
  53. #ifdef ENABLE_FBCON
  54.         &FBCON_bootstrap,
  55. #endif
  56. #ifdef ENABLE_PS2GS
  57.         &PS2GS_bootstrap,
  58. #endif
  59. #ifdef ENABLE_GGI
  60.         &GGI_bootstrap,
  61. #endif
  62. #ifdef ENABLE_VGL
  63.         &VGL_bootstrap,
  64. #endif
  65. #ifdef ENABLE_SVGALIB
  66.         &SVGALIB_bootstrap,
  67. #endif
  68. #ifdef ENABLE_AALIB
  69.     &AALIB_bootstrap,
  70. #endif
  71. #ifdef ENABLE_DIRECTX
  72.         &DIRECTX_bootstrap,
  73. #endif
  74. #ifdef ENABLE_WINDIB
  75.         &WINDIB_bootstrap,
  76. #endif
  77. #ifdef ENABLE_BWINDOW
  78.         &BWINDOW_bootstrap,
  79. #endif
  80. #ifdef ENABLE_TOOLBOX
  81.         &TOOLBOX_bootstrap,
  82. #endif
  83. #ifdef ENABLE_DRAWSPROCKET
  84.         &DSp_bootstrap,
  85. #endif
  86. #ifdef ENABLE_QUARTZ
  87.         &QZ_bootstrap,
  88. #endif
  89. #ifdef ENABLE_CYBERGRAPHICS
  90.         &CGX_bootstrap,
  91. #endif
  92. #ifdef ENABLE_DUMMYVIDEO
  93.         &DUMMY_bootstrap,
  94. #endif
  95. #ifdef ENABLE_PHOTON
  96.         &ph_bootstrap,
  97. #endif
  98. #ifdef ENABLE_KOLIBRIOS
  99.         &mosvideo_bootstrab,
  100. #endif
  101.         NULL
  102. };
  103.  
  104. SDL_VideoDevice *current_video = NULL;
  105.  
  106. /* Various local functions */
  107. int SDL_VideoInit(const char *driver_name, Uint32 flags);
  108. void SDL_VideoQuit(void);
  109. void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect* rects);
  110.  
  111. static SDL_GrabMode SDL_WM_GrabInputOff(void);
  112. #ifdef HAVE_OPENGL
  113. static int lock_count = 0;
  114. #endif
  115.  
  116.  
  117. typedef union{
  118.     unsigned val;
  119.     struct{
  120.         short  x;
  121.         short  y;
  122.     };
  123. }ksys_pos_t;
  124.  
  125. static inline
  126. ksys_pos_t _ksys_screen_size()
  127. {
  128.         ksys_pos_t size;
  129.     ksys_pos_t size_tmp;
  130.     __asm__ __volatile__(
  131.         "int $0x40"
  132.         :"=a"(size_tmp)
  133.         :"a"(14)
  134.         :"memory"
  135.     );
  136.     size.x = size_tmp.y;
  137.     size.y = size_tmp.x;
  138.     return size;
  139. }
  140.  
  141.  
  142. /*
  143.  * Initialize the video and event subsystems -- determine native pixel format
  144.  */
  145. int SDL_VideoInit (const char *driver_name, Uint32 flags)
  146. {
  147.         SDL_VideoDevice *video;
  148.         int index;
  149.         int i;
  150.         SDL_PixelFormat vformat;
  151.         Uint32 video_flags;
  152.  
  153.         /* Toggle the event thread flags, based on OS requirements */
  154. #if defined(MUST_THREAD_EVENTS)
  155.         flags |= SDL_INIT_EVENTTHREAD;
  156. #elif defined(CANT_THREAD_EVENTS)
  157.         if ( (flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) {
  158.                 SDL_SetError("OS doesn't support threaded events");
  159.                 return(-1);
  160.         }
  161. #endif
  162.  
  163.         /* Check to make sure we don't overwrite 'current_video' */
  164.         if ( current_video != NULL ) {
  165.                 SDL_VideoQuit();
  166.         }
  167.  
  168.         /* Select the proper video driver */
  169.         index = 0;
  170.         video = NULL;
  171.         if ( driver_name != NULL ) {
  172.                 for ( i=0; bootstrap[i]; ++i ) {
  173.                         if ( strncmp(bootstrap[i]->name, driver_name,
  174.                                      strlen(bootstrap[i]->name)) == 0 ) {
  175.                                 if ( bootstrap[i]->available() ) {
  176.                                         video = bootstrap[i]->create(index);
  177.                                         break;
  178.                                 }
  179.                         }
  180.                 }
  181.         } else {
  182.                 for ( i=0; bootstrap[i]; ++i ) {
  183.                         if ( bootstrap[i]->available() ) {
  184.                                 video = bootstrap[i]->create(index);
  185.                                 if ( video != NULL ) {
  186.                                         break;
  187.                                 }
  188.                         }
  189.                 }
  190.         }
  191.         if ( video == NULL ) {
  192.                 SDL_SetError("No available video device");
  193.                 return(-1);
  194.         }
  195.         current_video = video;
  196.         current_video->name = bootstrap[i]->name;
  197.  
  198.         /* Do some basic variable initialization */
  199.         video->screen = NULL;
  200.         video->shadow = NULL;
  201.         video->visible = NULL;
  202.         video->physpal = NULL;
  203.         video->gammacols = NULL;
  204.         video->gamma = NULL;
  205.         video->wm_title = NULL;
  206.         video->wm_icon  = NULL;
  207.         video->offset_x = 0;
  208.         video->offset_y = 0;
  209.         memset(&video->info, 0, (sizeof video->info));
  210.  
  211.         /* Set some very sane GL defaults */
  212.         video->gl_config.driver_loaded = 0;
  213.         video->gl_config.dll_handle = NULL;
  214.         video->gl_config.red_size = 5;
  215. #if 1 /* This seems to work on more video cards, as a default */
  216.         video->gl_config.green_size = 5;
  217. #else
  218.         video->gl_config.green_size = 6;
  219. #endif
  220.         video->gl_config.blue_size = 5;
  221.         video->gl_config.alpha_size = 0;
  222.         video->gl_config.buffer_size = 0;
  223.         video->gl_config.depth_size = 16;
  224.         video->gl_config.stencil_size = 0;
  225.         video->gl_config.double_buffer = 1;
  226.         video->gl_config.accum_red_size = 0;
  227.         video->gl_config.accum_green_size = 0;
  228.         video->gl_config.accum_blue_size = 0;
  229.         video->gl_config.accum_alpha_size = 0;
  230.        
  231.         /* Initialize the video subsystem */
  232.         memset(&vformat, 0, sizeof(vformat));
  233.         if ( video->VideoInit(video, &vformat) < 0 ) {
  234.                 SDL_VideoQuit();
  235.                 return(-1);
  236.         }
  237.  
  238.         /* Create a zero sized video surface of the appropriate format */
  239.         video_flags = SDL_SWSURFACE;
  240.         SDL_VideoSurface = SDL_CreateRGBSurface(video_flags, 0, 0,
  241.                                 vformat.BitsPerPixel,
  242.                                 vformat.Rmask, vformat.Gmask, vformat.Bmask, 0);
  243.         if ( SDL_VideoSurface == NULL ) {
  244.                 SDL_VideoQuit();
  245.                 return(-1);
  246.         }
  247.         SDL_PublicSurface = NULL;       /* Until SDL_SetVideoMode() */
  248.  
  249. #if 0 /* Don't change the current palette - may be used by other programs.
  250.        * The application can't do anything with the display surface until
  251.       * a video mode has been set anyway. :)
  252.       */
  253.         /* If we have a palettized surface, create a default palette */
  254.         if ( SDL_VideoSurface->format->palette ) {
  255.                 SDL_PixelFormat *vf = SDL_VideoSurface->format;
  256.                 SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel);
  257.                 video->SetColors(video,
  258.                                  0, vf->palette->ncolors, vf->palette->colors);
  259.         }
  260. #endif
  261.         video->info.vfmt = SDL_VideoSurface->format;
  262.        
  263.         ksys_pos_t screen_s = _ksys_screen_size();
  264.         video->info.current_h = screen_s.y;
  265.         video->info.current_w = screen_s.x;
  266.  
  267.         /* Start the event loop */
  268.         if ( SDL_StartEventLoop(flags) < 0 ) {
  269.                 SDL_VideoQuit();
  270.                 return(-1);
  271.         }
  272.         SDL_CursorInit(flags & SDL_INIT_EVENTTHREAD);
  273.  
  274.         /* We're ready to go! */
  275.         return(0);
  276. }
  277.  
  278. char *SDL_VideoDriverName(char *namebuf, int maxlen)
  279. {
  280.         if ( current_video != NULL ) {
  281.                 strncpy(namebuf, current_video->name, maxlen-1);
  282.                 namebuf[maxlen-1] = '\0';
  283.                 return(namebuf);
  284.         }
  285.         return(NULL);
  286. }
  287.  
  288. /*
  289.  * Get the current display surface
  290.  */
  291. SDL_Surface *SDL_GetVideoSurface(void)
  292. {
  293.         SDL_Surface *visible;
  294.  
  295.         visible = NULL;
  296.         if ( current_video ) {
  297.                 visible = current_video->visible;
  298.         }
  299.         return(visible);
  300. }
  301.  
  302. /*
  303.  * Get the current information about the video hardware
  304.  */
  305. const SDL_VideoInfo *SDL_GetVideoInfo(void)
  306. {
  307.         const SDL_VideoInfo *info;
  308.  
  309.         info = NULL;
  310.         if ( current_video ) {
  311.                 info = &current_video->info;
  312.         }
  313.         return(info);
  314. }
  315.  
  316. /*
  317.  * Return a pointer to an array of available screen dimensions for the
  318.  * given format, sorted largest to smallest.  Returns NULL if there are
  319.  * no dimensions available for a particular format, or (SDL_Rect **)-1
  320.  * if any dimension is okay for the given format.  If 'format' is NULL,
  321.  * the mode list will be for the format given by SDL_GetVideoInfo()->vfmt
  322.  */
  323. SDL_Rect ** SDL_ListModes (SDL_PixelFormat *format, Uint32 flags)
  324. {
  325.         SDL_VideoDevice *video = current_video;
  326.         SDL_VideoDevice *this  = current_video;
  327.         SDL_Rect **modes;
  328.  
  329.         modes = NULL;
  330.         if ( SDL_VideoSurface ) {
  331.                 if ( format == NULL ) {
  332.                         format = SDL_VideoSurface->format;
  333.                 }
  334.                 modes = video->ListModes(this, format, flags);
  335.         }
  336.         return(modes);
  337. }
  338.  
  339. /*
  340.  * Check to see if a particular video mode is supported.
  341.  * It returns 0 if the requested mode is not supported under any bit depth,
  342.  * or returns the bits-per-pixel of the closest available mode with the
  343.  * given width and height.  If this bits-per-pixel is different from the
  344.  * one used when setting the video mode, SDL_SetVideoMode() will succeed,
  345.  * but will emulate the requested bits-per-pixel with a shadow surface.
  346.  */
  347. static Uint8 SDL_closest_depths[4][8] = {
  348.         /* 8 bit closest depth ordering */
  349.         { 0, 8, 16, 15, 32, 24, 0, 0 },
  350.         /* 15,16 bit closest depth ordering */
  351.         { 0, 16, 15, 32, 24, 8, 0, 0 },
  352.         /* 24 bit closest depth ordering */
  353.         { 0, 24, 32, 16, 15, 8, 0, 0 },
  354.         /* 32 bit closest depth ordering */
  355.         { 0, 32, 16, 15, 24, 8, 0, 0 }
  356. };
  357.  
  358. int SDL_VideoModeOK (int width, int height, int bpp, Uint32 flags)
  359. {
  360.         int table, b, i;
  361.         int supported;
  362.         SDL_PixelFormat format;
  363.         SDL_Rect **sizes;
  364.  
  365.         /* Currently 1 and 4 bpp are not supported */
  366.         if ( bpp < 8 || bpp > 32 ) {
  367.                 return(0);
  368.         }
  369.         if ( (width == 0) || (height == 0) ) {
  370.                 return(0);
  371.         }
  372.  
  373.         /* Search through the list valid of modes */
  374.         memset(&format, 0, sizeof(format));
  375.         supported = 0;
  376.         table = ((bpp+7)/8)-1;
  377.         SDL_closest_depths[table][0] = bpp;
  378.         SDL_closest_depths[table][7] = 0;
  379.         for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) {
  380.                 format.BitsPerPixel = SDL_closest_depths[table][b];
  381.                 sizes = SDL_ListModes(&format, flags);
  382.                 if ( sizes == (SDL_Rect **)0 ) {
  383.                         /* No sizes supported at this bit-depth */
  384.                         continue;
  385.                 } else
  386. #ifdef macintosh /* MPW optimization bug? */
  387.                 if ( (sizes == (SDL_Rect **)0xFFFFFFFF) ||
  388. #else
  389.                 if ( (sizes == (SDL_Rect **)-1) ||
  390. #endif
  391.                      current_video->handles_any_size ) {
  392.                         /* Any size supported at this bit-depth */
  393.                         supported = 1;
  394.                         continue;
  395.                 } else
  396.                 for ( i=0; sizes[i]; ++i ) {
  397.                         if ((sizes[i]->w == width) && (sizes[i]->h == height)) {
  398.                                 supported = 1;
  399.                                 break;
  400.                         }
  401.                 }
  402.         }
  403.         if ( supported ) {
  404.                 --b;
  405.                 return(SDL_closest_depths[table][b]);
  406.         } else {
  407.                 return(0);
  408.         }
  409. }
  410.  
  411. /*
  412.  * Get the closest non-emulated video mode to the one requested
  413.  */
  414. static int SDL_GetVideoMode (int *w, int *h, int *BitsPerPixel, Uint32 flags)
  415. {
  416.         int table, b, i;
  417.         int supported;
  418.         int native_bpp;
  419.         SDL_PixelFormat format;
  420.         SDL_Rect **sizes;
  421.  
  422.         /* Try the original video mode, get the closest depth */
  423.         native_bpp = SDL_VideoModeOK(*w, *h, *BitsPerPixel, flags);
  424.         if ( native_bpp == *BitsPerPixel ) {
  425.                 return(1);
  426.         }
  427.         if ( native_bpp > 0 ) {
  428.                 *BitsPerPixel = native_bpp;
  429.                 return(1);
  430.         }
  431.  
  432.         /* No exact size match at any depth, look for closest match */
  433.         memset(&format, 0, sizeof(format));
  434.         supported = 0;
  435.         table = ((*BitsPerPixel+7)/8)-1;
  436.         SDL_closest_depths[table][0] = *BitsPerPixel;
  437.         SDL_closest_depths[table][7] = SDL_VideoSurface->format->BitsPerPixel;
  438.         for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) {
  439.                 format.BitsPerPixel = SDL_closest_depths[table][b];
  440.                 sizes = SDL_ListModes(&format, flags);
  441.                 if ( sizes == (SDL_Rect **)0 ) {
  442.                         /* No sizes supported at this bit-depth */
  443.                         continue;
  444.                 }
  445.                 for ( i=0; sizes[i]; ++i ) {
  446.                         if ((sizes[i]->w < *w) || (sizes[i]->h < *h)) {
  447.                                 if ( i > 0 ) {
  448.                                         --i;
  449.                                         *w = sizes[i]->w;
  450.                                         *h = sizes[i]->h;
  451.                                         *BitsPerPixel = SDL_closest_depths[table][b];
  452.                                         supported = 1;
  453.                                 } else {
  454.                                         /* Largest mode too small... */;
  455.                                 }
  456.                                 break;
  457.                         }
  458.                 }
  459.                 if ( (i > 0) && ! sizes[i] ) {
  460.                         /* The smallest mode was larger than requested, OK */
  461.                         --i;
  462.                         *w = sizes[i]->w;
  463.                         *h = sizes[i]->h;
  464.                         *BitsPerPixel = SDL_closest_depths[table][b];
  465.                         supported = 1;
  466.                 }
  467.         }
  468.         if ( ! supported ) {
  469.                 SDL_SetError("No video mode large enough for %dx%d", *w, *h);
  470.         }
  471.         return(supported);
  472. }
  473.  
  474. /* This should probably go somewhere else -- like SDL_surface.c */
  475. static void SDL_ClearSurface(SDL_Surface *surface)
  476. {
  477.         Uint32 black;
  478.  
  479.         black = SDL_MapRGB(surface->format, 0, 0, 0);
  480.         SDL_FillRect(surface, NULL, black);
  481.         if ((surface->flags&SDL_HWSURFACE) && (surface->flags&SDL_DOUBLEBUF)) {
  482.                 SDL_Flip(surface);
  483.                 SDL_FillRect(surface, NULL, black);
  484.         }
  485.         SDL_Flip(surface);
  486. }
  487.  
  488. /*
  489.  * Create a shadow surface suitable for fooling the app. :-)
  490.  */
  491. static void SDL_CreateShadowSurface(int depth)
  492. {
  493.         Uint32 Rmask, Gmask, Bmask;
  494.  
  495.         /* Allocate the shadow surface */
  496.         if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) {
  497.                 Rmask = (SDL_VideoSurface->format)->Rmask;
  498.                 Gmask = (SDL_VideoSurface->format)->Gmask;
  499.                 Bmask = (SDL_VideoSurface->format)->Bmask;
  500.         } else {
  501.                 Rmask = Gmask = Bmask = 0;
  502.         }
  503.         SDL_ShadowSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
  504.                                 SDL_VideoSurface->w, SDL_VideoSurface->h,
  505.                                                 depth, Rmask, Gmask, Bmask, 0);
  506.         if ( SDL_ShadowSurface == NULL ) {
  507.                 return;
  508.         }
  509.  
  510.         /* 8-bit shadow surfaces report that they have exclusive palette */
  511.         if ( SDL_ShadowSurface->format->palette ) {
  512.                 SDL_ShadowSurface->flags |= SDL_HWPALETTE;
  513.                 if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) {
  514.                         memcpy(SDL_ShadowSurface->format->palette->colors,
  515.                                 SDL_VideoSurface->format->palette->colors,
  516.                                 SDL_VideoSurface->format->palette->ncolors*
  517.                                                         sizeof(SDL_Color));
  518.                 } else {
  519.                         SDL_DitherColors(
  520.                         SDL_ShadowSurface->format->palette->colors, depth);
  521.                 }
  522.         }
  523.  
  524.         /* If the video surface is resizable, the shadow should say so */
  525.         if ( (SDL_VideoSurface->flags & SDL_RESIZABLE) == SDL_RESIZABLE ) {
  526.                 SDL_ShadowSurface->flags |= SDL_RESIZABLE;
  527.         }
  528.         /* If the video surface has no frame, the shadow should say so */
  529.         if ( (SDL_VideoSurface->flags & SDL_NOFRAME) == SDL_NOFRAME ) {
  530.                 SDL_ShadowSurface->flags |= SDL_NOFRAME;
  531.         }
  532.         /* If the video surface is fullscreen, the shadow should say so */
  533.         if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  534.                 SDL_ShadowSurface->flags |= SDL_FULLSCREEN;
  535.         }
  536.         /* If the video surface is flippable, the shadow should say so */
  537.         if ( (SDL_VideoSurface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  538.                 SDL_ShadowSurface->flags |= SDL_DOUBLEBUF;
  539.         }
  540.         return;
  541. }
  542.  
  543. /*
  544.  * Set the requested video mode, allocating a shadow buffer if necessary.
  545.  */
  546. SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags)
  547. {
  548.         SDL_VideoDevice *video, *this;
  549.         SDL_Surface *prev_mode, *mode;
  550.         int video_w;
  551.         int video_h;
  552.         int video_bpp;
  553.         int is_opengl;
  554.         SDL_GrabMode saved_grab;
  555.  
  556.         /* Start up the video driver, if necessary..
  557.            WARNING: This is the only function protected this way!
  558.          */
  559.         if ( ! current_video ) {
  560.                 if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) {
  561.                         return(NULL);
  562.                 }
  563.         }
  564.         this = video = current_video;
  565.  
  566.         /* Default to the current video bpp */
  567.         if ( bpp == 0 ) {
  568.                 flags |= SDL_ANYFORMAT;
  569.                 bpp = SDL_VideoSurface->format->BitsPerPixel;
  570.         }
  571.  
  572.         /* Get a good video mode, the closest one possible */
  573.         video_w = width;
  574.         video_h = height;
  575.         video_bpp = bpp;
  576.         if ( ! SDL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) {
  577.                 return(NULL);
  578.         }
  579.  
  580.         /* Check the requested flags */
  581.         /* There's no palette in > 8 bits-per-pixel mode */
  582.         if ( video_bpp > 8 ) {
  583.                 flags &= ~SDL_HWPALETTE;
  584.         }
  585. #if 0
  586.         if ( (flags&SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  587.                 /* There's no windowed double-buffering */
  588.                 flags &= ~SDL_DOUBLEBUF;
  589.         }
  590. #endif
  591.         if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  592.                 /* Use hardware surfaces when double-buffering */
  593.                 flags |= SDL_HWSURFACE;
  594.         }
  595.  
  596.         is_opengl = ( ( flags & SDL_OPENGL ) == SDL_OPENGL );
  597.         if ( is_opengl ) {
  598.                 /* These flags are for 2D video modes only */
  599.                 flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF);
  600.         }
  601.  
  602.         /* Reset the keyboard here so event callbacks can run */
  603.         SDL_ResetKeyboard();
  604.  
  605.         /* Clean up any previous video mode */
  606.         if ( SDL_PublicSurface != NULL ) {
  607.                 SDL_PublicSurface = NULL;
  608.         }
  609.         if ( SDL_ShadowSurface != NULL ) {
  610.                 SDL_Surface *ready_to_go;
  611.                 ready_to_go = SDL_ShadowSurface;
  612.                 SDL_ShadowSurface = NULL;
  613.                 SDL_FreeSurface(ready_to_go);
  614.         }
  615.         if ( video->physpal ) {
  616.                 free(video->physpal->colors);
  617.                 free(video->physpal);
  618.                 video->physpal = NULL;
  619.         }
  620.         if( video->gammacols) {
  621.                 free(video->gammacols);
  622.                 video->gammacols = NULL;
  623.         }
  624.  
  625.         /* Save the previous grab state and turn off grab for mode switch */
  626.         saved_grab = SDL_WM_GrabInputOff();
  627.  
  628.         /* Try to set the video mode, along with offset and clipping */
  629.         prev_mode = SDL_VideoSurface;
  630.         SDL_LockCursor();
  631.         SDL_VideoSurface = NULL;        /* In case it's freed by driver */
  632.         mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags);
  633.         if ( mode ) { /* Prevent resize events from mode change */
  634.             SDL_PrivateResize(mode->w, mode->h);
  635.         }
  636.         /*
  637.          * rcg11292000
  638.          * If you try to set an SDL_OPENGL surface, and fail to find a
  639.          * matching  visual, then the next call to SDL_SetVideoMode()
  640.          * will segfault, since  we no longer point to a dummy surface,
  641.          * but rather NULL.
  642.          * Sam 11/29/00
  643.          * WARNING, we need to make sure that the previous mode hasn't
  644.          * already been freed by the video driver.  What do we do in
  645.          * that case?  Should we call SDL_VideoInit() again?
  646.          */
  647.         SDL_VideoSurface = (mode != NULL) ? mode : prev_mode;
  648.  
  649.         if ( (mode != NULL) && (!is_opengl) ) {
  650.                 /* Sanity check */
  651.                 if ( (mode->w < width) || (mode->h < height) ) {
  652.                         SDL_SetError("Video mode smaller than requested");
  653.                         return(NULL);
  654.                 }
  655.  
  656.                 /* If we have a palettized surface, create a default palette */
  657.                 if ( mode->format->palette ) {
  658.                         SDL_PixelFormat *vf = mode->format;
  659.                         SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel);
  660.                         video->SetColors(this, 0, vf->palette->ncolors,
  661.                                                    vf->palette->colors);
  662.                 }
  663.  
  664.                 /* Clear the surface to black */
  665.                 video->offset_x = 0;
  666.                 video->offset_y = 0;
  667.                 mode->offset = 0;
  668.                 SDL_SetClipRect(mode, NULL);
  669.                 SDL_ClearSurface(mode);
  670.  
  671.                 /* Now adjust the offsets to match the desired mode */
  672.                 video->offset_x = (mode->w-width)/2;
  673.                 video->offset_y = (mode->h-height)/2;
  674.                 mode->offset = video->offset_y*mode->pitch +
  675.                                 video->offset_x*mode->format->BytesPerPixel;
  676. #ifdef DEBUG_VIDEO
  677.  SDL_printf("Requested mode: %dx%dx%d, obtained mode %dx%dx%d (offset %d)\n",
  678.                 width, height, bpp,
  679.                 mode->w, mode->h, mode->format->BitsPerPixel, mode->offset);
  680. #endif
  681.                 mode->w = width;
  682.                 mode->h = height;
  683.                 SDL_SetClipRect(mode, NULL);
  684.         }
  685.         SDL_ResetCursor();
  686.         SDL_UnlockCursor();
  687.  
  688.         /* If we failed setting a video mode, return NULL... (Uh Oh!) */
  689.         if ( mode == NULL ) {
  690.                 return(NULL);
  691.         }
  692.  
  693.         /* If there is no window manager, set the SDL_NOFRAME flag */
  694.         if ( ! video->info.wm_available ) {
  695.                 mode->flags |= SDL_NOFRAME;
  696.         }
  697.  
  698.         /* Reset the mouse cursor and grab for new video mode */
  699.         SDL_SetCursor(NULL);
  700.         if ( video->UpdateMouse ) {
  701.                 video->UpdateMouse(this);
  702.         }
  703.         SDL_WM_GrabInput(saved_grab);
  704.         SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */
  705.  
  706.         /* If we're running OpenGL, make the context current */
  707.         if ( (video->screen->flags & SDL_OPENGL) &&
  708.               video->GL_MakeCurrent ) {
  709.                 if ( video->GL_MakeCurrent(this) < 0 ) {
  710.                         return(NULL);
  711.                 }
  712.         }
  713.  
  714.         /* Set up a fake SDL surface for OpenGL "blitting" */
  715.         if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) {
  716.                 /* Load GL functions for performing the texture updates */
  717. #ifdef HAVE_OPENGL
  718. #define SDL_PROC(ret,func,params) \
  719. do { \
  720.         video->func = SDL_GL_GetProcAddress(#func); \
  721.         if ( ! video->func ) { \
  722.                 SDL_SetError("Couldn't load GL function: %s\n", #func); \
  723.                 return(NULL); \
  724.         } \
  725. } while ( 0 );
  726. #include "SDL_glfuncs.h"
  727. #undef SDL_PROC
  728.  
  729.                 /* Create a software surface for blitting */
  730. #ifdef GL_VERSION_1_2
  731.                 /* If the implementation either supports the packed pixels
  732.                    extension, or implements the core OpenGL 1.2 API, it will
  733.                    support the GL_UNSIGNED_SHORT_5_6_5 texture format.
  734.                  */
  735.                 if ( (bpp == 16) &&
  736.                      (strstr((const char *)video->glGetString(GL_EXTENSIONS),
  737.                                            "GL_EXT_packed_pixels") ||
  738.                      (strncmp((const char *)video->glGetString(GL_VERSION),
  739.                               "1.2", 3) == 0)) )
  740.                 {
  741.                         video->is_32bit = 0;
  742.                         SDL_VideoSurface = SDL_CreateRGBSurface(
  743.                                 flags,
  744.                                 width,
  745.                                 height,  
  746.                                 16,
  747.                                 31 << 11,
  748.                                 63 << 5,
  749.                                 31,
  750.                                 0
  751.                                 );
  752.                 }
  753.                 else
  754. #endif /* OpenGL 1.2 */
  755.                 {
  756.                         video->is_32bit = 1;
  757.                         SDL_VideoSurface = SDL_CreateRGBSurface(
  758.                                 flags,
  759.                                 width,
  760.                                 height,
  761.                                 32,
  762. #if SDL_BYTEORDER == SDL_LIL_ENDIAN
  763.                                 0x000000FF,
  764.                                 0x0000FF00,
  765.                                 0x00FF0000,
  766.                                 0xFF000000
  767. #else
  768.                                 0xFF000000,
  769.                                 0x00FF0000,
  770.                                 0x0000FF00,
  771.                                 0x000000FF
  772. #endif
  773.                                 );
  774.                 }
  775.                 if ( ! SDL_VideoSurface ) {
  776.                         return(NULL);
  777.                 }
  778.                 SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT;
  779.  
  780.                 /* Free the original video mode surface (is this safe?) */
  781.                 SDL_FreeSurface(mode);
  782.  
  783.                 /* Set the surface completely opaque & white by default */
  784.                 memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch );
  785.                 video->glGenTextures( 1, &video->texture );
  786.                 video->glBindTexture( GL_TEXTURE_2D, video->texture );
  787.                 video->glTexImage2D(
  788.                         GL_TEXTURE_2D,
  789.                         0,
  790.                         video->is_32bit ? GL_RGBA : GL_RGB,
  791.                         256,
  792.                         256,
  793.                         0,
  794.                         video->is_32bit ? GL_RGBA : GL_RGB,
  795. #ifdef GL_VERSION_1_2
  796.                         video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
  797. #else
  798.                         GL_UNSIGNED_BYTE,
  799. #endif
  800.                         NULL);
  801.  
  802.                 video->UpdateRects = SDL_GL_UpdateRectsLock;
  803. #else
  804.                 SDL_SetError("Somebody forgot to #define HAVE_OPENGL");
  805.                 return(NULL);
  806. #endif
  807.         }
  808.  
  809.         /* Create a shadow surface if necessary */
  810.         /* There are three conditions under which we create a shadow surface:
  811.                 1.  We need a particular bits-per-pixel that we didn't get.
  812.                 2.  We need a hardware palette and didn't get one.
  813.                 3.  We need a software surface and got a hardware surface.
  814.         */
  815.         if ( !(SDL_VideoSurface->flags & SDL_OPENGL) &&
  816.              (
  817.              (  !(flags&SDL_ANYFORMAT) &&
  818.                         (SDL_VideoSurface->format->BitsPerPixel != bpp)) ||
  819.              (   (flags&SDL_HWPALETTE) &&
  820.                                 !(SDL_VideoSurface->flags&SDL_HWPALETTE)) ||
  821.                 /* If the surface is in hardware, video writes are visible
  822.                    as soon as they are performed, so we need to buffer them
  823.                  */
  824.              (   ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) &&
  825.                                 (SDL_VideoSurface->flags&SDL_HWSURFACE))
  826.              ) ) {
  827.                 SDL_CreateShadowSurface(bpp);
  828.                 if ( SDL_ShadowSurface == NULL ) {
  829.                         SDL_SetError("Couldn't create shadow surface");
  830.                         return(NULL);
  831.                 }
  832.                 SDL_PublicSurface = SDL_ShadowSurface;
  833.         } else {
  834.                 SDL_PublicSurface = SDL_VideoSurface;
  835.         }
  836.         video->info.vfmt = SDL_VideoSurface->format;
  837.  
  838.         /* We're done! */
  839.         return(SDL_PublicSurface);
  840. }
  841.  
  842. /*
  843.  * Convert a surface into the video pixel format.
  844.  */
  845. SDL_Surface * SDL_DisplayFormat (SDL_Surface *surface)
  846. {
  847.         Uint32 flags;
  848.  
  849.         if ( ! SDL_PublicSurface ) {
  850.                 SDL_SetError("No video mode has been set");
  851.                 return(NULL);
  852.         }
  853.         /* Set the flags appropriate for copying to display surface */
  854.         flags  = (SDL_PublicSurface->flags&SDL_HWSURFACE);
  855. #ifdef AUTORLE_DISPLAYFORMAT
  856.         flags |= (surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA));
  857.         flags |= SDL_RLEACCELOK;
  858. #else
  859.         flags |= surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA|SDL_RLEACCELOK);
  860. #endif
  861.         return(SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags));
  862. }
  863.  
  864. /*
  865.  * Convert a surface into a format that's suitable for blitting to
  866.  * the screen, but including an alpha channel.
  867.  */
  868. SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface)
  869. {
  870.         SDL_PixelFormat *vf;
  871.         SDL_PixelFormat *format;
  872.         SDL_Surface *converted;
  873.         Uint32 flags;
  874.         /* default to ARGB8888 */
  875.         Uint32 amask = 0xff000000;
  876.         Uint32 rmask = 0x00ff0000;
  877.         Uint32 gmask = 0x0000ff00;
  878.         Uint32 bmask = 0x000000ff;
  879.  
  880.         if ( ! SDL_PublicSurface ) {
  881.                 SDL_SetError("No video mode has been set");
  882.                 return(NULL);
  883.         }
  884.         vf = SDL_PublicSurface->format;
  885.  
  886.         switch(vf->BytesPerPixel) {
  887.             case 2:
  888.                 /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
  889.                    For anything else (like ARGB4444) it doesn't matter
  890.                    since we have no special code for it anyway */
  891.                 if ( (vf->Rmask == 0x1f) &&
  892.                      (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
  893.                         rmask = 0xff;
  894.                         bmask = 0xff0000;
  895.                 }
  896.                 break;
  897.  
  898.             case 3:
  899.             case 4:
  900.                 /* Keep the video format, as long as the high 8 bits are
  901.                    unused or alpha */
  902.                 if ( (vf->Rmask == 0xff) && (vf->Bmask == 0xff0000) ) {
  903.                         rmask = 0xff;
  904.                         bmask = 0xff0000;
  905.                 }
  906.                 break;
  907.  
  908.             default:
  909.                 /* We have no other optimised formats right now. When/if a new
  910.                    optimised alpha format is written, add the converter here */
  911.                 break;
  912.         }
  913.         format = SDL_AllocFormat(32, rmask, gmask, bmask, amask);
  914.         flags = SDL_PublicSurface->flags & SDL_HWSURFACE;
  915.         flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
  916.         converted = SDL_ConvertSurface(surface, format, flags);
  917.         SDL_FreeFormat(format);
  918.         return(converted);
  919. }
  920.  
  921. /*
  922.  * Update a specific portion of the physical screen
  923.  */
  924. void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  925. {
  926.         if ( screen ) {
  927.                 SDL_Rect rect;
  928.  
  929.                 /* Perform some checking */
  930.                 if ( w == 0 )
  931.                         w = screen->w;
  932.                 if ( h == 0 )
  933.                         h = screen->h;
  934.                 if ( (int)(x+w) > screen->w )
  935.                         return;
  936.                 if ( (int)(y+h) > screen->h )
  937.                         return;
  938.  
  939.                 /* Fill the rectangle */
  940.                 rect.x = x;
  941.                 rect.y = y;
  942.                 rect.w = w;
  943.                 rect.h = h;
  944.                 SDL_UpdateRects(screen, 1, &rect);
  945.         }
  946. }
  947. void SDL_UpdateRects (SDL_Surface *screen, int numrects, SDL_Rect *rects)
  948. {
  949.         int i;
  950.         SDL_VideoDevice *video = current_video;
  951.         SDL_VideoDevice *this = current_video;
  952.  
  953.         if ( screen == SDL_ShadowSurface ) {
  954.                 /* Blit the shadow surface using saved mapping */
  955.                 SDL_Palette *pal = screen->format->palette;
  956.                 SDL_Color *saved_colors = NULL;
  957.                 if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
  958.                         /* simulated 8bpp, use correct physical palette */
  959.                         saved_colors = pal->colors;
  960.                         if ( video->gammacols ) {
  961.                                 /* gamma-corrected palette */
  962.                                 pal->colors = video->gammacols;
  963.                         } else if ( video->physpal ) {
  964.                                 /* physical palette different from logical */
  965.                                 pal->colors = video->physpal->colors;
  966.                         }
  967.                 }
  968.                 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
  969.                         SDL_LockCursor();
  970.                         SDL_DrawCursor(SDL_ShadowSurface);
  971.                         for ( i=0; i<numrects; ++i ) {
  972.                                 SDL_LowerBlit(SDL_ShadowSurface, &rects[i],
  973.                                                 SDL_VideoSurface, &rects[i]);
  974.                         }
  975.                         SDL_EraseCursor(SDL_ShadowSurface);
  976.                         SDL_UnlockCursor();
  977.                 } else {
  978.                         for ( i=0; i<numrects; ++i ) {
  979.                                 SDL_LowerBlit(SDL_ShadowSurface, &rects[i],
  980.                                                 SDL_VideoSurface, &rects[i]);
  981.                         }
  982.                 }
  983.                 if ( saved_colors )
  984.                         pal->colors = saved_colors;
  985.  
  986.                 /* Fall through to video surface update */
  987.                 screen = SDL_VideoSurface;
  988.         }
  989.         if ( screen == SDL_VideoSurface ) {
  990.                 /* Update the video surface */
  991.                 if ( screen->offset ) {
  992.                         for ( i=0; i<numrects; ++i ) {
  993.                                 rects[i].x += video->offset_x;
  994.                                 rects[i].y += video->offset_y;
  995.                         }
  996.                         video->UpdateRects(this, numrects, rects);
  997.                         for ( i=0; i<numrects; ++i ) {
  998.                                 rects[i].x -= video->offset_x;
  999.                                 rects[i].y -= video->offset_y;
  1000.                         }
  1001.                 } else {
  1002.                         video->UpdateRects(this, numrects, rects);
  1003.                 }
  1004.         }
  1005. }
  1006.  
  1007. /*
  1008.  * Performs hardware double buffering, if possible, or a full update if not.
  1009.  */
  1010. int SDL_Flip(SDL_Surface *screen)
  1011. {
  1012.         SDL_VideoDevice *video = current_video;
  1013.         /* Copy the shadow surface to the video surface */
  1014.         if ( screen == SDL_ShadowSurface ) {
  1015.                 SDL_Rect rect;
  1016.                 SDL_Palette *pal = screen->format->palette;
  1017.                 SDL_Color *saved_colors = NULL;
  1018.                 if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
  1019.                         /* simulated 8bpp, use correct physical palette */
  1020.                         saved_colors = pal->colors;
  1021.                         if ( video->gammacols ) {
  1022.                                 /* gamma-corrected palette */
  1023.                                 pal->colors = video->gammacols;
  1024.                         } else if ( video->physpal ) {
  1025.                                 /* physical palette different from logical */
  1026.                                 pal->colors = video->physpal->colors;
  1027.                         }
  1028.                 }
  1029.  
  1030.                 rect.x = 0;
  1031.                 rect.y = 0;
  1032.                 rect.w = screen->w;
  1033.                 rect.h = screen->h;
  1034.                 SDL_LowerBlit(SDL_ShadowSurface,&rect, SDL_VideoSurface,&rect);
  1035.  
  1036.                 if ( saved_colors )
  1037.                         pal->colors = saved_colors;
  1038.                 screen = SDL_VideoSurface;
  1039.         }
  1040.         if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1041.                 SDL_VideoDevice *this  = current_video;
  1042.                 return(video->FlipHWSurface(this, SDL_VideoSurface));
  1043.         } else {
  1044.                 SDL_UpdateRect(screen, 0, 0, 0, 0);
  1045.         }
  1046.         return(0);
  1047. }
  1048.  
  1049. static void SetPalette_logical(SDL_Surface *screen, SDL_Color *colors,
  1050.                                int firstcolor, int ncolors)
  1051. {
  1052.         SDL_Palette *pal = screen->format->palette;
  1053.         SDL_Palette *vidpal;
  1054.  
  1055.         if ( colors != (pal->colors + firstcolor) ) {
  1056.                 memcpy(pal->colors + firstcolor, colors,
  1057.                        ncolors * sizeof(*colors));
  1058.         }
  1059.  
  1060.         vidpal = SDL_VideoSurface->format->palette;
  1061.         if ( (screen == SDL_ShadowSurface) && vidpal ) {
  1062.                 /*
  1063.                  * This is a shadow surface, and the physical
  1064.                  * framebuffer is also indexed. Propagate the
  1065.                  * changes to its logical palette so that
  1066.                  * updates are always identity blits
  1067.                  */
  1068.                 memcpy(vidpal->colors + firstcolor, colors,
  1069.                        ncolors * sizeof(*colors));
  1070.         }
  1071.         SDL_FormatChanged(screen);
  1072. }
  1073.  
  1074. static int SetPalette_physical(SDL_Surface *screen,
  1075.                                SDL_Color *colors, int firstcolor, int ncolors)
  1076. {
  1077.         SDL_VideoDevice *video = current_video;
  1078.         int gotall = 1;
  1079.  
  1080.         if ( video->physpal ) {
  1081.                 /* We need to copy the new colors, since we haven't
  1082.                  * already done the copy in the logical set above.
  1083.                  */
  1084.                 memcpy(video->physpal->colors + firstcolor,
  1085.                        colors, ncolors * sizeof(*colors));
  1086.         }
  1087.         if ( screen == SDL_ShadowSurface ) {
  1088.                 if ( SDL_VideoSurface->flags & SDL_HWPALETTE ) {
  1089.                         /*
  1090.                          * The real screen is also indexed - set its physical
  1091.                          * palette. The physical palette does not include the
  1092.                          * gamma modification, we apply it directly instead,
  1093.                          * but this only happens if we have hardware palette.
  1094.                          */
  1095.                         screen = SDL_VideoSurface;
  1096.                 } else {
  1097.                         /*
  1098.                          * The video surface is not indexed - invalidate any
  1099.                          * active shadow-to-video blit mappings.
  1100.                          */
  1101.                         if ( screen->map->dst == SDL_VideoSurface ) {
  1102.                                 SDL_InvalidateMap(screen->map);
  1103.                         }
  1104.                         if ( video->gamma ) {
  1105.                                 if( ! video->gammacols ) {
  1106.                                         SDL_Palette *pp = video->physpal;
  1107.                                         if(!pp)
  1108.                                                 pp = screen->format->palette;
  1109.                                         video->gammacols = malloc(pp->ncolors
  1110.                                                           * sizeof(SDL_Color));
  1111.                                         SDL_ApplyGamma(video->gamma,
  1112.                                                        pp->colors,
  1113.                                                        video->gammacols,
  1114.                                                        pp->ncolors);
  1115.                                 } else {
  1116.                                         SDL_ApplyGamma(video->gamma, colors,
  1117.                                                        video->gammacols
  1118.                                                        + firstcolor,
  1119.                                                        ncolors);
  1120.                                 }
  1121.                         }
  1122.                         SDL_UpdateRect(screen, 0, 0, 0, 0);
  1123.                 }
  1124.         }
  1125.  
  1126.         if ( screen == SDL_VideoSurface ) {
  1127.                 SDL_Color gcolors[256];
  1128.  
  1129.                 if ( video->gamma ) {
  1130.                         SDL_ApplyGamma(video->gamma, colors, gcolors, ncolors);
  1131.                         colors = gcolors;
  1132.                 }
  1133.                 gotall = video->SetColors(video, firstcolor, ncolors, colors);
  1134.                 if ( ! gotall ) {
  1135.                         /* The video flags shouldn't have SDL_HWPALETTE, and
  1136.                            the video driver is responsible for copying back the
  1137.                            correct colors into the video surface palette.
  1138.                         */
  1139.                         ;
  1140.                 }
  1141.                 SDL_CursorPaletteChanged();
  1142.         }
  1143.         return gotall;
  1144. }
  1145.  
  1146. /*
  1147.  * Set the physical and/or logical colormap of a surface:
  1148.  * Only the screen has a physical colormap. It determines what is actually
  1149.  * sent to the display.
  1150.  * The logical colormap is used to map blits to/from the surface.
  1151.  * 'which' is one or both of SDL_LOGPAL, SDL_PHYSPAL
  1152.  *
  1153.  * Return nonzero if all colours were set as requested, or 0 otherwise.
  1154.  */
  1155. int SDL_SetPalette(SDL_Surface *screen, int which,
  1156.                    SDL_Color *colors, int firstcolor, int ncolors)
  1157. {
  1158.         SDL_Palette *pal;
  1159.         int gotall;
  1160.         int palsize;
  1161.  
  1162.         if ( ! current_video ) {
  1163.                 return 0;
  1164.         }
  1165.         if ( screen != SDL_PublicSurface ) {
  1166.                 /* only screens have physical palettes */
  1167.                 which &= ~SDL_PHYSPAL;
  1168.         } else if( (screen->flags & SDL_HWPALETTE) != SDL_HWPALETTE ) {
  1169.                 /* hardware palettes required for split colormaps */
  1170.                 which |= SDL_PHYSPAL | SDL_LOGPAL;
  1171.         }
  1172.  
  1173.         /* Verify the parameters */
  1174.         pal = screen->format->palette;
  1175.         if( !pal ) {
  1176.                 return 0;       /* not a palettized surface */
  1177.         }
  1178.         gotall = 1;
  1179.         palsize = 1 << screen->format->BitsPerPixel;
  1180.         if ( ncolors > (palsize - firstcolor) ) {
  1181.                 ncolors = (palsize - firstcolor);
  1182.                 gotall = 0;
  1183.         }
  1184.  
  1185.         if ( which & SDL_LOGPAL ) {
  1186.                 /*
  1187.                  * Logical palette change: The actual screen isn't affected,
  1188.                  * but the internal colormap is altered so that the
  1189.                  * interpretation of the pixel values (for blits etc) is
  1190.                  * changed.
  1191.                  */
  1192.                 SetPalette_logical(screen, colors, firstcolor, ncolors);
  1193.         }
  1194.         if ( which & SDL_PHYSPAL ) {
  1195.                 SDL_VideoDevice *video = current_video;
  1196.                 /*
  1197.                  * Physical palette change: This doesn't affect the
  1198.                  * program's idea of what the screen looks like, but changes
  1199.                  * its actual appearance.
  1200.                  */
  1201.                 if(!video)
  1202.                         return gotall;  /* video not yet initialized */
  1203.                 if(!video->physpal && !(which & SDL_LOGPAL) ) {
  1204.                         /* Lazy physical palette allocation */
  1205.                         int size;
  1206.                         SDL_Palette *pp = malloc(sizeof(*pp));
  1207.                         current_video->physpal = pp;
  1208.                         pp->ncolors = pal->ncolors;
  1209.                         size = pp->ncolors * sizeof(SDL_Color);
  1210.                         pp->colors = malloc(size);
  1211.                         memcpy(pp->colors, pal->colors, size);
  1212.                 }
  1213.                 if ( ! SetPalette_physical(screen,
  1214.                                            colors, firstcolor, ncolors) ) {
  1215.                         gotall = 0;
  1216.                 }
  1217.         }
  1218.         return gotall;
  1219. }
  1220.  
  1221. int SDL_SetColors(SDL_Surface *screen, SDL_Color *colors, int firstcolor,
  1222.                   int ncolors)
  1223. {
  1224.         return SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL,
  1225.                               colors, firstcolor, ncolors);
  1226. }
  1227.  
  1228. /*
  1229.  * Clean up the video subsystem
  1230.  */
  1231. void SDL_VideoQuit (void)
  1232. {
  1233.         SDL_Surface *ready_to_go;
  1234.  
  1235.         if ( current_video ) {
  1236.                 SDL_VideoDevice *video = current_video;
  1237.                 SDL_VideoDevice *this  = current_video;
  1238.  
  1239.                 /* Halt event processing before doing anything else */
  1240.                 SDL_StopEventLoop();
  1241.  
  1242.                 /* Clean up allocated window manager items */
  1243.                 if ( SDL_PublicSurface ) {
  1244.                         SDL_PublicSurface = NULL;
  1245.                 }
  1246.                 SDL_CursorQuit();
  1247.  
  1248.                 /* Just in case... */
  1249.                 SDL_WM_GrabInputOff();
  1250.  
  1251.                 /* Clean up the system video */
  1252.                 video->VideoQuit(this);
  1253.  
  1254.                 /* Free any lingering surfaces */
  1255.                 ready_to_go = SDL_ShadowSurface;
  1256.                 SDL_ShadowSurface = NULL;
  1257.                 SDL_FreeSurface(ready_to_go);
  1258.                 if ( SDL_VideoSurface != NULL ) {
  1259.                         ready_to_go = SDL_VideoSurface;
  1260.                         SDL_VideoSurface = NULL;
  1261.                         SDL_FreeSurface(ready_to_go);
  1262.                 }
  1263.                 SDL_PublicSurface = NULL;
  1264.  
  1265.                 /* Clean up miscellaneous memory */
  1266.                 if ( video->physpal ) {
  1267.                         free(video->physpal->colors);
  1268.                         free(video->physpal);
  1269.                         video->physpal = NULL;
  1270.                 }
  1271.                 if ( video->gammacols ) {
  1272.                         free(video->gammacols);
  1273.                         video->gammacols = NULL;
  1274.                 }
  1275.                 if ( video->gamma ) {
  1276.                         free(video->gamma);
  1277.                         video->gamma = NULL;
  1278.                 }
  1279.                 if ( video->wm_title != NULL ) {
  1280.                         free(video->wm_title);
  1281.                         video->wm_title = NULL;
  1282.                 }
  1283.                 if ( video->wm_icon != NULL ) {
  1284.                         free(video->wm_icon);
  1285.                         video->wm_icon = NULL;
  1286.                 }
  1287.  
  1288.                 /* Finish cleaning up video subsystem */
  1289.                 video->free(this);
  1290.                 current_video = NULL;
  1291.         }
  1292.         return;
  1293. }
  1294.  
  1295. /* Load the GL driver library */
  1296. int SDL_GL_LoadLibrary(const char *path)
  1297. {
  1298.         SDL_VideoDevice *video = current_video;
  1299.         SDL_VideoDevice *this = current_video;
  1300.         int retval;
  1301.  
  1302.         retval = -1;
  1303.         if ( video && video->GL_LoadLibrary ) {
  1304.                 retval = video->GL_LoadLibrary(this, path);
  1305.         } else {
  1306.                 SDL_SetError("No dynamic GL support in video driver");
  1307.         }
  1308.         return(retval);
  1309. }
  1310.  
  1311. void *SDL_GL_GetProcAddress(const char* proc)
  1312. {
  1313.         SDL_VideoDevice *video = current_video;
  1314.         SDL_VideoDevice *this = current_video;
  1315.         void *func;
  1316.  
  1317.         func = NULL;
  1318.         if ( video->GL_GetProcAddress ) {
  1319.                 if ( video->gl_config.driver_loaded ) {
  1320.                         func = video->GL_GetProcAddress(this, proc);
  1321.                 } else {
  1322.                         SDL_SetError("No GL driver has been loaded");
  1323.                 }
  1324.         } else {
  1325.                 SDL_SetError("No dynamic GL support in video driver");
  1326.         }
  1327.         return func;
  1328. }
  1329.  
  1330. /* Set the specified GL attribute for setting up a GL video mode */
  1331. int SDL_GL_SetAttribute( SDL_GLattr attr, int value )
  1332. {
  1333.         int retval;
  1334.         SDL_VideoDevice *video = current_video;
  1335.  
  1336.         retval = 0;
  1337.         switch (attr) {
  1338.                 case SDL_GL_RED_SIZE:
  1339.                         video->gl_config.red_size = value;
  1340.                         break;
  1341.                 case SDL_GL_GREEN_SIZE:
  1342.                         video->gl_config.green_size = value;
  1343.                         break;
  1344.                 case SDL_GL_BLUE_SIZE:
  1345.                         video->gl_config.blue_size = value;
  1346.                         break;
  1347.                 case SDL_GL_ALPHA_SIZE:
  1348.                         video->gl_config.alpha_size = value;
  1349.                         break;
  1350.                 case SDL_GL_DOUBLEBUFFER:
  1351.                         video->gl_config.double_buffer = value;
  1352.                         break;
  1353.                 case SDL_GL_BUFFER_SIZE:
  1354.                         video->gl_config.buffer_size = value;
  1355.                         break;
  1356.                 case SDL_GL_DEPTH_SIZE:
  1357.                         video->gl_config.depth_size = value;
  1358.                         break;
  1359.                 case SDL_GL_STENCIL_SIZE:
  1360.                         video->gl_config.stencil_size = value;
  1361.                         break;
  1362.                 case SDL_GL_ACCUM_RED_SIZE:
  1363.                         video->gl_config.accum_red_size = value;
  1364.                         break;
  1365.                 case SDL_GL_ACCUM_GREEN_SIZE:
  1366.                         video->gl_config.accum_green_size = value;
  1367.                         break;
  1368.                 case SDL_GL_ACCUM_BLUE_SIZE:
  1369.                         video->gl_config.accum_blue_size = value;
  1370.                         break;
  1371.                 case SDL_GL_ACCUM_ALPHA_SIZE:
  1372.                         video->gl_config.accum_alpha_size = value;
  1373.                         break;
  1374.                 default:
  1375.                         SDL_SetError("Unknown OpenGL attribute");
  1376.                         retval = -1;
  1377.                         break;
  1378.         }
  1379.         return(retval);
  1380. }
  1381.  
  1382. /* Retrieve an attribute value from the windowing system. */
  1383. int SDL_GL_GetAttribute(SDL_GLattr attr, int* value)
  1384. {
  1385.         int retval = -1;
  1386.         SDL_VideoDevice* video = current_video;
  1387.         SDL_VideoDevice* this = current_video;
  1388.  
  1389.         if ( video->GL_GetAttribute ) {
  1390.                 retval = this->GL_GetAttribute(this, attr, value);
  1391.         } else {
  1392.                 *value = 0;
  1393.                 SDL_SetError("GL_GetAttribute not supported");
  1394.         }
  1395.         return retval;
  1396. }
  1397.  
  1398. /* Perform a GL buffer swap on the current GL context */
  1399. void SDL_GL_SwapBuffers(void)
  1400. {
  1401.         SDL_VideoDevice *video = current_video;
  1402.         SDL_VideoDevice *this = current_video;
  1403.  
  1404.         if ( video->screen->flags & SDL_OPENGL ) {
  1405.                 video->GL_SwapBuffers( this );
  1406.         }
  1407. }
  1408.  
  1409. /* Update rects with locking */
  1410. void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect *rects)
  1411. {
  1412.         SDL_GL_Lock();
  1413.         SDL_GL_UpdateRects(numrects, rects);
  1414.         SDL_GL_Unlock();
  1415. }
  1416.  
  1417. /* Update rects without state setting and changing (the caller is responsible for it) */
  1418. void SDL_GL_UpdateRects(int numrects, SDL_Rect *rects)
  1419. {
  1420. #ifdef HAVE_OPENGL
  1421.         SDL_VideoDevice *this = current_video;
  1422.         SDL_Rect update, tmp;
  1423.         int x, y, i;
  1424.  
  1425.         for ( i = 0; i < numrects; i++ )
  1426.         {
  1427.                 tmp.y = rects[i].y;
  1428.                 tmp.h = rects[i].h;
  1429.                 for ( y = 0; y <= rects[i].h / 256; y++ )
  1430.                 {
  1431.                         tmp.x = rects[i].x;
  1432.                         tmp.w = rects[i].w;
  1433.                         for ( x = 0; x <= rects[i].w / 256; x++ )
  1434.                         {
  1435.                                 update.x = tmp.x;
  1436.                                 update.y = tmp.y;
  1437.                                 update.w = tmp.w;
  1438.                                 update.h = tmp.h;
  1439.  
  1440.                                 if ( update.w > 256 )
  1441.                                         update.w = 256;
  1442.  
  1443.                                 if ( update.h > 256 )
  1444.                                         update.h = 256;
  1445.                        
  1446.                                 this->glFlush();
  1447.                                 this->glTexSubImage2D(
  1448.                                         GL_TEXTURE_2D,
  1449.                                         0,
  1450.                                         0,
  1451.                                         0,
  1452.                                         update.w,
  1453.                                         update.h,
  1454.                                         this->is_32bit? GL_RGBA : GL_RGB,
  1455. #ifdef GL_VERSION_1_2
  1456.                                         this->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
  1457. #else
  1458.                                         GL_UNSIGNED_BYTE,
  1459. #endif
  1460.                                         (Uint8 *)this->screen->pixels +
  1461.                                                 this->screen->format->BytesPerPixel * update.x +
  1462.                                                 update.y * this->screen->pitch );
  1463.        
  1464.                                 this->glFlush();
  1465.                                 /*
  1466.                                 * Note the parens around the function name:
  1467.                                 * This is because some OpenGL implementations define glTexCoord etc
  1468.                                 * as macros, and we don't want them expanded here.
  1469.                                 */
  1470.                                 this->glBegin(GL_TRIANGLE_STRIP);
  1471.                                         (this->glTexCoord2f)( 0.0, 0.0 );      
  1472.                                         (this->glVertex2i)( update.x, update.y );
  1473.                                         (this->glTexCoord2f)( (float)(update.w / 256.0), 0.0 );
  1474.                                         (this->glVertex2i)( update.x + update.w, update.y );
  1475.                                         (this->glTexCoord2f)( 0.0, (float)(update.h / 256.0) );
  1476.                                         (this->glVertex2i)( update.x, update.y + update.h );
  1477.                                         (this->glTexCoord2f)( (float)(update.w / 256.0), (float)(update.h / 256.0) );  
  1478.                                         (this->glVertex2i)( update.x + update.w , update.y + update.h );
  1479.                                 this->glEnd(); 
  1480.                        
  1481.                                 tmp.x += 256;
  1482.                                 tmp.w -= 256;
  1483.                         }
  1484.                         tmp.y += 256;
  1485.                         tmp.h -= 256;
  1486.                 }
  1487.         }
  1488. #endif
  1489. }
  1490.  
  1491. /* Lock == save current state */
  1492. void SDL_GL_Lock()
  1493. {
  1494. #ifdef HAVE_OPENGL
  1495.         lock_count--;
  1496.         if (lock_count==-1)
  1497.         {
  1498.                 SDL_VideoDevice *this = current_video;
  1499.  
  1500.                 this->glPushAttrib( GL_ALL_ATTRIB_BITS );       /* TODO: narrow range of what is saved */
  1501.                 this->glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
  1502.  
  1503.                 this->glEnable(GL_TEXTURE_2D);
  1504.                 this->glEnable(GL_BLEND);
  1505.                 this->glDisable(GL_FOG);
  1506.                 this->glDisable(GL_ALPHA_TEST);
  1507.                 this->glDisable(GL_DEPTH_TEST);
  1508.                 this->glDisable(GL_SCISSOR_TEST);      
  1509.                 this->glDisable(GL_STENCIL_TEST);
  1510.                 this->glDisable(GL_CULL_FACE);
  1511.  
  1512.                 this->glBindTexture( GL_TEXTURE_2D, this->texture );
  1513.                 this->glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  1514.                 this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  1515.                 this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  1516.                 this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  1517.                 this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
  1518.  
  1519.                 this->glPixelStorei( GL_UNPACK_ROW_LENGTH, this->screen->pitch / this->screen->format->BytesPerPixel );
  1520.                 this->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1521.                 (this->glColor4f)(1.0, 1.0, 1.0, 1.0);          /* Solaris workaround */
  1522.  
  1523.                 this->glViewport(0, 0, this->screen->w, this->screen->h);
  1524.                 this->glMatrixMode(GL_PROJECTION);
  1525.                 this->glPushMatrix();
  1526.                 this->glLoadIdentity();
  1527.  
  1528.                 this->glOrtho(0.0, (GLdouble) this->screen->w, (GLdouble) this->screen->h, 0.0, 0.0, 1.0);
  1529.  
  1530.                 this->glMatrixMode(GL_MODELVIEW);
  1531.                 this->glPushMatrix();
  1532.                 this->glLoadIdentity();
  1533.         }
  1534. #endif
  1535. }
  1536.  
  1537. /* Unlock == restore saved state */
  1538. void SDL_GL_Unlock()
  1539. {
  1540. #ifdef HAVE_OPENGL
  1541.         lock_count++;
  1542.         if (lock_count==0)
  1543.         {
  1544.                 SDL_VideoDevice *this = current_video;
  1545.  
  1546.                 this->glPopMatrix();
  1547.                 this->glMatrixMode(GL_PROJECTION);
  1548.                 this->glPopMatrix();
  1549.  
  1550.                 this->glPopClientAttrib();
  1551.                 this->glPopAttrib();
  1552.         }
  1553. #endif
  1554. }
  1555.  
  1556. /*
  1557.  * Sets/Gets the title and icon text of the display window, if any.
  1558.  */
  1559. void SDL_WM_SetCaption (const char *title, const char *icon)
  1560. {
  1561.         SDL_VideoDevice *video = current_video;
  1562.         SDL_VideoDevice *this  = current_video;
  1563.  
  1564.         if ( video ) {
  1565.                 if ( title ) {
  1566.                         if ( video->wm_title ) {
  1567.                                 free(video->wm_title);
  1568.                         }
  1569.                         video->wm_title = (char *)malloc(strlen(title)+1);
  1570.                         if ( video->wm_title != NULL ) {
  1571.                                 strcpy(video->wm_title, title);
  1572.                         }
  1573.                 }
  1574.                 if ( icon ) {
  1575.                         if ( video->wm_icon ) {
  1576.                                 free(video->wm_icon);
  1577.                         }
  1578.                         video->wm_icon = (char *)malloc(strlen(icon)+1);
  1579.                         if ( video->wm_icon != NULL ) {
  1580.                                 strcpy(video->wm_icon, icon);
  1581.                         }
  1582.                 }
  1583.                 if ( (title || icon) && (video->SetCaption != NULL) ) {
  1584.                         video->SetCaption(this, video->wm_title,video->wm_icon);
  1585.                 }
  1586.         }
  1587. }
  1588. void SDL_WM_GetCaption (char **title, char **icon)
  1589. {
  1590.         SDL_VideoDevice *video = current_video;
  1591.  
  1592.         if ( video ) {
  1593.                 if ( title ) {
  1594.                         *title = video->wm_title;
  1595.                 }
  1596.                 if ( icon ) {
  1597.                         *icon = video->wm_icon;
  1598.                 }
  1599.         }
  1600. }
  1601.  
  1602. /* Utility function used by SDL_WM_SetIcon() */
  1603. static void CreateMaskFromColorKey(SDL_Surface *icon, Uint8 *mask)
  1604. {
  1605.         int x, y;
  1606.         Uint32 colorkey;
  1607. #define SET_MASKBIT(icon, x, y, mask) \
  1608.         mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
  1609.  
  1610.         colorkey = icon->format->colorkey;
  1611.         switch (icon->format->BytesPerPixel) {
  1612.                 case 1: { Uint8 *pixels;
  1613.                         for ( y=0; y<icon->h; ++y ) {
  1614.                                 pixels = (Uint8 *)icon->pixels + y*icon->pitch;
  1615.                                 for ( x=0; x<icon->w; ++x ) {
  1616.                                         if ( *pixels++ == colorkey ) {
  1617.                                                 SET_MASKBIT(icon, x, y, mask);
  1618.                                         }
  1619.                                 }
  1620.                         }
  1621.                 }
  1622.                 break;
  1623.  
  1624.                 case 2: { Uint16 *pixels;
  1625.                         for ( y=0; y<icon->h; ++y ) {
  1626.                                 pixels = (Uint16 *)icon->pixels +
  1627.                                                    y*icon->pitch/2;
  1628.                                 for ( x=0; x<icon->w; ++x ) {
  1629.                                         if ( *pixels++ == colorkey ) {
  1630.                                                 SET_MASKBIT(icon, x, y, mask);
  1631.                                         }
  1632.                                 }
  1633.                         }
  1634.                 }
  1635.                 break;
  1636.  
  1637.                 case 4: { Uint32 *pixels;
  1638.                         for ( y=0; y<icon->h; ++y ) {
  1639.                                 pixels = (Uint32 *)icon->pixels +
  1640.                                                    y*icon->pitch/4;
  1641.                                 for ( x=0; x<icon->w; ++x ) {
  1642.                                         if ( *pixels++ == colorkey ) {
  1643.                                                 SET_MASKBIT(icon, x, y, mask);
  1644.                                         }
  1645.                                 }
  1646.                         }
  1647.                 }
  1648.                 break;
  1649.         }
  1650. }
  1651.  
  1652. /*
  1653.  * Sets the window manager icon for the display window.
  1654.  */
  1655. void SDL_WM_SetIcon (SDL_Surface *icon, Uint8 *mask)
  1656. {
  1657.         SDL_VideoDevice *video = current_video;
  1658.         SDL_VideoDevice *this  = current_video;
  1659.  
  1660.         if ( icon && video->SetIcon ) {
  1661.                 /* Generate a mask if necessary, and create the icon! */
  1662.                 if ( mask == NULL ) {
  1663.                         int mask_len = icon->h*(icon->w+7)/8;
  1664.                         mask = (Uint8 *)malloc(mask_len);
  1665.                         if ( mask == NULL ) {
  1666.                                 return;
  1667.                         }
  1668.                         memset(mask, ~0, mask_len);
  1669.                         if ( icon->flags & SDL_SRCCOLORKEY ) {
  1670.                                 CreateMaskFromColorKey(icon, mask);
  1671.                         }
  1672.                         video->SetIcon(video, icon, mask);
  1673.                         free(mask);
  1674.                 } else {
  1675.                         video->SetIcon(this, icon, mask);
  1676.                 }
  1677.         }
  1678. }
  1679.  
  1680. /*
  1681.  * Grab or ungrab the keyboard and mouse input.
  1682.  * This function returns the final grab mode after calling the
  1683.  * driver dependent function.
  1684.  */
  1685. static SDL_GrabMode SDL_WM_GrabInputRaw(SDL_GrabMode mode)
  1686. {
  1687.         SDL_VideoDevice *video = current_video;
  1688.         SDL_VideoDevice *this  = current_video;
  1689.  
  1690.         /* Only do something if we have support for grabs */
  1691.         /*if ( video->GrabInput == NULL ) {
  1692.                 return(video->input_grab);
  1693.         }*/
  1694.  
  1695.         /* If the final grab mode if off, only then do we actually grab */
  1696. #ifdef DEBUG_GRAB
  1697.   SDL_printf("SDL_WM_GrabInputRaw(%d) ... ", mode);
  1698. #endif
  1699.         /*if ( mode == SDL_GRAB_OFF ) {
  1700.                 if ( video->input_grab != SDL_GRAB_OFF ) {
  1701.                         mode = video->GrabInput(this, mode);
  1702.                 }
  1703.         } else {
  1704.                 if ( video->input_grab == SDL_GRAB_OFF ) {
  1705.                         mode = video->GrabInput(this, mode);
  1706.                 }
  1707.         }*/
  1708.         if ( mode != video->input_grab ) {
  1709.                 video->input_grab = mode;
  1710.                 if ( video->CheckMouseMode ) {
  1711.                         video->CheckMouseMode(this);
  1712.                 }
  1713.         }
  1714. #ifdef DEBUG_GRAB
  1715.   SDL_printf("Final mode %d\n", video->input_grab);
  1716. #endif
  1717.  
  1718.         /* Return the final grab state */
  1719.         if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1720.                 mode -= SDL_GRAB_FULLSCREEN;
  1721.         }
  1722.         return(mode);
  1723. }
  1724. SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode)
  1725. {
  1726.         SDL_VideoDevice *video = current_video;
  1727.  
  1728.         /* If the video isn't initialized yet, we can't do anything */
  1729.         if ( ! video ) {
  1730.                 return SDL_GRAB_OFF;
  1731.         }
  1732.  
  1733.         /* Return the current mode on query */
  1734.         if ( mode == SDL_GRAB_QUERY ) {
  1735.                 mode = video->input_grab;
  1736.                 if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1737.                         mode -= SDL_GRAB_FULLSCREEN;
  1738.                 }
  1739.                 return(mode);
  1740.         }
  1741.  
  1742. #ifdef DEBUG_GRAB
  1743.   SDL_printf("SDL_WM_GrabInput(%d) ... ", mode);
  1744. #endif
  1745.         /* If the video surface is fullscreen, we always grab */
  1746.         if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1747.                 mode -= SDL_GRAB_FULLSCREEN;
  1748.         }
  1749.         if ( SDL_VideoSurface && (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
  1750.                 mode += SDL_GRAB_FULLSCREEN;
  1751.         }
  1752.         return(SDL_WM_GrabInputRaw(mode));
  1753. }
  1754. static SDL_GrabMode SDL_WM_GrabInputOff(void)
  1755. {
  1756.         SDL_GrabMode mode;
  1757.  
  1758.         /* First query the current grab state */
  1759.         mode = SDL_WM_GrabInput(SDL_GRAB_QUERY);
  1760.  
  1761.         /* Now explicitly turn off input grab */
  1762.         SDL_WM_GrabInputRaw(SDL_GRAB_OFF);
  1763.  
  1764.         /* Return the old state */
  1765.         return(mode);
  1766. }
  1767.  
  1768. /*
  1769.  * Iconify the window in window managed environments.
  1770.  * A successful iconification will result in an SDL_APPACTIVE loss event.
  1771.  */
  1772. int SDL_WM_IconifyWindow(void)
  1773. {
  1774.         SDL_VideoDevice *video = current_video;
  1775.         SDL_VideoDevice *this  = current_video;
  1776.         int retval;
  1777.  
  1778.         retval = 0;
  1779.         if ( video->IconifyWindow ) {
  1780.                 retval = video->IconifyWindow(this);
  1781.         }
  1782.         return(retval);
  1783. }
  1784.  
  1785. /*
  1786.  * Toggle fullscreen mode
  1787.  */
  1788. int SDL_WM_ToggleFullScreen(SDL_Surface *surface)
  1789. {
  1790.         SDL_VideoDevice *video = current_video;
  1791.         SDL_VideoDevice *this  = current_video;
  1792.         int toggled;
  1793.  
  1794.         toggled = 0;
  1795.         if ( SDL_PublicSurface && (surface == SDL_PublicSurface) &&
  1796.              video->ToggleFullScreen ) {
  1797.                 if ( surface->flags & SDL_FULLSCREEN ) {
  1798.                         toggled = video->ToggleFullScreen(this, 0);
  1799.                         if ( toggled ) {
  1800.                                 SDL_VideoSurface->flags &= ~SDL_FULLSCREEN;
  1801.                                 SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
  1802.                         }
  1803.                 } else {
  1804.                         toggled = video->ToggleFullScreen(this, 1);
  1805.                         if ( toggled ) {
  1806.                                 SDL_VideoSurface->flags |= SDL_FULLSCREEN;
  1807.                                 SDL_PublicSurface->flags |= SDL_FULLSCREEN;
  1808.                         }
  1809.                 }
  1810.                 /* Double-check the grab state inside SDL_WM_GrabInput() */
  1811.                 if ( toggled ) {
  1812.                         SDL_WM_GrabInput(video->input_grab);
  1813.                 }
  1814.         }
  1815.         return(toggled);
  1816. }
  1817.  
  1818. /*
  1819.  * Get some platform dependent window manager information
  1820.  */
  1821. int SDL_GetWMInfo (SDL_SysWMinfo *info)
  1822. {
  1823.         SDL_VideoDevice *video = current_video;
  1824.         SDL_VideoDevice *this  = current_video;
  1825.  
  1826.         if ( video && video->GetWMInfo ) {
  1827.                 return(video->GetWMInfo(this, info));
  1828.         } else {
  1829.                 return(0);
  1830.         }
  1831. }
  1832.