src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 02 Apr 2009 04:06:55 +0000
branchSDL-1.2
changeset 4165 3b8ac3d311a2
parent 4159 a1b03ba2fcd0
child 4249 429c8dd3175d
permissions -rw-r--r--
Hello.

This patch provides basic support for video on the Sony PS3
Linux framebuffer. Scaling, format-conversion, and drawing is
done from the SPEs, so there is little performance impact to
PPE applications. This is by no means production quality code,
but it is a very good start and a good example of how to use the
PS3's hardware capabilities to accelerate video playback on
the box.

The driver has been verified to work with ffplay, mplayer and xine.
This piece of software has been developed at the IBM R&D Lab
in Boeblingen, Germany and is now returned to the community.

Enjoy !

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