src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 27 Sep 2009 05:18:43 +0000
branchSDL-1.2
changeset 4249 429c8dd3175d
parent 4165 3b8ac3d311a2
child 4295 d62725f761a1
permissions -rw-r--r--
Fixed bug #713

Don't clamp the mouse coordinates to the video surface size, instead clamp them to the last known window size.

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