src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 18 Jul 2004 19:46:38 +0000
changeset 910 4ab6d1fd028f
parent 883 50f5a29c6a17
child 916 46916168361d
permissions -rw-r--r--
Date: Sat, 26 Jun 2004 14:58:42 +0300
From: "Mike Gorchak"
Subject: QNX 6.3 fixes for SDL

Sam, I've added new OpenGL framework for SDL, which appeared in the new QNX version - 6.3. I've leave compatibility with previous QNX versions. And I've moved all GL specific functions to the separate module, like it done for the other platforms.

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