Subversion Repositories Kolibri OS

Rev

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