src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 29 Dec 2011 04:57:42 -0500
branchSDL-1.2
changeset 6111 2280c0954104
parent 4399 ae9c094e9200
child 6125 760a3162e180
permissions -rw-r--r--
Fixed bug 1346

alarantalara@gmail.com 2011-12-19 20:43:13 PST

On little endian systems using the Quartz code, an unusual set of RBGA masks is
used when using the windowed video mode.
This set is not taken into account in SDL_DisplayFormatAlpha and so it converts
the supplied surface to a format that does not match the video surface,
preventing fast blitting.

This was observed in recent builds of Battle for Wesnoth when SDL was updated
to cover the problem when switching to full screen in Lion
(https://gna.org/bugs/?18319).

You can observe the performance issue if you download Wesnoth 1.9.13 for OS X
at
http://sourceforge.net/projects/wesnoth/files/wesnoth/wesnoth-1.9.13/Wesnoth_1.9.13.dmg/download
and replace the included SDL library with any build of SDL 1.2.14 or later. (I
have already patched the included version, so the problem is not observable
without replacement.)

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