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

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

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