src/video/SDL_video.c
author Patrice Mandin <patmandin@gmail.com>
Sun, 12 Jun 2005 16:12:55 +0000
changeset 1076 8d3b95ece376
parent 1052 68f607298ca9
child 1133 609c060fd2a2
permissions -rw-r--r--
[PATCH] SDL_GetVideoMode() do not find the best video mode

The current GetVideoMode() function stops at the first mode which has any
dimensions smaller than the one asked, and gives the previous in the list.

If I ask 336x224 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200
SDL will give me 640x400, because 640x200 as height smaller than what I
asked.

However the best mode is the smaller which has both dimensions bigger
than the one asked (384x240 in my example).

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