src/video/SDL_video.c
author Patrice Mandin <patmandin@gmail.com>
Thu, 19 Jan 2006 21:28:52 +0000
changeset 1257 448a9a64537b
parent 1254 c2ee0f7fa711
child 1266 a7bea6db3c3e
permissions -rw-r--r--
[PATCH] SDL_GetVideoMode() does not find best mode, part 2

Following commit 1.51, I come accross a problem when SDL must choose between
several video modes that could suit the one asked.

If I ask 320x240 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200

The smallest selectables modes are 384x240 and 320x400. And SDL choose the later
in this list, but 384x240 is more suitable. So I added a check to compare
the pixel count (surface) of modes, and select the one which has the smallest
pixel count.

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