src/video/SDL_video.c
changeset 0 74212992fb08
child 1 cf2af46e9e2a
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/video/SDL_video.c	Thu Apr 26 16:45:43 2001 +0000
     1.3 @@ -0,0 +1,1783 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Library General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Library General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Library General Public
    1.19 +    License along with this library; if not, write to the Free
    1.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@devolution.com
    1.24 +*/
    1.25 +
    1.26 +#ifdef SAVE_RCSID
    1.27 +static char rcsid =
    1.28 + "@(#) $Id$";
    1.29 +#endif
    1.30 +
    1.31 +/* The high-level video driver subsystem */
    1.32 +
    1.33 +#include <stdio.h>
    1.34 +#include <stdlib.h>
    1.35 +#include <string.h>
    1.36 +
    1.37 +#include "SDL.h"
    1.38 +#include "SDL_error.h"
    1.39 +#include "SDL_video.h"
    1.40 +#include "SDL_events.h"
    1.41 +#include "SDL_mutex.h"
    1.42 +#include "SDL_sysvideo.h"
    1.43 +#include "SDL_sysevents.h"
    1.44 +#include "SDL_blit.h"
    1.45 +#include "SDL_pixels_c.h"
    1.46 +#include "SDL_events_c.h"
    1.47 +#include "SDL_cursor_c.h"
    1.48 +
    1.49 +/* Available video drivers */
    1.50 +static VideoBootStrap *bootstrap[] = {
    1.51 +#ifdef ENABLE_X11
    1.52 +	&X11_bootstrap,
    1.53 +#endif
    1.54 +#ifdef ENABLE_DGA
    1.55 +	&DGA_bootstrap,
    1.56 +#endif
    1.57 +#ifdef ENABLE_FBCON
    1.58 +	&FBCON_bootstrap,
    1.59 +#endif
    1.60 +#ifdef ENABLE_PS2GS
    1.61 +	&PS2GS_bootstrap,
    1.62 +#endif
    1.63 +#ifdef ENABLE_GGI
    1.64 +	&GGI_bootstrap,
    1.65 +#endif
    1.66 +#ifdef ENABLE_SVGALIB
    1.67 +	&SVGALIB_bootstrap,
    1.68 +#endif
    1.69 +#ifdef ENABLE_AALIB
    1.70 +    &AALIB_bootstrap,
    1.71 +#endif
    1.72 +#ifdef ENABLE_DIRECTX
    1.73 +	&DIRECTX_bootstrap,
    1.74 +#endif
    1.75 +#ifdef ENABLE_WINDIB
    1.76 +	&WINDIB_bootstrap,
    1.77 +#endif
    1.78 +#ifdef ENABLE_BWINDOW
    1.79 +	&BWINDOW_bootstrap,
    1.80 +#endif
    1.81 +#ifdef ENABLE_TOOLBOX
    1.82 +	&TOOLBOX_bootstrap,
    1.83 +#endif
    1.84 +#ifdef ENABLE_DRAWSPROCKET
    1.85 +	&DSp_bootstrap,
    1.86 +#endif
    1.87 +#ifdef ENABLE_CYBERGRAPHICS
    1.88 +	&CGX_bootstrap,
    1.89 +#endif
    1.90 +	NULL
    1.91 +};
    1.92 +SDL_VideoDevice *current_video = NULL;
    1.93 +
    1.94 +/* Places to store title and icon text for the app */
    1.95 +static char *wm_title = NULL;
    1.96 +static char *wm_icon  = NULL;
    1.97 +
    1.98 +/* Various local functions */
    1.99 +int SDL_VideoInit(const char *driver_name, Uint32 flags);
   1.100 +void SDL_VideoQuit(void);
   1.101 +void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect* rects);
   1.102 +
   1.103 +static SDL_GrabMode SDL_WM_GrabInputOff(void);
   1.104 +#ifdef HAVE_OPENGL
   1.105 +static int lock_count = 0;
   1.106 +#endif
   1.107 +
   1.108 +
   1.109 +/*
   1.110 + * Initialize the video and event subsystems -- determine native pixel format
   1.111 + */
   1.112 +int SDL_VideoInit (const char *driver_name, Uint32 flags)
   1.113 +{
   1.114 +	SDL_VideoDevice *video;
   1.115 +	int index;
   1.116 +	int i;
   1.117 +	SDL_PixelFormat vformat;
   1.118 +	Uint32 video_flags;
   1.119 +
   1.120 +	/* Toggle the event thread flags, based on OS requirements */
   1.121 +#if defined(MUST_THREAD_EVENTS)
   1.122 +	flags |= SDL_INIT_EVENTTHREAD;
   1.123 +#elif defined(CANT_THREAD_EVENTS)
   1.124 +	if ( (flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) {
   1.125 +		SDL_SetError("OS doesn't support threaded events");
   1.126 +		return(-1);
   1.127 +	}
   1.128 +#endif
   1.129 +
   1.130 +	/* Check to make sure we don't overwrite 'current_video' */
   1.131 +	if ( current_video != NULL ) {
   1.132 +		SDL_VideoQuit();
   1.133 +	}
   1.134 +
   1.135 +	/* Select the proper video driver */
   1.136 +	index = 0;
   1.137 +	video = NULL;
   1.138 +	if ( driver_name != NULL ) {
   1.139 +#if 0	/* This will be replaced with a better driver selection API */
   1.140 +		if ( strrchr(driver_name, ':') != NULL ) {
   1.141 +			index = atoi(strrchr(driver_name, ':')+1);
   1.142 +		}
   1.143 +#endif
   1.144 +		for ( i=0; bootstrap[i]; ++i ) {
   1.145 +			if ( strncmp(bootstrap[i]->name, driver_name,
   1.146 +			             strlen(bootstrap[i]->name)) == 0 ) {
   1.147 +				if ( bootstrap[i]->available() ) {
   1.148 +					video = bootstrap[i]->create(index);
   1.149 +					break;
   1.150 +				}
   1.151 +			}
   1.152 +		}
   1.153 +	} else {
   1.154 +		for ( i=0; bootstrap[i]; ++i ) {
   1.155 +			if ( bootstrap[i]->available() ) {
   1.156 +				video = bootstrap[i]->create(index);
   1.157 +				if ( video != NULL ) {
   1.158 +					break;
   1.159 +				}
   1.160 +			}
   1.161 +		}
   1.162 +	}
   1.163 +	if ( video == NULL ) {
   1.164 +		SDL_SetError("No available video device");
   1.165 +		return(-1);
   1.166 +	}
   1.167 +	current_video = video;
   1.168 +	current_video->name = bootstrap[i]->name;
   1.169 +
   1.170 +	/* Do some basic variable initialization */
   1.171 +	video->screen = NULL;
   1.172 +	video->shadow = NULL;
   1.173 +	video->visible = NULL;
   1.174 +	video->physpal = NULL;
   1.175 +	video->gammacols = NULL;
   1.176 +	video->gamma = NULL;
   1.177 +	video->wm_title = NULL;
   1.178 +	video->wm_icon  = NULL;
   1.179 +	video->offset_x = 0;
   1.180 +	video->offset_y = 0;
   1.181 +	memset(&video->info, 0, (sizeof video->info));
   1.182 +
   1.183 +	/* Set some very sane GL defaults */
   1.184 +	video->gl_config.driver_loaded = 0;
   1.185 +	video->gl_config.dll_handle = NULL;
   1.186 +	video->gl_config.red_size = 5;
   1.187 +#if 1 /* This seems to work on more video cards, as a default */
   1.188 +	video->gl_config.green_size = 5;
   1.189 +#else
   1.190 +	video->gl_config.green_size = 6;
   1.191 +#endif
   1.192 +	video->gl_config.blue_size = 5;
   1.193 +	video->gl_config.alpha_size = 0;
   1.194 +	video->gl_config.buffer_size = 0;
   1.195 +	video->gl_config.depth_size = 16;
   1.196 +	video->gl_config.stencil_size = 0;
   1.197 +	video->gl_config.double_buffer = 1;
   1.198 +	video->gl_config.accum_red_size = 0;
   1.199 +	video->gl_config.accum_green_size = 0;
   1.200 +	video->gl_config.accum_blue_size = 0;
   1.201 +	video->gl_config.accum_alpha_size = 0;
   1.202 +	
   1.203 +	/* Initialize the video subsystem */
   1.204 +	memset(&vformat, 0, sizeof(vformat));
   1.205 +	if ( video->VideoInit(video, &vformat) < 0 ) {
   1.206 +		SDL_VideoQuit();
   1.207 +		return(-1);
   1.208 +	}
   1.209 +
   1.210 +	/* Create a zero sized video surface of the appropriate format */
   1.211 +	video_flags = SDL_SWSURFACE;
   1.212 +	SDL_VideoSurface = SDL_CreateRGBSurface(video_flags, 0, 0,
   1.213 +				vformat.BitsPerPixel,
   1.214 +				vformat.Rmask, vformat.Gmask, vformat.Bmask, 0);
   1.215 +	if ( SDL_VideoSurface == NULL ) {
   1.216 +		SDL_VideoQuit();
   1.217 +		return(-1);
   1.218 +	}
   1.219 +	SDL_PublicSurface = NULL;	/* Until SDL_SetVideoMode() */
   1.220 +
   1.221 +#if 0 /* Don't change the current palette - may be used by other programs.
   1.222 +       * The application can't do anything with the display surface until
   1.223 +       * a video mode has been set anyway. :)
   1.224 +       */
   1.225 +	/* If we have a palettized surface, create a default palette */
   1.226 +	if ( SDL_VideoSurface->format->palette ) {
   1.227 +	        SDL_PixelFormat *vf = SDL_VideoSurface->format;
   1.228 +		SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel);
   1.229 +		video->SetColors(video,
   1.230 +				 0, vf->palette->ncolors, vf->palette->colors);
   1.231 +	}
   1.232 +#endif
   1.233 +	video->info.vfmt = SDL_VideoSurface->format;
   1.234 +
   1.235 +	/* Start the event loop */
   1.236 +	if ( SDL_StartEventLoop(flags) < 0 ) {
   1.237 +		SDL_VideoQuit();
   1.238 +		return(-1);
   1.239 +	}
   1.240 +	SDL_CursorInit(flags & SDL_INIT_EVENTTHREAD);
   1.241 +
   1.242 +	/* We're ready to go! */
   1.243 +	return(0);
   1.244 +}
   1.245 +
   1.246 +char *SDL_VideoDriverName(char *namebuf, int maxlen)
   1.247 +{
   1.248 +	if ( current_video != NULL ) {
   1.249 +		strncpy(namebuf, current_video->name, maxlen-1);
   1.250 +		namebuf[maxlen-1] = '\0';
   1.251 +		return(namebuf);
   1.252 +	}
   1.253 +	return(NULL);
   1.254 +}
   1.255 +
   1.256 +/*
   1.257 + * Get the current display surface
   1.258 + */
   1.259 +SDL_Surface *SDL_GetVideoSurface(void)
   1.260 +{
   1.261 +	SDL_Surface *visible;
   1.262 +
   1.263 +	visible = NULL;
   1.264 +	if ( current_video ) {
   1.265 +		visible = current_video->visible;
   1.266 +	}
   1.267 +	return(visible);
   1.268 +}
   1.269 +
   1.270 +/*
   1.271 + * Get the current information about the video hardware
   1.272 + */
   1.273 +const SDL_VideoInfo *SDL_GetVideoInfo(void)
   1.274 +{
   1.275 +	const SDL_VideoInfo *info;
   1.276 +
   1.277 +	info = NULL;
   1.278 +	if ( current_video ) {
   1.279 +		info = &current_video->info;
   1.280 +	}
   1.281 +	return(info);
   1.282 +}
   1.283 +
   1.284 +/*
   1.285 + * Return a pointer to an array of available screen dimensions for the
   1.286 + * given format, sorted largest to smallest.  Returns NULL if there are
   1.287 + * no dimensions available for a particular format, or (SDL_Rect **)-1
   1.288 + * if any dimension is okay for the given format.  If 'format' is NULL,
   1.289 + * the mode list will be for the format given by SDL_GetVideoInfo()->vfmt
   1.290 + */
   1.291 +SDL_Rect ** SDL_ListModes (SDL_PixelFormat *format, Uint32 flags)
   1.292 +{
   1.293 +	SDL_VideoDevice *video = current_video;
   1.294 +	SDL_VideoDevice *this  = current_video;
   1.295 +	SDL_Rect **modes;
   1.296 +
   1.297 +	modes = NULL;
   1.298 +	if ( SDL_VideoSurface ) {
   1.299 +		if ( format == NULL ) {
   1.300 +			format = SDL_VideoSurface->format;
   1.301 +		}
   1.302 +		modes = video->ListModes(this, format, flags);
   1.303 +	}
   1.304 +	return(modes);
   1.305 +}
   1.306 +
   1.307 +/*
   1.308 + * Check to see if a particular video mode is supported.
   1.309 + * It returns 0 if the requested mode is not supported under any bit depth,
   1.310 + * or returns the bits-per-pixel of the closest available mode with the
   1.311 + * given width and height.  If this bits-per-pixel is different from the
   1.312 + * one used when setting the video mode, SDL_SetVideoMode() will succeed,
   1.313 + * but will emulate the requested bits-per-pixel with a shadow surface.
   1.314 + */
   1.315 +static Uint8 SDL_closest_depths[4][8] = {
   1.316 +	/* 8 bit closest depth ordering */
   1.317 +	{ 0, 8, 16, 15, 32, 24, 0, 0 },
   1.318 +	/* 15,16 bit closest depth ordering */
   1.319 +	{ 0, 16, 15, 32, 24, 8, 0, 0 },
   1.320 +	/* 24 bit closest depth ordering */
   1.321 +	{ 0, 24, 32, 16, 15, 8, 0, 0 },
   1.322 +	/* 32 bit closest depth ordering */
   1.323 +	{ 0, 32, 16, 15, 24, 8, 0, 0 }
   1.324 +};
   1.325 +
   1.326 +int SDL_VideoModeOK (int width, int height, int bpp, Uint32 flags) 
   1.327 +{
   1.328 +	int table, b, i;
   1.329 +	int supported;
   1.330 +	SDL_PixelFormat format;
   1.331 +	SDL_Rect **sizes;
   1.332 +
   1.333 +	/* Currently 1 and 4 bpp are not supported */
   1.334 +	if ( bpp < 8 || bpp > 32 ) {
   1.335 +		return(0);
   1.336 +	}
   1.337 +	if ( (width == 0) || (height == 0) ) {
   1.338 +		return(0);
   1.339 +	}
   1.340 +
   1.341 +	/* Search through the list valid of modes */
   1.342 +	memset(&format, 0, sizeof(format));
   1.343 +	supported = 0;
   1.344 +	table = ((bpp+7)/8)-1;
   1.345 +	SDL_closest_depths[table][0] = bpp;
   1.346 +	SDL_closest_depths[table][7] = 0;
   1.347 +	for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) {
   1.348 +		format.BitsPerPixel = SDL_closest_depths[table][b];
   1.349 +		sizes = SDL_ListModes(&format, flags);
   1.350 +		if ( sizes == (SDL_Rect **)0 ) {
   1.351 +			/* No sizes supported at this bit-depth */
   1.352 +			continue;
   1.353 +		} else 
   1.354 +#ifdef macintosh /* MPW optimization bug? */
   1.355 +		if ( (sizes == (SDL_Rect **)0xFFFFFFFF) ||
   1.356 +#else
   1.357 +		if ( (sizes == (SDL_Rect **)-1) ||
   1.358 +#endif
   1.359 +		     current_video->handles_any_size ) {
   1.360 +			/* Any size supported at this bit-depth */
   1.361 +			supported = 1;
   1.362 +			continue;
   1.363 +		} else
   1.364 +		for ( i=0; sizes[i]; ++i ) {
   1.365 +			if ((sizes[i]->w == width) && (sizes[i]->h == height)) {
   1.366 +				supported = 1;
   1.367 +				break;
   1.368 +			}
   1.369 +		}
   1.370 +	}
   1.371 +	if ( supported ) {
   1.372 +		--b;
   1.373 +		return(SDL_closest_depths[table][b]);
   1.374 +	} else {
   1.375 +		return(0);
   1.376 +	}
   1.377 +}
   1.378 +
   1.379 +/*
   1.380 + * Get the closest non-emulated video mode to the one requested
   1.381 + */
   1.382 +static int SDL_GetVideoMode (int *w, int *h, int *BitsPerPixel, Uint32 flags)
   1.383 +{
   1.384 +	int table, b, i;
   1.385 +	int supported;
   1.386 +	int native_bpp;
   1.387 +	SDL_PixelFormat format;
   1.388 +	SDL_Rect **sizes;
   1.389 +
   1.390 +	/* Try the original video mode, get the closest depth */
   1.391 +	native_bpp = SDL_VideoModeOK(*w, *h, *BitsPerPixel, flags);
   1.392 +	if ( native_bpp == *BitsPerPixel ) {
   1.393 +		return(1);
   1.394 +	}
   1.395 +	if ( native_bpp > 0 ) {
   1.396 +		*BitsPerPixel = native_bpp;
   1.397 +		return(1);
   1.398 +	}
   1.399 +
   1.400 +	/* No exact size match at any depth, look for closest match */
   1.401 +	memset(&format, 0, sizeof(format));
   1.402 +	supported = 0;
   1.403 +	table = ((*BitsPerPixel+7)/8)-1;
   1.404 +	SDL_closest_depths[table][0] = *BitsPerPixel;
   1.405 +	SDL_closest_depths[table][7] = SDL_VideoSurface->format->BitsPerPixel;
   1.406 +	for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) {
   1.407 +		format.BitsPerPixel = SDL_closest_depths[table][b];
   1.408 +		sizes = SDL_ListModes(&format, flags);
   1.409 +		if ( sizes == (SDL_Rect **)0 ) {
   1.410 +			/* No sizes supported at this bit-depth */
   1.411 +			continue;
   1.412 +		}
   1.413 +		for ( i=0; sizes[i]; ++i ) {
   1.414 +			if ((sizes[i]->w < *w) || (sizes[i]->h < *h)) {
   1.415 +				if ( i > 0 ) {
   1.416 +					--i;
   1.417 +					*w = sizes[i]->w;
   1.418 +					*h = sizes[i]->h;
   1.419 +					*BitsPerPixel = SDL_closest_depths[table][b];
   1.420 +					supported = 1;
   1.421 +				} else {
   1.422 +					/* Largest mode too small... */;
   1.423 +				}
   1.424 +				break;
   1.425 +			}
   1.426 +		}
   1.427 +		if ( (i > 0) && ! sizes[i] ) {
   1.428 +			/* The smallest mode was larger than requested, OK */
   1.429 +			--i;
   1.430 +			*w = sizes[i]->w;
   1.431 +			*h = sizes[i]->h;
   1.432 +			*BitsPerPixel = SDL_closest_depths[table][b];
   1.433 +			supported = 1;
   1.434 +		}
   1.435 +	}
   1.436 +	if ( ! supported ) {
   1.437 +		SDL_SetError("No video mode large enough for %dx%d", *w, *h);
   1.438 +	}
   1.439 +	return(supported);
   1.440 +}
   1.441 +
   1.442 +/* This should probably go somewhere else -- like SDL_surface.c */
   1.443 +static void SDL_ClearSurface(SDL_Surface *surface)
   1.444 +{
   1.445 +	Uint32 black;
   1.446 +
   1.447 +	black = SDL_MapRGB(surface->format, 0, 0, 0);
   1.448 +	SDL_FillRect(surface, NULL, black);
   1.449 +	if ((surface->flags&SDL_HWSURFACE) && (surface->flags&SDL_DOUBLEBUF)) {
   1.450 +		SDL_Flip(surface);
   1.451 +		SDL_FillRect(surface, NULL, black);
   1.452 +	}
   1.453 +	SDL_Flip(surface);
   1.454 +}
   1.455 +
   1.456 +/*
   1.457 + * Create a shadow surface suitable for fooling the app. :-)
   1.458 + */
   1.459 +static void SDL_CreateShadowSurface(int depth)
   1.460 +{
   1.461 +	Uint32 Rmask, Gmask, Bmask;
   1.462 +
   1.463 +	/* Allocate the shadow surface */
   1.464 +	if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) {
   1.465 +		Rmask = (SDL_VideoSurface->format)->Rmask;
   1.466 +		Gmask = (SDL_VideoSurface->format)->Gmask;
   1.467 +		Bmask = (SDL_VideoSurface->format)->Bmask;
   1.468 +	} else {
   1.469 +		Rmask = Gmask = Bmask = 0;
   1.470 +	}
   1.471 +	SDL_ShadowSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
   1.472 +				SDL_VideoSurface->w, SDL_VideoSurface->h,
   1.473 +						depth, Rmask, Gmask, Bmask, 0);
   1.474 +	if ( SDL_ShadowSurface == NULL ) {
   1.475 +		return;
   1.476 +	}
   1.477 +
   1.478 +	/* 8-bit shadow surfaces report that they have exclusive palette */
   1.479 +	if ( SDL_ShadowSurface->format->palette ) {
   1.480 +		SDL_ShadowSurface->flags |= SDL_HWPALETTE;
   1.481 +		if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) {
   1.482 +			memcpy(SDL_ShadowSurface->format->palette->colors,
   1.483 +				SDL_VideoSurface->format->palette->colors,
   1.484 +				SDL_VideoSurface->format->palette->ncolors*
   1.485 +							sizeof(SDL_Color));
   1.486 +		} else {
   1.487 +			SDL_DitherColors(
   1.488 +			SDL_ShadowSurface->format->palette->colors, depth);
   1.489 +		}
   1.490 +	}
   1.491 +
   1.492 +	/* If the video surface is resizable, the shadow should say so */
   1.493 +	if ( (SDL_VideoSurface->flags & SDL_RESIZABLE) == SDL_RESIZABLE ) {
   1.494 +		SDL_ShadowSurface->flags |= SDL_RESIZABLE;
   1.495 +	}
   1.496 +	/* If the video surface has no frame, the shadow should say so */
   1.497 +	if ( (SDL_VideoSurface->flags & SDL_NOFRAME) == SDL_NOFRAME ) {
   1.498 +		SDL_ShadowSurface->flags |= SDL_NOFRAME;
   1.499 +	}
   1.500 +	/* If the video surface is fullscreen, the shadow should say so */
   1.501 +	if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
   1.502 +		SDL_ShadowSurface->flags |= SDL_FULLSCREEN;
   1.503 +	}
   1.504 +	/* If the video surface is flippable, the shadow should say so */
   1.505 +	if ( (SDL_VideoSurface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
   1.506 +		SDL_ShadowSurface->flags |= SDL_DOUBLEBUF;
   1.507 +	}
   1.508 +	return;
   1.509 +}
   1.510 +
   1.511 +/*
   1.512 + * Set the requested video mode, allocating a shadow buffer if necessary.
   1.513 + */
   1.514 +SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags)
   1.515 +{
   1.516 +	SDL_VideoDevice *video, *this;
   1.517 +	SDL_Surface *prev_mode, *mode;
   1.518 +	int video_w;
   1.519 +	int video_h;
   1.520 +	int video_bpp;
   1.521 +	int is_opengl;
   1.522 +	SDL_GrabMode saved_grab;
   1.523 +
   1.524 +	/* Start up the video driver, if necessary..
   1.525 +	   WARNING: This is the only function protected this way!
   1.526 +	 */
   1.527 +	if ( ! current_video ) {
   1.528 +		if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) {
   1.529 +			return(NULL);
   1.530 +		}
   1.531 +	}
   1.532 +	this = video = current_video;
   1.533 +
   1.534 +	/* Default to the current video bpp */
   1.535 +	if ( bpp == 0 ) {
   1.536 +		flags |= SDL_ANYFORMAT;
   1.537 +		bpp = SDL_VideoSurface->format->BitsPerPixel;
   1.538 +	}
   1.539 +
   1.540 +	/* Get a good video mode, the closest one possible */
   1.541 +	video_w = width;
   1.542 +	video_h = height;
   1.543 +	video_bpp = bpp;
   1.544 +	if ( ! SDL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) {
   1.545 +		return(NULL);
   1.546 +	}
   1.547 +
   1.548 +	/* Check the requested flags */
   1.549 +	/* There's no palette in > 8 bits-per-pixel mode */
   1.550 +	if ( video_bpp > 8 ) {
   1.551 +		flags &= ~SDL_HWPALETTE;
   1.552 +	}
   1.553 +#if 0
   1.554 +	if ( (flags&SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
   1.555 +		/* There's no windowed double-buffering */
   1.556 +		flags &= ~SDL_DOUBLEBUF;
   1.557 +	}
   1.558 +#endif
   1.559 +	if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
   1.560 +		/* Use hardware surfaces when double-buffering */
   1.561 +		flags |= SDL_HWSURFACE;
   1.562 +	}
   1.563 +
   1.564 +	is_opengl = ( ( flags & SDL_OPENGL ) == SDL_OPENGL );
   1.565 +	if ( is_opengl ) {
   1.566 +		/* These flags are for 2D video modes only */
   1.567 +		flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF);
   1.568 +	}
   1.569 +
   1.570 +	/* Clean up any previous video mode */
   1.571 +	if ( SDL_PublicSurface != NULL ) {
   1.572 +		SDL_PublicSurface = NULL;
   1.573 +	}
   1.574 +	if ( SDL_ShadowSurface != NULL ) {
   1.575 +		SDL_Surface *ready_to_go;
   1.576 +		ready_to_go = SDL_ShadowSurface;
   1.577 +		SDL_ShadowSurface = NULL;
   1.578 +		SDL_FreeSurface(ready_to_go);
   1.579 +	}
   1.580 +	if ( video->physpal ) {
   1.581 +		free(video->physpal->colors);
   1.582 +		free(video->physpal);
   1.583 +		video->physpal = NULL;
   1.584 +	}
   1.585 +	if( video->gammacols) {
   1.586 +	        free(video->gammacols);
   1.587 +		video->gammacols = NULL;
   1.588 +	}
   1.589 +
   1.590 +	/* Save the previous grab state and turn off grab for mode switch */
   1.591 +	saved_grab = SDL_WM_GrabInputOff();
   1.592 +
   1.593 +	/* Try to set the video mode, along with offset and clipping */
   1.594 +	prev_mode = SDL_VideoSurface;
   1.595 +	SDL_LockCursor();
   1.596 +	SDL_VideoSurface = NULL;	/* In case it's freed by driver */
   1.597 +	mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags);
   1.598 +	if ( mode ) { /* Prevent resize events from mode change */
   1.599 +	    SDL_PrivateResize(mode->w, mode->h);
   1.600 +        }
   1.601 +	/*
   1.602 +	 * rcg11292000
   1.603 +	 * If you try to set an SDL_OPENGL surface, and fail to find a
   1.604 +	 * matching  visual, then the next call to SDL_SetVideoMode()
   1.605 +	 * will segfault, since  we no longer point to a dummy surface,
   1.606 +	 * but rather NULL.
   1.607 +	 * Sam 11/29/00
   1.608 +	 * WARNING, we need to make sure that the previous mode hasn't
   1.609 +	 * already been freed by the video driver.  What do we do in
   1.610 +	 * that case?  Should we call SDL_VideoInit() again?
   1.611 +	 */
   1.612 +	SDL_VideoSurface = (mode != NULL) ? mode : prev_mode;
   1.613 +
   1.614 +	if ( (mode != NULL) && (!is_opengl) ) {
   1.615 +		/* Sanity check */
   1.616 +		if ( (mode->w < width) || (mode->h < height) ) {
   1.617 +			SDL_SetError("Video mode smaller than requested");
   1.618 +			return(NULL);
   1.619 +		}
   1.620 +
   1.621 +		/* If we have a palettized surface, create a default palette */
   1.622 +		if ( mode->format->palette ) {
   1.623 +	        	SDL_PixelFormat *vf = mode->format;
   1.624 +			SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel);
   1.625 +			video->SetColors(this, 0, vf->palette->ncolors,
   1.626 +			                           vf->palette->colors);
   1.627 +		}
   1.628 +
   1.629 +		/* Clear the surface to black */
   1.630 +		video->offset_x = 0;
   1.631 +		video->offset_y = 0;
   1.632 +		mode->offset = 0;
   1.633 +		SDL_SetClipRect(mode, NULL);
   1.634 +		SDL_ClearSurface(mode);
   1.635 +
   1.636 +		/* Now adjust the offsets to match the desired mode */
   1.637 +		video->offset_x = (mode->w-width)/2;
   1.638 +		video->offset_y = (mode->h-height)/2;
   1.639 +		mode->offset = video->offset_y*mode->pitch +
   1.640 +				video->offset_x*mode->format->BytesPerPixel;
   1.641 +#ifdef DEBUG_VIDEO
   1.642 +  fprintf(stderr,
   1.643 +	"Requested mode: %dx%dx%d, obtained mode %dx%dx%d (offset %d)\n",
   1.644 +		width, height, bpp,
   1.645 +		mode->w, mode->h, mode->format->BitsPerPixel, mode->offset);
   1.646 +#endif
   1.647 +		mode->w = width;
   1.648 +		mode->h = height;
   1.649 +		SDL_SetClipRect(mode, NULL);
   1.650 +	}
   1.651 +	SDL_ResetCursor();
   1.652 +	SDL_UnlockCursor();
   1.653 +
   1.654 +	/* If we failed setting a video mode, return NULL... (Uh Oh!) */
   1.655 +	if ( mode == NULL ) {
   1.656 +		return(NULL);
   1.657 +	}
   1.658 +
   1.659 +	/* If there is no window manager, set the SDL_NOFRAME flag */
   1.660 +	if ( ! video->info.wm_available ) {
   1.661 +		mode->flags |= SDL_NOFRAME;
   1.662 +	}
   1.663 +
   1.664 +	/* Reset the mouse cursor and grab for new video mode */
   1.665 +	SDL_SetCursor(NULL);
   1.666 +	if ( video->UpdateMouse ) {
   1.667 +		video->UpdateMouse(this);
   1.668 +	}
   1.669 +	SDL_WM_GrabInput(saved_grab);
   1.670 +	SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */
   1.671 +
   1.672 +	/* If we're running OpenGL, make the context current */
   1.673 +	if ( (video->screen->flags & SDL_OPENGL) &&
   1.674 +	      video->GL_MakeCurrent ) {
   1.675 +		if ( video->GL_MakeCurrent(this) < 0 ) {
   1.676 +			return(NULL);
   1.677 +		}
   1.678 +	}
   1.679 +
   1.680 +	/* Set up a fake SDL surface for OpenGL "blitting" */
   1.681 +	if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) {
   1.682 +		/* Load GL functions for performing the texture updates */
   1.683 +#ifdef HAVE_OPENGL
   1.684 +#define SDL_PROC(ret,func,params) \
   1.685 +do { \
   1.686 +	video->func = SDL_GL_GetProcAddress(#func); \
   1.687 +	if ( ! video->func ) { \
   1.688 +		SDL_SetError("Couldn't load GL function: %s\n", #func); \
   1.689 +		return(NULL); \
   1.690 +	} \
   1.691 +} while ( 0 );
   1.692 +#include "SDL_glfuncs.h"
   1.693 +#undef SDL_PROC	
   1.694 +
   1.695 +		/* Create a software surface for blitting */
   1.696 +#ifdef GL_VERSION_1_2
   1.697 +		/* If the implementation either supports the packed pixels
   1.698 +		   extension, or implements the core OpenGL 1.2 API, it will
   1.699 +		   support the GL_UNSIGNED_SHORT_5_6_5 texture format.
   1.700 +		 */
   1.701 +		if ( (bpp == 16) &&
   1.702 +		     (strstr((const char *)video->glGetString(GL_EXTENSIONS),
   1.703 +		                           "GL_EXT_packed_pixels") ||
   1.704 +		     (strncmp((const char *)video->glGetString(GL_VERSION),
   1.705 +		              "1.2", 3) == 0)) )
   1.706 +		{
   1.707 +			video->is_32bit = 0;
   1.708 +			SDL_VideoSurface = SDL_CreateRGBSurface(
   1.709 +				flags, 
   1.710 +				width, 
   1.711 +				height,  
   1.712 +				16,
   1.713 +				31 << 11,
   1.714 +				63 << 5,
   1.715 +				31,
   1.716 +				0
   1.717 +				);
   1.718 +		}
   1.719 +		else
   1.720 +#endif /* OpenGL 1.2 */
   1.721 +		{
   1.722 +			video->is_32bit = 1;
   1.723 +			SDL_VideoSurface = SDL_CreateRGBSurface(
   1.724 +				flags, 
   1.725 +				width, 
   1.726 +				height, 
   1.727 +				32, 
   1.728 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN
   1.729 +				0x000000FF,
   1.730 +				0x0000FF00,
   1.731 +				0x00FF0000,
   1.732 +				0xFF000000
   1.733 +#else
   1.734 +				0xFF000000,
   1.735 +				0x00FF0000,
   1.736 +				0x0000FF00,
   1.737 +				0x000000FF
   1.738 +#endif
   1.739 +				);
   1.740 +		}
   1.741 +		if ( ! SDL_VideoSurface ) {
   1.742 +			return(NULL);
   1.743 +		}
   1.744 +		SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT;
   1.745 +
   1.746 +		/* Free the original video mode surface (is this safe?) */
   1.747 +		SDL_FreeSurface(mode);
   1.748 +
   1.749 +                /* Set the surface completely opaque & white by default */
   1.750 +		memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch );
   1.751 +		video->glGenTextures( 1, &video->texture );
   1.752 +		video->glBindTexture( GL_TEXTURE_2D, video->texture );
   1.753 +		video->glTexImage2D(
   1.754 +			GL_TEXTURE_2D,
   1.755 +			0,
   1.756 +			video->is_32bit ? GL_RGBA : GL_RGB,
   1.757 +			256,
   1.758 +			256,
   1.759 +			0,
   1.760 +			video->is_32bit ? GL_RGBA : GL_RGB,
   1.761 +#ifdef GL_VERSION_1_2
   1.762 +			video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
   1.763 +#else
   1.764 +			GL_UNSIGNED_BYTE,
   1.765 +#endif
   1.766 +			NULL);
   1.767 +
   1.768 +		video->UpdateRects = SDL_GL_UpdateRectsLock;
   1.769 +#else
   1.770 +		SDL_SetError("Somebody forgot to #define HAVE_OPENGL");
   1.771 +		return(NULL);
   1.772 +#endif
   1.773 +	}
   1.774 +
   1.775 +	/* Create a shadow surface if necessary */
   1.776 +	/* There are three conditions under which we create a shadow surface:
   1.777 +		1.  We need a particular bits-per-pixel that we didn't get.
   1.778 +		2.  We need a hardware palette and didn't get one.
   1.779 +		3.  We need a software surface and got a hardware surface.
   1.780 +	*/
   1.781 +	if ( !(SDL_VideoSurface->flags & SDL_OPENGL) &&
   1.782 +	     (
   1.783 +	     (  !(flags&SDL_ANYFORMAT) &&
   1.784 +			(SDL_VideoSurface->format->BitsPerPixel != bpp)) ||
   1.785 +	     (   (flags&SDL_HWPALETTE) && 
   1.786 +				!(SDL_VideoSurface->flags&SDL_HWPALETTE)) ||
   1.787 +		/* If the surface is in hardware, video writes are visible
   1.788 +		   as soon as they are performed, so we need to buffer them
   1.789 +		 */
   1.790 +	     (   ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) &&
   1.791 +				(SDL_VideoSurface->flags&SDL_HWSURFACE))
   1.792 +	     ) ) {
   1.793 +		SDL_CreateShadowSurface(bpp);
   1.794 +		if ( SDL_ShadowSurface == NULL ) {
   1.795 +			SDL_SetError("Couldn't create shadow surface");
   1.796 +			return(NULL);
   1.797 +		}
   1.798 +		SDL_PublicSurface = SDL_ShadowSurface;
   1.799 +	} else {
   1.800 +		SDL_PublicSurface = SDL_VideoSurface;
   1.801 +	}
   1.802 +	video->info.vfmt = SDL_VideoSurface->format;
   1.803 +
   1.804 +	/* We're done! */
   1.805 +	return(SDL_PublicSurface);
   1.806 +}
   1.807 +
   1.808 +/* 
   1.809 + * Convert a surface into the video pixel format.
   1.810 + */
   1.811 +SDL_Surface * SDL_DisplayFormat (SDL_Surface *surface)
   1.812 +{
   1.813 +	Uint32 flags;
   1.814 +
   1.815 +	if ( ! SDL_PublicSurface ) {
   1.816 +		SDL_SetError("No video mode has been set");
   1.817 +		return(NULL);
   1.818 +	}
   1.819 +	/* Set the flags appropriate for copying to display surface */
   1.820 +	flags  = (SDL_PublicSurface->flags&SDL_HWSURFACE);
   1.821 +#ifdef AUTORLE_DISPLAYFORMAT
   1.822 +	flags |= (surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA));
   1.823 +	flags |= SDL_RLEACCELOK;
   1.824 +#else
   1.825 +	flags |= surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA|SDL_RLEACCELOK);
   1.826 +#endif
   1.827 +	return(SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags));
   1.828 +}
   1.829 +
   1.830 +/*
   1.831 + * Convert a surface into a format that's suitable for blitting to
   1.832 + * the screen, but including an alpha channel.
   1.833 + */
   1.834 +SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface)
   1.835 +{
   1.836 +	SDL_PixelFormat *vf;
   1.837 +	SDL_PixelFormat *format;
   1.838 +	SDL_Surface *converted;
   1.839 +	Uint32 flags;
   1.840 +	/* default to ARGB8888 */
   1.841 +	Uint32 amask = 0xff000000;
   1.842 +	Uint32 rmask = 0x00ff0000;
   1.843 +	Uint32 gmask = 0x0000ff00;
   1.844 +	Uint32 bmask = 0x000000ff;
   1.845 +
   1.846 +	if ( ! SDL_PublicSurface ) {
   1.847 +		SDL_SetError("No video mode has been set");
   1.848 +		return(NULL);
   1.849 +	}
   1.850 +	vf = SDL_PublicSurface->format;
   1.851 +
   1.852 +	switch(vf->BytesPerPixel) {
   1.853 +	    case 2:
   1.854 +		/* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
   1.855 +		   For anything else (like ARGB4444) it doesn't matter
   1.856 +		   since we have no special code for it anyway */
   1.857 +		if ( (vf->Rmask == 0x1f) &&
   1.858 +		     (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
   1.859 +			rmask = 0xff;
   1.860 +			bmask = 0xff0000;
   1.861 +		}
   1.862 +		break;
   1.863 +
   1.864 +	    case 3:
   1.865 +	    case 4:
   1.866 +		/* Keep the video format, as long as the high 8 bits are
   1.867 +		   unused or alpha */
   1.868 +		if ( (vf->Rmask == 0xff) && (vf->Bmask == 0xff0000) ) {
   1.869 +			rmask = 0xff;
   1.870 +			bmask = 0xff0000;
   1.871 +		}
   1.872 +		break;
   1.873 +
   1.874 +	    default:
   1.875 +		/* We have no other optimised formats right now. When/if a new
   1.876 +		   optimised alpha format is written, add the converter here */
   1.877 +		break;
   1.878 +	}
   1.879 +	format = SDL_AllocFormat(32, rmask, gmask, bmask, amask);
   1.880 +	flags = SDL_PublicSurface->flags & SDL_HWSURFACE;
   1.881 +	flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
   1.882 +	converted = SDL_ConvertSurface(surface, format, flags);
   1.883 +	SDL_FreeFormat(format);
   1.884 +	return(converted);
   1.885 +}
   1.886 +
   1.887 +/*
   1.888 + * Update a specific portion of the physical screen
   1.889 + */
   1.890 +void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
   1.891 +{
   1.892 +	if ( screen ) {
   1.893 +		SDL_Rect rect;
   1.894 +
   1.895 +		/* Perform some checking */
   1.896 +		if ( w == 0 )
   1.897 +			w = screen->w;
   1.898 +		if ( h == 0 )
   1.899 +			h = screen->h;
   1.900 +		if ( (int)(x+w) > screen->w )
   1.901 +			return;
   1.902 +		if ( (int)(y+h) > screen->h )
   1.903 +			return;
   1.904 +
   1.905 +		/* Fill the rectangle */
   1.906 +		rect.x = x;
   1.907 +		rect.y = y;
   1.908 +		rect.w = w;
   1.909 +		rect.h = h;
   1.910 +		SDL_UpdateRects(screen, 1, &rect);
   1.911 +	}
   1.912 +}
   1.913 +void SDL_UpdateRects (SDL_Surface *screen, int numrects, SDL_Rect *rects)
   1.914 +{
   1.915 +	int i;
   1.916 +	SDL_VideoDevice *video = current_video;
   1.917 +	SDL_VideoDevice *this = current_video;
   1.918 +
   1.919 +	if ( screen == SDL_ShadowSurface ) {
   1.920 +		/* Blit the shadow surface using saved mapping */
   1.921 +	        SDL_Palette *pal = screen->format->palette;
   1.922 +		SDL_Color *saved_colors = NULL;
   1.923 +	        if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
   1.924 +			/* simulated 8bpp, use correct physical palette */
   1.925 +			saved_colors = pal->colors;
   1.926 +			if ( video->gammacols ) {
   1.927 +				/* gamma-corrected palette */
   1.928 +				pal->colors = video->gammacols;
   1.929 +			} else if ( video->physpal ) {
   1.930 +				/* physical palette different from logical */
   1.931 +				pal->colors = video->physpal->colors;
   1.932 +			}
   1.933 +		}
   1.934 +		if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
   1.935 +			SDL_LockCursor();
   1.936 +			SDL_DrawCursor(SDL_ShadowSurface);
   1.937 +			for ( i=0; i<numrects; ++i ) {
   1.938 +				SDL_LowerBlit(SDL_ShadowSurface, &rects[i], 
   1.939 +						SDL_VideoSurface, &rects[i]);
   1.940 +			}
   1.941 +			SDL_EraseCursor(SDL_ShadowSurface);
   1.942 +			SDL_UnlockCursor();
   1.943 +		} else {
   1.944 +			for ( i=0; i<numrects; ++i ) {
   1.945 +				SDL_LowerBlit(SDL_ShadowSurface, &rects[i], 
   1.946 +						SDL_VideoSurface, &rects[i]);
   1.947 +			}
   1.948 +		}
   1.949 +		if ( saved_colors )
   1.950 +			pal->colors = saved_colors;
   1.951 +
   1.952 +		/* Fall through to video surface update */
   1.953 +		screen = SDL_VideoSurface;
   1.954 +	}
   1.955 +	if ( screen == SDL_VideoSurface ) {
   1.956 +		/* Update the video surface */
   1.957 +		if ( screen->offset ) {
   1.958 +			for ( i=0; i<numrects; ++i ) {
   1.959 +				rects[i].x += video->offset_x;
   1.960 +				rects[i].y += video->offset_y;
   1.961 +			}
   1.962 +			video->UpdateRects(this, numrects, rects);
   1.963 +			for ( i=0; i<numrects; ++i ) {
   1.964 +				rects[i].x -= video->offset_x;
   1.965 +				rects[i].y -= video->offset_y;
   1.966 +			}
   1.967 +		} else {
   1.968 +			video->UpdateRects(this, numrects, rects);
   1.969 +		}
   1.970 +	}
   1.971 +}
   1.972 +
   1.973 +/*
   1.974 + * Performs hardware double buffering, if possible, or a full update if not.
   1.975 + */
   1.976 +int SDL_Flip(SDL_Surface *screen)
   1.977 +{
   1.978 +	SDL_VideoDevice *video = current_video;
   1.979 +	/* Copy the shadow surface to the video surface */
   1.980 +	if ( screen == SDL_ShadowSurface ) {
   1.981 +		SDL_Rect rect;
   1.982 +	        SDL_Palette *pal = screen->format->palette;
   1.983 +		SDL_Color *saved_colors = NULL;
   1.984 +	        if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
   1.985 +			/* simulated 8bpp, use correct physical palette */
   1.986 +			saved_colors = pal->colors;
   1.987 +			if ( video->gammacols ) {
   1.988 +				/* gamma-corrected palette */
   1.989 +				pal->colors = video->gammacols;
   1.990 +			} else if ( video->physpal ) {
   1.991 +				/* physical palette different from logical */
   1.992 +				pal->colors = video->physpal->colors;
   1.993 +			}
   1.994 +		}
   1.995 +
   1.996 +		rect.x = 0;
   1.997 +		rect.y = 0;
   1.998 +		rect.w = screen->w;
   1.999 +		rect.h = screen->h;
  1.1000 +		SDL_LowerBlit(SDL_ShadowSurface,&rect, SDL_VideoSurface,&rect);
  1.1001 +
  1.1002 +		if ( saved_colors )
  1.1003 +			pal->colors = saved_colors;
  1.1004 +		screen = SDL_VideoSurface;
  1.1005 +	}
  1.1006 +	if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1.1007 +		SDL_VideoDevice *this  = current_video;
  1.1008 +		return(video->FlipHWSurface(this, SDL_VideoSurface));
  1.1009 +	} else {
  1.1010 +		SDL_UpdateRect(screen, 0, 0, 0, 0);
  1.1011 +	}
  1.1012 +	return(0);
  1.1013 +}
  1.1014 +
  1.1015 +static void SetPalette_logical(SDL_Surface *screen, SDL_Color *colors,
  1.1016 +			       int firstcolor, int ncolors)
  1.1017 +{
  1.1018 +        SDL_Palette *pal = screen->format->palette;
  1.1019 +	SDL_Palette *vidpal;
  1.1020 +
  1.1021 +	if ( colors != (pal->colors + firstcolor) ) {
  1.1022 +	        memcpy(pal->colors + firstcolor, colors,
  1.1023 +		       ncolors * sizeof(*colors));
  1.1024 +	}
  1.1025 +
  1.1026 +	vidpal = SDL_VideoSurface->format->palette;
  1.1027 +	if ( (screen == SDL_ShadowSurface) && vidpal ) {
  1.1028 +	        /*
  1.1029 +		 * This is a shadow surface, and the physical
  1.1030 +		 * framebuffer is also indexed. Propagate the
  1.1031 +		 * changes to its logical palette so that
  1.1032 +		 * updates are always identity blits
  1.1033 +		 */
  1.1034 +		memcpy(vidpal->colors + firstcolor, colors,
  1.1035 +		       ncolors * sizeof(*colors));
  1.1036 +	}
  1.1037 +	SDL_FormatChanged(screen);
  1.1038 +}
  1.1039 +
  1.1040 +static int SetPalette_physical(SDL_Surface *screen,
  1.1041 +                               SDL_Color *colors, int firstcolor, int ncolors)
  1.1042 +{
  1.1043 +	SDL_VideoDevice *video = current_video;
  1.1044 +	int gotall = 1;
  1.1045 +
  1.1046 +	if ( video->physpal ) {
  1.1047 +		/* We need to copy the new colors, since we haven't
  1.1048 +		 * already done the copy in the logical set above.
  1.1049 +		 */
  1.1050 +		memcpy(video->physpal->colors + firstcolor,
  1.1051 +		       colors, ncolors * sizeof(*colors));
  1.1052 +	}
  1.1053 +	if ( screen == SDL_ShadowSurface ) {
  1.1054 +		if ( SDL_VideoSurface->flags & SDL_HWPALETTE ) {
  1.1055 +			/*
  1.1056 +			 * The real screen is also indexed - set its physical
  1.1057 +			 * palette. The physical palette does not include the
  1.1058 +			 * gamma modification, we apply it directly instead,
  1.1059 +			 * but this only happens if we have hardware palette.
  1.1060 +			 */
  1.1061 +			screen = SDL_VideoSurface;
  1.1062 +		} else {
  1.1063 +			/*
  1.1064 +			 * The video surface is not indexed - invalidate any
  1.1065 +			 * active shadow-to-video blit mappings.
  1.1066 +			 */
  1.1067 +			if ( screen->map->dst == SDL_VideoSurface ) {
  1.1068 +				SDL_InvalidateMap(screen->map);
  1.1069 +			}
  1.1070 +			if ( video->gamma ) {
  1.1071 +				if( ! video->gammacols ) {
  1.1072 +					SDL_Palette *pp = video->physpal;
  1.1073 +					if(!pp)
  1.1074 +						pp = screen->format->palette;
  1.1075 +					video->gammacols = malloc(pp->ncolors
  1.1076 +							  * sizeof(SDL_Color));
  1.1077 +					SDL_ApplyGamma(video->gamma,
  1.1078 +						       pp->colors,
  1.1079 +						       video->gammacols,
  1.1080 +						       pp->ncolors);
  1.1081 +				} else {
  1.1082 +					SDL_ApplyGamma(video->gamma, colors,
  1.1083 +						       video->gammacols
  1.1084 +						       + firstcolor,
  1.1085 +						       ncolors);
  1.1086 +				}
  1.1087 +			}
  1.1088 +			SDL_UpdateRect(screen, 0, 0, 0, 0);
  1.1089 +		}
  1.1090 +	}
  1.1091 +
  1.1092 +	if ( screen == SDL_VideoSurface ) {
  1.1093 +		SDL_Color gcolors[256];
  1.1094 +
  1.1095 +	        if ( video->gamma ) {
  1.1096 +		        SDL_ApplyGamma(video->gamma, colors, gcolors, ncolors);
  1.1097 +			colors = gcolors;
  1.1098 +		}
  1.1099 +		gotall = video->SetColors(video, firstcolor, ncolors, colors);
  1.1100 +		if ( ! gotall ) {
  1.1101 +			/* The video flags shouldn't have SDL_HWPALETTE, and
  1.1102 +			   the video driver is responsible for copying back the
  1.1103 +			   correct colors into the video surface palette.
  1.1104 +			*/
  1.1105 +			;
  1.1106 +		}
  1.1107 +		SDL_CursorPaletteChanged();
  1.1108 +	}
  1.1109 +	return gotall;
  1.1110 +}
  1.1111 +
  1.1112 +/*
  1.1113 + * Set the physical and/or logical colormap of a surface:
  1.1114 + * Only the screen has a physical colormap. It determines what is actually
  1.1115 + * sent to the display.
  1.1116 + * The logical colormap is used to map blits to/from the surface.
  1.1117 + * 'which' is one or both of SDL_LOGPAL, SDL_PHYSPAL
  1.1118 + *
  1.1119 + * Return nonzero if all colours were set as requested, or 0 otherwise.
  1.1120 + */
  1.1121 +int SDL_SetPalette(SDL_Surface *screen, int which,
  1.1122 +		   SDL_Color *colors, int firstcolor, int ncolors)
  1.1123 +{
  1.1124 +        SDL_Palette *pal;
  1.1125 +	int gotall;
  1.1126 +	int palsize;
  1.1127 +
  1.1128 +	if ( screen != SDL_PublicSurface ) {
  1.1129 +	        /* only screens have physical palettes */
  1.1130 +	        which &= ~SDL_PHYSPAL;
  1.1131 +	} else if( (screen->flags & SDL_HWPALETTE) != SDL_HWPALETTE ) {
  1.1132 +	        /* hardware palettes required for split colormaps */
  1.1133 +	        which |= SDL_PHYSPAL | SDL_LOGPAL;
  1.1134 +	}
  1.1135 +
  1.1136 +	/* Verify the parameters */
  1.1137 +	pal = screen->format->palette;
  1.1138 +	if( !pal ) {
  1.1139 +	        return 0;	/* not a palettized surface */
  1.1140 +	}
  1.1141 +	gotall = 1;
  1.1142 +	palsize = 1 << screen->format->BitsPerPixel;
  1.1143 +	if ( ncolors > (palsize - firstcolor) ) {
  1.1144 +	        ncolors = (palsize - firstcolor);
  1.1145 +		gotall = 0;
  1.1146 +	}
  1.1147 +
  1.1148 +	if ( which & SDL_LOGPAL ) {
  1.1149 +		/*
  1.1150 +		 * Logical palette change: The actual screen isn't affected,
  1.1151 +		 * but the internal colormap is altered so that the
  1.1152 +		 * interpretation of the pixel values (for blits etc) is
  1.1153 +		 * changed.
  1.1154 +		 */
  1.1155 +	        SetPalette_logical(screen, colors, firstcolor, ncolors);
  1.1156 +	}
  1.1157 +	if ( which & SDL_PHYSPAL ) {
  1.1158 +		SDL_VideoDevice *video = current_video;
  1.1159 +	        /*
  1.1160 +		 * Physical palette change: This doesn't affect the
  1.1161 +		 * program's idea of what the screen looks like, but changes
  1.1162 +		 * its actual appearance.
  1.1163 +		 */
  1.1164 +	        if(!video)
  1.1165 +		        return gotall;	/* video not yet initialized */
  1.1166 +		if(!video->physpal && !(which & SDL_LOGPAL) ) {
  1.1167 +			/* Lazy physical palette allocation */
  1.1168 +		        int size;
  1.1169 +			SDL_Palette *pp = malloc(sizeof(*pp));
  1.1170 +			current_video->physpal = pp;
  1.1171 +			pp->ncolors = pal->ncolors;
  1.1172 +			size = pp->ncolors * sizeof(SDL_Color);
  1.1173 +			pp->colors = malloc(size);
  1.1174 +			memcpy(pp->colors, pal->colors, size);
  1.1175 +		}
  1.1176 +		if ( ! SetPalette_physical(screen,
  1.1177 +		                           colors, firstcolor, ncolors) ) {
  1.1178 +			gotall = 0;
  1.1179 +		}
  1.1180 +	}
  1.1181 +	return gotall;
  1.1182 +}
  1.1183 +
  1.1184 +int SDL_SetColors(SDL_Surface *screen, SDL_Color *colors, int firstcolor,
  1.1185 +		  int ncolors)
  1.1186 +{
  1.1187 +        return SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL,
  1.1188 +			      colors, firstcolor, ncolors);
  1.1189 +}
  1.1190 +
  1.1191 +/*
  1.1192 + * Clean up the video subsystem
  1.1193 + */
  1.1194 +void SDL_VideoQuit (void)
  1.1195 +{
  1.1196 +	SDL_Surface *ready_to_go;
  1.1197 +
  1.1198 +	if ( current_video ) {
  1.1199 +		SDL_VideoDevice *video = current_video;
  1.1200 +		SDL_VideoDevice *this  = current_video;
  1.1201 +
  1.1202 +		/* Halt event processing before doing anything else */
  1.1203 +		SDL_StopEventLoop();
  1.1204 +
  1.1205 +		/* Clean up allocated window manager items */
  1.1206 +		if ( SDL_PublicSurface ) {
  1.1207 +			SDL_PublicSurface = NULL;
  1.1208 +		}
  1.1209 +		SDL_CursorQuit();
  1.1210 +
  1.1211 +		/* Just in case... */
  1.1212 +		SDL_WM_GrabInputOff();
  1.1213 +
  1.1214 +		/* Clean up the system video */
  1.1215 +		video->VideoQuit(this);
  1.1216 +
  1.1217 +		/* Free any lingering surfaces */
  1.1218 +		ready_to_go = SDL_ShadowSurface;
  1.1219 +		SDL_ShadowSurface = NULL;
  1.1220 +		SDL_FreeSurface(ready_to_go);
  1.1221 +		if ( SDL_VideoSurface != NULL ) {
  1.1222 +			ready_to_go = SDL_VideoSurface;
  1.1223 +			SDL_VideoSurface = NULL;
  1.1224 +			SDL_FreeSurface(ready_to_go);
  1.1225 +		}
  1.1226 +		SDL_PublicSurface = NULL;
  1.1227 +
  1.1228 +		/* Clean up miscellaneous memory */
  1.1229 +		if ( video->physpal ) {
  1.1230 +			free(video->physpal->colors);
  1.1231 +			free(video->physpal);
  1.1232 +			video->physpal = NULL;
  1.1233 +		}
  1.1234 +		if ( video->gammacols ) {
  1.1235 +			free(video->gammacols);
  1.1236 +			video->gammacols = NULL;
  1.1237 +		}
  1.1238 +		if ( video->gamma ) {
  1.1239 +			free(video->gamma);
  1.1240 +			video->gamma = NULL;
  1.1241 +		}
  1.1242 +		if ( wm_title != NULL ) {
  1.1243 +			free(wm_title);
  1.1244 +			wm_title = NULL;
  1.1245 +		}
  1.1246 +		if ( wm_icon != NULL ) {
  1.1247 +			free(wm_icon);
  1.1248 +			wm_icon = NULL;
  1.1249 +		}
  1.1250 +
  1.1251 +		/* Finish cleaning up video subsystem */
  1.1252 +		video->free(this);
  1.1253 +		current_video = NULL;
  1.1254 +	}
  1.1255 +	return;
  1.1256 +}
  1.1257 +
  1.1258 +/* Load the GL driver library */
  1.1259 +int SDL_GL_LoadLibrary(const char *path)
  1.1260 +{
  1.1261 +	SDL_VideoDevice *video = current_video;
  1.1262 +	SDL_VideoDevice *this = current_video;
  1.1263 +	int retval;
  1.1264 +
  1.1265 +	retval = -1;
  1.1266 +	if ( video->GL_LoadLibrary ) {
  1.1267 +		retval = video->GL_LoadLibrary(this, path);
  1.1268 +	} else {
  1.1269 +		SDL_SetError("No dynamic GL support in video driver");
  1.1270 +	}
  1.1271 +	return(retval);
  1.1272 +}
  1.1273 +
  1.1274 +void *SDL_GL_GetProcAddress(const char* proc)
  1.1275 +{
  1.1276 +	SDL_VideoDevice *video = current_video;
  1.1277 +	SDL_VideoDevice *this = current_video;
  1.1278 +	void *func;
  1.1279 +
  1.1280 +	func = NULL;
  1.1281 +	if ( video->GL_GetProcAddress ) {
  1.1282 +		if ( video->gl_config.driver_loaded ) {
  1.1283 +			func = video->GL_GetProcAddress(this, proc);
  1.1284 +		} else {
  1.1285 +			SDL_SetError("No GL driver has been loaded");
  1.1286 +		}
  1.1287 +	} else {
  1.1288 +		SDL_SetError("No dynamic GL support in video driver");
  1.1289 +	}
  1.1290 +	return func;
  1.1291 +}
  1.1292 +
  1.1293 +/* Set the specified GL attribute for setting up a GL video mode */
  1.1294 +int SDL_GL_SetAttribute( SDL_GLattr attr, int value )
  1.1295 +{
  1.1296 +	int retval;
  1.1297 +	SDL_VideoDevice *video = current_video;
  1.1298 +
  1.1299 +	retval = 0;
  1.1300 +	switch (attr) {
  1.1301 +		case SDL_GL_RED_SIZE:
  1.1302 +			video->gl_config.red_size = value;
  1.1303 +			break;
  1.1304 +		case SDL_GL_GREEN_SIZE:
  1.1305 +			video->gl_config.green_size = value;
  1.1306 +			break;
  1.1307 +		case SDL_GL_BLUE_SIZE:
  1.1308 +			video->gl_config.blue_size = value;
  1.1309 +			break;
  1.1310 +		case SDL_GL_ALPHA_SIZE:
  1.1311 +			video->gl_config.alpha_size = value;
  1.1312 +			break;
  1.1313 +		case SDL_GL_DOUBLEBUFFER:
  1.1314 +			video->gl_config.double_buffer = value;
  1.1315 +			break;
  1.1316 +        	case SDL_GL_BUFFER_SIZE:
  1.1317 +	        	video->gl_config.buffer_size = value;
  1.1318 +			break;
  1.1319 +		case SDL_GL_DEPTH_SIZE:
  1.1320 +			video->gl_config.depth_size = value;
  1.1321 +			break;
  1.1322 +		case SDL_GL_STENCIL_SIZE:
  1.1323 +			video->gl_config.stencil_size = value;
  1.1324 +			break;
  1.1325 +	        case SDL_GL_ACCUM_RED_SIZE:
  1.1326 +			video->gl_config.accum_red_size = value;
  1.1327 +			break;
  1.1328 +	        case SDL_GL_ACCUM_GREEN_SIZE:
  1.1329 +			video->gl_config.accum_green_size = value;
  1.1330 +			break;
  1.1331 +	        case SDL_GL_ACCUM_BLUE_SIZE:
  1.1332 +			video->gl_config.accum_blue_size = value;
  1.1333 +			break;
  1.1334 +	        case SDL_GL_ACCUM_ALPHA_SIZE:
  1.1335 +			video->gl_config.accum_alpha_size = value;
  1.1336 +			break;
  1.1337 +		default:
  1.1338 +			SDL_SetError("Unknown OpenGL attribute");
  1.1339 +			retval = -1;
  1.1340 +			break;
  1.1341 +	}
  1.1342 +	return(retval);
  1.1343 +}
  1.1344 +
  1.1345 +/* Retrieve an attribute value from the windowing system. */
  1.1346 +int SDL_GL_GetAttribute(SDL_GLattr attr, int* value)
  1.1347 +{
  1.1348 +	int retval = -1;
  1.1349 +	SDL_VideoDevice* video = current_video;
  1.1350 +	SDL_VideoDevice* this = current_video;
  1.1351 +
  1.1352 +	if ( video->GL_GetAttribute ) {
  1.1353 +		retval = this->GL_GetAttribute(this, attr, value);
  1.1354 +	}
  1.1355 +
  1.1356 +	return retval;
  1.1357 +}
  1.1358 +
  1.1359 +/* Perform a GL buffer swap on the current GL context */
  1.1360 +void SDL_GL_SwapBuffers(void)
  1.1361 +{
  1.1362 +	SDL_VideoDevice *video = current_video;
  1.1363 +	SDL_VideoDevice *this = current_video;
  1.1364 +
  1.1365 +	if ( video->screen->flags & SDL_OPENGL ) {
  1.1366 +		video->GL_SwapBuffers( this );
  1.1367 +	}
  1.1368 +}
  1.1369 +
  1.1370 +/* Update rects with locking */
  1.1371 +void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect *rects)
  1.1372 +{
  1.1373 +	SDL_GL_Lock();
  1.1374 + 	SDL_GL_UpdateRects(numrects, rects);
  1.1375 +	SDL_GL_Unlock();
  1.1376 +}
  1.1377 +
  1.1378 +/* Update rects without state setting and changing (the caller is responsible for it) */
  1.1379 +void SDL_GL_UpdateRects(int numrects, SDL_Rect *rects)
  1.1380 +{
  1.1381 +#ifdef HAVE_OPENGL
  1.1382 +	SDL_VideoDevice *this = current_video;
  1.1383 +	SDL_Rect update, tmp;
  1.1384 +	int x, y, i;
  1.1385 +
  1.1386 +	for ( i = 0; i < numrects; i++ )
  1.1387 +	{
  1.1388 +		tmp.y = rects[i].y;
  1.1389 +		tmp.h = rects[i].h;
  1.1390 +		for ( y = 0; y <= rects[i].h / 256; y++ )
  1.1391 +		{
  1.1392 +			tmp.x = rects[i].x;
  1.1393 +			tmp.w = rects[i].w;
  1.1394 +			for ( x = 0; x <= rects[i].w / 256; x++ )
  1.1395 +			{
  1.1396 +				update.x = tmp.x;
  1.1397 +				update.y = tmp.y;
  1.1398 +				update.w = tmp.w;
  1.1399 +				update.h = tmp.h;
  1.1400 +
  1.1401 +				if ( update.w > 256 )
  1.1402 +					update.w = 256;
  1.1403 +
  1.1404 +				if ( update.h > 256 )
  1.1405 +					update.h = 256;
  1.1406 +			
  1.1407 +				this->glFlush();
  1.1408 +				this->glTexSubImage2D( 
  1.1409 +					GL_TEXTURE_2D, 
  1.1410 +					0, 
  1.1411 +					0, 
  1.1412 +					0, 
  1.1413 +					update.w, 
  1.1414 +					update.h, 
  1.1415 +					this->is_32bit? GL_RGBA : GL_RGB,
  1.1416 +#ifdef GL_VERSION_1_2
  1.1417 +					this->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
  1.1418 +#else
  1.1419 +					GL_UNSIGNED_BYTE,
  1.1420 +#endif
  1.1421 +					(Uint8 *)this->screen->pixels + 
  1.1422 +						this->screen->format->BytesPerPixel * update.x + 
  1.1423 +						update.y * this->screen->pitch );
  1.1424 +	
  1.1425 +				this->glFlush();
  1.1426 +				/*
  1.1427 +				* Note the parens around the function name:
  1.1428 +				* This is because some OpenGL implementations define glTexCoord etc 
  1.1429 +				* as macros, and we don't want them expanded here.
  1.1430 +				*/
  1.1431 +				this->glBegin(GL_TRIANGLE_STRIP);
  1.1432 +					(this->glTexCoord2f)( 0.0, 0.0 );	
  1.1433 +					(this->glVertex2i)( update.x, update.y );
  1.1434 +					(this->glTexCoord2f)( (float)(update.w / 256.0), 0.0 );	
  1.1435 +					(this->glVertex2i)( update.x + update.w, update.y );
  1.1436 +					(this->glTexCoord2f)( 0.0, (float)(update.h / 256.0) );
  1.1437 +					(this->glVertex2i)( update.x, update.y + update.h );
  1.1438 +					(this->glTexCoord2f)( (float)(update.w / 256.0), (float)(update.h / 256.0) );	
  1.1439 +					(this->glVertex2i)( update.x + update.w	, update.y + update.h );
  1.1440 +				this->glEnd();	
  1.1441 +			
  1.1442 +				tmp.x += 256;
  1.1443 +				tmp.w -= 256;
  1.1444 +			}
  1.1445 +			tmp.y += 256;
  1.1446 +			tmp.h -= 256;
  1.1447 +		}
  1.1448 +	}
  1.1449 +#endif
  1.1450 +}
  1.1451 +
  1.1452 +/* Lock == save current state */
  1.1453 +void SDL_GL_Lock()
  1.1454 +{
  1.1455 +#ifdef HAVE_OPENGL
  1.1456 +	lock_count--;
  1.1457 +	if (lock_count==-1)
  1.1458 +	{
  1.1459 +		SDL_VideoDevice *this = current_video;
  1.1460 +
  1.1461 +		this->glPushAttrib( GL_ALL_ATTRIB_BITS );	/* TODO: narrow range of what is saved */
  1.1462 +		this->glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
  1.1463 +
  1.1464 +		this->glEnable(GL_TEXTURE_2D);
  1.1465 +		this->glEnable(GL_BLEND);
  1.1466 +		this->glDisable(GL_FOG);
  1.1467 +		this->glDisable(GL_ALPHA_TEST);
  1.1468 +		this->glDisable(GL_DEPTH_TEST);
  1.1469 +		this->glDisable(GL_SCISSOR_TEST);	
  1.1470 +		this->glDisable(GL_STENCIL_TEST);
  1.1471 +		this->glDisable(GL_CULL_FACE);
  1.1472 +
  1.1473 +		this->glBindTexture( GL_TEXTURE_2D, this->texture );
  1.1474 +		this->glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  1.1475 +		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  1.1476 +		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  1.1477 +		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  1.1478 +		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
  1.1479 +
  1.1480 +		this->glPixelStorei( GL_UNPACK_ROW_LENGTH, this->screen->pitch / this->screen->format->BytesPerPixel );
  1.1481 +		this->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1.1482 +		(this->glColor4f)(1.0, 1.0, 1.0, 1.0);		/* Solaris workaround */
  1.1483 +
  1.1484 +		this->glViewport(0, 0, this->screen->w, this->screen->h);
  1.1485 +		this->glMatrixMode(GL_PROJECTION);
  1.1486 +		this->glPushMatrix();
  1.1487 +		this->glLoadIdentity();
  1.1488 +
  1.1489 +		this->glOrtho(0.0, (GLdouble) this->screen->w, (GLdouble) this->screen->h, 0.0, 0.0, 1.0);
  1.1490 +
  1.1491 +		this->glMatrixMode(GL_MODELVIEW);
  1.1492 +		this->glPushMatrix();
  1.1493 +		this->glLoadIdentity();
  1.1494 +	}
  1.1495 +#endif
  1.1496 +}
  1.1497 +
  1.1498 +/* Unlock == restore saved state */
  1.1499 +void SDL_GL_Unlock()
  1.1500 +{
  1.1501 +#ifdef HAVE_OPENGL
  1.1502 +	lock_count++;
  1.1503 +	if (lock_count==0)
  1.1504 +	{
  1.1505 +		SDL_VideoDevice *this = current_video;
  1.1506 +
  1.1507 +		this->glPopMatrix();
  1.1508 +		this->glMatrixMode(GL_PROJECTION);
  1.1509 +		this->glPopMatrix();
  1.1510 +
  1.1511 +		this->glPopClientAttrib();
  1.1512 +		this->glPopAttrib();
  1.1513 +	}
  1.1514 +#endif
  1.1515 +}
  1.1516 +
  1.1517 +/*
  1.1518 + * Sets/Gets the title and icon text of the display window, if any.
  1.1519 + */
  1.1520 +void SDL_WM_SetCaption (const char *title, const char *icon)
  1.1521 +{
  1.1522 +	SDL_VideoDevice *video = current_video;
  1.1523 +	SDL_VideoDevice *this  = current_video;
  1.1524 +
  1.1525 +	if ( title ) {
  1.1526 +		if ( wm_title ) {
  1.1527 +			free(wm_title);
  1.1528 +		}
  1.1529 +		wm_title = (char *)malloc(strlen(title)+1);
  1.1530 +		if ( wm_title != NULL ) {
  1.1531 +			strcpy(wm_title, title);
  1.1532 +		}
  1.1533 +	}
  1.1534 +	if ( icon ) {
  1.1535 +		if ( wm_icon ) {
  1.1536 +			free(wm_icon);
  1.1537 +		}
  1.1538 +		wm_icon = (char *)malloc(strlen(icon)+1);
  1.1539 +		if ( wm_icon != NULL ) {
  1.1540 +			strcpy(wm_icon, icon);
  1.1541 +		}
  1.1542 +	}
  1.1543 +	if ( (title || icon) && video && (video->SetCaption != NULL) ) {
  1.1544 +		video->SetCaption(this, wm_title, wm_icon);
  1.1545 +	}
  1.1546 +}
  1.1547 +void SDL_WM_GetCaption (char **title, char **icon)
  1.1548 +{
  1.1549 +	if ( title ) {
  1.1550 +		*title = wm_title;
  1.1551 +	}
  1.1552 +	if ( icon ) {
  1.1553 +		*icon = wm_icon;
  1.1554 +	}
  1.1555 +}
  1.1556 +
  1.1557 +/* Utility function used by SDL_WM_SetIcon() */
  1.1558 +static void CreateMaskFromColorKey(SDL_Surface *icon, Uint8 *mask)
  1.1559 +{
  1.1560 +	int x, y;
  1.1561 +	Uint32 colorkey;
  1.1562 +#define SET_MASKBIT(icon, x, y, mask) \
  1.1563 +	mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
  1.1564 +
  1.1565 +	colorkey = icon->format->colorkey;
  1.1566 +	switch (icon->format->BytesPerPixel) {
  1.1567 +		case 1: { Uint8 *pixels;
  1.1568 +			for ( y=0; y<icon->h; ++y ) {
  1.1569 +				pixels = (Uint8 *)icon->pixels + y*icon->pitch;
  1.1570 +				for ( x=0; x<icon->w; ++x ) {
  1.1571 +					if ( *pixels++ == colorkey ) {
  1.1572 +						SET_MASKBIT(icon, x, y, mask);
  1.1573 +					}
  1.1574 +				}
  1.1575 +			}
  1.1576 +		}
  1.1577 +		break;
  1.1578 +
  1.1579 +		case 2: { Uint16 *pixels;
  1.1580 +			for ( y=0; y<icon->h; ++y ) {
  1.1581 +				pixels = (Uint16 *)icon->pixels +
  1.1582 +				                   y*icon->pitch/2;
  1.1583 +				for ( x=0; x<icon->w; ++x ) {
  1.1584 +					if ( *pixels++ == colorkey ) {
  1.1585 +						SET_MASKBIT(icon, x, y, mask);
  1.1586 +					}
  1.1587 +				}
  1.1588 +			}
  1.1589 +		}
  1.1590 +		break;
  1.1591 +
  1.1592 +		case 4: { Uint32 *pixels;
  1.1593 +			for ( y=0; y<icon->h; ++y ) {
  1.1594 +				pixels = (Uint32 *)icon->pixels +
  1.1595 +				                   y*icon->pitch/4;
  1.1596 +				for ( x=0; x<icon->w; ++x ) {
  1.1597 +					if ( *pixels++ == colorkey ) {
  1.1598 +						SET_MASKBIT(icon, x, y, mask);
  1.1599 +					}
  1.1600 +				}
  1.1601 +			}
  1.1602 +		}
  1.1603 +		break;
  1.1604 +	}
  1.1605 +}
  1.1606 +
  1.1607 +/*
  1.1608 + * Sets the window manager icon for the display window.
  1.1609 + */
  1.1610 +void SDL_WM_SetIcon (SDL_Surface *icon, Uint8 *mask)
  1.1611 +{
  1.1612 +	SDL_VideoDevice *video = current_video;
  1.1613 +	SDL_VideoDevice *this  = current_video;
  1.1614 +
  1.1615 +	if ( icon && video->SetIcon ) {
  1.1616 +		/* Generate a mask if necessary, and create the icon! */
  1.1617 +		if ( mask == NULL ) {
  1.1618 +			int mask_len = icon->h*(icon->w+7)/8;
  1.1619 +			mask = (Uint8 *)malloc(mask_len);
  1.1620 +			if ( mask == NULL ) {
  1.1621 +				return;
  1.1622 +			}
  1.1623 +			memset(mask, ~0, mask_len);
  1.1624 +			if ( icon->flags & SDL_SRCCOLORKEY ) {
  1.1625 +				CreateMaskFromColorKey(icon, mask);
  1.1626 +			}
  1.1627 +			video->SetIcon(video, icon, mask);
  1.1628 +			free(mask);
  1.1629 +		} else {
  1.1630 +			video->SetIcon(this, icon, mask);
  1.1631 +		}
  1.1632 +	}
  1.1633 +}
  1.1634 +
  1.1635 +/*
  1.1636 + * Grab or ungrab the keyboard and mouse input.
  1.1637 + * This function returns the final grab mode after calling the
  1.1638 + * driver dependent function.
  1.1639 + */
  1.1640 +static SDL_GrabMode SDL_WM_GrabInputRaw(SDL_GrabMode mode)
  1.1641 +{
  1.1642 +	SDL_VideoDevice *video = current_video;
  1.1643 +	SDL_VideoDevice *this  = current_video;
  1.1644 +
  1.1645 +	/* Only do something if we have support for grabs */
  1.1646 +	if ( video->GrabInput == NULL ) {
  1.1647 +		return(video->input_grab);
  1.1648 +	}
  1.1649 +
  1.1650 +	/* If the final grab mode if off, only then do we actually grab */
  1.1651 +#ifdef DEBUG_GRAB
  1.1652 +  printf("SDL_WM_GrabInputRaw(%d) ... ", mode);
  1.1653 +#endif
  1.1654 +	if ( mode == SDL_GRAB_OFF ) {
  1.1655 +		if ( video->input_grab != SDL_GRAB_OFF ) {
  1.1656 +			mode = video->GrabInput(this, mode);
  1.1657 +		}
  1.1658 +	} else {
  1.1659 +		if ( video->input_grab == SDL_GRAB_OFF ) {
  1.1660 +			mode = video->GrabInput(this, mode);
  1.1661 +		}
  1.1662 +	}
  1.1663 +	if ( mode != video->input_grab ) {
  1.1664 +		video->input_grab = mode;
  1.1665 +		if ( video->CheckMouseMode ) {
  1.1666 +			video->CheckMouseMode(this);
  1.1667 +		}
  1.1668 +	}
  1.1669 +#ifdef DEBUG_GRAB
  1.1670 +  printf("Final mode %d\n", video->input_grab);
  1.1671 +#endif
  1.1672 +
  1.1673 +	/* Return the final grab state */
  1.1674 +	if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1.1675 +		mode -= SDL_GRAB_FULLSCREEN;
  1.1676 +	}
  1.1677 +	return(mode);
  1.1678 +}
  1.1679 +SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode)
  1.1680 +{
  1.1681 +	SDL_VideoDevice *video = current_video;
  1.1682 +
  1.1683 +    /* If the video isn't initialized yet, we can't do anything */
  1.1684 +    if ( ! video ) {
  1.1685 +        return SDL_GRAB_OFF;
  1.1686 +    }
  1.1687 +
  1.1688 +	/* Return the current mode on query */
  1.1689 +	if ( mode == SDL_GRAB_QUERY ) {
  1.1690 +		mode = video->input_grab;
  1.1691 +		if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1.1692 +			mode -= SDL_GRAB_FULLSCREEN;
  1.1693 +		}
  1.1694 +		return(mode);
  1.1695 +	}
  1.1696 +
  1.1697 +#ifdef DEBUG_GRAB
  1.1698 +  printf("SDL_WM_GrabInput(%d) ... ", mode);
  1.1699 +#endif
  1.1700 +	/* If the video surface is fullscreen, we always grab */
  1.1701 +	if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1.1702 +		mode -= SDL_GRAB_FULLSCREEN;
  1.1703 +	}
  1.1704 +	if ( SDL_VideoSurface && (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
  1.1705 +		mode += SDL_GRAB_FULLSCREEN;
  1.1706 +	}
  1.1707 +	return(SDL_WM_GrabInputRaw(mode));
  1.1708 +}
  1.1709 +static SDL_GrabMode SDL_WM_GrabInputOff(void)
  1.1710 +{
  1.1711 +	SDL_GrabMode mode;
  1.1712 +
  1.1713 +	/* First query the current grab state */
  1.1714 +	mode = SDL_WM_GrabInput(SDL_GRAB_QUERY);
  1.1715 +
  1.1716 +	/* Now explicitly turn off input grab */
  1.1717 +	SDL_WM_GrabInputRaw(SDL_GRAB_OFF);
  1.1718 +
  1.1719 +	/* Return the old state */
  1.1720 +	return(mode);
  1.1721 +}
  1.1722 +
  1.1723 +/*
  1.1724 + * Iconify the window in window managed environments.
  1.1725 + * A successful iconification will result in an SDL_APPACTIVE loss event.
  1.1726 + */
  1.1727 +int SDL_WM_IconifyWindow(void)
  1.1728 +{
  1.1729 +	SDL_VideoDevice *video = current_video;
  1.1730 +	SDL_VideoDevice *this  = current_video;
  1.1731 +	int retval;
  1.1732 +
  1.1733 +	retval = 0;
  1.1734 +	if ( video->IconifyWindow ) {
  1.1735 +		retval = video->IconifyWindow(this);
  1.1736 +	}
  1.1737 +	return(retval);
  1.1738 +}
  1.1739 +
  1.1740 +/*
  1.1741 + * Toggle fullscreen mode
  1.1742 + */
  1.1743 +int SDL_WM_ToggleFullScreen(SDL_Surface *surface)
  1.1744 +{
  1.1745 +	SDL_VideoDevice *video = current_video;
  1.1746 +	SDL_VideoDevice *this  = current_video;
  1.1747 +	int toggled;
  1.1748 +
  1.1749 +	toggled = 0;
  1.1750 +	if ( SDL_PublicSurface && (surface == SDL_PublicSurface) &&
  1.1751 +	     video->ToggleFullScreen ) {
  1.1752 +		if ( surface->flags & SDL_FULLSCREEN ) {
  1.1753 +			toggled = video->ToggleFullScreen(this, 0);
  1.1754 +			if ( toggled ) {
  1.1755 +				SDL_VideoSurface->flags &= ~SDL_FULLSCREEN;
  1.1756 +				SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
  1.1757 +			}
  1.1758 +		} else {
  1.1759 +			toggled = video->ToggleFullScreen(this, 1);
  1.1760 +			if ( toggled ) {
  1.1761 +				SDL_VideoSurface->flags |= SDL_FULLSCREEN;
  1.1762 +				SDL_PublicSurface->flags |= SDL_FULLSCREEN;
  1.1763 +			}
  1.1764 +		}
  1.1765 +		/* Double-check the grab state inside SDL_WM_GrabInput() */
  1.1766 +		if ( toggled ) {
  1.1767 +			SDL_WM_GrabInput(video->input_grab);
  1.1768 +		}
  1.1769 +	}
  1.1770 +	return(toggled);
  1.1771 +}
  1.1772 +
  1.1773 +/*
  1.1774 + * Get some platform dependent window manager information
  1.1775 + */
  1.1776 +int SDL_GetWMInfo (SDL_SysWMinfo *info)
  1.1777 +{
  1.1778 +	SDL_VideoDevice *video = current_video;
  1.1779 +	SDL_VideoDevice *this  = current_video;
  1.1780 +
  1.1781 +	if ( video && video->GetWMInfo ) {
  1.1782 +		return(video->GetWMInfo(this, info));
  1.1783 +	} else {
  1.1784 +		return(0);
  1.1785 +	}
  1.1786 +}