src/video/windib/SDL_dibvideo.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 20 Aug 2002 00:20:06 +0000
changeset 453 a6fa62b1be09
parent 448 323c766f5a46
child 514 1080bfc4aa96
permissions -rw-r--r--
Updated for embedded Visual C++ 4.0
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999  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@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 #include <stdio.h>
    29 #include <stdlib.h>
    30 #include <malloc.h>
    31 #include <windows.h>
    32 
    33 /* Not yet in the mingw32 cross-compile headers */
    34 #ifndef CDS_FULLSCREEN
    35 #define CDS_FULLSCREEN	4
    36 #endif
    37 
    38 #include "SDL.h"
    39 #include "SDL_mutex.h"
    40 #include "SDL_syswm.h"
    41 #include "SDL_sysvideo.h"
    42 #include "SDL_sysevents.h"
    43 #include "SDL_events_c.h"
    44 #include "SDL_pixels_c.h"
    45 #include "SDL_dibvideo.h"
    46 #include "SDL_syswm_c.h"
    47 #include "SDL_sysmouse_c.h"
    48 #include "SDL_dibevents_c.h"
    49 #include "SDL_wingl_c.h"
    50 
    51 #ifdef _WIN32_WCE
    52 #define NO_GETDIBITS
    53 #define NO_CHANGEDISPLAYSETTINGS
    54 #define NO_GAMMA_SUPPORT
    55 #endif
    56 #ifndef WS_MAXIMIZE
    57 #define WS_MAXIMIZE		0
    58 #endif
    59 #ifndef SWP_NOCOPYBITS
    60 #define SWP_NOCOPYBITS	0
    61 #endif
    62 #ifndef PC_NOCOLLAPSE
    63 #define PC_NOCOLLAPSE	0
    64 #endif
    65 
    66 /* Initialization/Query functions */
    67 static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat);
    68 static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
    69 SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
    70 static int DIB_SetColors(_THIS, int firstcolor, int ncolors,
    71 			 SDL_Color *colors);
    72 static void DIB_CheckGamma(_THIS);
    73 void DIB_SwapGamma(_THIS);
    74 void DIB_QuitGamma(_THIS);
    75 int DIB_SetGammaRamp(_THIS, Uint16 *ramp);
    76 int DIB_GetGammaRamp(_THIS, Uint16 *ramp);
    77 static void DIB_VideoQuit(_THIS);
    78 
    79 /* Hardware surface functions */
    80 static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface);
    81 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface);
    82 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface);
    83 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface);
    84 
    85 /* Windows message handling functions */
    86 static void DIB_RealizePalette(_THIS);
    87 static void DIB_PaletteChanged(_THIS, HWND window);
    88 static void DIB_WinPAINT(_THIS, HDC hdc);
    89 
    90 /* helper fn */
    91 static int DIB_SussScreenDepth();
    92 
    93 /* DIB driver bootstrap functions */
    94 
    95 static int DIB_Available(void)
    96 {
    97 	return(1);
    98 }
    99 
   100 static void DIB_DeleteDevice(SDL_VideoDevice *device)
   101 {
   102 	if ( device ) {
   103 		if ( device->hidden ) {
   104 			free(device->hidden);
   105 		}
   106 		if ( device->gl_data ) {
   107 			free(device->gl_data);
   108 		}
   109 		free(device);
   110 	}
   111 }
   112 
   113 static SDL_VideoDevice *DIB_CreateDevice(int devindex)
   114 {
   115 	SDL_VideoDevice *device;
   116 
   117 	/* Initialize all variables that we clean on shutdown */
   118 	device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
   119 	if ( device ) {
   120 		memset(device, 0, (sizeof *device));
   121 		device->hidden = (struct SDL_PrivateVideoData *)
   122 				malloc((sizeof *device->hidden));
   123 		device->gl_data = (struct SDL_PrivateGLData *)
   124 				malloc((sizeof *device->gl_data));
   125 	}
   126 	if ( (device == NULL) || (device->hidden == NULL) ||
   127 		                 (device->gl_data == NULL) ) {
   128 		SDL_OutOfMemory();
   129 		DIB_DeleteDevice(device);
   130 		return(NULL);
   131 	}
   132 	memset(device->hidden, 0, (sizeof *device->hidden));
   133 	memset(device->gl_data, 0, (sizeof *device->gl_data));
   134 
   135 	/* Set the function pointers */
   136 	device->VideoInit = DIB_VideoInit;
   137 	device->ListModes = DIB_ListModes;
   138 	device->SetVideoMode = DIB_SetVideoMode;
   139 	device->UpdateMouse = WIN_UpdateMouse;
   140 	device->SetColors = DIB_SetColors;
   141 	device->UpdateRects = NULL;
   142 	device->VideoQuit = DIB_VideoQuit;
   143 	device->AllocHWSurface = DIB_AllocHWSurface;
   144 	device->CheckHWBlit = NULL;
   145 	device->FillHWRect = NULL;
   146 	device->SetHWColorKey = NULL;
   147 	device->SetHWAlpha = NULL;
   148 	device->LockHWSurface = DIB_LockHWSurface;
   149 	device->UnlockHWSurface = DIB_UnlockHWSurface;
   150 	device->FlipHWSurface = NULL;
   151 	device->FreeHWSurface = DIB_FreeHWSurface;
   152 	device->SetGammaRamp = DIB_SetGammaRamp;
   153 	device->GetGammaRamp = DIB_GetGammaRamp;
   154 #ifdef HAVE_OPENGL
   155 	device->GL_LoadLibrary = WIN_GL_LoadLibrary;
   156 	device->GL_GetProcAddress = WIN_GL_GetProcAddress;
   157 	device->GL_GetAttribute = WIN_GL_GetAttribute;
   158 	device->GL_MakeCurrent = WIN_GL_MakeCurrent;
   159 	device->GL_SwapBuffers = WIN_GL_SwapBuffers;
   160 #endif
   161 	device->SetCaption = WIN_SetWMCaption;
   162 	device->SetIcon = WIN_SetWMIcon;
   163 	device->IconifyWindow = WIN_IconifyWindow;
   164 	device->GrabInput = WIN_GrabInput;
   165 	device->GetWMInfo = WIN_GetWMInfo;
   166 	device->FreeWMCursor = WIN_FreeWMCursor;
   167 	device->CreateWMCursor = WIN_CreateWMCursor;
   168 	device->ShowWMCursor = WIN_ShowWMCursor;
   169 	device->WarpWMCursor = WIN_WarpWMCursor;
   170 	device->CheckMouseMode = WIN_CheckMouseMode;
   171 	device->InitOSKeymap = DIB_InitOSKeymap;
   172 	device->PumpEvents = DIB_PumpEvents;
   173 
   174 	/* Set up the windows message handling functions */
   175 	WIN_RealizePalette = DIB_RealizePalette;
   176 	WIN_PaletteChanged = DIB_PaletteChanged;
   177 	WIN_WinPAINT = DIB_WinPAINT;
   178 	HandleMessage = DIB_HandleMessage;
   179 
   180 	device->free = DIB_DeleteDevice;
   181 
   182 	/* We're finally ready */
   183 	return device;
   184 }
   185 
   186 VideoBootStrap WINDIB_bootstrap = {
   187 	"windib", "Win95/98/NT/2000 GDI",
   188 	DIB_Available, DIB_CreateDevice
   189 };
   190 
   191 #ifndef NO_CHANGEDISPLAYSETTINGS
   192 
   193 static int cmpmodes(const void *va, const void *vb)
   194 {
   195     SDL_Rect *a = *(SDL_Rect **)va;
   196     SDL_Rect *b = *(SDL_Rect **)vb;
   197     if(a->w > b->w)
   198         return -1;
   199     return b->h - a->h;
   200 }
   201 
   202 static int DIB_AddMode(_THIS, int bpp, int w, int h)
   203 {
   204 	SDL_Rect *mode;
   205 	int i, index;
   206 	int next_mode;
   207 
   208 	/* Check to see if we already have this mode */
   209 	if ( bpp < 8 ) {  /* Not supported */
   210 		return(0);
   211 	}
   212 	index = ((bpp+7)/8)-1;
   213 	for ( i=0; i<SDL_nummodes[index]; ++i ) {
   214 		mode = SDL_modelist[index][i];
   215 		if ( (mode->w == w) && (mode->h == h) ) {
   216 			return(0);
   217 		}
   218 	}
   219 
   220 	/* Set up the new video mode rectangle */
   221 	mode = (SDL_Rect *)malloc(sizeof *mode);
   222 	if ( mode == NULL ) {
   223 		SDL_OutOfMemory();
   224 		return(-1);
   225 	}
   226 	mode->x = 0;
   227 	mode->y = 0;
   228 	mode->w = w;
   229 	mode->h = h;
   230 
   231 	/* Allocate the new list of modes, and fill in the new mode */
   232 	next_mode = SDL_nummodes[index];
   233 	SDL_modelist[index] = (SDL_Rect **)
   234 	       realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
   235 	if ( SDL_modelist[index] == NULL ) {
   236 		SDL_OutOfMemory();
   237 		SDL_nummodes[index] = 0;
   238 		free(mode);
   239 		return(-1);
   240 	}
   241 	SDL_modelist[index][next_mode] = mode;
   242 	SDL_modelist[index][next_mode+1] = NULL;
   243 	SDL_nummodes[index]++;
   244 
   245 	return(0);
   246 }
   247 
   248 #endif /* !NO_CHANGEDISPLAYSETTINGS */
   249 
   250 static HPALETTE DIB_CreatePalette(int bpp)
   251 {
   252 /*	RJR: March 28, 2000
   253 	moved palette creation here from "DIB_VideoInit" */
   254 
   255 	HPALETTE handle = NULL;
   256 	
   257 	if ( bpp <= 8 )
   258 	{
   259 		LOGPALETTE *palette;
   260 		HDC hdc;
   261 		int ncolors;
   262 		int i;
   263 
   264 		ncolors = 1;
   265 		for ( i=0; i<bpp; ++i ) {
   266 			ncolors *= 2;
   267 		}
   268 		palette = (LOGPALETTE *)malloc(sizeof(*palette)+
   269 					ncolors*sizeof(PALETTEENTRY));
   270 		palette->palVersion = 0x300;
   271 		palette->palNumEntries = ncolors;
   272 		hdc = GetDC(SDL_Window);
   273 		GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry);
   274 		ReleaseDC(SDL_Window, hdc);
   275 		handle = CreatePalette(palette);
   276 		free(palette);
   277 	}
   278 	
   279 	return handle;
   280 }
   281 
   282 int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat)
   283 {
   284 #ifndef NO_CHANGEDISPLAYSETTINGS
   285 	int i;
   286 	DEVMODE settings;
   287 #endif
   288 
   289 	/* Create the window */
   290 	if ( DIB_CreateWindow(this) < 0 ) {
   291 		return(-1);
   292 	}
   293 #ifndef DISABLE_AUDIO
   294 	DX5_SoundFocus(SDL_Window);
   295 #endif
   296 
   297 	/* Determine the screen depth */
   298 	vformat->BitsPerPixel = DIB_SussScreenDepth();
   299 	switch (vformat->BitsPerPixel) {
   300 		case 15:
   301 			vformat->Rmask = 0x00007c00;
   302 			vformat->Gmask = 0x000003e0;
   303 			vformat->Bmask = 0x0000001f;
   304 			vformat->BitsPerPixel = 16;
   305 			break;
   306 		case 16:
   307 			vformat->Rmask = 0x0000f800;
   308 			vformat->Gmask = 0x000007e0;
   309 			vformat->Bmask = 0x0000001f;
   310 			break;
   311 		case 24:
   312 		case 32:
   313 			/* GDI defined as 8-8-8 */
   314 			vformat->Rmask = 0x00ff0000;
   315 			vformat->Gmask = 0x0000ff00;
   316 			vformat->Bmask = 0x000000ff;
   317 			break;
   318 		default:
   319 			break;
   320 	}
   321 
   322 	/* See if gamma is supported on this screen */
   323 	DIB_CheckGamma(this);
   324 
   325 #ifndef NO_CHANGEDISPLAYSETTINGS
   326 	/* Query for the list of available video modes */
   327 	for ( i=0; EnumDisplaySettings(NULL, i, &settings); ++i ) {
   328 		DIB_AddMode(this, settings.dmBitsPerPel,
   329 			settings.dmPelsWidth, settings.dmPelsHeight);
   330 	}
   331 	/* Sort the mode lists */
   332 	for ( i=0; i<NUM_MODELISTS; ++i ) {
   333 		if ( SDL_nummodes[i] > 0 ) {
   334 			qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes);
   335 		}
   336 	}
   337 #endif /* !NO_CHANGEDISPLAYSETTINGS */
   338 
   339 	/* Grab an identity palette if we are in a palettized mode */
   340 	if ( vformat->BitsPerPixel <= 8 ) {
   341 	/*	RJR: March 28, 2000
   342 		moved palette creation to "DIB_CreatePalette" */
   343 		screen_pal = DIB_CreatePalette(vformat->BitsPerPixel);
   344 	}
   345 
   346 	/* Fill in some window manager capabilities */
   347 	this->info.wm_available = 1;
   348 
   349 	/* We're done! */
   350 	return(0);
   351 }
   352 
   353 /* We support any format at any dimension */
   354 SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
   355 {
   356 #ifdef NO_CHANGEDISPLAYSETTINGS
   357 	return((SDL_Rect **)-1);
   358 #else
   359 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
   360 		return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
   361 	} else {
   362 		return((SDL_Rect **)-1);
   363 	}
   364 #endif
   365 }
   366 
   367 
   368 /*
   369   Helper fn to work out which screen depth windows is currently using.
   370   15 bit mode is considered 555 format, 16 bit is 565.
   371   returns 0 for unknown mode.
   372   (Derived from code in sept 1999 Windows Developer Journal
   373   http://www.wdj.com/code/archive.html)
   374 */
   375 static int DIB_SussScreenDepth()
   376 {
   377 #ifdef NO_GETDIBITS
   378 	int depth;
   379 	HDC hdc;
   380 
   381 	hdc = GetDC(SDL_Window);
   382 	depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
   383 	ReleaseDC(SDL_Window, hdc);
   384 #ifndef _WIN32_WCE
   385 	// AFAIK 16 bit CE devices have indeed RGB 565
   386 	if ( depth == 16 ) {
   387 		depth = 15;	/* GDI defined as RGB 555 */
   388 	}
   389 #endif
   390 	return(depth);
   391 #else
   392     int dib_size;
   393     LPBITMAPINFOHEADER dib_hdr;
   394     HDC hdc;
   395     HBITMAP hbm;
   396 
   397     /* Allocate enough space for a DIB header plus palette (for
   398      * 8-bit modes) or bitfields (for 16- and 32-bit modes)
   399      */
   400     dib_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD);
   401     dib_hdr = (LPBITMAPINFOHEADER) malloc(dib_size);
   402     memset(dib_hdr, 0, dib_size);
   403     dib_hdr->biSize = sizeof(BITMAPINFOHEADER);
   404     
   405     /* Get a device-dependent bitmap that's compatible with the
   406        screen.
   407      */
   408     hdc = GetDC(NULL);
   409     hbm = CreateCompatibleBitmap( hdc, 1, 1 );
   410 
   411     /* Convert the DDB to a DIB.  We need to call GetDIBits twice:
   412      * the first call just fills in the BITMAPINFOHEADER; the 
   413      * second fills in the bitfields or palette.
   414      */
   415     GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS);
   416     GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS);
   417     DeleteObject(hbm);
   418     ReleaseDC(NULL, hdc);
   419 
   420     switch( dib_hdr->biBitCount )
   421     {
   422     case 8:     return 8;
   423     case 24:    return 24;
   424     case 32:    return 32;
   425     case 16:
   426         if( dib_hdr->biCompression == BI_BITFIELDS ) {
   427             /* check the red mask */
   428             switch( ((DWORD*)((char*)dib_hdr + dib_hdr->biSize))[0] ) {
   429                 case 0xf800: return 16;    /* 565 */
   430                 case 0x7c00: return 15;    /* 555 */
   431             }
   432         }
   433     }
   434     return 0;    /* poo. */
   435 #endif /* NO_GETDIBITS */
   436 }
   437 
   438 
   439 /* Various screen update functions available */
   440 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
   441 
   442 SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current,
   443 				int width, int height, int bpp, Uint32 flags)
   444 {
   445 	SDL_Surface *video;
   446 	Uint32 prev_flags;
   447 	DWORD style;
   448 	const DWORD directstyle =
   449 			(WS_POPUP);
   450 	const DWORD windowstyle = 
   451 			(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
   452 	const DWORD resizestyle =
   453 			(WS_THICKFRAME|WS_MAXIMIZEBOX);
   454 	int binfo_size;
   455 	BITMAPINFO *binfo;
   456 	HDC hdc;
   457 	RECT bounds;
   458 	int x, y;
   459 	BOOL was_visible;
   460 	Uint32 Rmask, Gmask, Bmask;
   461 
   462 	/* See whether or not we should center the window */
   463 	was_visible = IsWindowVisible(SDL_Window);
   464 
   465 	/* Clean up any GL context that may be hanging around */
   466 	if ( current->flags & SDL_OPENGL ) {
   467 		WIN_GL_ShutDown(this);
   468 	}
   469 
   470 	/* Recalculate the bitmasks if necessary */
   471 	if ( bpp == current->format->BitsPerPixel ) {
   472 		video = current;
   473 	} else {
   474 		switch (bpp) {
   475 			case 15:
   476 			case 16:
   477 				if ( DIB_SussScreenDepth() == 15 ) {
   478 					/* 5-5-5 */
   479 					Rmask = 0x00007c00;
   480 					Gmask = 0x000003e0;
   481 					Bmask = 0x0000001f;
   482 				} else {
   483 					/* 5-6-5 */
   484 					Rmask = 0x0000f800;
   485 					Gmask = 0x000007e0;
   486 					Bmask = 0x0000001f;
   487 				}
   488 				break;
   489 			case 24:
   490 			case 32:
   491 				/* GDI defined as 8-8-8 */
   492 				Rmask = 0x00ff0000;
   493 				Gmask = 0x0000ff00;
   494 				Bmask = 0x000000ff;
   495 				break;
   496 			default:
   497 				Rmask = 0x00000000;
   498 				Gmask = 0x00000000;
   499 				Bmask = 0x00000000;
   500 				break;
   501 		}
   502 		video = SDL_CreateRGBSurface(SDL_SWSURFACE,
   503 					0, 0, bpp, Rmask, Gmask, Bmask, 0);
   504 		if ( video == NULL ) {
   505 			SDL_OutOfMemory();
   506 			return(NULL);
   507 		}
   508 	}
   509 
   510 	/* Fill in part of the video surface */
   511 	prev_flags = video->flags;
   512 	video->flags = 0;	/* Clear flags */
   513 	video->w = width;
   514 	video->h = height;
   515 	video->pitch = SDL_CalculatePitch(video);
   516 
   517 #ifndef NO_CHANGEDISPLAYSETTINGS
   518 	/* Set fullscreen mode if appropriate */
   519 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
   520 		DEVMODE settings;
   521 
   522 		memset(&settings, 0, sizeof(DEVMODE));
   523 		settings.dmSize = sizeof(DEVMODE);
   524 		settings.dmBitsPerPel = video->format->BitsPerPixel;
   525 		settings.dmPelsWidth = width;
   526 		settings.dmPelsHeight = height;
   527 		settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
   528 		if ( ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) {
   529 			video->flags |= SDL_FULLSCREEN;
   530 			SDL_fullscreen_mode = settings;
   531 		}
   532 	}
   533 #endif /* !NO_CHANGEDISPLAYSETTINGS */
   534 
   535 	/* Reset the palette and create a new one if necessary */
   536 	if ( screen_pal != NULL ) {
   537 	/*	RJR: March 28, 2000
   538 		delete identity palette if switching from a palettized mode */
   539 		DeleteObject(screen_pal);
   540 		screen_pal = NULL;
   541 	}
   542 	if ( bpp <= 8 )
   543 	{
   544 	/*	RJR: March 28, 2000
   545 		create identity palette switching to a palettized mode */
   546 		screen_pal = DIB_CreatePalette(bpp);
   547 	}
   548 
   549 	style = GetWindowLong(SDL_Window, GWL_STYLE);
   550 	style &= ~(resizestyle|WS_MAXIMIZE);
   551 	if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
   552 		style &= ~windowstyle;
   553 		style |= directstyle;
   554 	} else {
   555 #ifndef NO_CHANGEDISPLAYSETTINGS
   556 		if ( (prev_flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
   557 			ChangeDisplaySettings(NULL, 0);
   558 		}
   559 #endif
   560 		if ( flags & SDL_NOFRAME ) {
   561 			style &= ~windowstyle;
   562 			style |= directstyle;
   563 			video->flags |= SDL_NOFRAME;
   564 		} else {
   565 			style &= ~directstyle;
   566 			style |= windowstyle;
   567 			if ( flags & SDL_RESIZABLE ) {
   568 				style |= resizestyle;
   569 				video->flags |= SDL_RESIZABLE;
   570 			}
   571 		}
   572 #if WS_MAXIMIZE
   573 		if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
   574 #endif
   575 	}
   576 
   577 	/* DJM: Don't piss of anyone who has setup his own window */
   578 	if (!SDL_windowid)
   579 		SetWindowLong(SDL_Window, GWL_STYLE, style);
   580 
   581 	/* Delete the old bitmap if necessary */
   582 	if ( screen_bmp != NULL ) {
   583 		DeleteObject(screen_bmp);
   584 	}
   585 	if ( ! (flags & SDL_OPENGL) ) {
   586 		BOOL is16bitmode = (video->format->BytesPerPixel == 2);
   587 
   588 		/* Suss out the bitmap info header */
   589 		binfo_size = sizeof(*binfo);
   590 		if( is16bitmode ) {
   591 			/* 16bit modes, palette area used for rgb bitmasks */
   592 			binfo_size += 3*sizeof(DWORD);
   593 		} else if ( video->format->palette ) {
   594 			binfo_size += video->format->palette->ncolors *
   595 							sizeof(RGBQUAD);
   596 		}
   597 		binfo = (BITMAPINFO *)malloc(binfo_size);
   598 		if ( ! binfo ) {
   599 			if ( video != current ) {
   600 				SDL_FreeSurface(video);
   601 			}
   602 			SDL_OutOfMemory();
   603 			return(NULL);
   604 		}
   605 
   606 		binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
   607 		binfo->bmiHeader.biWidth = video->w;
   608 		binfo->bmiHeader.biHeight = -video->h;	/* -ve for topdown bitmap */
   609 		binfo->bmiHeader.biPlanes = 1;
   610 		binfo->bmiHeader.biSizeImage = video->h * video->pitch;
   611 		binfo->bmiHeader.biXPelsPerMeter = 0;
   612 		binfo->bmiHeader.biYPelsPerMeter = 0;
   613 		binfo->bmiHeader.biClrUsed = 0;
   614 		binfo->bmiHeader.biClrImportant = 0;
   615 		binfo->bmiHeader.biBitCount = video->format->BitsPerPixel;
   616 
   617 		if ( is16bitmode ) {
   618 			/* BI_BITFIELDS tells CreateDIBSection about the rgb masks in the palette */
   619 			binfo->bmiHeader.biCompression = BI_BITFIELDS;
   620 			((Uint32*)binfo->bmiColors)[0] = video->format->Rmask;
   621 			((Uint32*)binfo->bmiColors)[1] = video->format->Gmask;
   622 			((Uint32*)binfo->bmiColors)[2] = video->format->Bmask;
   623 		} else {
   624 			binfo->bmiHeader.biCompression = BI_RGB;	/* BI_BITFIELDS for 565 vs 555 */
   625 			if ( video->format->palette ) {
   626 				memset(binfo->bmiColors, 0,
   627 					video->format->palette->ncolors*sizeof(RGBQUAD));
   628 			}
   629 		}
   630 
   631 		/* Create the offscreen bitmap buffer */
   632 		hdc = GetDC(SDL_Window);
   633 		screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS,
   634 					(void **)(&video->pixels), NULL, 0);
   635 		ReleaseDC(SDL_Window, hdc);
   636 		free(binfo);
   637 		if ( screen_bmp == NULL ) {
   638 			if ( video != current ) {
   639 				SDL_FreeSurface(video);
   640 			}
   641 			SDL_SetError("Couldn't create DIB section");
   642 			return(NULL);
   643 		}
   644 		this->UpdateRects = DIB_NormalUpdate;
   645 
   646 		/* Set video surface flags */
   647 		if ( bpp <= 8 ) {
   648 			/* BitBlt() maps colors for us */
   649 			video->flags |= SDL_HWPALETTE;
   650 		}
   651 	}
   652 
   653 	/* Resize the window */
   654 	if ( SDL_windowid == NULL ) {
   655 		HWND top;
   656 		UINT swp_flags;
   657 
   658 		SDL_resizing = 1;
   659 		bounds.left = 0;
   660 		bounds.top = 0;
   661 		bounds.right = video->w;
   662 		bounds.bottom = video->h;
   663 		AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE, 0);
   664 		width = bounds.right-bounds.left;
   665 		height = bounds.bottom-bounds.top;
   666 		x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
   667 		y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
   668 		if ( y < 0 ) { /* Cover up title bar for more client area */
   669 			y -= GetSystemMetrics(SM_CYCAPTION)/2;
   670 		}
   671 		swp_flags = (SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
   672 		if ( was_visible && !(flags & SDL_FULLSCREEN) ) {
   673 			swp_flags |= SWP_NOMOVE;
   674 		}
   675 		if ( flags & SDL_FULLSCREEN ) {
   676 			top = HWND_TOPMOST;
   677 		} else {
   678 			top = HWND_NOTOPMOST;
   679 		}
   680 		SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
   681 		SDL_resizing = 0;
   682 		SetForegroundWindow(SDL_Window);
   683 	}
   684 
   685 	/* Set up for OpenGL */
   686 	if ( flags & SDL_OPENGL ) {
   687 		if ( WIN_GL_SetupWindow(this) < 0 ) {
   688 			return(NULL);
   689 		}
   690 		video->flags |= SDL_OPENGL;
   691 	}
   692 
   693 	/* We're live! */
   694 	return(video);
   695 }
   696 
   697 /* We don't actually allow hardware surfaces in the DIB driver */
   698 static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface)
   699 {
   700 	return(-1);
   701 }
   702 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface)
   703 {
   704 	return;
   705 }
   706 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface)
   707 {
   708 	return(0);
   709 }
   710 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface)
   711 {
   712 	return;
   713 }
   714 
   715 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
   716 {
   717 	HDC hdc, mdc;
   718 	int i;
   719 
   720 	hdc = GetDC(SDL_Window);
   721 	if ( screen_pal ) {
   722 		SelectPalette(hdc, screen_pal, FALSE);
   723 	}
   724 	mdc = CreateCompatibleDC(hdc);
   725 	SelectObject(mdc, screen_bmp);
   726 	for ( i=0; i<numrects; ++i ) {
   727 		BitBlt(hdc, rects[i].x, rects[i].y, rects[i].w, rects[i].h,
   728 					mdc, rects[i].x, rects[i].y, SRCCOPY);
   729 	}
   730 	DeleteDC(mdc);
   731 	ReleaseDC(SDL_Window, hdc);
   732 }
   733 
   734 int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
   735 {
   736 	RGBQUAD *pal;
   737 	int i;
   738 #ifndef _WIN32_WCE
   739 	HDC hdc, mdc;
   740 #else
   741 	HDC hdc;
   742 #endif
   743 
   744 	/* Update the display palette */
   745 	hdc = GetDC(SDL_Window);
   746 	if ( screen_pal ) {
   747 		PALETTEENTRY *entries;
   748 
   749 		entries = (PALETTEENTRY *)alloca(ncolors*sizeof(PALETTEENTRY));
   750 		for ( i=0; i<ncolors; ++i ) {
   751 			entries[i].peRed   = colors[i].r;
   752 			entries[i].peGreen = colors[i].g;
   753 			entries[i].peBlue  = colors[i].b;
   754 			entries[i].peFlags = PC_NOCOLLAPSE;
   755 		}
   756 		SetPaletteEntries(screen_pal, firstcolor, ncolors, entries);
   757 		SelectPalette(hdc, screen_pal, FALSE);
   758 		RealizePalette(hdc);
   759 	}
   760 
   761 	/* Copy palette colors into DIB palette */
   762 	pal = (RGBQUAD *)alloca(ncolors*sizeof(RGBQUAD));
   763 	for ( i=0; i<ncolors; ++i ) {
   764 		pal[i].rgbRed = colors[i].r;
   765 		pal[i].rgbGreen = colors[i].g;
   766 		pal[i].rgbBlue = colors[i].b;
   767 		pal[i].rgbReserved = 0;
   768 	}
   769 
   770 	/* Set the DIB palette and update the display */
   771 #ifndef _WIN32_WCE
   772 	mdc = CreateCompatibleDC(hdc);
   773 	SelectObject(mdc, screen_bmp);
   774 	SetDIBColorTable(mdc, firstcolor, ncolors, pal);
   775 	BitBlt(hdc, 0, 0, this->screen->w, this->screen->h,
   776 	       mdc, 0, 0, SRCCOPY);
   777 	DeleteDC(mdc);
   778 #endif
   779 	ReleaseDC(SDL_Window, hdc);
   780 	return(1);
   781 }
   782 
   783 static void DIB_CheckGamma(_THIS)
   784 {
   785 #ifndef NO_GAMMA_SUPPORT
   786 	HDC hdc;
   787 	WORD ramp[3*256];
   788 
   789 	/* If we fail to get gamma, disable gamma control */
   790 	hdc = GetDC(SDL_Window);
   791 	if ( ! GetDeviceGammaRamp(hdc, ramp) ) {
   792 		this->GetGammaRamp = NULL;
   793 		this->SetGammaRamp = NULL;
   794 	}
   795 	ReleaseDC(SDL_Window, hdc);
   796 #endif /* !NO_GAMMA_SUPPORT */
   797 }
   798 void DIB_SwapGamma(_THIS)
   799 {
   800 #ifndef NO_GAMMA_SUPPORT
   801 	HDC hdc;
   802 
   803 	if ( gamma_saved ) {
   804 		hdc = GetDC(SDL_Window);
   805 		if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   806 			/* About to leave active state, restore gamma */
   807 			SetDeviceGammaRamp(hdc, gamma_saved);
   808 		} else {
   809 			/* About to enter active state, set game gamma */
   810 			GetDeviceGammaRamp(hdc, gamma_saved);
   811 			SetDeviceGammaRamp(hdc, this->gamma);
   812 		}
   813 		ReleaseDC(SDL_Window, hdc);
   814 	}
   815 #endif /* !NO_GAMMA_SUPPORT */
   816 }
   817 void DIB_QuitGamma(_THIS)
   818 {
   819 #ifndef NO_GAMMA_SUPPORT
   820 	if ( gamma_saved ) {
   821 		/* Restore the original gamma if necessary */
   822 		if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   823 			HDC hdc;
   824 
   825 			hdc = GetDC(SDL_Window);
   826 			SetDeviceGammaRamp(hdc, gamma_saved);
   827 			ReleaseDC(SDL_Window, hdc);
   828 		}
   829 
   830 		/* Free the saved gamma memory */
   831 		free(gamma_saved);
   832 		gamma_saved = 0;
   833 	}
   834 #endif /* !NO_GAMMA_SUPPORT */
   835 }
   836 
   837 int DIB_SetGammaRamp(_THIS, Uint16 *ramp)
   838 {
   839 #ifdef NO_GAMMA_SUPPORT
   840 	SDL_SetError("SDL compiled without gamma ramp support");
   841 	return -1;
   842 #else
   843 	HDC hdc;
   844 	BOOL succeeded;
   845 
   846 	/* Set the ramp for the display */
   847 	if ( ! gamma_saved ) {
   848 		gamma_saved = (WORD *)malloc(3*256*sizeof(*gamma_saved));
   849 		if ( ! gamma_saved ) {
   850 			SDL_OutOfMemory();
   851 			return -1;
   852 		}
   853 		hdc = GetDC(SDL_Window);
   854 		GetDeviceGammaRamp(hdc, gamma_saved);
   855 		ReleaseDC(SDL_Window, hdc);
   856 	}
   857 	if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   858 		hdc = GetDC(SDL_Window);
   859 		succeeded = SetDeviceGammaRamp(hdc, ramp);
   860 		ReleaseDC(SDL_Window, hdc);
   861 	} else {
   862 		succeeded = TRUE;
   863 	}
   864 	return succeeded ? 0 : -1;
   865 #endif /* !NO_GAMMA_SUPPORT */
   866 }
   867 
   868 int DIB_GetGammaRamp(_THIS, Uint16 *ramp)
   869 {
   870 #ifdef NO_GAMMA_SUPPORT
   871 	SDL_SetError("SDL compiled without gamma ramp support");
   872 	return -1;
   873 #else
   874 	HDC hdc;
   875 	BOOL succeeded;
   876 
   877 	/* Get the ramp from the display */
   878 	hdc = GetDC(SDL_Window);
   879 	succeeded = GetDeviceGammaRamp(hdc, ramp);
   880 	ReleaseDC(SDL_Window, hdc);
   881 	return succeeded ? 0 : -1;
   882 #endif /* !NO_GAMMA_SUPPORT */
   883 }
   884 
   885 static void FlushMessageQueue()
   886 {
   887 	MSG  msg;
   888 	while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
   889 		if ( msg.message == WM_QUIT ) break;
   890 		TranslateMessage( &msg );
   891 		DispatchMessage( &msg );
   892 	}
   893 }
   894 
   895 void DIB_VideoQuit(_THIS)
   896 {
   897 	/* Destroy the window and everything associated with it */
   898 	if ( SDL_Window ) {
   899 		/* Delete the screen bitmap (also frees screen->pixels) */
   900 		if ( this->screen ) {
   901 #ifndef NO_CHANGEDISPLAYSETTINGS
   902 			if ( this->screen->flags & SDL_FULLSCREEN ) {
   903 				ChangeDisplaySettings(NULL, 0);
   904 				ShowWindow(SDL_Window, SW_HIDE);
   905 			}
   906 #endif
   907 			if ( this->screen->flags & SDL_OPENGL ) {
   908 				WIN_GL_ShutDown(this);
   909 			}
   910 			this->screen->pixels = NULL;
   911 		}
   912 		if ( screen_bmp ) {
   913 			DeleteObject(screen_bmp);
   914 			screen_bmp = NULL;
   915 		}
   916 		if ( screen_icn ) {
   917 			DestroyIcon(screen_icn);
   918 			screen_icn = NULL;
   919 		}
   920 		DIB_QuitGamma(this);
   921 		DIB_DestroyWindow(this);
   922 		FlushMessageQueue();
   923 
   924 		SDL_Window = NULL;
   925 	}
   926 }
   927 
   928 /* Exported for the windows message loop only */
   929 static void DIB_FocusPalette(_THIS, int foreground)
   930 {
   931 	if ( screen_pal != NULL ) {
   932 		HDC hdc;
   933 
   934 		hdc = GetDC(SDL_Window);
   935 		SelectPalette(hdc, screen_pal, FALSE);
   936 		if ( RealizePalette(hdc) )
   937 			InvalidateRect(SDL_Window, NULL, FALSE);
   938 		ReleaseDC(SDL_Window, hdc);
   939 	}
   940 }
   941 static void DIB_RealizePalette(_THIS)
   942 {
   943 	DIB_FocusPalette(this, 1);
   944 }
   945 static void DIB_PaletteChanged(_THIS, HWND window)
   946 {
   947 	if ( window != SDL_Window ) {
   948 		DIB_FocusPalette(this, 0);
   949 	}
   950 }
   951 
   952 /* Exported for the windows message loop only */
   953 static void DIB_WinPAINT(_THIS, HDC hdc)
   954 {
   955 	HDC mdc;
   956 
   957 	if ( screen_pal ) {
   958 		SelectPalette(hdc, screen_pal, FALSE);
   959 	}
   960 	mdc = CreateCompatibleDC(hdc);
   961 	SelectObject(mdc, screen_bmp);
   962 	BitBlt(hdc, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h,
   963 							mdc, 0, 0, SRCCOPY);
   964 	DeleteDC(mdc);
   965 }
   966 
   967 /* Stub in case DirectX isn't available */
   968 #ifndef ENABLE_DIRECTX
   969 void DX5_SoundFocus(HWND hwnd)
   970 {
   971 	return;
   972 }
   973 #endif