src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Apr 2003 15:46:56 +0000
changeset 610 95433459fbd2
parent 580 be6495850a62
child 630 550bccdf04bd
permissions -rw-r--r--
Date: Mon, 14 Apr 2003 22:08:27 +0100
From: Patrice Mandin
Subject: [SDL][PATCH] 2 patches for sdl

Here are 2 patches for SDL:

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