src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 11 Apr 2004 19:54:40 +0000
changeset 883 50f5a29c6a17
parent 853 dddfc37e1f65
child 910 4ab6d1fd028f
permissions -rw-r--r--
Date: Sat, 10 Apr 2004 02:25:33 -0400
From: Glenn Maynard
To: sdl@libsdl.org
Subject: [SDL] SDL_SetVideoMode() failing and not setting an error (patch)

Running an OpenGL SDL application off 1.2.7, at SDL_InitSubSystem(SDL_INIT_VIDEO) time:

Warning: Unable to initialize AAlib mouseUsing AAlib driver: Slang driver 1.0 (slang)

SDL_SetVideoMode then fails; SDL_GetError() returns "".

The installation problem is straightforward: X (the higher priority
driver) isn't running, so SDL is falling back on aalib. However,
no error is being set when aalib fails to initialize. This also
happens with the svgalib driver.

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