src/video/SDL_video.c
author Patrice Mandin <patmandin@gmail.com>
Thu, 19 Jan 2006 21:28:52 +0000
changeset 1257 448a9a64537b
parent 1254 c2ee0f7fa711
child 1266 a7bea6db3c3e
permissions -rw-r--r--
[PATCH] SDL_GetVideoMode() does not find best mode, part 2

Following commit 1.51, I come accross a problem when SDL must choose between
several video modes that could suit the one asked.

If I ask 320x240 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200

The smallest selectables modes are 384x240 and 320x400. And SDL choose the later
in this list, but 384x240 is more suitable. So I added a check to compare
the pixel count (surface) of modes, and select the one which has the smallest
pixel count.

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