symbian-qemu-0.9.1-12/libsdl-trunk/src/video/dga/SDL_dgavideo.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2     SDL - Simple DirectMedia Layer
       
     3     Copyright (C) 1997-2006 Sam Lantinga
       
     4 
       
     5     This library is free software; you can redistribute it and/or
       
     6     modify it under the terms of the GNU Lesser General Public
       
     7     License as published by the Free Software Foundation; either
       
     8     version 2.1 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     Lesser General Public License for more details.
       
    14 
       
    15     You should have received a copy of the GNU Lesser General Public
       
    16     License along with this library; if not, write to the Free Software
       
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    18 
       
    19     Sam Lantinga
       
    20     slouken@libsdl.org
       
    21 */
       
    22 #include "SDL_config.h"
       
    23 
       
    24 /* DGA 2.0 based SDL video driver implementation.
       
    25 */
       
    26 
       
    27 #include <stdio.h>
       
    28 
       
    29 #include <X11/Xlib.h>
       
    30 #include "../Xext/extensions/xf86dga.h"
       
    31 
       
    32 #include "SDL_video.h"
       
    33 #include "SDL_mouse.h"
       
    34 #include "../SDL_sysvideo.h"
       
    35 #include "../SDL_pixels_c.h"
       
    36 #include "../../events/SDL_events_c.h"
       
    37 #include "SDL_dgavideo.h"
       
    38 #include "SDL_dgamouse_c.h"
       
    39 #include "SDL_dgaevents_c.h"
       
    40 
       
    41 /* get function pointers... */
       
    42 #include "../x11/SDL_x11dyn.h"
       
    43 
       
    44 /*#define DGA_DEBUG*/
       
    45 
       
    46 /* Heheh we're using X11 event code */
       
    47 extern void X11_SaveScreenSaver(Display *display, int *saved_timeout, BOOL *dpms);
       
    48 extern void X11_DisableScreenSaver(Display *display);
       
    49 extern void X11_RestoreScreenSaver(Display *display, int saved_timeout, BOOL dpms);
       
    50 
       
    51 /* Initialization/Query functions */
       
    52 static int DGA_VideoInit(_THIS, SDL_PixelFormat *vformat);
       
    53 static SDL_Rect **DGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
       
    54 static SDL_Surface *DGA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
       
    55 static int DGA_SetColors(_THIS, int firstcolor, int ncolors,
       
    56 			 SDL_Color *colors);
       
    57 static int DGA_SetGammaRamp(_THIS, Uint16 *ramp);
       
    58 static void DGA_VideoQuit(_THIS);
       
    59 
       
    60 /* Hardware surface functions */
       
    61 static int DGA_InitHWSurfaces(_THIS, SDL_Surface *screen, Uint8 *base, int size);
       
    62 static void DGA_FreeHWSurfaces(_THIS);
       
    63 static int DGA_AllocHWSurface(_THIS, SDL_Surface *surface);
       
    64 static int DGA_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);
       
    65 static int DGA_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst);
       
    66 static int DGA_LockHWSurface(_THIS, SDL_Surface *surface);
       
    67 static void DGA_UnlockHWSurface(_THIS, SDL_Surface *surface);
       
    68 static void DGA_FreeHWSurface(_THIS, SDL_Surface *surface);
       
    69 static int DGA_FlipHWSurface(_THIS, SDL_Surface *surface);
       
    70 
       
    71 /* DGA driver bootstrap functions */
       
    72 
       
    73 static int DGA_Available(void)
       
    74 {
       
    75 	const char *display = NULL;
       
    76 	Display *dpy = NULL;
       
    77 	int available = 0;
       
    78 
       
    79 	/* The driver is available is available if the display is local
       
    80 	   and the DGA 2.0+ extension is available, and we can map mem.
       
    81 	*/
       
    82 	if ( SDL_X11_LoadSymbols() ) {
       
    83 		if ( (SDL_strncmp(XDisplayName(display), ":", 1) == 0) ||
       
    84 		     (SDL_strncmp(XDisplayName(display), "unix:", 5) == 0) ) {
       
    85 			dpy = XOpenDisplay(display);
       
    86 			if ( dpy ) {
       
    87 				int events, errors, major, minor;
       
    88 
       
    89 				if ( SDL_NAME(XDGAQueryExtension)(dpy, &events, &errors) &&
       
    90 				     SDL_NAME(XDGAQueryVersion)(dpy, &major, &minor) ) {
       
    91 					int screen;
       
    92 
       
    93 					screen = DefaultScreen(dpy);
       
    94 					if ( (major >= 2) && 
       
    95 					     SDL_NAME(XDGAOpenFramebuffer)(dpy, screen) ) {
       
    96 						available = 1;
       
    97 						SDL_NAME(XDGACloseFramebuffer)(dpy, screen);
       
    98 					}
       
    99 				}
       
   100 				XCloseDisplay(dpy);
       
   101 			}
       
   102 		}
       
   103 		SDL_X11_UnloadSymbols();
       
   104 	}
       
   105 	return(available);
       
   106 }
       
   107 
       
   108 static void DGA_DeleteDevice(SDL_VideoDevice *device)
       
   109 {
       
   110 	if (device != NULL) {
       
   111 		SDL_free(device->hidden);
       
   112 		SDL_free(device);
       
   113 		SDL_X11_UnloadSymbols();
       
   114 	}
       
   115 }
       
   116 
       
   117 static SDL_VideoDevice *DGA_CreateDevice(int devindex)
       
   118 {
       
   119 	SDL_VideoDevice *device = NULL;
       
   120 
       
   121 	/* Initialize all variables that we clean on shutdown */
       
   122 	if (SDL_X11_LoadSymbols()) {
       
   123 		device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
       
   124 		if ( device ) {
       
   125 			SDL_memset(device, 0, (sizeof *device));
       
   126 			device->hidden = (struct SDL_PrivateVideoData *)
       
   127 					SDL_malloc((sizeof *device->hidden));
       
   128 		}
       
   129 		if ( (device == NULL) || (device->hidden == NULL) ) {
       
   130 			SDL_OutOfMemory();
       
   131 			if ( device ) {
       
   132 				SDL_free(device);
       
   133 			}
       
   134 			SDL_X11_UnloadSymbols();
       
   135 			return(0);
       
   136 		}
       
   137 		SDL_memset(device->hidden, 0, (sizeof *device->hidden));
       
   138 
       
   139 		/* Set the function pointers */
       
   140 		device->VideoInit = DGA_VideoInit;
       
   141 		device->ListModes = DGA_ListModes;
       
   142 		device->SetVideoMode = DGA_SetVideoMode;
       
   143 		device->SetColors = DGA_SetColors;
       
   144 		device->UpdateRects = NULL;
       
   145 		device->VideoQuit = DGA_VideoQuit;
       
   146 		device->AllocHWSurface = DGA_AllocHWSurface;
       
   147 		device->CheckHWBlit = DGA_CheckHWBlit;
       
   148 		device->FillHWRect = DGA_FillHWRect;
       
   149 		device->SetHWColorKey = NULL;
       
   150 		device->SetHWAlpha = NULL;
       
   151 		device->LockHWSurface = DGA_LockHWSurface;
       
   152 		device->UnlockHWSurface = DGA_UnlockHWSurface;
       
   153 		device->FlipHWSurface = DGA_FlipHWSurface;
       
   154 		device->FreeHWSurface = DGA_FreeHWSurface;
       
   155 		device->SetGammaRamp = DGA_SetGammaRamp;
       
   156 		device->GetGammaRamp = NULL;
       
   157 		device->SetCaption = NULL;
       
   158 		device->SetIcon = NULL;
       
   159 		device->IconifyWindow = NULL;
       
   160 		device->GrabInput = NULL;
       
   161 		device->GetWMInfo = NULL;
       
   162 		device->InitOSKeymap = DGA_InitOSKeymap;
       
   163 		device->PumpEvents = DGA_PumpEvents;
       
   164 
       
   165 		device->free = DGA_DeleteDevice;
       
   166 	}
       
   167 
       
   168 	return device;
       
   169 }
       
   170 
       
   171 VideoBootStrap DGA_bootstrap = {
       
   172 	"dga", "XFree86 DGA 2.0",
       
   173 	DGA_Available, DGA_CreateDevice
       
   174 };
       
   175 
       
   176 static int DGA_AddMode(_THIS, int bpp, int w, int h)
       
   177 {
       
   178 	SDL_Rect *mode;
       
   179 	int index;
       
   180 	int next_mode;
       
   181 
       
   182 	/* Check to see if we already have this mode */
       
   183 	if ( bpp < 8 ) {  /* Not supported */
       
   184 		return(0);
       
   185 	}
       
   186 	index = ((bpp+7)/8)-1;
       
   187 	if ( SDL_nummodes[index] > 0 ) {
       
   188 		mode = SDL_modelist[index][SDL_nummodes[index]-1];
       
   189 		if ( (mode->w == w) && (mode->h == h) ) {
       
   190 			return(0);
       
   191 		}
       
   192 	}
       
   193 
       
   194 	/* Set up the new video mode rectangle */
       
   195 	mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
       
   196 	if ( mode == NULL ) {
       
   197 		SDL_OutOfMemory();
       
   198 		return(-1);
       
   199 	}
       
   200 	mode->x = 0;
       
   201 	mode->y = 0;
       
   202 	mode->w = w;
       
   203 	mode->h = h;
       
   204 
       
   205 	/* Allocate the new list of modes, and fill in the new mode */
       
   206 	next_mode = SDL_nummodes[index];
       
   207 	SDL_modelist[index] = (SDL_Rect **)
       
   208 	       SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
       
   209 	if ( SDL_modelist[index] == NULL ) {
       
   210 		SDL_OutOfMemory();
       
   211 		SDL_nummodes[index] = 0;
       
   212 		SDL_free(mode);
       
   213 		return(-1);
       
   214 	}
       
   215 	SDL_modelist[index][next_mode] = mode;
       
   216 	SDL_modelist[index][next_mode+1] = NULL;
       
   217 	SDL_nummodes[index]++;
       
   218 
       
   219 	return(0);
       
   220 }
       
   221 
       
   222 /* This whole function is a hack. :) */
       
   223 static Uint32 get_video_size(_THIS)
       
   224 {
       
   225 	/* This is a non-exported function from libXxf86dga.a */
       
   226 	extern unsigned char *SDL_NAME(XDGAGetMappedMemory)(int screen);
       
   227 	FILE *proc;
       
   228 	unsigned long mem;
       
   229 	unsigned start, stop;
       
   230 	char line[BUFSIZ];
       
   231 	Uint32 size;
       
   232 
       
   233 	mem = (unsigned long)SDL_NAME(XDGAGetMappedMemory)(DGA_Screen);
       
   234 	size = 0;
       
   235 	proc = fopen("/proc/self/maps", "r");
       
   236 	if ( proc ) {
       
   237 		while ( fgets(line, sizeof(line)-1, proc) ) {
       
   238 			SDL_sscanf(line, "%x-%x", &start, &stop);
       
   239 			if ( start == mem ) {
       
   240 				size = (Uint32)((stop-start)/1024);
       
   241 				break;
       
   242 			}
       
   243 		}
       
   244 		fclose(proc);
       
   245 	}
       
   246 	return(size);
       
   247 }
       
   248 
       
   249 #ifdef DGA_DEBUG
       
   250 static void PrintMode(SDL_NAME(XDGAMode) *mode)
       
   251 {
       
   252 	printf("Mode: %s (%dx%d) at %d bpp (%f refresh, %d pitch) num: %d\n",
       
   253 		mode->name,
       
   254 		mode->viewportWidth, mode->viewportHeight,
       
   255 		mode->depth == 24 ? mode->bitsPerPixel : mode->depth,
       
   256 		mode->verticalRefresh, mode->bytesPerScanline, mode->num);
       
   257 	printf("\tRGB: 0x%8.8x 0x%8.8x 0x%8.8x (%d - %s)\n",
       
   258 		mode->redMask, mode->greenMask, mode->blueMask,
       
   259 		mode->visualClass,
       
   260 		mode->visualClass == TrueColor ? "truecolor" :
       
   261 		mode->visualClass == DirectColor ? "directcolor" :
       
   262 		mode->visualClass == PseudoColor ? "pseudocolor" : "unknown");
       
   263 	printf("\tFlags: ");
       
   264 	if ( mode->flags & XDGAConcurrentAccess )
       
   265 		printf(" XDGAConcurrentAccess");
       
   266 	if ( mode->flags & XDGASolidFillRect )
       
   267 		printf(" XDGASolidFillRect");
       
   268 	if ( mode->flags & XDGABlitRect )
       
   269 		printf(" XDGABlitRect");
       
   270 	if ( mode->flags & XDGABlitTransRect )
       
   271 		printf(" XDGABlitTransRect");
       
   272 	if ( mode->flags & XDGAPixmap )
       
   273 		printf(" XDGAPixmap");
       
   274 	if ( mode->flags & XDGAInterlaced )
       
   275 		printf(" XDGAInterlaced");
       
   276 	if ( mode->flags & XDGADoublescan )
       
   277 		printf(" XDGADoublescan");
       
   278 	if ( mode->viewportFlags & XDGAFlipRetrace )
       
   279 		printf(" XDGAFlipRetrace");
       
   280 	if ( mode->viewportFlags & XDGAFlipImmediate )
       
   281 		printf(" XDGAFlipImmediate");
       
   282 	printf("\n");
       
   283 }
       
   284 #endif /* DGA_DEBUG */
       
   285 
       
   286 static int cmpmodes(const void *va, const void *vb)
       
   287 {
       
   288     const SDL_NAME(XDGAMode) *a = (const SDL_NAME(XDGAMode) *)va;
       
   289     const SDL_NAME(XDGAMode) *b = (const SDL_NAME(XDGAMode) *)vb;
       
   290 
       
   291     if ( (a->viewportWidth == b->viewportWidth) &&
       
   292          (b->viewportHeight == a->viewportHeight) ) {
       
   293         /* Prefer 32 bpp over 24 bpp, 16 bpp over 15 bpp */
       
   294         int a_bpp = a->depth == 24 ? a->bitsPerPixel : a->depth;
       
   295         int b_bpp = b->depth == 24 ? b->bitsPerPixel : b->depth;
       
   296         if ( a_bpp != b_bpp ) {
       
   297             return b_bpp - a_bpp;
       
   298         }
       
   299         /* Prefer DirectColor visuals, for gamma support */
       
   300         if ( a->visualClass == DirectColor && b->visualClass != DirectColor )
       
   301             return -1;
       
   302         if ( b->visualClass == DirectColor && a->visualClass != DirectColor )
       
   303             return 1;
       
   304         /* Maintain server refresh rate sorting */
       
   305         return a->num - b->num;
       
   306     } else if ( a->viewportWidth == b->viewportWidth ) {
       
   307         return b->viewportHeight - a->viewportHeight;
       
   308     } else {
       
   309         return b->viewportWidth - a->viewportWidth;
       
   310     }
       
   311 }
       
   312 static void UpdateHWInfo(_THIS, SDL_NAME(XDGAMode) *mode)
       
   313 {
       
   314 	this->info.wm_available = 0;
       
   315 	this->info.hw_available = 1;
       
   316 	if ( mode->flags & XDGABlitRect ) {
       
   317 		this->info.blit_hw = 1;
       
   318 	} else {
       
   319 		this->info.blit_hw = 0;
       
   320 	}
       
   321 	if ( mode->flags & XDGABlitTransRect ) {
       
   322 		this->info.blit_hw_CC = 1;
       
   323 	} else {
       
   324 		this->info.blit_hw_CC = 0;
       
   325 	}
       
   326 	if ( mode->flags & XDGASolidFillRect ) {
       
   327 		this->info.blit_fill = 1;
       
   328 	} else {
       
   329 		this->info.blit_fill = 0;
       
   330 	}
       
   331 	this->info.video_mem = get_video_size(this);
       
   332 }
       
   333 
       
   334 static int DGA_VideoInit(_THIS, SDL_PixelFormat *vformat)
       
   335 {
       
   336 	const char *display;
       
   337 	int event_base, error_base;
       
   338 	int major_version, minor_version;
       
   339 	Visual *visual;
       
   340 	SDL_NAME(XDGAMode) *modes;
       
   341 	int i, num_modes;
       
   342 
       
   343 	/* Open the X11 display */
       
   344 	display = NULL;		/* Get it from DISPLAY environment variable */
       
   345 
       
   346 	DGA_Display = XOpenDisplay(display);
       
   347 	if ( DGA_Display == NULL ) {
       
   348 		SDL_SetError("Couldn't open X11 display");
       
   349 		return(-1);
       
   350 	}
       
   351 
       
   352 	/* Check for the DGA extension */
       
   353 	if ( ! SDL_NAME(XDGAQueryExtension)(DGA_Display, &event_base, &error_base) ||
       
   354 	     ! SDL_NAME(XDGAQueryVersion)(DGA_Display, &major_version, &minor_version) ) {
       
   355 		SDL_SetError("DGA extension not available");
       
   356 		XCloseDisplay(DGA_Display);
       
   357 		return(-1);
       
   358 	}
       
   359 	if ( major_version < 2 ) {
       
   360 		SDL_SetError("DGA driver requires DGA 2.0 or newer");
       
   361 		XCloseDisplay(DGA_Display);
       
   362 		return(-1);
       
   363 	}
       
   364 	DGA_event_base = event_base;
       
   365 
       
   366 	/* Determine the current screen size */
       
   367 	this->info.current_w = DisplayWidth(DGA_Display, DGA_Screen);
       
   368 	this->info.current_h = DisplayHeight(DGA_Display, DGA_Screen);
       
   369 
       
   370 	/* Determine the current screen depth */
       
   371 	visual = DefaultVisual(DGA_Display, DGA_Screen);
       
   372 	{
       
   373 		XPixmapFormatValues *pix_format;
       
   374 		int i, num_formats;
       
   375 
       
   376 		vformat->BitsPerPixel = DefaultDepth(DGA_Display, DGA_Screen);
       
   377 		pix_format = XListPixmapFormats(DGA_Display, &num_formats);
       
   378 		if ( pix_format == NULL ) {
       
   379 			SDL_SetError("Couldn't determine screen formats");
       
   380 			XCloseDisplay(DGA_Display);
       
   381 			return(-1);
       
   382 		}
       
   383 		for ( i=0; i<num_formats; ++i ) {
       
   384 			if ( vformat->BitsPerPixel == pix_format[i].depth )
       
   385 				break;
       
   386 		}
       
   387 		if ( i != num_formats )
       
   388 			vformat->BitsPerPixel = pix_format[i].bits_per_pixel;
       
   389 		XFree((char *)pix_format);
       
   390 	}
       
   391 	if ( vformat->BitsPerPixel > 8 ) {
       
   392 		vformat->Rmask = visual->red_mask;
       
   393 		vformat->Gmask = visual->green_mask;
       
   394 		vformat->Bmask = visual->blue_mask;
       
   395 	}
       
   396 
       
   397 	/* Open access to the framebuffer */
       
   398 	if ( ! SDL_NAME(XDGAOpenFramebuffer)(DGA_Display, DGA_Screen) ) {
       
   399 		SDL_SetError("Unable to map the video memory");
       
   400 		XCloseDisplay(DGA_Display);
       
   401 		return(-1);
       
   402 	}
       
   403 
       
   404 	/* Save DPMS and screensaver settings */
       
   405 	X11_SaveScreenSaver(DGA_Display, &screensaver_timeout, &dpms_enabled);
       
   406 	X11_DisableScreenSaver(DGA_Display);
       
   407 
       
   408 	/* Query for the list of available video modes */
       
   409 	modes = SDL_NAME(XDGAQueryModes)(DGA_Display, DGA_Screen, &num_modes);
       
   410 	SDL_qsort(modes, num_modes, sizeof *modes, cmpmodes);
       
   411 	for ( i=0; i<num_modes; ++i ) {
       
   412 		if ( ((modes[i].visualClass == PseudoColor) ||
       
   413 		      (modes[i].visualClass == DirectColor) ||
       
   414 		      (modes[i].visualClass == TrueColor)) && 
       
   415 		     !(modes[i].flags & (XDGAInterlaced|XDGADoublescan)) ) {
       
   416 #ifdef DGA_DEBUG
       
   417 			PrintMode(&modes[i]);
       
   418 #endif
       
   419 			DGA_AddMode(this, modes[i].bitsPerPixel,
       
   420 			            modes[i].viewportWidth,
       
   421 			            modes[i].viewportHeight);
       
   422 		}
       
   423 	}
       
   424 	UpdateHWInfo(this, modes);
       
   425 	XFree(modes);
       
   426 
       
   427 	/* Create the hardware surface lock mutex */
       
   428 	hw_lock = SDL_CreateMutex();
       
   429 	if ( hw_lock == NULL ) {
       
   430 		SDL_SetError("Unable to create lock mutex");
       
   431 		DGA_VideoQuit(this);
       
   432 		return(-1);
       
   433 	}
       
   434 
       
   435 #ifdef LOCK_DGA_DISPLAY
       
   436 	/* Create the event lock so we're thread-safe.. :-/ */
       
   437 	event_lock = SDL_CreateMutex();
       
   438 #endif /* LOCK_DGA_DISPLAY */
       
   439 
       
   440 	/* We're done! */
       
   441 	return(0);
       
   442 }
       
   443 
       
   444 SDL_Rect **DGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
       
   445 {
       
   446 	return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
       
   447 }
       
   448 
       
   449 /* Various screen update functions available */
       
   450 static void DGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
       
   451 
       
   452 SDL_Surface *DGA_SetVideoMode(_THIS, SDL_Surface *current,
       
   453 				int width, int height, int bpp, Uint32 flags)
       
   454 {
       
   455 	SDL_NAME(XDGAMode) *modes;
       
   456 	int i, num_modes;
       
   457 	SDL_NAME(XDGADevice) *mode;
       
   458 	int screen_len;
       
   459 	Uint8 *surfaces_mem;
       
   460 	int surfaces_len;
       
   461 
       
   462 	/* Free any previous colormap */
       
   463 	if ( DGA_colormap ) {
       
   464 		XFreeColormap(DGA_Display, DGA_colormap);
       
   465 		DGA_colormap = 0;
       
   466 	}
       
   467 
       
   468 	/* Search for a matching video mode */
       
   469 	modes = SDL_NAME(XDGAQueryModes)(DGA_Display, DGA_Screen, &num_modes);
       
   470 	SDL_qsort(modes, num_modes, sizeof *modes, cmpmodes);
       
   471 	for ( i=0; i<num_modes; ++i ) {
       
   472 		int depth;
       
   473 
       
   474 		depth = modes[i].depth;
       
   475 		if ( depth == 24 ) { /* Distinguish between 24 and 32 bpp */
       
   476 			depth = modes[i].bitsPerPixel;
       
   477 		}
       
   478 		if ( (depth == bpp) &&
       
   479 		     (modes[i].viewportWidth == width) &&
       
   480 		     (modes[i].viewportHeight == height) &&
       
   481 		     ((modes[i].visualClass == PseudoColor) ||
       
   482 		      (modes[i].visualClass == DirectColor) ||
       
   483 		      (modes[i].visualClass == TrueColor)) &&
       
   484 		     !(modes[i].flags & (XDGAInterlaced|XDGADoublescan)) ) {
       
   485 			break;
       
   486 		}
       
   487 	}
       
   488 	if ( i == num_modes ) {
       
   489 		SDL_SetError("No matching video mode found");
       
   490 		return(NULL);
       
   491 	}
       
   492 #ifdef DGA_DEBUG
       
   493 	PrintMode(&modes[i]);
       
   494 #endif
       
   495 
       
   496 	/* Set the video mode */
       
   497 	mode = SDL_NAME(XDGASetMode)(DGA_Display, DGA_Screen, modes[i].num);
       
   498 	XFree(modes);
       
   499 	if ( mode == NULL ) {
       
   500 		SDL_SetError("Unable to switch to requested mode");
       
   501 		return(NULL);
       
   502 	}
       
   503 	DGA_visualClass = mode->mode.visualClass;
       
   504 	memory_base = (Uint8 *)mode->data;
       
   505 	memory_pitch = mode->mode.bytesPerScanline;
       
   506 
       
   507 	/* Set up the new mode framebuffer */
       
   508 	current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE);
       
   509 	current->w = mode->mode.viewportWidth;
       
   510 	current->h = mode->mode.viewportHeight;
       
   511 	current->pitch = memory_pitch;
       
   512 	current->pixels = memory_base;
       
   513 	if ( ! SDL_ReallocFormat(current, mode->mode.bitsPerPixel,
       
   514 	                                  mode->mode.redMask,
       
   515 	                                  mode->mode.greenMask,
       
   516 	                                  mode->mode.blueMask, 0) ) {
       
   517 		return(NULL);
       
   518 	}
       
   519 	screen_len = current->h*current->pitch;
       
   520 
       
   521 	/* Create a colormap if necessary */
       
   522 	if ( (DGA_visualClass == PseudoColor) ||
       
   523              (DGA_visualClass == DirectColor) ) {
       
   524 		DGA_colormap = SDL_NAME(XDGACreateColormap)(DGA_Display, DGA_Screen,
       
   525 							mode, AllocAll);
       
   526 		if ( DGA_visualClass == PseudoColor ) {
       
   527 			current->flags |= SDL_HWPALETTE;
       
   528 		} else {
       
   529 	    		/* Initialize the colormap to the identity mapping */
       
   530 	    		SDL_GetGammaRamp(0, 0, 0);
       
   531 	    		this->screen = current;
       
   532 	    		DGA_SetGammaRamp(this, this->gamma);
       
   533 			this->screen = NULL;
       
   534 		}
       
   535 	} else {
       
   536 		DGA_colormap = SDL_NAME(XDGACreateColormap)(DGA_Display, DGA_Screen,
       
   537 							mode, AllocNone);
       
   538 	}
       
   539 	SDL_NAME(XDGAInstallColormap)(DGA_Display, DGA_Screen, DGA_colormap);
       
   540 
       
   541 	/* Update the hardware capabilities */
       
   542 	UpdateHWInfo(this, &mode->mode);
       
   543 
       
   544 	/* Set up the information for hardware surfaces */
       
   545 	surfaces_mem = (Uint8 *)current->pixels + screen_len;
       
   546 	surfaces_len = (mode->mode.imageHeight*current->pitch - screen_len);
       
   547 
       
   548 	/* Update for double-buffering, if we can */
       
   549 	SDL_NAME(XDGASetViewport)(DGA_Display, DGA_Screen, 0, 0, XDGAFlipRetrace);
       
   550 	if ( flags & SDL_DOUBLEBUF ) {
       
   551 		if ( mode->mode.imageHeight >= (current->h*2) ) {
       
   552 			current->flags |= SDL_DOUBLEBUF;
       
   553 			flip_page = 0;
       
   554 			flip_yoffset[0] = 0;
       
   555 			flip_yoffset[1] = current->h;
       
   556 			flip_address[0] = memory_base;
       
   557 			flip_address[1] = memory_base+screen_len;
       
   558 			surfaces_mem += screen_len;
       
   559 			surfaces_len -= screen_len;
       
   560 		}
       
   561 	}
       
   562 
       
   563 	/* Allocate memory tracking for hardware surfaces */
       
   564 	DGA_FreeHWSurfaces(this);
       
   565 	if ( surfaces_len < 0 ) {
       
   566 		surfaces_len = 0;
       
   567 	}
       
   568 	DGA_InitHWSurfaces(this, current, surfaces_mem, surfaces_len);
       
   569 
       
   570 	/* Expose the back buffer as surface memory */
       
   571 	if ( current->flags & SDL_DOUBLEBUF ) {
       
   572 		this->screen = current;
       
   573 		DGA_FlipHWSurface(this, current);
       
   574 		this->screen = NULL;
       
   575 	}
       
   576 
       
   577 	/* Set the update rectangle function */
       
   578 	this->UpdateRects = DGA_DirectUpdate;
       
   579 
       
   580 	/* Enable mouse and keyboard support */
       
   581 	{ long input_mask;
       
   582 	  input_mask = (KeyPressMask | KeyReleaseMask);
       
   583 	  input_mask |= (ButtonPressMask | ButtonReleaseMask);
       
   584 	  input_mask |= PointerMotionMask;
       
   585 	  SDL_NAME(XDGASelectInput)(DGA_Display, DGA_Screen, input_mask);
       
   586 	}
       
   587 
       
   588 	/* We're done */
       
   589 	return(current);
       
   590 }
       
   591 
       
   592 #ifdef DGA_DEBUG
       
   593 static void DGA_DumpHWSurfaces(_THIS)
       
   594 {
       
   595 	vidmem_bucket *bucket;
       
   596 
       
   597 	printf("Memory left: %d (%d total)\n", surfaces_memleft, surfaces_memtotal);
       
   598 	printf("\n");
       
   599 	printf("         Base  Size\n");
       
   600 	for ( bucket=&surfaces; bucket; bucket=bucket->next ) {
       
   601 		printf("Bucket:  %p, %d (%s)\n", bucket->base, bucket->size, bucket->used ? "used" : "free");
       
   602 		if ( bucket->prev ) {
       
   603 			if ( bucket->base != bucket->prev->base+bucket->prev->size ) {
       
   604 				printf("Warning, corrupt bucket list! (prev)\n");
       
   605 			}
       
   606 		} else {
       
   607 			if ( bucket != &surfaces ) {
       
   608 				printf("Warning, corrupt bucket list! (!prev)\n");
       
   609 			}
       
   610 		}
       
   611 		if ( bucket->next ) {
       
   612 			if ( bucket->next->base != bucket->base+bucket->size ) {
       
   613 				printf("Warning, corrupt bucket list! (next)\n");
       
   614 			}
       
   615 		}
       
   616 	}
       
   617 	printf("\n");
       
   618 }
       
   619 #endif
       
   620 
       
   621 static int DGA_InitHWSurfaces(_THIS, SDL_Surface *screen, Uint8 *base, int size)
       
   622 {
       
   623 	vidmem_bucket *bucket;
       
   624 
       
   625 	surfaces_memtotal = size;
       
   626 	surfaces_memleft = size;
       
   627 
       
   628 	if ( surfaces_memleft > 0 ) {
       
   629 		bucket = (vidmem_bucket *)SDL_malloc(sizeof(*bucket));
       
   630 		if ( bucket == NULL ) {
       
   631 			SDL_OutOfMemory();
       
   632 			return(-1);
       
   633 		}
       
   634 		bucket->prev = &surfaces;
       
   635 		bucket->used = 0;
       
   636 		bucket->dirty = 0;
       
   637 		bucket->base = base;
       
   638 		bucket->size = size;
       
   639 		bucket->next = NULL;
       
   640 	} else {
       
   641 		bucket = NULL;
       
   642 	}
       
   643 
       
   644 	surfaces.prev = NULL;
       
   645 	surfaces.used = 1;
       
   646 	surfaces.dirty = 0;
       
   647 	surfaces.base = screen->pixels;
       
   648 	surfaces.size = (unsigned int)((long)base - (long)surfaces.base);
       
   649 	surfaces.next = bucket;
       
   650 	screen->hwdata = (struct private_hwdata *)&surfaces;
       
   651 	return(0);
       
   652 }
       
   653 static void DGA_FreeHWSurfaces(_THIS)
       
   654 {
       
   655 	vidmem_bucket *bucket, *freeable;
       
   656 
       
   657 	bucket = surfaces.next;
       
   658 	while ( bucket ) {
       
   659 		freeable = bucket;
       
   660 		bucket = bucket->next;
       
   661 		SDL_free(freeable);
       
   662 	}
       
   663 	surfaces.next = NULL;
       
   664 }
       
   665 
       
   666 static __inline__ void DGA_AddBusySurface(SDL_Surface *surface)
       
   667 {
       
   668 	((vidmem_bucket *)surface->hwdata)->dirty = 1;
       
   669 }
       
   670 
       
   671 static __inline__ int DGA_IsSurfaceBusy(SDL_Surface *surface)
       
   672 {
       
   673 	return ((vidmem_bucket *)surface->hwdata)->dirty;
       
   674 }
       
   675 
       
   676 static __inline__ void DGA_WaitBusySurfaces(_THIS)
       
   677 {
       
   678 	vidmem_bucket *bucket;
       
   679 
       
   680 	/* Wait for graphic operations to complete */
       
   681 	SDL_NAME(XDGASync)(DGA_Display, DGA_Screen);
       
   682 
       
   683 	/* Clear all surface dirty bits */
       
   684 	for ( bucket=&surfaces; bucket; bucket=bucket->next ) {
       
   685 		bucket->dirty = 0;
       
   686 	}
       
   687 }
       
   688 
       
   689 static int DGA_AllocHWSurface(_THIS, SDL_Surface *surface)
       
   690 {
       
   691 	vidmem_bucket *bucket;
       
   692 	int size;
       
   693 	int extra;
       
   694 	int retval = 0;
       
   695 
       
   696 /* Temporarily, we only allow surfaces the same width as display.
       
   697    Some blitters require the pitch between two hardware surfaces
       
   698    to be the same.  Others have interesting alignment restrictions.
       
   699 */
       
   700 if ( surface->pitch > SDL_VideoSurface->pitch ) {
       
   701 	SDL_SetError("Surface requested wider than screen");
       
   702 	return(-1);
       
   703 }
       
   704 surface->pitch = SDL_VideoSurface->pitch;
       
   705 	size = surface->h * surface->pitch;
       
   706 #ifdef DGA_DEBUG
       
   707 	fprintf(stderr, "Allocating bucket of %d bytes\n", size);
       
   708 #endif
       
   709 	LOCK_DISPLAY();
       
   710 
       
   711 	/* Quick check for available mem */
       
   712 	if ( size > surfaces_memleft ) {
       
   713 		SDL_SetError("Not enough video memory");
       
   714 		retval = -1;
       
   715 		goto done;
       
   716 	}
       
   717 
       
   718 	/* Search for an empty bucket big enough */
       
   719 	for ( bucket=&surfaces; bucket; bucket=bucket->next ) {
       
   720 		if ( ! bucket->used && (size <= bucket->size) ) {
       
   721 			break;
       
   722 		}
       
   723 	}
       
   724 	if ( bucket == NULL ) {
       
   725 		SDL_SetError("Video memory too fragmented");
       
   726 		retval = -1;
       
   727 		goto done;
       
   728 	}
       
   729 
       
   730 	/* Create a new bucket for left-over memory */
       
   731 	extra = (bucket->size - size);
       
   732 	if ( extra ) {
       
   733 		vidmem_bucket *newbucket;
       
   734 
       
   735 #ifdef DGA_DEBUG
       
   736 	fprintf(stderr, "Adding new free bucket of %d bytes\n", extra);
       
   737 #endif
       
   738 		newbucket = (vidmem_bucket *)SDL_malloc(sizeof(*newbucket));
       
   739 		if ( newbucket == NULL ) {
       
   740 			SDL_OutOfMemory();
       
   741 			retval = -1;
       
   742 			goto done;
       
   743 		}
       
   744 		newbucket->prev = bucket;
       
   745 		newbucket->used = 0;
       
   746 		newbucket->base = bucket->base+size;
       
   747 		newbucket->size = extra;
       
   748 		newbucket->next = bucket->next;
       
   749 		if ( bucket->next ) {
       
   750 			bucket->next->prev = newbucket;
       
   751 		}
       
   752 		bucket->next = newbucket;
       
   753 	}
       
   754 
       
   755 	/* Set the current bucket values and return it! */
       
   756 	bucket->used = 1;
       
   757 	bucket->size = size;
       
   758 	bucket->dirty = 0;
       
   759 #ifdef DGA_DEBUG
       
   760 	fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base);
       
   761 #endif
       
   762 	surfaces_memleft -= size;
       
   763 	surface->flags |= SDL_HWSURFACE;
       
   764 	surface->pixels = bucket->base;
       
   765 	surface->hwdata = (struct private_hwdata *)bucket;
       
   766 done:
       
   767 	UNLOCK_DISPLAY();
       
   768 	return(retval);
       
   769 }
       
   770 static void DGA_FreeHWSurface(_THIS, SDL_Surface *surface)
       
   771 {
       
   772 	vidmem_bucket *bucket, *freeable;
       
   773 
       
   774 	/* Wait for any pending operations involving this surface */
       
   775 	if ( DGA_IsSurfaceBusy(surface) ) {
       
   776 		LOCK_DISPLAY();
       
   777 		DGA_WaitBusySurfaces(this);
       
   778 		UNLOCK_DISPLAY();
       
   779 	}
       
   780 
       
   781 	/* Look for the bucket in the current list */
       
   782 	for ( bucket=&surfaces; bucket; bucket=bucket->next ) {
       
   783 		if ( bucket == (vidmem_bucket *)surface->hwdata ) {
       
   784 			break;
       
   785 		}
       
   786 	}
       
   787 	if ( bucket && bucket->used ) {
       
   788 		/* Add the memory back to the total */
       
   789 #ifdef DGA_DEBUG
       
   790 	printf("Freeing bucket of %d bytes\n", bucket->size);
       
   791 #endif
       
   792 		surfaces_memleft += bucket->size;
       
   793 
       
   794 		/* Can we merge the space with surrounding buckets? */
       
   795 		bucket->used = 0;
       
   796 		if ( bucket->next && ! bucket->next->used ) {
       
   797 #ifdef DGA_DEBUG
       
   798 	printf("Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size);
       
   799 #endif
       
   800 			freeable = bucket->next;
       
   801 			bucket->size += bucket->next->size;
       
   802 			bucket->next = bucket->next->next;
       
   803 			if ( bucket->next ) {
       
   804 				bucket->next->prev = bucket;
       
   805 			}
       
   806 			SDL_free(freeable);
       
   807 		}
       
   808 		if ( bucket->prev && ! bucket->prev->used ) {
       
   809 #ifdef DGA_DEBUG
       
   810 	printf("Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size);
       
   811 #endif
       
   812 			freeable = bucket;
       
   813 			bucket->prev->size += bucket->size;
       
   814 			bucket->prev->next = bucket->next;
       
   815 			if ( bucket->next ) {
       
   816 				bucket->next->prev = bucket->prev;
       
   817 			}
       
   818 			SDL_free(freeable);
       
   819 		}
       
   820 	}
       
   821 	surface->pixels = NULL;
       
   822 	surface->hwdata = NULL;
       
   823 }
       
   824 
       
   825 static __inline__ void DGA_dst_to_xy(_THIS, SDL_Surface *dst, int *x, int *y)
       
   826 {
       
   827 	*x = (long)((Uint8 *)dst->pixels - memory_base)%memory_pitch;
       
   828 	*y = (long)((Uint8 *)dst->pixels - memory_base)/memory_pitch;
       
   829 }
       
   830 
       
   831 static int DGA_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color)
       
   832 {
       
   833 	int x, y;
       
   834 	unsigned int w, h;
       
   835 
       
   836 	/* Don't fill the visible part of the screen, wait until flipped */
       
   837 	LOCK_DISPLAY();
       
   838 	if ( was_flipped && (dst == this->screen) ) {
       
   839 		while ( SDL_NAME(XDGAGetViewportStatus)(DGA_Display, DGA_Screen) )
       
   840 			/* Keep waiting for the hardware ... */ ;
       
   841 		was_flipped = 0;
       
   842 	}
       
   843 	DGA_dst_to_xy(this, dst, &x, &y);
       
   844 	x += rect->x;
       
   845 	y += rect->y;
       
   846 	w = rect->w;
       
   847 	h = rect->h;
       
   848 #if 0
       
   849   printf("Hardware accelerated rectangle fill: %dx%d at %d,%d\n", w, h, x, y);
       
   850 #endif
       
   851 	SDL_NAME(XDGAFillRectangle)(DGA_Display, DGA_Screen, x, y, w, h, color);
       
   852 	if ( !(this->screen->flags & SDL_DOUBLEBUF) ) {
       
   853 		XFlush(DGA_Display);
       
   854 	}
       
   855 	DGA_AddBusySurface(dst);
       
   856 	UNLOCK_DISPLAY();
       
   857 	return(0);
       
   858 }
       
   859 
       
   860 static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
       
   861                        SDL_Surface *dst, SDL_Rect *dstrect)
       
   862 {
       
   863 	SDL_VideoDevice *this;
       
   864 	int srcx, srcy;
       
   865 	int dstx, dsty;
       
   866 	unsigned int w, h;
       
   867 
       
   868 	this = current_video;
       
   869 	/* Don't blit to the visible part of the screen, wait until flipped */
       
   870 	LOCK_DISPLAY();
       
   871 	if ( was_flipped && (dst == this->screen) ) {
       
   872 		while ( SDL_NAME(XDGAGetViewportStatus)(DGA_Display, DGA_Screen) )
       
   873 			/* Keep waiting for the hardware ... */ ;
       
   874 		was_flipped = 0;
       
   875 	}
       
   876 	DGA_dst_to_xy(this, src, &srcx, &srcy);
       
   877 	srcx += srcrect->x;
       
   878 	srcy += srcrect->y;
       
   879 	DGA_dst_to_xy(this, dst, &dstx, &dsty);
       
   880 	dstx += dstrect->x;
       
   881 	dsty += dstrect->y;
       
   882 	w = srcrect->w;
       
   883 	h = srcrect->h;
       
   884 #if 0
       
   885   printf("Blitting %dx%d from %d,%d to %d,%d\n", w, h, srcx, srcy, dstx, dsty);
       
   886 #endif
       
   887 	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
       
   888 		SDL_NAME(XDGACopyTransparentArea)(DGA_Display, DGA_Screen,
       
   889 			srcx, srcy, w, h, dstx, dsty, src->format->colorkey);
       
   890 	} else {
       
   891 		SDL_NAME(XDGACopyArea)(DGA_Display, DGA_Screen,
       
   892 			srcx, srcy, w, h, dstx, dsty);
       
   893 	}
       
   894 	if ( !(this->screen->flags & SDL_DOUBLEBUF) ) {
       
   895 		XFlush(DGA_Display);
       
   896 	}
       
   897 	DGA_AddBusySurface(src);
       
   898 	DGA_AddBusySurface(dst);
       
   899 	UNLOCK_DISPLAY();
       
   900 	return(0);
       
   901 }
       
   902 
       
   903 static int DGA_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
       
   904 {
       
   905 	int accelerated;
       
   906 
       
   907 	/* Set initial acceleration on */
       
   908 	src->flags |= SDL_HWACCEL;
       
   909 
       
   910 	/* Set the surface attributes */
       
   911 	if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
       
   912 		if ( ! this->info.blit_hw_A ) {
       
   913 			src->flags &= ~SDL_HWACCEL;
       
   914 		}
       
   915 	}
       
   916 	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
       
   917 		if ( ! this->info.blit_hw_CC ) {
       
   918 			src->flags &= ~SDL_HWACCEL;
       
   919 		}
       
   920 	}
       
   921 
       
   922 	/* Check to see if final surface blit is accelerated */
       
   923 	accelerated = !!(src->flags & SDL_HWACCEL);
       
   924 	if ( accelerated ) {
       
   925 		src->map->hw_blit = HWAccelBlit;
       
   926 	}
       
   927 	return(accelerated);
       
   928 }
       
   929 
       
   930 static __inline__ void DGA_WaitFlip(_THIS)
       
   931 {
       
   932 	if ( was_flipped ) {
       
   933 		while ( SDL_NAME(XDGAGetViewportStatus)(DGA_Display, DGA_Screen) )
       
   934 			/* Keep waiting for the hardware ... */ ;
       
   935 		was_flipped = 0;
       
   936 	}
       
   937 }
       
   938 
       
   939 static int DGA_LockHWSurface(_THIS, SDL_Surface *surface)
       
   940 {
       
   941 	if ( surface == this->screen ) {
       
   942 		SDL_mutexP(hw_lock);
       
   943 		LOCK_DISPLAY();
       
   944 		if ( DGA_IsSurfaceBusy(surface) ) {
       
   945 			DGA_WaitBusySurfaces(this);
       
   946 		}
       
   947 		DGA_WaitFlip(this);
       
   948 		UNLOCK_DISPLAY();
       
   949 	} else {
       
   950 		if ( DGA_IsSurfaceBusy(surface) ) {
       
   951 			LOCK_DISPLAY();
       
   952 			DGA_WaitBusySurfaces(this);
       
   953 			UNLOCK_DISPLAY();
       
   954 		}
       
   955 	}
       
   956 	return(0);
       
   957 }
       
   958 static void DGA_UnlockHWSurface(_THIS, SDL_Surface *surface)
       
   959 {
       
   960 	if ( surface == this->screen ) {
       
   961 		SDL_mutexV(hw_lock);
       
   962 	}
       
   963 }
       
   964 
       
   965 static int DGA_FlipHWSurface(_THIS, SDL_Surface *surface)
       
   966 {
       
   967 	/* Wait for vertical retrace and then flip display */
       
   968 	LOCK_DISPLAY();
       
   969 	if ( DGA_IsSurfaceBusy(this->screen) ) {
       
   970 		DGA_WaitBusySurfaces(this);
       
   971 	}
       
   972 	DGA_WaitFlip(this);
       
   973 	SDL_NAME(XDGASetViewport)(DGA_Display, DGA_Screen,
       
   974 	                0, flip_yoffset[flip_page], XDGAFlipRetrace);
       
   975 	XFlush(DGA_Display);
       
   976 	UNLOCK_DISPLAY();
       
   977 	was_flipped = 1;
       
   978 	flip_page = !flip_page;
       
   979 
       
   980 	surface->pixels = flip_address[flip_page];
       
   981 	return(0);
       
   982 }
       
   983 
       
   984 static void DGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
       
   985 {
       
   986 	/* The application is already updating the visible video memory */
       
   987 	return;
       
   988 }
       
   989 
       
   990 static int DGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
       
   991 {
       
   992         int i;
       
   993 	XColor  *xcmap;
       
   994 
       
   995 	/* This happens on initialization */
       
   996 	if ( ! DGA_colormap ) {
       
   997 		return(0);
       
   998 	}
       
   999 	xcmap = SDL_stack_alloc(XColor, ncolors);
       
  1000 	for ( i=0; i<ncolors; ++i ) {
       
  1001 		xcmap[i].pixel = firstcolor + i;
       
  1002 		xcmap[i].red   = (colors[i].r<<8)|colors[i].r;
       
  1003 		xcmap[i].green = (colors[i].g<<8)|colors[i].g;
       
  1004 		xcmap[i].blue  = (colors[i].b<<8)|colors[i].b;
       
  1005 		xcmap[i].flags = (DoRed|DoGreen|DoBlue);
       
  1006 	}
       
  1007 	LOCK_DISPLAY();
       
  1008 	XStoreColors(DGA_Display, DGA_colormap, xcmap, ncolors);
       
  1009 	XSync(DGA_Display, False);
       
  1010 	UNLOCK_DISPLAY();
       
  1011 	SDL_stack_free(xcmap);
       
  1012 
       
  1013 	/* That was easy. :) */
       
  1014 	return(1);
       
  1015 }
       
  1016 
       
  1017 int DGA_SetGammaRamp(_THIS, Uint16 *ramp)
       
  1018 {
       
  1019 	int i, ncolors;
       
  1020 	XColor xcmap[256];
       
  1021 
       
  1022 	/* See if actually setting the gamma is supported */
       
  1023 	if ( DGA_visualClass != DirectColor ) {
       
  1024 	    SDL_SetError("Gamma correction not supported on this visual");
       
  1025 	    return(-1);
       
  1026 	}
       
  1027 
       
  1028 	/* Calculate the appropriate palette for the given gamma ramp */
       
  1029 	if ( this->screen->format->BitsPerPixel <= 16 ) {
       
  1030 		ncolors = 64; /* Is this right? */
       
  1031 	} else {
       
  1032 		ncolors = 256;
       
  1033 	}
       
  1034 	for ( i=0; i<ncolors; ++i ) {
       
  1035 		Uint8 c = (256 * i / ncolors);
       
  1036 		xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c);
       
  1037 		xcmap[i].red   = ramp[0*256+c];
       
  1038 		xcmap[i].green = ramp[1*256+c];
       
  1039 		xcmap[i].blue  = ramp[2*256+c];
       
  1040 		xcmap[i].flags = (DoRed|DoGreen|DoBlue);
       
  1041 	}
       
  1042 	LOCK_DISPLAY();
       
  1043 	XStoreColors(DGA_Display, DGA_colormap, xcmap, ncolors);
       
  1044 	XSync(DGA_Display, False);
       
  1045 	UNLOCK_DISPLAY();
       
  1046 	return(0);
       
  1047 }
       
  1048 
       
  1049 void DGA_VideoQuit(_THIS)
       
  1050 {
       
  1051 	int i, j;
       
  1052 
       
  1053 	if ( DGA_Display ) {
       
  1054 		/* Free colormap, if necessary */
       
  1055 		if ( DGA_colormap ) {
       
  1056 			XFreeColormap(DGA_Display, DGA_colormap);
       
  1057 			DGA_colormap = 0;
       
  1058 		}
       
  1059 
       
  1060 		/* Unmap memory and reset video mode */
       
  1061 		SDL_NAME(XDGACloseFramebuffer)(DGA_Display, DGA_Screen);
       
  1062 		if ( this->screen ) {
       
  1063 			/* Tell SDL not to free the pixels */
       
  1064 			DGA_FreeHWSurface(this, this->screen);
       
  1065 		}
       
  1066 		SDL_NAME(XDGASetMode)(DGA_Display, DGA_Screen, 0);
       
  1067 
       
  1068 		/* Clear the lock mutex */
       
  1069 		if ( hw_lock != NULL ) {
       
  1070 			SDL_DestroyMutex(hw_lock);
       
  1071 			hw_lock = NULL;
       
  1072 		}
       
  1073 #ifdef LOCK_DGA_DISPLAY
       
  1074 		if ( event_lock != NULL ) {
       
  1075 			SDL_DestroyMutex(event_lock);
       
  1076 			event_lock = NULL;
       
  1077 		}
       
  1078 #endif /* LOCK_DGA_DISPLAY */
       
  1079 
       
  1080 		/* Clean up defined video modes */
       
  1081 		for ( i=0; i<NUM_MODELISTS; ++i ) {
       
  1082 			if ( SDL_modelist[i] != NULL ) {
       
  1083 				for ( j=0; SDL_modelist[i][j]; ++j ) {
       
  1084 					SDL_free(SDL_modelist[i][j]);
       
  1085 				}
       
  1086 				SDL_free(SDL_modelist[i]);
       
  1087 				SDL_modelist[i] = NULL;
       
  1088 			}
       
  1089 		}
       
  1090 
       
  1091 		/* Clean up the memory bucket list */
       
  1092 		DGA_FreeHWSurfaces(this);
       
  1093 
       
  1094 		/* Restore DPMS and screensaver settings */
       
  1095 		X11_RestoreScreenSaver(DGA_Display, screensaver_timeout, dpms_enabled);
       
  1096 
       
  1097 		/* Close up the display */
       
  1098 		XCloseDisplay(DGA_Display);
       
  1099 	}
       
  1100 }