Subversion Repositories Kolibri OS

Rev

Rev 8218 | Rev 9769 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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