src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 02 Apr 2009 04:06:55 +0000
branchSDL-1.2
changeset 4165 3b8ac3d311a2
parent 4159 a1b03ba2fcd0
child 4249 429c8dd3175d
permissions -rw-r--r--
Hello.

This patch provides basic support for video on the Sony PS3
Linux framebuffer. Scaling, format-conversion, and drawing is
done from the SPEs, so there is little performance impact to
PPE applications. This is by no means production quality code,
but it is a very good start and a good example of how to use the
PS3's hardware capabilities to accelerate video playback on
the box.

The driver has been verified to work with ffplay, mplayer and xine.
This piece of software has been developed at the IBM R&D Lab
in Boeblingen, Germany and is now returned to the community.

Enjoy !

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