src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 18 Jul 2004 19:46:38 +0000
changeset 910 4ab6d1fd028f
parent 883 50f5a29c6a17
child 916 46916168361d
permissions -rw-r--r--
Date: Sat, 26 Jun 2004 14:58:42 +0300
From: "Mike Gorchak"
Subject: QNX 6.3 fixes for SDL

Sam, I've added new OpenGL framework for SDL, which appeared in the new QNX version - 6.3. I've leave compatibility with previous QNX versions. And I've moved all GL specific functions to the separate module, like it done for the other platforms.

SDL is now ready for the QNX 6.3 :)
     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 #ifdef __QNXNTO__
   568     #include <sys/neutrino.h>
   569 #endif /* __QNXNTO__ */
   570 
   571 /*
   572  * Set the requested video mode, allocating a shadow buffer if necessary.
   573  */
   574 SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags)
   575 {
   576 	SDL_VideoDevice *video, *this;
   577 	SDL_Surface *prev_mode, *mode;
   578 	int video_w;
   579 	int video_h;
   580 	int video_bpp;
   581 	int is_opengl;
   582 	SDL_GrabMode saved_grab;
   583 
   584 	/* Start up the video driver, if necessary..
   585 	   WARNING: This is the only function protected this way!
   586 	 */
   587 	if ( ! current_video ) {
   588 		if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) {
   589 			return(NULL);
   590 		}
   591 	}
   592 	this = video = current_video;
   593 
   594 	/* Default to the current video bpp */
   595 	if ( bpp == 0 ) {
   596 		flags |= SDL_ANYFORMAT;
   597 		bpp = SDL_VideoSurface->format->BitsPerPixel;
   598 	}
   599 
   600 	/* Get a good video mode, the closest one possible */
   601 	video_w = width;
   602 	video_h = height;
   603 	video_bpp = bpp;
   604 	if ( ! SDL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) {
   605 		return(NULL);
   606 	}
   607 
   608 	/* Check the requested flags */
   609 	/* There's no palette in > 8 bits-per-pixel mode */
   610 	if ( video_bpp > 8 ) {
   611 		flags &= ~SDL_HWPALETTE;
   612 	}
   613 #if 0
   614 	if ( (flags&SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
   615 		/* There's no windowed double-buffering */
   616 		flags &= ~SDL_DOUBLEBUF;
   617 	}
   618 #endif
   619 	if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
   620 		/* Use hardware surfaces when double-buffering */
   621 		flags |= SDL_HWSURFACE;
   622 	}
   623 
   624 	is_opengl = ( ( flags & SDL_OPENGL ) == SDL_OPENGL );
   625 	if ( is_opengl ) {
   626 		/* These flags are for 2D video modes only */
   627 		flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF);
   628 	}
   629 
   630 	/* Reset the keyboard here so event callbacks can run */
   631 	SDL_ResetKeyboard();
   632 	SDL_ResetMouse();
   633 
   634 	/* Clean up any previous video mode */
   635 	if ( SDL_PublicSurface != NULL ) {
   636 		SDL_PublicSurface = NULL;
   637 	}
   638 	if ( SDL_ShadowSurface != NULL ) {
   639 		SDL_Surface *ready_to_go;
   640 		ready_to_go = SDL_ShadowSurface;
   641 		SDL_ShadowSurface = NULL;
   642 		SDL_FreeSurface(ready_to_go);
   643 	}
   644 	if ( video->physpal ) {
   645 		free(video->physpal->colors);
   646 		free(video->physpal);
   647 		video->physpal = NULL;
   648 	}
   649 	if( video->gammacols) {
   650 		free(video->gammacols);
   651 		video->gammacols = NULL;
   652 	}
   653 
   654 	/* Save the previous grab state and turn off grab for mode switch */
   655 	saved_grab = SDL_WM_GrabInputOff();
   656 
   657 	/* Try to set the video mode, along with offset and clipping */
   658 	prev_mode = SDL_VideoSurface;
   659 	SDL_LockCursor();
   660 	SDL_VideoSurface = NULL;	/* In case it's freed by driver */
   661 	mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags);
   662 	if ( mode ) { /* Prevent resize events from mode change */
   663 	    SDL_PrivateResize(mode->w, mode->h);
   664 
   665 	    /* Sam - If we asked for OpenGL mode, and didn't get it, fail */
   666 	    if ( is_opengl && !(mode->flags & SDL_OPENGL) ) {
   667 		mode = NULL;
   668 		SDL_SetError("OpenGL not available");
   669 	    }
   670 	}
   671 	/*
   672 	 * rcg11292000
   673 	 * If you try to set an SDL_OPENGL surface, and fail to find a
   674 	 * matching  visual, then the next call to SDL_SetVideoMode()
   675 	 * will segfault, since  we no longer point to a dummy surface,
   676 	 * but rather NULL.
   677 	 * Sam 11/29/00
   678 	 * WARNING, we need to make sure that the previous mode hasn't
   679 	 * already been freed by the video driver.  What do we do in
   680 	 * that case?  Should we call SDL_VideoInit() again?
   681 	 */
   682 	SDL_VideoSurface = (mode != NULL) ? mode : prev_mode;
   683 
   684 	if ( (mode != NULL) && (!is_opengl) ) {
   685 		/* Sanity check */
   686 		if ( (mode->w < width) || (mode->h < height) ) {
   687 			SDL_SetError("Video mode smaller than requested");
   688 			return(NULL);
   689 		}
   690 
   691 		/* If we have a palettized surface, create a default palette */
   692 		if ( mode->format->palette ) {
   693 			SDL_PixelFormat *vf = mode->format;
   694 			SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel);
   695 			video->SetColors(this, 0, vf->palette->ncolors,
   696 			                           vf->palette->colors);
   697 		}
   698 
   699 		/* Clear the surface to black */
   700 		video->offset_x = 0;
   701 		video->offset_y = 0;
   702 		mode->offset = 0;
   703 		SDL_SetClipRect(mode, NULL);
   704 		SDL_ClearSurface(mode);
   705 
   706 		/* Now adjust the offsets to match the desired mode */
   707 		video->offset_x = (mode->w-width)/2;
   708 		video->offset_y = (mode->h-height)/2;
   709 		mode->offset = video->offset_y*mode->pitch +
   710 				video->offset_x*mode->format->BytesPerPixel;
   711 #ifdef DEBUG_VIDEO
   712   fprintf(stderr,
   713 	"Requested mode: %dx%dx%d, obtained mode %dx%dx%d (offset %d)\n",
   714 		width, height, bpp,
   715 		mode->w, mode->h, mode->format->BitsPerPixel, mode->offset);
   716 #endif
   717 		mode->w = width;
   718 		mode->h = height;
   719 		SDL_SetClipRect(mode, NULL);
   720 	}
   721 	SDL_ResetCursor();
   722 	SDL_UnlockCursor();
   723 
   724 	/* If we failed setting a video mode, return NULL... (Uh Oh!) */
   725 	if ( mode == NULL ) {
   726 		return(NULL);
   727 	}
   728 
   729 	/* If there is no window manager, set the SDL_NOFRAME flag */
   730 	if ( ! video->info.wm_available ) {
   731 		mode->flags |= SDL_NOFRAME;
   732 	}
   733 
   734 	/* Reset the mouse cursor and grab for new video mode */
   735 	SDL_SetCursor(NULL);
   736 	if ( video->UpdateMouse ) {
   737 		video->UpdateMouse(this);
   738 	}
   739 	SDL_WM_GrabInput(saved_grab);
   740 	SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */
   741 
   742 #ifdef HAVE_OPENGL
   743 	/* Load GL symbols (before MakeCurrent, where we need glGetString). */
   744 	if ( flags & (SDL_OPENGL | SDL_OPENGLBLIT) ) {
   745 
   746 #ifdef __QNXNTO__
   747     #if (_NTO_VERSION < 630)
   748        #define __SDL_NOGETPROCADDR__
   749     #endif /* 6.3.0 */
   750 #endif /* __QNXNTO__ */
   751 
   752 #ifdef __SDL_NOGETPROCADDR__
   753     #define SDL_PROC(ret,func,params) video->func=func;
   754 #else
   755     #define SDL_PROC(ret,func,params) \
   756     do { \
   757         video->func = SDL_GL_GetProcAddress(#func); \
   758         if ( ! video->func ) { \
   759             SDL_SetError("Couldn't load GL function: %s\n", #func); \
   760         return(NULL); \
   761         } \
   762     } while ( 0 );
   763 
   764 #endif /* __SDL_NOGETPROCADDR__ */
   765 
   766 #include "SDL_glfuncs.h"
   767 #undef SDL_PROC	
   768 	}
   769 #endif /* HAVE_OPENGL */
   770 
   771 	/* If we're running OpenGL, make the context current */
   772 	if ( (video->screen->flags & SDL_OPENGL) &&
   773 	      video->GL_MakeCurrent ) {
   774 		if ( video->GL_MakeCurrent(this) < 0 ) {
   775 			return(NULL);
   776 		}
   777 	}
   778 
   779 	/* Set up a fake SDL surface for OpenGL "blitting" */
   780 	if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) {
   781 		/* Load GL functions for performing the texture updates */
   782 #ifdef HAVE_OPENGL
   783 
   784 		/* Create a software surface for blitting */
   785 #ifdef GL_VERSION_1_2
   786 		/* If the implementation either supports the packed pixels
   787 		   extension, or implements the core OpenGL 1.2 API, it will
   788 		   support the GL_UNSIGNED_SHORT_5_6_5 texture format.
   789 		 */
   790 		if ( (bpp == 16) &&
   791 		     (strstr((const char *)video->glGetString(GL_EXTENSIONS), "GL_EXT_packed_pixels") ||
   792 		     (atof((const char *)video->glGetString(GL_VERSION)) >= 1.2f))
   793 		   ) {
   794 			video->is_32bit = 0;
   795 			SDL_VideoSurface = SDL_CreateRGBSurface(
   796 				flags, 
   797 				width, 
   798 				height,  
   799 				16,
   800 				31 << 11,
   801 				63 << 5,
   802 				31,
   803 				0
   804 				);
   805 		}
   806 		else
   807 #endif /* OpenGL 1.2 */
   808 		{
   809 			video->is_32bit = 1;
   810 			SDL_VideoSurface = SDL_CreateRGBSurface(
   811 				flags, 
   812 				width, 
   813 				height, 
   814 				32, 
   815 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   816 				0x000000FF,
   817 				0x0000FF00,
   818 				0x00FF0000,
   819 				0xFF000000
   820 #else
   821 				0xFF000000,
   822 				0x00FF0000,
   823 				0x0000FF00,
   824 				0x000000FF
   825 #endif
   826 				);
   827 		}
   828 		if ( ! SDL_VideoSurface ) {
   829 			return(NULL);
   830 		}
   831 		SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT;
   832 
   833 		/* Free the original video mode surface (is this safe?) */
   834 		SDL_FreeSurface(mode);
   835 
   836 		/* Set the surface completely opaque & white by default */
   837 		memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch );
   838 		video->glGenTextures( 1, &video->texture );
   839 		video->glBindTexture( GL_TEXTURE_2D, video->texture );
   840 		video->glTexImage2D(
   841 			GL_TEXTURE_2D,
   842 			0,
   843 			video->is_32bit ? GL_RGBA : GL_RGB,
   844 			256,
   845 			256,
   846 			0,
   847 			video->is_32bit ? GL_RGBA : GL_RGB,
   848 #ifdef GL_VERSION_1_2
   849 			video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
   850 #else
   851 			GL_UNSIGNED_BYTE,
   852 #endif
   853 			NULL);
   854 
   855 		video->UpdateRects = SDL_GL_UpdateRectsLock;
   856 #else
   857 		SDL_SetError("Somebody forgot to #define HAVE_OPENGL");
   858 		return(NULL);
   859 #endif
   860 	}
   861 
   862 	/* Create a shadow surface if necessary */
   863 	/* There are three conditions under which we create a shadow surface:
   864 		1.  We need a particular bits-per-pixel that we didn't get.
   865 		2.  We need a hardware palette and didn't get one.
   866 		3.  We need a software surface and got a hardware surface.
   867 	*/
   868 	if ( !(SDL_VideoSurface->flags & SDL_OPENGL) &&
   869 	     (
   870 	     (  !(flags&SDL_ANYFORMAT) &&
   871 			(SDL_VideoSurface->format->BitsPerPixel != bpp)) ||
   872 	     (   (flags&SDL_HWPALETTE) && 
   873 				!(SDL_VideoSurface->flags&SDL_HWPALETTE)) ||
   874 		/* If the surface is in hardware, video writes are visible
   875 		   as soon as they are performed, so we need to buffer them
   876 		 */
   877 	     (   ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) &&
   878 				(SDL_VideoSurface->flags&SDL_HWSURFACE)) ||
   879 	     (   (flags&SDL_DOUBLEBUF) &&
   880 				(SDL_VideoSurface->flags&SDL_HWSURFACE) &&
   881 				!(SDL_VideoSurface->flags&SDL_DOUBLEBUF))
   882 	     ) ) {
   883 		SDL_CreateShadowSurface(bpp);
   884 		if ( SDL_ShadowSurface == NULL ) {
   885 			SDL_SetError("Couldn't create shadow surface");
   886 			return(NULL);
   887 		}
   888 		SDL_PublicSurface = SDL_ShadowSurface;
   889 	} else {
   890 		SDL_PublicSurface = SDL_VideoSurface;
   891 	}
   892 	video->info.vfmt = SDL_VideoSurface->format;
   893 
   894 	/* We're done! */
   895 	return(SDL_PublicSurface);
   896 }
   897 
   898 /* 
   899  * Convert a surface into the video pixel format.
   900  */
   901 SDL_Surface * SDL_DisplayFormat (SDL_Surface *surface)
   902 {
   903 	Uint32 flags;
   904 
   905 	if ( ! SDL_PublicSurface ) {
   906 		SDL_SetError("No video mode has been set");
   907 		return(NULL);
   908 	}
   909 	/* Set the flags appropriate for copying to display surface */
   910 	if (((SDL_PublicSurface->flags&SDL_HWSURFACE) == SDL_HWSURFACE) && current_video->info.blit_hw)
   911 		flags = SDL_HWSURFACE;
   912 	else 
   913 		flags = SDL_SWSURFACE;
   914 #ifdef AUTORLE_DISPLAYFORMAT
   915 	flags |= (surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA));
   916 	flags |= SDL_RLEACCELOK;
   917 #else
   918 	flags |= surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA|SDL_RLEACCELOK);
   919 #endif
   920 	return(SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags));
   921 }
   922 
   923 /*
   924  * Convert a surface into a format that's suitable for blitting to
   925  * the screen, but including an alpha channel.
   926  */
   927 SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface)
   928 {
   929 	SDL_PixelFormat *vf;
   930 	SDL_PixelFormat *format;
   931 	SDL_Surface *converted;
   932 	Uint32 flags;
   933 	/* default to ARGB8888 */
   934 	Uint32 amask = 0xff000000;
   935 	Uint32 rmask = 0x00ff0000;
   936 	Uint32 gmask = 0x0000ff00;
   937 	Uint32 bmask = 0x000000ff;
   938 
   939 	if ( ! SDL_PublicSurface ) {
   940 		SDL_SetError("No video mode has been set");
   941 		return(NULL);
   942 	}
   943 	vf = SDL_PublicSurface->format;
   944 
   945 	switch(vf->BytesPerPixel) {
   946 	    case 2:
   947 		/* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
   948 		   For anything else (like ARGB4444) it doesn't matter
   949 		   since we have no special code for it anyway */
   950 		if ( (vf->Rmask == 0x1f) &&
   951 		     (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
   952 			rmask = 0xff;
   953 			bmask = 0xff0000;
   954 		}
   955 		break;
   956 
   957 	    case 3:
   958 	    case 4:
   959 		/* Keep the video format, as long as the high 8 bits are
   960 		   unused or alpha */
   961 		if ( (vf->Rmask == 0xff) && (vf->Bmask == 0xff0000) ) {
   962 			rmask = 0xff;
   963 			bmask = 0xff0000;
   964 		}
   965 		break;
   966 
   967 	    default:
   968 		/* We have no other optimised formats right now. When/if a new
   969 		   optimised alpha format is written, add the converter here */
   970 		break;
   971 	}
   972 	format = SDL_AllocFormat(32, rmask, gmask, bmask, amask);
   973 	flags = SDL_PublicSurface->flags & SDL_HWSURFACE;
   974 	flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
   975 	converted = SDL_ConvertSurface(surface, format, flags);
   976 	SDL_FreeFormat(format);
   977 	return(converted);
   978 }
   979 
   980 /*
   981  * Update a specific portion of the physical screen
   982  */
   983 void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
   984 {
   985 	if ( screen ) {
   986 		SDL_Rect rect;
   987 
   988 		/* Perform some checking */
   989 		if ( w == 0 )
   990 			w = screen->w;
   991 		if ( h == 0 )
   992 			h = screen->h;
   993 		if ( (int)(x+w) > screen->w )
   994 			return;
   995 		if ( (int)(y+h) > screen->h )
   996 			return;
   997 
   998 		/* Fill the rectangle */
   999 		rect.x = x;
  1000 		rect.y = y;
  1001 		rect.w = w;
  1002 		rect.h = h;
  1003 		SDL_UpdateRects(screen, 1, &rect);
  1004 	}
  1005 }
  1006 void SDL_UpdateRects (SDL_Surface *screen, int numrects, SDL_Rect *rects)
  1007 {
  1008 	int i;
  1009 	SDL_VideoDevice *video = current_video;
  1010 	SDL_VideoDevice *this = current_video;
  1011 
  1012 	if ( screen == SDL_ShadowSurface ) {
  1013 		/* Blit the shadow surface using saved mapping */
  1014 		SDL_Palette *pal = screen->format->palette;
  1015 		SDL_Color *saved_colors = NULL;
  1016 		if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
  1017 			/* simulated 8bpp, use correct physical palette */
  1018 			saved_colors = pal->colors;
  1019 			if ( video->gammacols ) {
  1020 				/* gamma-corrected palette */
  1021 				pal->colors = video->gammacols;
  1022 			} else if ( video->physpal ) {
  1023 				/* physical palette different from logical */
  1024 				pal->colors = video->physpal->colors;
  1025 			}
  1026 		}
  1027 		if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
  1028 			SDL_LockCursor();
  1029 			SDL_DrawCursor(SDL_ShadowSurface);
  1030 			for ( i=0; i<numrects; ++i ) {
  1031 				SDL_LowerBlit(SDL_ShadowSurface, &rects[i], 
  1032 						SDL_VideoSurface, &rects[i]);
  1033 			}
  1034 			SDL_EraseCursor(SDL_ShadowSurface);
  1035 			SDL_UnlockCursor();
  1036 		} else {
  1037 			for ( i=0; i<numrects; ++i ) {
  1038 				SDL_LowerBlit(SDL_ShadowSurface, &rects[i], 
  1039 						SDL_VideoSurface, &rects[i]);
  1040 			}
  1041 		}
  1042 		if ( saved_colors ) {
  1043 			pal->colors = saved_colors;
  1044 		}
  1045 
  1046 		/* Fall through to video surface update */
  1047 		screen = SDL_VideoSurface;
  1048 	}
  1049 	if ( screen == SDL_VideoSurface ) {
  1050 		/* Update the video surface */
  1051 		if ( screen->offset ) {
  1052 			for ( i=0; i<numrects; ++i ) {
  1053 				rects[i].x += video->offset_x;
  1054 				rects[i].y += video->offset_y;
  1055 			}
  1056 			video->UpdateRects(this, numrects, rects);
  1057 			for ( i=0; i<numrects; ++i ) {
  1058 				rects[i].x -= video->offset_x;
  1059 				rects[i].y -= video->offset_y;
  1060 			}
  1061 		} else {
  1062 			video->UpdateRects(this, numrects, rects);
  1063 		}
  1064 	}
  1065 }
  1066 
  1067 /*
  1068  * Performs hardware double buffering, if possible, or a full update if not.
  1069  */
  1070 int SDL_Flip(SDL_Surface *screen)
  1071 {
  1072 	SDL_VideoDevice *video = current_video;
  1073 	/* Copy the shadow surface to the video surface */
  1074 	if ( screen == SDL_ShadowSurface ) {
  1075 		SDL_Rect rect;
  1076 		SDL_Palette *pal = screen->format->palette;
  1077 		SDL_Color *saved_colors = NULL;
  1078 		if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
  1079 			/* simulated 8bpp, use correct physical palette */
  1080 			saved_colors = pal->colors;
  1081 			if ( video->gammacols ) {
  1082 				/* gamma-corrected palette */
  1083 				pal->colors = video->gammacols;
  1084 			} else if ( video->physpal ) {
  1085 				/* physical palette different from logical */
  1086 				pal->colors = video->physpal->colors;
  1087 			}
  1088 		}
  1089 
  1090 		rect.x = 0;
  1091 		rect.y = 0;
  1092 		rect.w = screen->w;
  1093 		rect.h = screen->h;
  1094 		if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
  1095 			SDL_LockCursor();
  1096 			SDL_DrawCursor(SDL_ShadowSurface);
  1097 			SDL_LowerBlit(SDL_ShadowSurface, &rect,
  1098 					SDL_VideoSurface, &rect);
  1099 			SDL_EraseCursor(SDL_ShadowSurface);
  1100 			SDL_UnlockCursor();
  1101 		} else {
  1102 			SDL_LowerBlit(SDL_ShadowSurface, &rect,
  1103 					SDL_VideoSurface, &rect);
  1104 		}
  1105 		if ( saved_colors ) {
  1106 			pal->colors = saved_colors;
  1107 		}
  1108 
  1109 		/* Fall through to video surface update */
  1110 		screen = SDL_VideoSurface;
  1111 	}
  1112 	if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1113 		SDL_VideoDevice *this  = current_video;
  1114 		return(video->FlipHWSurface(this, SDL_VideoSurface));
  1115 	} else {
  1116 		SDL_UpdateRect(screen, 0, 0, 0, 0);
  1117 	}
  1118 	return(0);
  1119 }
  1120 
  1121 static void SetPalette_logical(SDL_Surface *screen, SDL_Color *colors,
  1122 			       int firstcolor, int ncolors)
  1123 {
  1124 	SDL_Palette *pal = screen->format->palette;
  1125 	SDL_Palette *vidpal;
  1126 
  1127 	if ( colors != (pal->colors + firstcolor) ) {
  1128 		memcpy(pal->colors + firstcolor, colors,
  1129 		       ncolors * sizeof(*colors));
  1130 	}
  1131 
  1132 	vidpal = SDL_VideoSurface->format->palette;
  1133 	if ( (screen == SDL_ShadowSurface) && vidpal ) {
  1134 		/*
  1135 		 * This is a shadow surface, and the physical
  1136 		 * framebuffer is also indexed. Propagate the
  1137 		 * changes to its logical palette so that
  1138 		 * updates are always identity blits
  1139 		 */
  1140 		memcpy(vidpal->colors + firstcolor, colors,
  1141 		       ncolors * sizeof(*colors));
  1142 	}
  1143 	SDL_FormatChanged(screen);
  1144 }
  1145 
  1146 static int SetPalette_physical(SDL_Surface *screen,
  1147                                SDL_Color *colors, int firstcolor, int ncolors)
  1148 {
  1149 	SDL_VideoDevice *video = current_video;
  1150 	int gotall = 1;
  1151 
  1152 	if ( video->physpal ) {
  1153 		/* We need to copy the new colors, since we haven't
  1154 		 * already done the copy in the logical set above.
  1155 		 */
  1156 		memcpy(video->physpal->colors + firstcolor,
  1157 		       colors, ncolors * sizeof(*colors));
  1158 	}
  1159 	if ( screen == SDL_ShadowSurface ) {
  1160 		if ( SDL_VideoSurface->flags & SDL_HWPALETTE ) {
  1161 			/*
  1162 			 * The real screen is also indexed - set its physical
  1163 			 * palette. The physical palette does not include the
  1164 			 * gamma modification, we apply it directly instead,
  1165 			 * but this only happens if we have hardware palette.
  1166 			 */
  1167 			screen = SDL_VideoSurface;
  1168 		} else {
  1169 			/*
  1170 			 * The video surface is not indexed - invalidate any
  1171 			 * active shadow-to-video blit mappings.
  1172 			 */
  1173 			if ( screen->map->dst == SDL_VideoSurface ) {
  1174 				SDL_InvalidateMap(screen->map);
  1175 			}
  1176 			if ( video->gamma ) {
  1177 				if( ! video->gammacols ) {
  1178 					SDL_Palette *pp = video->physpal;
  1179 					if(!pp)
  1180 						pp = screen->format->palette;
  1181 					video->gammacols = malloc(pp->ncolors
  1182 							  * sizeof(SDL_Color));
  1183 					SDL_ApplyGamma(video->gamma,
  1184 						       pp->colors,
  1185 						       video->gammacols,
  1186 						       pp->ncolors);
  1187 				} else {
  1188 					SDL_ApplyGamma(video->gamma, colors,
  1189 						       video->gammacols
  1190 						       + firstcolor,
  1191 						       ncolors);
  1192 				}
  1193 			}
  1194 			SDL_UpdateRect(screen, 0, 0, 0, 0);
  1195 		}
  1196 	}
  1197 
  1198 	if ( screen == SDL_VideoSurface ) {
  1199 		SDL_Color gcolors[256];
  1200 
  1201 		if ( video->gamma ) {
  1202 			SDL_ApplyGamma(video->gamma, colors, gcolors, ncolors);
  1203 			colors = gcolors;
  1204 		}
  1205 		gotall = video->SetColors(video, firstcolor, ncolors, colors);
  1206 		if ( ! gotall ) {
  1207 			/* The video flags shouldn't have SDL_HWPALETTE, and
  1208 			   the video driver is responsible for copying back the
  1209 			   correct colors into the video surface palette.
  1210 			*/
  1211 			;
  1212 		}
  1213 		SDL_CursorPaletteChanged();
  1214 	}
  1215 	return gotall;
  1216 }
  1217 
  1218 /*
  1219  * Set the physical and/or logical colormap of a surface:
  1220  * Only the screen has a physical colormap. It determines what is actually
  1221  * sent to the display.
  1222  * The logical colormap is used to map blits to/from the surface.
  1223  * 'which' is one or both of SDL_LOGPAL, SDL_PHYSPAL
  1224  *
  1225  * Return nonzero if all colours were set as requested, or 0 otherwise.
  1226  */
  1227 int SDL_SetPalette(SDL_Surface *screen, int which,
  1228 		   SDL_Color *colors, int firstcolor, int ncolors)
  1229 {
  1230 	SDL_Palette *pal;
  1231 	int gotall;
  1232 	int palsize;
  1233 
  1234 	if ( ! current_video ) {
  1235 		return 0;
  1236 	}
  1237 	if ( screen != SDL_PublicSurface ) {
  1238 		/* only screens have physical palettes */
  1239 		which &= ~SDL_PHYSPAL;
  1240 	} else if( (screen->flags & SDL_HWPALETTE) != SDL_HWPALETTE ) {
  1241 		/* hardware palettes required for split colormaps */
  1242 		which |= SDL_PHYSPAL | SDL_LOGPAL;
  1243 	}
  1244 
  1245 	/* Verify the parameters */
  1246 	pal = screen->format->palette;
  1247 	if( !pal ) {
  1248 		return 0;	/* not a palettized surface */
  1249 	}
  1250 	gotall = 1;
  1251 	palsize = 1 << screen->format->BitsPerPixel;
  1252 	if ( ncolors > (palsize - firstcolor) ) {
  1253 		ncolors = (palsize - firstcolor);
  1254 		gotall = 0;
  1255 	}
  1256 
  1257 	if ( which & SDL_LOGPAL ) {
  1258 		/*
  1259 		 * Logical palette change: The actual screen isn't affected,
  1260 		 * but the internal colormap is altered so that the
  1261 		 * interpretation of the pixel values (for blits etc) is
  1262 		 * changed.
  1263 		 */
  1264 		SetPalette_logical(screen, colors, firstcolor, ncolors);
  1265 	}
  1266 	if ( which & SDL_PHYSPAL ) {
  1267 		SDL_VideoDevice *video = current_video;
  1268 		/*
  1269 		 * Physical palette change: This doesn't affect the
  1270 		 * program's idea of what the screen looks like, but changes
  1271 		 * its actual appearance.
  1272 		 */
  1273 		if(!video)
  1274 			return gotall;	/* video not yet initialized */
  1275 		if(!video->physpal && !(which & SDL_LOGPAL) ) {
  1276 			/* Lazy physical palette allocation */
  1277 			int size;
  1278 			SDL_Palette *pp = malloc(sizeof(*pp));
  1279 			current_video->physpal = pp;
  1280 			pp->ncolors = pal->ncolors;
  1281 			size = pp->ncolors * sizeof(SDL_Color);
  1282 			pp->colors = malloc(size);
  1283 			memcpy(pp->colors, pal->colors, size);
  1284 		}
  1285 		if ( ! SetPalette_physical(screen,
  1286 		                           colors, firstcolor, ncolors) ) {
  1287 			gotall = 0;
  1288 		}
  1289 	}
  1290 	return gotall;
  1291 }
  1292 
  1293 int SDL_SetColors(SDL_Surface *screen, SDL_Color *colors, int firstcolor,
  1294 		  int ncolors)
  1295 {
  1296 	return SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL,
  1297 			      colors, firstcolor, ncolors);
  1298 }
  1299 
  1300 /*
  1301  * Clean up the video subsystem
  1302  */
  1303 void SDL_VideoQuit (void)
  1304 {
  1305 	SDL_Surface *ready_to_go;
  1306 
  1307 	if ( current_video ) {
  1308 		SDL_VideoDevice *video = current_video;
  1309 		SDL_VideoDevice *this  = current_video;
  1310 
  1311 		/* Halt event processing before doing anything else */
  1312 		SDL_StopEventLoop();
  1313 
  1314 		/* Clean up allocated window manager items */
  1315 		if ( SDL_PublicSurface ) {
  1316 			SDL_PublicSurface = NULL;
  1317 		}
  1318 		SDL_CursorQuit();
  1319 
  1320 		/* Just in case... */
  1321 		SDL_WM_GrabInputOff();
  1322 
  1323 		/* Clean up the system video */
  1324 		video->VideoQuit(this);
  1325 
  1326 		/* Free any lingering surfaces */
  1327 		ready_to_go = SDL_ShadowSurface;
  1328 		SDL_ShadowSurface = NULL;
  1329 		SDL_FreeSurface(ready_to_go);
  1330 		if ( SDL_VideoSurface != NULL ) {
  1331 			ready_to_go = SDL_VideoSurface;
  1332 			SDL_VideoSurface = NULL;
  1333 			SDL_FreeSurface(ready_to_go);
  1334 		}
  1335 		SDL_PublicSurface = NULL;
  1336 
  1337 		/* Clean up miscellaneous memory */
  1338 		if ( video->physpal ) {
  1339 			free(video->physpal->colors);
  1340 			free(video->physpal);
  1341 			video->physpal = NULL;
  1342 		}
  1343 		if ( video->gammacols ) {
  1344 			free(video->gammacols);
  1345 			video->gammacols = NULL;
  1346 		}
  1347 		if ( video->gamma ) {
  1348 			free(video->gamma);
  1349 			video->gamma = NULL;
  1350 		}
  1351 		if ( video->wm_title != NULL ) {
  1352 			free(video->wm_title);
  1353 			video->wm_title = NULL;
  1354 		}
  1355 		if ( video->wm_icon != NULL ) {
  1356 			free(video->wm_icon);
  1357 			video->wm_icon = NULL;
  1358 		}
  1359 
  1360 		/* Finish cleaning up video subsystem */
  1361 		video->free(this);
  1362 		current_video = NULL;
  1363 	}
  1364 	return;
  1365 }
  1366 
  1367 /* Load the GL driver library */
  1368 int SDL_GL_LoadLibrary(const char *path)
  1369 {
  1370 	SDL_VideoDevice *video = current_video;
  1371 	SDL_VideoDevice *this = current_video;
  1372 	int retval;
  1373 
  1374 	retval = -1;
  1375 	if ( video == NULL ) {
  1376 		SDL_SetError("Video subsystem has not been initialized");
  1377 	} else {
  1378 		if ( video->GL_LoadLibrary ) {
  1379 			retval = video->GL_LoadLibrary(this, path);
  1380 		} else {
  1381 			SDL_SetError("No dynamic GL support in video driver");
  1382 		}
  1383 	}
  1384 	return(retval);
  1385 }
  1386 
  1387 void *SDL_GL_GetProcAddress(const char* proc)
  1388 {
  1389 	SDL_VideoDevice *video = current_video;
  1390 	SDL_VideoDevice *this = current_video;
  1391 	void *func;
  1392 
  1393 	func = NULL;
  1394 	if ( video->GL_GetProcAddress ) {
  1395 		if ( video->gl_config.driver_loaded ) {
  1396 			func = video->GL_GetProcAddress(this, proc);
  1397 		} else {
  1398 			SDL_SetError("No GL driver has been loaded");
  1399 		}
  1400 	} else {
  1401 		SDL_SetError("No dynamic GL support in video driver");
  1402 	}
  1403 	return func;
  1404 }
  1405 
  1406 /* Set the specified GL attribute for setting up a GL video mode */
  1407 int SDL_GL_SetAttribute( SDL_GLattr attr, int value )
  1408 {
  1409 	int retval;
  1410 	SDL_VideoDevice *video = current_video;
  1411 
  1412 	retval = 0;
  1413 	switch (attr) {
  1414 		case SDL_GL_RED_SIZE:
  1415 			video->gl_config.red_size = value;
  1416 			break;
  1417 		case SDL_GL_GREEN_SIZE:
  1418 			video->gl_config.green_size = value;
  1419 			break;
  1420 		case SDL_GL_BLUE_SIZE:
  1421 			video->gl_config.blue_size = value;
  1422 			break;
  1423 		case SDL_GL_ALPHA_SIZE:
  1424 			video->gl_config.alpha_size = value;
  1425 			break;
  1426 		case SDL_GL_DOUBLEBUFFER:
  1427 			video->gl_config.double_buffer = value;
  1428 			break;
  1429 		case SDL_GL_BUFFER_SIZE:
  1430 			video->gl_config.buffer_size = value;
  1431 			break;
  1432 		case SDL_GL_DEPTH_SIZE:
  1433 			video->gl_config.depth_size = value;
  1434 			break;
  1435 		case SDL_GL_STENCIL_SIZE:
  1436 			video->gl_config.stencil_size = value;
  1437 			break;
  1438 		case SDL_GL_ACCUM_RED_SIZE:
  1439 			video->gl_config.accum_red_size = value;
  1440 			break;
  1441 		case SDL_GL_ACCUM_GREEN_SIZE:
  1442 			video->gl_config.accum_green_size = value;
  1443 			break;
  1444 		case SDL_GL_ACCUM_BLUE_SIZE:
  1445 			video->gl_config.accum_blue_size = value;
  1446 			break;
  1447 		case SDL_GL_ACCUM_ALPHA_SIZE:
  1448 			video->gl_config.accum_alpha_size = value;
  1449 			break;
  1450 		case SDL_GL_STEREO:
  1451 			video->gl_config.stereo = value;
  1452 			break;
  1453 		case SDL_GL_MULTISAMPLEBUFFERS:
  1454 			video->gl_config.multisamplebuffers = value;
  1455 			break;
  1456 		case SDL_GL_MULTISAMPLESAMPLES:
  1457 			video->gl_config.multisamplesamples = value;
  1458 			break;
  1459 		default:
  1460 			SDL_SetError("Unknown OpenGL attribute");
  1461 			retval = -1;
  1462 			break;
  1463 	}
  1464 	return(retval);
  1465 }
  1466 
  1467 /* Retrieve an attribute value from the windowing system. */
  1468 int SDL_GL_GetAttribute(SDL_GLattr attr, int* value)
  1469 {
  1470 	int retval = -1;
  1471 	SDL_VideoDevice* video = current_video;
  1472 	SDL_VideoDevice* this = current_video;
  1473 
  1474 	if ( video->GL_GetAttribute ) {
  1475 		retval = this->GL_GetAttribute(this, attr, value);
  1476 	} else {
  1477 		*value = 0;
  1478 		SDL_SetError("GL_GetAttribute not supported");
  1479 	}
  1480 	return retval;
  1481 }
  1482 
  1483 /* Perform a GL buffer swap on the current GL context */
  1484 void SDL_GL_SwapBuffers(void)
  1485 {
  1486 	SDL_VideoDevice *video = current_video;
  1487 	SDL_VideoDevice *this = current_video;
  1488 
  1489 	if ( video->screen->flags & SDL_OPENGL ) {
  1490 		video->GL_SwapBuffers(this);
  1491 	} else {
  1492 		SDL_SetError("OpenGL video mode has not been set");
  1493 	}
  1494 }
  1495 
  1496 /* Update rects with locking */
  1497 void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect *rects)
  1498 {
  1499 	SDL_GL_Lock();
  1500  	SDL_GL_UpdateRects(numrects, rects);
  1501 	SDL_GL_Unlock();
  1502 }
  1503 
  1504 /* Update rects without state setting and changing (the caller is responsible for it) */
  1505 void SDL_GL_UpdateRects(int numrects, SDL_Rect *rects)
  1506 {
  1507 #ifdef HAVE_OPENGL
  1508 	SDL_VideoDevice *this = current_video;
  1509 	SDL_Rect update, tmp;
  1510 	int x, y, i;
  1511 
  1512 	for ( i = 0; i < numrects; i++ )
  1513 	{
  1514 		tmp.y = rects[i].y;
  1515 		tmp.h = rects[i].h;
  1516 		for ( y = 0; y <= rects[i].h / 256; y++ )
  1517 		{
  1518 			tmp.x = rects[i].x;
  1519 			tmp.w = rects[i].w;
  1520 			for ( x = 0; x <= rects[i].w / 256; x++ )
  1521 			{
  1522 				update.x = tmp.x;
  1523 				update.y = tmp.y;
  1524 				update.w = tmp.w;
  1525 				update.h = tmp.h;
  1526 
  1527 				if ( update.w > 256 )
  1528 					update.w = 256;
  1529 
  1530 				if ( update.h > 256 )
  1531 					update.h = 256;
  1532 			
  1533 				this->glFlush();
  1534 				this->glTexSubImage2D( 
  1535 					GL_TEXTURE_2D, 
  1536 					0, 
  1537 					0, 
  1538 					0, 
  1539 					update.w, 
  1540 					update.h, 
  1541 					this->is_32bit? GL_RGBA : GL_RGB,
  1542 #ifdef GL_VERSION_1_2
  1543 					this->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
  1544 #else
  1545 					GL_UNSIGNED_BYTE,
  1546 #endif
  1547 					(Uint8 *)this->screen->pixels + 
  1548 						this->screen->format->BytesPerPixel * update.x + 
  1549 						update.y * this->screen->pitch );
  1550 	
  1551 				this->glFlush();
  1552 				/*
  1553 				* Note the parens around the function name:
  1554 				* This is because some OpenGL implementations define glTexCoord etc 
  1555 				* as macros, and we don't want them expanded here.
  1556 				*/
  1557 				this->glBegin(GL_TRIANGLE_STRIP);
  1558 					(this->glTexCoord2f)( 0.0, 0.0 );	
  1559 					(this->glVertex2i)( update.x, update.y );
  1560 					(this->glTexCoord2f)( (float)(update.w / 256.0), 0.0 );	
  1561 					(this->glVertex2i)( update.x + update.w, update.y );
  1562 					(this->glTexCoord2f)( 0.0, (float)(update.h / 256.0) );
  1563 					(this->glVertex2i)( update.x, update.y + update.h );
  1564 					(this->glTexCoord2f)( (float)(update.w / 256.0), (float)(update.h / 256.0) );	
  1565 					(this->glVertex2i)( update.x + update.w	, update.y + update.h );
  1566 				this->glEnd();	
  1567 			
  1568 				tmp.x += 256;
  1569 				tmp.w -= 256;
  1570 			}
  1571 			tmp.y += 256;
  1572 			tmp.h -= 256;
  1573 		}
  1574 	}
  1575 #endif
  1576 }
  1577 
  1578 /* Lock == save current state */
  1579 void SDL_GL_Lock()
  1580 {
  1581 #ifdef HAVE_OPENGL
  1582 	lock_count--;
  1583 	if (lock_count==-1)
  1584 	{
  1585 		SDL_VideoDevice *this = current_video;
  1586 
  1587 		this->glPushAttrib( GL_ALL_ATTRIB_BITS );	/* TODO: narrow range of what is saved */
  1588 #ifdef GL_CLIENT_PIXEL_STORE_BIT
  1589 		this->glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
  1590 #endif
  1591 
  1592 		this->glEnable(GL_TEXTURE_2D);
  1593 		this->glEnable(GL_BLEND);
  1594 		this->glDisable(GL_FOG);
  1595 		this->glDisable(GL_ALPHA_TEST);
  1596 		this->glDisable(GL_DEPTH_TEST);
  1597 		this->glDisable(GL_SCISSOR_TEST);	
  1598 		this->glDisable(GL_STENCIL_TEST);
  1599 		this->glDisable(GL_CULL_FACE);
  1600 
  1601 		this->glBindTexture( GL_TEXTURE_2D, this->texture );
  1602 		this->glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  1603 		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  1604 		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  1605 		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  1606 		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
  1607 
  1608 		this->glPixelStorei( GL_UNPACK_ROW_LENGTH, this->screen->pitch / this->screen->format->BytesPerPixel );
  1609 		this->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1610 		(this->glColor4f)(1.0, 1.0, 1.0, 1.0);		/* Solaris workaround */
  1611 
  1612 		this->glViewport(0, 0, this->screen->w, this->screen->h);
  1613 		this->glMatrixMode(GL_PROJECTION);
  1614 		this->glPushMatrix();
  1615 		this->glLoadIdentity();
  1616 
  1617 		this->glOrtho(0.0, (GLdouble) this->screen->w, (GLdouble) this->screen->h, 0.0, 0.0, 1.0);
  1618 
  1619 		this->glMatrixMode(GL_MODELVIEW);
  1620 		this->glPushMatrix();
  1621 		this->glLoadIdentity();
  1622 	}
  1623 #endif
  1624 }
  1625 
  1626 /* Unlock == restore saved state */
  1627 void SDL_GL_Unlock()
  1628 {
  1629 #ifdef HAVE_OPENGL
  1630 	lock_count++;
  1631 	if (lock_count==0)
  1632 	{
  1633 		SDL_VideoDevice *this = current_video;
  1634 
  1635 		this->glPopMatrix();
  1636 		this->glMatrixMode(GL_PROJECTION);
  1637 		this->glPopMatrix();
  1638 
  1639 		this->glPopClientAttrib();
  1640 		this->glPopAttrib();
  1641 	}
  1642 #endif
  1643 }
  1644 
  1645 /*
  1646  * Sets/Gets the title and icon text of the display window, if any.
  1647  */
  1648 void SDL_WM_SetCaption (const char *title, const char *icon)
  1649 {
  1650 	SDL_VideoDevice *video = current_video;
  1651 	SDL_VideoDevice *this  = current_video;
  1652 
  1653 	if ( video ) {
  1654 		if ( title ) {
  1655 			if ( video->wm_title ) {
  1656 				free(video->wm_title);
  1657 			}
  1658 			video->wm_title = (char *)malloc(strlen(title)+1);
  1659 			if ( video->wm_title != NULL ) {
  1660 				strcpy(video->wm_title, title);
  1661 			}
  1662 		}
  1663 		if ( icon ) {
  1664 			if ( video->wm_icon ) {
  1665 				free(video->wm_icon);
  1666 			}
  1667 			video->wm_icon = (char *)malloc(strlen(icon)+1);
  1668 			if ( video->wm_icon != NULL ) {
  1669 				strcpy(video->wm_icon, icon);
  1670 			}
  1671 		}
  1672 		if ( (title || icon) && (video->SetCaption != NULL) ) {
  1673 			video->SetCaption(this, video->wm_title,video->wm_icon);
  1674 		}
  1675 	}
  1676 }
  1677 void SDL_WM_GetCaption (char **title, char **icon)
  1678 {
  1679 	SDL_VideoDevice *video = current_video;
  1680 
  1681 	if ( video ) {
  1682 		if ( title ) {
  1683 			*title = video->wm_title;
  1684 		}
  1685 		if ( icon ) {
  1686 			*icon = video->wm_icon;
  1687 		}
  1688 	}
  1689 }
  1690 
  1691 /* Utility function used by SDL_WM_SetIcon();
  1692  * flags & 1 for color key, flags & 2 for alpha channel. */
  1693 static void CreateMaskFromColorKeyOrAlpha(SDL_Surface *icon, Uint8 *mask, int flags)
  1694 {
  1695 	int x, y;
  1696 	Uint32 colorkey;
  1697 #define SET_MASKBIT(icon, x, y, mask) \
  1698 	mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
  1699 
  1700 	colorkey = icon->format->colorkey;
  1701 	switch (icon->format->BytesPerPixel) {
  1702 		case 1: { Uint8 *pixels;
  1703 			for ( y=0; y<icon->h; ++y ) {
  1704 				pixels = (Uint8 *)icon->pixels + y*icon->pitch;
  1705 				for ( x=0; x<icon->w; ++x ) {
  1706 					if ( *pixels++ == colorkey ) {
  1707 						SET_MASKBIT(icon, x, y, mask);
  1708 					}
  1709 				}
  1710 			}
  1711 		}
  1712 		break;
  1713 
  1714 		case 2: { Uint16 *pixels;
  1715 			for ( y=0; y<icon->h; ++y ) {
  1716 				pixels = (Uint16 *)icon->pixels +
  1717 				                   y*icon->pitch/2;
  1718 				for ( x=0; x<icon->w; ++x ) {
  1719 					if ( (flags & 1) && *pixels == colorkey ) {
  1720 						SET_MASKBIT(icon, x, y, mask);
  1721 					} else if((flags & 2) && (*pixels & icon->format->Amask) == 0) {
  1722 						SET_MASKBIT(icon, x, y, mask);
  1723 					}
  1724 					pixels++;
  1725 				}
  1726 			}
  1727 		}
  1728 		break;
  1729 
  1730 		case 4: { Uint32 *pixels;
  1731 			for ( y=0; y<icon->h; ++y ) {
  1732 				pixels = (Uint32 *)icon->pixels +
  1733 				                   y*icon->pitch/4;
  1734 				for ( x=0; x<icon->w; ++x ) {
  1735 					if ( (flags & 1) && *pixels == colorkey ) {
  1736 						SET_MASKBIT(icon, x, y, mask);
  1737 					} else if((flags & 2) && (*pixels & icon->format->Amask) == 0) {
  1738 						SET_MASKBIT(icon, x, y, mask);
  1739 					}
  1740 					pixels++;
  1741 				}
  1742 			}
  1743 		}
  1744 		break;
  1745 	}
  1746 }
  1747 
  1748 /*
  1749  * Sets the window manager icon for the display window.
  1750  */
  1751 void SDL_WM_SetIcon (SDL_Surface *icon, Uint8 *mask)
  1752 {
  1753 	SDL_VideoDevice *video = current_video;
  1754 	SDL_VideoDevice *this  = current_video;
  1755 
  1756 	if ( icon && video->SetIcon ) {
  1757 		/* Generate a mask if necessary, and create the icon! */
  1758 		if ( mask == NULL ) {
  1759 			int mask_len = icon->h*(icon->w+7)/8;
  1760 			int flags = 0;
  1761 			mask = (Uint8 *)malloc(mask_len);
  1762 			if ( mask == NULL ) {
  1763 				return;
  1764 			}
  1765 			memset(mask, ~0, mask_len);
  1766 			if ( icon->flags & SDL_SRCCOLORKEY ) flags |= 1;
  1767 			if ( icon->flags & SDL_SRCALPHA ) flags |= 2;
  1768 			if( flags ) {
  1769 				CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
  1770 			}
  1771 			video->SetIcon(video, icon, mask);
  1772 			free(mask);
  1773 		} else {
  1774 			video->SetIcon(this, icon, mask);
  1775 		}
  1776 	}
  1777 }
  1778 
  1779 /*
  1780  * Grab or ungrab the keyboard and mouse input.
  1781  * This function returns the final grab mode after calling the
  1782  * driver dependent function.
  1783  */
  1784 static SDL_GrabMode SDL_WM_GrabInputRaw(SDL_GrabMode mode)
  1785 {
  1786 	SDL_VideoDevice *video = current_video;
  1787 	SDL_VideoDevice *this  = current_video;
  1788 
  1789 	/* Only do something if we have support for grabs */
  1790 	if ( video->GrabInput == NULL ) {
  1791 		return(video->input_grab);
  1792 	}
  1793 
  1794 	/* If the final grab mode if off, only then do we actually grab */
  1795 #ifdef DEBUG_GRAB
  1796   printf("SDL_WM_GrabInputRaw(%d) ... ", mode);
  1797 #endif
  1798 	if ( mode == SDL_GRAB_OFF ) {
  1799 		if ( video->input_grab != SDL_GRAB_OFF ) {
  1800 			mode = video->GrabInput(this, mode);
  1801 		}
  1802 	} else {
  1803 		if ( video->input_grab == SDL_GRAB_OFF ) {
  1804 			mode = video->GrabInput(this, mode);
  1805 		}
  1806 	}
  1807 	if ( mode != video->input_grab ) {
  1808 		video->input_grab = mode;
  1809 		if ( video->CheckMouseMode ) {
  1810 			video->CheckMouseMode(this);
  1811 		}
  1812 	}
  1813 #ifdef DEBUG_GRAB
  1814   printf("Final mode %d\n", video->input_grab);
  1815 #endif
  1816 
  1817 	/* Return the final grab state */
  1818 	if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1819 		mode -= SDL_GRAB_FULLSCREEN;
  1820 	}
  1821 	return(mode);
  1822 }
  1823 SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode)
  1824 {
  1825 	SDL_VideoDevice *video = current_video;
  1826 
  1827 	/* If the video isn't initialized yet, we can't do anything */
  1828 	if ( ! video ) {
  1829 		return SDL_GRAB_OFF;
  1830 	}
  1831 
  1832 	/* Return the current mode on query */
  1833 	if ( mode == SDL_GRAB_QUERY ) {
  1834 		mode = video->input_grab;
  1835 		if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1836 			mode -= SDL_GRAB_FULLSCREEN;
  1837 		}
  1838 		return(mode);
  1839 	}
  1840 
  1841 #ifdef DEBUG_GRAB
  1842   printf("SDL_WM_GrabInput(%d) ... ", mode);
  1843 #endif
  1844 	/* If the video surface is fullscreen, we always grab */
  1845 	if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1846 		mode -= SDL_GRAB_FULLSCREEN;
  1847 	}
  1848 	if ( SDL_VideoSurface && (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
  1849 		mode += SDL_GRAB_FULLSCREEN;
  1850 	}
  1851 	return(SDL_WM_GrabInputRaw(mode));
  1852 }
  1853 static SDL_GrabMode SDL_WM_GrabInputOff(void)
  1854 {
  1855 	SDL_GrabMode mode;
  1856 
  1857 	/* First query the current grab state */
  1858 	mode = SDL_WM_GrabInput(SDL_GRAB_QUERY);
  1859 
  1860 	/* Now explicitly turn off input grab */
  1861 	SDL_WM_GrabInputRaw(SDL_GRAB_OFF);
  1862 
  1863 	/* Return the old state */
  1864 	return(mode);
  1865 }
  1866 
  1867 /*
  1868  * Iconify the window in window managed environments.
  1869  * A successful iconification will result in an SDL_APPACTIVE loss event.
  1870  */
  1871 int SDL_WM_IconifyWindow(void)
  1872 {
  1873 	SDL_VideoDevice *video = current_video;
  1874 	SDL_VideoDevice *this  = current_video;
  1875 	int retval;
  1876 
  1877 	retval = 0;
  1878 	if ( video->IconifyWindow ) {
  1879 		retval = video->IconifyWindow(this);
  1880 	}
  1881 	return(retval);
  1882 }
  1883 
  1884 /*
  1885  * Toggle fullscreen mode
  1886  */
  1887 int SDL_WM_ToggleFullScreen(SDL_Surface *surface)
  1888 {
  1889 	SDL_VideoDevice *video = current_video;
  1890 	SDL_VideoDevice *this  = current_video;
  1891 	int toggled;
  1892 
  1893 	toggled = 0;
  1894 	if ( SDL_PublicSurface && (surface == SDL_PublicSurface) &&
  1895 	     video->ToggleFullScreen ) {
  1896 		if ( surface->flags & SDL_FULLSCREEN ) {
  1897 			toggled = video->ToggleFullScreen(this, 0);
  1898 			if ( toggled ) {
  1899 				SDL_VideoSurface->flags &= ~SDL_FULLSCREEN;
  1900 				SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
  1901 			}
  1902 		} else {
  1903 			toggled = video->ToggleFullScreen(this, 1);
  1904 			if ( toggled ) {
  1905 				SDL_VideoSurface->flags |= SDL_FULLSCREEN;
  1906 				SDL_PublicSurface->flags |= SDL_FULLSCREEN;
  1907 			}
  1908 		}
  1909 		/* Double-check the grab state inside SDL_WM_GrabInput() */
  1910 		if ( toggled ) {
  1911 			SDL_WM_GrabInput(video->input_grab);
  1912 		}
  1913 	}
  1914 	return(toggled);
  1915 }
  1916 
  1917 /*
  1918  * Get some platform dependent window manager information
  1919  */
  1920 int SDL_GetWMInfo (SDL_SysWMinfo *info)
  1921 {
  1922 	SDL_VideoDevice *video = current_video;
  1923 	SDL_VideoDevice *this  = current_video;
  1924 
  1925 	if ( video && video->GetWMInfo ) {
  1926 		return(video->GetWMInfo(this, info));
  1927 	} else {
  1928 		return(0);
  1929 	}
  1930 }