src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 29 Dec 2011 04:57:42 -0500
branchSDL-1.2
changeset 6111 2280c0954104
parent 4399 ae9c094e9200
child 6125 760a3162e180
permissions -rw-r--r--
Fixed bug 1346

alarantalara@gmail.com 2011-12-19 20:43:13 PST

On little endian systems using the Quartz code, an unusual set of RBGA masks is
used when using the windowed video mode.
This set is not taken into account in SDL_DisplayFormatAlpha and so it converts
the supplied surface to a format that does not match the video surface,
preventing fast blitting.

This was observed in recent builds of Battle for Wesnoth when SDL was updated
to cover the problem when switching to full screen in Lion
(https://gna.org/bugs/?18319).

You can observe the performance issue if you download Wesnoth 1.9.13 for OS X
at
http://sourceforge.net/projects/wesnoth/files/wesnoth/wesnoth-1.9.13/Wesnoth_1.9.13.dmg/download
and replace the included SDL library with any build of SDL 1.2.14 or later. (I
have already patched the included version, so the problem is not observable
without replacement.)

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