Subversion Repositories Kolibri OS

Rev

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