src/video/SDL_video.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 08 Sep 2005 06:16:14 +0000
changeset 1133 609c060fd2a2
parent 1076 8d3b95ece376
child 1140 af8b0f9ac2f4
permissions -rw-r--r--
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:


To: SDL Developers <sdl@libsdl.org>
From: =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb@algonet.se>
Date: Mon, 30 May 2005 23:29:04 +0200
Subject: [SDL] Mac OS X Video Drivers [patch]

I've updated/added the Carbon and X11 video drivers
to the Mac OS X port of SDL 1.2 (the CVS version),
and made the Cocoa driver and runtime *optional*.

The default is still Cocoa, and the "Quartz" driver.
But you can now also use "toolbox" for Carbon, and
"x11" for running with Apple's (or other) X11 server:

export SDL_VIDEODRIVER=x11
export SDL_VIDEO_GL_DRIVER=/usr/X11R6/lib/libGL.dylib

It also checks if the frameworks are available, by a:
#include <Carbon/Carbon.h> or #import <Cocoa/Cocoa.h>
(this should make it configure on plain Darwin as well?)


Here are the new configure targets:
--enable-video-cocoa use Cocoa/Quartz video driver default=yes
--enable-video-carbon use Carbon/QuickDraw video driver default=yes
--enable-video-x11 use X11 video driver default=no

./configure --enable-video-cocoa --enable-video-carbon
--enable-video-x11 \
--x-includes=/usr/X11R6/include --x-libraries=/usr/X11R6/lib

The Carbon version is just an updated version of the old
SDL driver for Mac OS 9, and could probably be improved...
(but it does work, including the Carbon version of SDLmain)

If you disable cocoa, you can run with -framework Carbon only,
and the C version of SDL_main.c. And if you disable carbon too,
you can still use the X11 version which doesn't require SDLmain.

I updated the DrawSprocket version, but did not include it.
(no blitters or VRAM GWorlds etc. available on OS X anyway)
Besides for Mac OS 9, I don't think there's any use for it ?

And note that any performance on Mac OS X equals OpenGL anyway...
You can get "fair" software SDL results on captured CG displays,
but for decent frame rates you need to be using GL for rendering.


Finally, here is the patch itself:
http://www.algonet.se/~afb/SDL-12CVS-macvideo.patch

--anders

PS. It says "video", but as usual it applies to mouse/keyboard too.


------


To: A list for developers using the SDL library <sdl@libsdl.org>
From: =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb@algonet.se>
Date: Sun, 4 Sep 2005 10:02:15 +0200
Subject: [SDL] Updated Mac patch

Updated the previous Mac patch to disable Carbon by default.
Also "fixed" the SDL.spec again, so that it builds on Darwin.

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