src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 11 Apr 2004 19:54:40 +0000
changeset 883 50f5a29c6a17
parent 853 dddfc37e1f65
child 910 4ab6d1fd028f
permissions -rw-r--r--
Date: Sat, 10 Apr 2004 02:25:33 -0400
From: Glenn Maynard
To: sdl@libsdl.org
Subject: [SDL] SDL_SetVideoMode() failing and not setting an error (patch)

Running an OpenGL SDL application off 1.2.7, at SDL_InitSubSystem(SDL_INIT_VIDEO) time:

Warning: Unable to initialize AAlib mouseUsing AAlib driver: Slang driver 1.0 (slang)

SDL_SetVideoMode then fails; SDL_GetError() returns "".

The installation problem is straightforward: X (the higher priority
driver) isn't running, so SDL is falling back on aalib. However,
no error is being set when aalib fails to initialize. This also
happens with the svgalib driver.

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