src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 28 Jul 2003 01:47:55 +0000
changeset 662 66c02f83f5bf
parent 656 864e2d2a9a55
child 663 8bedd6d61642
permissions -rw-r--r--
Date: Sun, 27 Jul 2003 22:37:59 +0200
From: Max Horn
Subject: SDL whitespace patch

this patch is lowest priority: it only contains indention fixes. In
some places, instead of tabs, whitespaces where used for indention. But
of course that only "looks good" if you use the exact same tab width as
the author of those files. I tried to replace such cases with tabs for
a more uniform indention. I only did that for a few files.

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