2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
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.
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.
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
22 #include "SDL_config.h"
24 #define WIN32_LEAN_AND_MEAN
27 /* Not yet in the mingw32 cross-compile headers */
28 #ifndef CDS_FULLSCREEN
29 #define CDS_FULLSCREEN 4
32 #include "SDL_syswm.h"
33 #include "../SDL_sysvideo.h"
34 #include "../SDL_pixels_c.h"
35 #include "../../events/SDL_sysevents.h"
36 #include "../../events/SDL_events_c.h"
37 #include "SDL_gapidibvideo.h"
38 #include "SDL_dibvideo.h"
39 #include "../wincommon/SDL_syswm_c.h"
40 #include "../wincommon/SDL_sysmouse_c.h"
41 #include "SDL_dibevents_c.h"
42 #include "../wincommon/SDL_wingl_c.h"
46 #ifndef DM_DISPLAYORIENTATION
47 #define DM_DISPLAYORIENTATION 0x00800000L
49 #ifndef DM_DISPLAYQUERYORIENTATION
50 #define DM_DISPLAYQUERYORIENTATION 0x01000000L
66 #define NO_GAMMA_SUPPORT
68 #define NO_CHANGEDISPLAYSETTINGS
70 #define ChangeDisplaySettings(lpDevMode, dwFlags) ChangeDisplaySettingsEx(NULL, (lpDevMode), 0, (dwFlags), 0)
77 #define WS_THICKFRAME 0
79 #ifndef SWP_NOCOPYBITS
80 #define SWP_NOCOPYBITS 0
83 #define PC_NOCOLLAPSE 0
87 // defined and used in SDL_sysevents.c
88 extern HINSTANCE aygshell;
91 /* Initialization/Query functions */
92 static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat);
93 static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
94 SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
95 static int DIB_SetColors(_THIS, int firstcolor, int ncolors,
97 static void DIB_CheckGamma(_THIS);
98 void DIB_SwapGamma(_THIS);
99 void DIB_QuitGamma(_THIS);
100 int DIB_SetGammaRamp(_THIS, Uint16 *ramp);
101 int DIB_GetGammaRamp(_THIS, Uint16 *ramp);
102 static void DIB_VideoQuit(_THIS);
104 /* Hardware surface functions */
105 static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface);
106 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface);
107 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface);
108 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface);
110 /* Windows message handling functions */
111 static void DIB_GrabStaticColors(HWND window);
112 static void DIB_ReleaseStaticColors(HWND window);
113 static void DIB_Activate(_THIS, BOOL active, BOOL minimized);
114 static void DIB_RealizePalette(_THIS);
115 static void DIB_PaletteChanged(_THIS, HWND window);
116 static void DIB_WinPAINT(_THIS, HDC hdc);
119 static int DIB_SussScreenDepth();
121 /* DIB driver bootstrap functions */
123 static int DIB_Available(void)
128 static void DIB_DeleteDevice(SDL_VideoDevice *device)
131 if ( device->hidden ) {
132 if ( device->hidden->dibInfo ) {
133 SDL_free( device->hidden->dibInfo );
135 SDL_free(device->hidden);
137 if ( device->gl_data ) {
138 SDL_free(device->gl_data);
144 static SDL_VideoDevice *DIB_CreateDevice(int devindex)
146 SDL_VideoDevice *device;
148 /* Initialize all variables that we clean on shutdown */
149 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
151 SDL_memset(device, 0, (sizeof *device));
152 device->hidden = (struct SDL_PrivateVideoData *)
153 SDL_malloc((sizeof *device->hidden));
155 SDL_memset(device->hidden, 0, (sizeof *device->hidden));
156 device->hidden->dibInfo = (DibInfo *)SDL_malloc((sizeof(DibInfo)));
157 if(device->hidden->dibInfo == NULL)
159 SDL_free(device->hidden);
160 device->hidden = NULL;
164 device->gl_data = (struct SDL_PrivateGLData *)
165 SDL_malloc((sizeof *device->gl_data));
167 if ( (device == NULL) || (device->hidden == NULL) ||
168 (device->gl_data == NULL) ) {
170 DIB_DeleteDevice(device);
173 SDL_memset(device->hidden->dibInfo, 0, (sizeof *device->hidden->dibInfo));
174 SDL_memset(device->gl_data, 0, (sizeof *device->gl_data));
176 /* Set the function pointers */
177 device->VideoInit = DIB_VideoInit;
178 device->ListModes = DIB_ListModes;
179 device->SetVideoMode = DIB_SetVideoMode;
180 device->UpdateMouse = WIN_UpdateMouse;
181 device->SetColors = DIB_SetColors;
182 device->UpdateRects = NULL;
183 device->VideoQuit = DIB_VideoQuit;
184 device->AllocHWSurface = DIB_AllocHWSurface;
185 device->CheckHWBlit = NULL;
186 device->FillHWRect = NULL;
187 device->SetHWColorKey = NULL;
188 device->SetHWAlpha = NULL;
189 device->LockHWSurface = DIB_LockHWSurface;
190 device->UnlockHWSurface = DIB_UnlockHWSurface;
191 device->FlipHWSurface = NULL;
192 device->FreeHWSurface = DIB_FreeHWSurface;
193 device->SetGammaRamp = DIB_SetGammaRamp;
194 device->GetGammaRamp = DIB_GetGammaRamp;
196 device->GL_LoadLibrary = WIN_GL_LoadLibrary;
197 device->GL_GetProcAddress = WIN_GL_GetProcAddress;
198 device->GL_GetAttribute = WIN_GL_GetAttribute;
199 device->GL_MakeCurrent = WIN_GL_MakeCurrent;
200 device->GL_SwapBuffers = WIN_GL_SwapBuffers;
202 device->SetCaption = WIN_SetWMCaption;
203 device->SetIcon = WIN_SetWMIcon;
204 device->IconifyWindow = WIN_IconifyWindow;
205 device->GrabInput = WIN_GrabInput;
206 device->GetWMInfo = WIN_GetWMInfo;
207 device->FreeWMCursor = WIN_FreeWMCursor;
208 device->CreateWMCursor = WIN_CreateWMCursor;
209 device->ShowWMCursor = WIN_ShowWMCursor;
210 device->WarpWMCursor = WIN_WarpWMCursor;
211 device->CheckMouseMode = WIN_CheckMouseMode;
212 device->InitOSKeymap = DIB_InitOSKeymap;
213 device->PumpEvents = DIB_PumpEvents;
215 /* Set up the windows message handling functions */
216 WIN_Activate = DIB_Activate;
217 WIN_RealizePalette = DIB_RealizePalette;
218 WIN_PaletteChanged = DIB_PaletteChanged;
219 WIN_WinPAINT = DIB_WinPAINT;
220 HandleMessage = DIB_HandleMessage;
222 device->free = DIB_DeleteDevice;
224 /* We're finally ready */
228 VideoBootStrap WINDIB_bootstrap = {
229 "windib", "Win95/98/NT/2000/CE GDI",
230 DIB_Available, DIB_CreateDevice
233 static int cmpmodes(const void *va, const void *vb)
235 SDL_Rect *a = *(SDL_Rect **)va;
236 SDL_Rect *b = *(SDL_Rect **)vb;
243 static int DIB_AddMode(_THIS, int bpp, int w, int h)
249 /* Check to see if we already have this mode */
250 if ( bpp < 8 || bpp > 32 ) { /* Not supported */
253 index = ((bpp+7)/8)-1;
254 for ( i=0; i<SDL_nummodes[index]; ++i ) {
255 mode = SDL_modelist[index][i];
256 if ( (mode->w == w) && (mode->h == h) ) {
261 /* Set up the new video mode rectangle */
262 mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
263 if ( mode == NULL ) {
272 /* Allocate the new list of modes, and fill in the new mode */
273 next_mode = SDL_nummodes[index];
274 SDL_modelist[index] = (SDL_Rect **)
275 SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
276 if ( SDL_modelist[index] == NULL ) {
278 SDL_nummodes[index] = 0;
282 SDL_modelist[index][next_mode] = mode;
283 SDL_modelist[index][next_mode+1] = NULL;
284 SDL_nummodes[index]++;
289 static void DIB_CreatePalette(_THIS, int bpp)
291 /* RJR: March 28, 2000
292 moved palette creation here from "DIB_VideoInit" */
298 ncolors = (1 << bpp);
299 palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+
300 ncolors*sizeof(PALETTEENTRY));
301 palette->palVersion = 0x300;
302 palette->palNumEntries = ncolors;
303 hdc = GetDC(SDL_Window);
304 GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry);
305 ReleaseDC(SDL_Window, hdc);
306 screen_pal = CreatePalette(palette);
307 screen_logpal = palette;
310 int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat)
312 const char *env = NULL;
313 #ifndef NO_CHANGEDISPLAYSETTINGS
318 /* Create the window */
319 if ( DIB_CreateWindow(this) < 0 ) {
323 #if !SDL_AUDIO_DISABLED
324 DX5_SoundFocus(SDL_Window);
327 /* Determine the screen depth */
328 vformat->BitsPerPixel = DIB_SussScreenDepth();
329 switch (vformat->BitsPerPixel) {
331 vformat->Rmask = 0x00007c00;
332 vformat->Gmask = 0x000003e0;
333 vformat->Bmask = 0x0000001f;
334 vformat->BitsPerPixel = 16;
337 vformat->Rmask = 0x0000f800;
338 vformat->Gmask = 0x000007e0;
339 vformat->Bmask = 0x0000001f;
343 /* GDI defined as 8-8-8 */
344 vformat->Rmask = 0x00ff0000;
345 vformat->Gmask = 0x0000ff00;
346 vformat->Bmask = 0x000000ff;
352 /* See if gamma is supported on this screen */
353 DIB_CheckGamma(this);
355 #ifndef NO_CHANGEDISPLAYSETTINGS
357 settings.dmSize = sizeof(DEVMODE);
358 settings.dmDriverExtra = 0;
360 settings.dmFields = DM_DISPLAYQUERYORIENTATION;
361 this->hidden->supportRotation = ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL;
363 /* Query for the desktop resolution */
364 SDL_desktop_mode.dmSize = sizeof(SDL_desktop_mode);
365 SDL_desktop_mode.dmDriverExtra = 0;
366 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode);
367 this->info.current_w = SDL_desktop_mode.dmPelsWidth;
368 this->info.current_h = SDL_desktop_mode.dmPelsHeight;
370 /* Query for the list of available video modes */
371 for ( i=0; EnumDisplaySettings(NULL, i, &settings); ++i ) {
372 DIB_AddMode(this, settings.dmBitsPerPel,
373 settings.dmPelsWidth, settings.dmPelsHeight);
375 if( this->hidden->supportRotation )
376 DIB_AddMode(this, settings.dmBitsPerPel,
377 settings.dmPelsHeight, settings.dmPelsWidth);
380 /* Sort the mode lists */
381 for ( i=0; i<NUM_MODELISTS; ++i ) {
382 if ( SDL_nummodes[i] > 0 ) {
383 SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes);
387 // WinCE and fullscreen mode:
388 // We use only vformat->BitsPerPixel that allow SDL to
389 // emulate other bpp (8, 32) and use triple buffer,
390 // because SDL surface conversion is much faster than the WinCE one.
391 // Although it should be tested on devices with graphics accelerator.
393 DIB_AddMode(this, vformat->BitsPerPixel,
394 GetDeviceCaps(GetDC(NULL), HORZRES),
395 GetDeviceCaps(GetDC(NULL), VERTRES));
397 #endif /* !NO_CHANGEDISPLAYSETTINGS */
399 /* Grab an identity palette if we are in a palettized mode */
400 if ( vformat->BitsPerPixel <= 8 ) {
401 /* RJR: March 28, 2000
402 moved palette creation to "DIB_CreatePalette" */
403 DIB_CreatePalette(this, vformat->BitsPerPixel);
406 /* Fill in some window manager capabilities */
407 this->info.wm_available = 1;
410 this->hidden->origRotation = -1;
413 /* Allow environment override of screensaver disable. */
414 env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
416 allow_screensaver = SDL_atoi(env);
418 #ifdef SDL_VIDEO_DISABLE_SCREENSAVER
419 allow_screensaver = 0;
421 allow_screensaver = 1;
429 /* We support any format at any dimension */
430 SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
432 if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
433 return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
435 return((SDL_Rect **)-1);
441 Helper fn to work out which screen depth windows is currently using.
442 15 bit mode is considered 555 format, 16 bit is 565.
443 returns 0 for unknown mode.
444 (Derived from code in sept 1999 Windows Developer Journal
445 http://www.wdj.com/code/archive.html)
447 static int DIB_SussScreenDepth()
453 hdc = GetDC(SDL_Window);
454 depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
455 ReleaseDC(SDL_Window, hdc);
460 LPBITMAPINFOHEADER dib_hdr;
464 /* Allocate enough space for a DIB header plus palette (for
465 * 8-bit modes) or bitfields (for 16- and 32-bit modes)
467 dib_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD);
468 dib_hdr = (LPBITMAPINFOHEADER) SDL_malloc(dib_size);
469 SDL_memset(dib_hdr, 0, dib_size);
470 dib_hdr->biSize = sizeof(BITMAPINFOHEADER);
472 /* Get a device-dependent bitmap that's compatible with the
476 hbm = CreateCompatibleBitmap( hdc, 1, 1 );
478 /* Convert the DDB to a DIB. We need to call GetDIBits twice:
479 * the first call just fills in the BITMAPINFOHEADER; the
480 * second fills in the bitfields or palette.
482 GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS);
483 GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS);
485 ReleaseDC(NULL, hdc);
488 switch( dib_hdr->biBitCount )
490 case 8: depth = 8; break;
491 case 24: depth = 24; break;
492 case 32: depth = 32; break;
494 if( dib_hdr->biCompression == BI_BITFIELDS ) {
495 /* check the red mask */
496 switch( ((DWORD*)((char*)dib_hdr + dib_hdr->biSize))[0] ) {
497 case 0xf800: depth = 16; break; /* 565 */
498 case 0x7c00: depth = 15; break; /* 555 */
504 #endif /* NO_GETDIBITS */
508 /* Various screen update functions available */
509 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
511 static void DIB_ResizeWindow(_THIS, int width, int height, int prev_width, int prev_height, Uint32 flags)
517 /* Resize the window */
518 if ( !SDL_windowid && !IsZoomed(SDL_Window) ) {
520 if ( !SDL_windowid ) {
524 const char *window = NULL;
525 const char *center = NULL;
527 if ( width != prev_width || height != prev_height ) {
528 window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
529 center = SDL_getenv("SDL_VIDEO_CENTERED");
531 if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) {
535 if ( SDL_strcmp(window, "center") == 0 ) {
540 swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW);
542 bounds.left = SDL_windowX;
543 bounds.top = SDL_windowY;
544 bounds.right = SDL_windowX+width;
545 bounds.bottom = SDL_windowY+height;
547 AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0);
549 // The bMenu parameter must be FALSE; menu bars are not supported
550 AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), 0, 0);
552 width = bounds.right-bounds.left;
553 height = bounds.bottom-bounds.top;
554 if ( (flags & SDL_FULLSCREEN) ) {
555 x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
556 y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
557 } else if ( center ) {
558 x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
559 y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
560 } else if ( SDL_windowX || SDL_windowY || window ) {
565 swp_flags |= SWP_NOMOVE;
567 if ( flags & SDL_FULLSCREEN ) {
570 top = HWND_NOTOPMOST;
572 SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
573 if ( !(flags & SDL_FULLSCREEN) ) {
574 SDL_windowX = SDL_bounds.left;
575 SDL_windowY = SDL_bounds.top;
577 SetForegroundWindow(SDL_Window);
581 SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current,
582 int width, int height, int bpp, Uint32 flags)
588 const DWORD directstyle =
590 const DWORD windowstyle =
591 (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
592 const DWORD resizestyle =
593 (WS_THICKFRAME|WS_MAXIMIZEBOX);
597 Uint32 Rmask, Gmask, Bmask;
601 prev_flags = current->flags;
604 * Special case for OpenGL windows...since the app needs to call
605 * SDL_SetVideoMode() in response to resize events to continue to
606 * function, but WGL handles the GL context details behind the scenes,
607 * there's no sense in tearing the context down just to rebuild it
608 * to what it already was...tearing it down sacrifices your GL state
609 * and uploaded textures. So if we're requesting the same video mode
610 * attributes just resize the window and return immediately.
613 ((current->flags & ~SDL_ANYFORMAT) == (flags & ~SDL_ANYFORMAT)) &&
614 (current->format->BitsPerPixel == bpp) &&
615 (flags & SDL_OPENGL) &&
616 !(flags & SDL_FULLSCREEN) ) { /* probably not safe for fs */
620 DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags);
625 /* Clean up any GL context that may be hanging around */
626 if ( current->flags & SDL_OPENGL ) {
627 WIN_GL_ShutDown(this);
631 /* Recalculate the bitmasks if necessary */
632 if ( bpp == current->format->BitsPerPixel ) {
638 if ( DIB_SussScreenDepth() == 15 ) {
652 /* GDI defined as 8-8-8 */
663 video = SDL_CreateRGBSurface(SDL_SWSURFACE,
664 0, 0, bpp, Rmask, Gmask, Bmask, 0);
665 if ( video == NULL ) {
671 /* Fill in part of the video surface */
672 video->flags = 0; /* Clear flags */
675 video->pitch = SDL_CalculatePitch(video);
677 /* Small fix for WinCE/Win32 - when activating window
678 SDL_VideoSurface is equal to zero, so activating code
679 is not called properly for fullscreen windows because
680 macros WINDIB_FULLSCREEN uses SDL_VideoSurface
682 SDL_VideoSurface = video;
684 #if defined(_WIN32_WCE)
685 if ( flags & SDL_FULLSCREEN )
686 video->flags |= SDL_FULLSCREEN;
689 #ifndef NO_CHANGEDISPLAYSETTINGS
690 /* Set fullscreen mode if appropriate */
691 if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
695 SDL_memset(&settings, 0, sizeof(DEVMODE));
696 settings.dmSize = sizeof(DEVMODE);
699 // try to rotate screen to fit requested resolution
700 if( this->hidden->supportRotation )
705 settings.dmFields = DM_DISPLAYORIENTATION;
706 ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL);
707 rotation = settings.dmDisplayOrientation;
709 if( (width > GetDeviceCaps(GetDC(NULL), HORZRES))
710 && (height < GetDeviceCaps(GetDC(NULL), VERTRES)))
715 settings.dmDisplayOrientation = DMDO_90;
718 settings.dmDisplayOrientation = DMDO_180;
721 if( settings.dmDisplayOrientation != rotation )
724 this->hidden->origRotation = rotation;
725 ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL);
728 if( (width < GetDeviceCaps(GetDC(NULL), HORZRES))
729 && (height > GetDeviceCaps(GetDC(NULL), VERTRES)))
734 settings.dmDisplayOrientation = DMDO_0;
737 settings.dmDisplayOrientation = DMDO_270;
740 if( settings.dmDisplayOrientation != rotation )
743 this->hidden->origRotation = rotation;
744 ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL);
752 settings.dmBitsPerPel = video->format->BitsPerPixel;
753 settings.dmPelsWidth = width;
754 settings.dmPelsHeight = height;
755 settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
756 if ( width <= (int)SDL_desktop_mode.dmPelsWidth &&
757 height <= (int)SDL_desktop_mode.dmPelsHeight ) {
758 settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency;
759 settings.dmFields |= DM_DISPLAYFREQUENCY;
761 changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
762 if ( ! changed && (settings.dmFields & DM_DISPLAYFREQUENCY) ) {
763 settings.dmFields &= ~DM_DISPLAYFREQUENCY;
764 changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
770 video->flags |= SDL_FULLSCREEN;
771 SDL_fullscreen_mode = settings;
775 #endif /* !NO_CHANGEDISPLAYSETTINGS */
777 /* Reset the palette and create a new one if necessary */
778 if ( grab_palette ) {
779 DIB_ReleaseStaticColors(SDL_Window);
780 grab_palette = FALSE;
782 if ( screen_pal != NULL ) {
783 /* RJR: March 28, 2000
784 delete identity palette if switching from a palettized mode */
785 DeleteObject(screen_pal);
788 if ( screen_logpal != NULL ) {
789 SDL_free(screen_logpal);
790 screen_logpal = NULL;
795 /* RJR: March 28, 2000
796 create identity palette switching to a palettized mode */
797 DIB_CreatePalette(this, bpp);
800 style = GetWindowLong(SDL_Window, GWL_STYLE);
801 style &= ~(resizestyle|WS_MAXIMIZE);
802 if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
803 style &= ~windowstyle;
804 style |= directstyle;
806 #ifndef NO_CHANGEDISPLAYSETTINGS
807 if ( (prev_flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
808 ChangeDisplaySettings(NULL, 0);
811 if ( flags & SDL_NOFRAME ) {
812 style &= ~windowstyle;
813 style |= directstyle;
814 video->flags |= SDL_NOFRAME;
816 style &= ~directstyle;
817 style |= windowstyle;
818 if ( flags & SDL_RESIZABLE ) {
819 style |= resizestyle;
820 video->flags |= SDL_RESIZABLE;
823 #if WS_MAXIMIZE && !defined(_WIN32_WCE)
824 if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
828 /* DJM: Don't piss of anyone who has setup his own window */
830 SetWindowLong(SDL_Window, GWL_STYLE, style);
832 /* Delete the old bitmap if necessary */
833 if ( screen_bmp != NULL ) {
834 DeleteObject(screen_bmp);
836 if ( ! (flags & SDL_OPENGL) ) {
837 BOOL is16bitmode = (video->format->BytesPerPixel == 2);
839 /* Suss out the bitmap info header */
840 binfo_size = sizeof(*binfo);
842 /* 16bit modes, palette area used for rgb bitmasks */
843 binfo_size += 3*sizeof(DWORD);
844 } else if ( video->format->palette ) {
845 binfo_size += video->format->palette->ncolors *
848 binfo = (BITMAPINFO *)SDL_malloc(binfo_size);
850 if ( video != current ) {
851 SDL_FreeSurface(video);
857 binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
858 binfo->bmiHeader.biWidth = video->w;
859 binfo->bmiHeader.biHeight = -video->h; /* -ve for topdown bitmap */
860 binfo->bmiHeader.biPlanes = 1;
861 binfo->bmiHeader.biSizeImage = video->h * video->pitch;
862 binfo->bmiHeader.biXPelsPerMeter = 0;
863 binfo->bmiHeader.biYPelsPerMeter = 0;
864 binfo->bmiHeader.biClrUsed = 0;
865 binfo->bmiHeader.biClrImportant = 0;
866 binfo->bmiHeader.biBitCount = video->format->BitsPerPixel;
869 /* BI_BITFIELDS tells CreateDIBSection about the rgb masks in the palette */
870 binfo->bmiHeader.biCompression = BI_BITFIELDS;
871 ((Uint32*)binfo->bmiColors)[0] = video->format->Rmask;
872 ((Uint32*)binfo->bmiColors)[1] = video->format->Gmask;
873 ((Uint32*)binfo->bmiColors)[2] = video->format->Bmask;
875 binfo->bmiHeader.biCompression = BI_RGB; /* BI_BITFIELDS for 565 vs 555 */
876 if ( video->format->palette ) {
877 SDL_memset(binfo->bmiColors, 0,
878 video->format->palette->ncolors*sizeof(RGBQUAD));
882 /* Create the offscreen bitmap buffer */
883 hdc = GetDC(SDL_Window);
884 screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS,
885 (void **)(&video->pixels), NULL, 0);
886 ReleaseDC(SDL_Window, hdc);
888 if ( screen_bmp == NULL ) {
889 if ( video != current ) {
890 SDL_FreeSurface(video);
892 SDL_SetError("Couldn't create DIB section");
895 this->UpdateRects = DIB_NormalUpdate;
897 /* Set video surface flags */
898 if ( screen_pal && (flags & (SDL_FULLSCREEN|SDL_HWPALETTE)) ) {
902 /* BitBlt() maps colors for us */
903 video->flags |= SDL_HWPALETTE;
906 DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags);
909 /* Set up for OpenGL */
910 if ( flags & SDL_OPENGL ) {
911 if ( WIN_GL_SetupWindow(this) < 0 ) {
914 video->flags |= SDL_OPENGL;
918 Flush the message loop or this can cause big problems later
919 Especially if the user decides to use dialog boxes or assert()!
921 WIN_FlushMessageQueue();
927 /* We don't actually allow hardware surfaces in the DIB driver */
928 static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface)
932 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface)
936 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface)
940 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface)
945 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
950 hdc = GetDC(SDL_Window);
952 SelectPalette(hdc, screen_pal, FALSE);
954 mdc = CreateCompatibleDC(hdc);
955 SelectObject(mdc, screen_bmp);
956 for ( i=0; i<numrects; ++i ) {
957 BitBlt(hdc, rects[i].x, rects[i].y, rects[i].w, rects[i].h,
958 mdc, rects[i].x, rects[i].y, SRCCOPY);
961 ReleaseDC(SDL_Window, hdc);
964 static int FindPaletteIndex(LOGPALETTE *pal, BYTE r, BYTE g, BYTE b)
968 int nentries = pal->palNumEntries;
970 for ( i = 0; i < nentries; ++i ) {
971 entry = &pal->palPalEntry[i];
972 if ( entry->peRed == r && entry->peGreen == g && entry->peBlue == b ) {
979 static BOOL CheckPaletteEntry(LOGPALETTE *pal, int index, BYTE r, BYTE g, BYTE b)
984 entry = &pal->palPalEntry[index];
985 if ( entry->peRed != r || entry->peGreen != g || entry->peBlue != b ) {
986 int found = FindPaletteIndex(pal, r, g, b);
988 pal->palPalEntry[found] = *entry;
1000 int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
1002 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
1009 int moved_entries = 0;
1011 /* Update the display palette */
1012 hdc = GetDC(SDL_Window);
1014 PALETTEENTRY *entry;
1016 for ( i=0; i<ncolors; ++i ) {
1017 entry = &screen_logpal->palPalEntry[firstcolor+i];
1018 entry->peRed = colors[i].r;
1019 entry->peGreen = colors[i].g;
1020 entry->peBlue = colors[i].b;
1021 entry->peFlags = PC_NOCOLLAPSE;
1023 #if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE)
1024 /* Check to make sure black and white are in position */
1025 if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) {
1026 moved_entries += CheckPaletteEntry(screen_logpal, 0, 0x00, 0x00, 0x00);
1027 moved_entries += CheckPaletteEntry(screen_logpal, screen_logpal->palNumEntries-1, 0xff, 0xff, 0xff);
1030 If we don't have full access to the palette, what we
1031 really want to do is find the 236 most diverse colors
1032 in the desired palette, set those entries (10-245) and
1033 then map everything into the new system palette.
1038 /* Copy the entries into the system palette */
1039 UnrealizeObject(screen_pal);
1041 SetPaletteEntries(screen_pal, 0, screen_logpal->palNumEntries, screen_logpal->palPalEntry);
1042 SelectPalette(hdc, screen_pal, FALSE);
1043 RealizePalette(hdc);
1046 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
1047 /* Copy palette colors into DIB palette */
1048 pal = SDL_stack_alloc(RGBQUAD, ncolors);
1049 for ( i=0; i<ncolors; ++i ) {
1050 pal[i].rgbRed = colors[i].r;
1051 pal[i].rgbGreen = colors[i].g;
1052 pal[i].rgbBlue = colors[i].b;
1053 pal[i].rgbReserved = 0;
1056 /* Set the DIB palette and update the display */
1057 mdc = CreateCompatibleDC(hdc);
1058 SelectObject(mdc, screen_bmp);
1059 SetDIBColorTable(mdc, firstcolor, ncolors, pal);
1060 if ( moved_entries || !grab_palette ) {
1061 BitBlt(hdc, 0, 0, this->screen->w, this->screen->h,
1062 mdc, 0, 0, SRCCOPY);
1065 SDL_stack_free(pal);
1067 ReleaseDC(SDL_Window, hdc);
1072 static void DIB_CheckGamma(_THIS)
1074 #ifndef NO_GAMMA_SUPPORT
1078 /* If we fail to get gamma, disable gamma control */
1079 hdc = GetDC(SDL_Window);
1080 if ( ! GetDeviceGammaRamp(hdc, ramp) ) {
1081 this->GetGammaRamp = NULL;
1082 this->SetGammaRamp = NULL;
1084 ReleaseDC(SDL_Window, hdc);
1085 #endif /* !NO_GAMMA_SUPPORT */
1087 void DIB_SwapGamma(_THIS)
1089 #ifndef NO_GAMMA_SUPPORT
1092 if ( gamma_saved ) {
1093 hdc = GetDC(SDL_Window);
1094 if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
1095 /* About to leave active state, restore gamma */
1096 SetDeviceGammaRamp(hdc, gamma_saved);
1098 /* About to enter active state, set game gamma */
1099 GetDeviceGammaRamp(hdc, gamma_saved);
1100 SetDeviceGammaRamp(hdc, this->gamma);
1102 ReleaseDC(SDL_Window, hdc);
1104 #endif /* !NO_GAMMA_SUPPORT */
1106 void DIB_QuitGamma(_THIS)
1108 #ifndef NO_GAMMA_SUPPORT
1109 if ( gamma_saved ) {
1110 /* Restore the original gamma if necessary */
1111 if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
1114 hdc = GetDC(SDL_Window);
1115 SetDeviceGammaRamp(hdc, gamma_saved);
1116 ReleaseDC(SDL_Window, hdc);
1119 /* Free the saved gamma memory */
1120 SDL_free(gamma_saved);
1123 #endif /* !NO_GAMMA_SUPPORT */
1126 int DIB_SetGammaRamp(_THIS, Uint16 *ramp)
1128 #ifdef NO_GAMMA_SUPPORT
1129 SDL_SetError("SDL compiled without gamma ramp support");
1135 /* Set the ramp for the display */
1136 if ( ! gamma_saved ) {
1137 gamma_saved = (WORD *)SDL_malloc(3*256*sizeof(*gamma_saved));
1138 if ( ! gamma_saved ) {
1142 hdc = GetDC(SDL_Window);
1143 GetDeviceGammaRamp(hdc, gamma_saved);
1144 ReleaseDC(SDL_Window, hdc);
1146 if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
1147 hdc = GetDC(SDL_Window);
1148 succeeded = SetDeviceGammaRamp(hdc, ramp);
1149 ReleaseDC(SDL_Window, hdc);
1153 return succeeded ? 0 : -1;
1154 #endif /* !NO_GAMMA_SUPPORT */
1157 int DIB_GetGammaRamp(_THIS, Uint16 *ramp)
1159 #ifdef NO_GAMMA_SUPPORT
1160 SDL_SetError("SDL compiled without gamma ramp support");
1166 /* Get the ramp from the display */
1167 hdc = GetDC(SDL_Window);
1168 succeeded = GetDeviceGammaRamp(hdc, ramp);
1169 ReleaseDC(SDL_Window, hdc);
1170 return succeeded ? 0 : -1;
1171 #endif /* !NO_GAMMA_SUPPORT */
1174 void DIB_VideoQuit(_THIS)
1178 /* Destroy the window and everything associated with it */
1180 /* Delete the screen bitmap (also frees screen->pixels) */
1181 if ( this->screen ) {
1182 if ( grab_palette ) {
1183 DIB_ReleaseStaticColors(SDL_Window);
1185 #ifndef NO_CHANGEDISPLAYSETTINGS
1186 if ( this->screen->flags & SDL_FULLSCREEN ) {
1187 ChangeDisplaySettings(NULL, 0);
1188 ShowWindow(SDL_Window, SW_HIDE);
1191 if ( this->screen->flags & SDL_OPENGL ) {
1192 WIN_GL_ShutDown(this);
1194 this->screen->pixels = NULL;
1196 if ( screen_pal != NULL ) {
1197 DeleteObject(screen_pal);
1200 if ( screen_logpal != NULL ) {
1201 SDL_free(screen_logpal);
1202 screen_logpal = NULL;
1205 DeleteObject(screen_bmp);
1209 DestroyIcon(screen_icn);
1212 DIB_QuitGamma(this);
1213 DIB_DestroyWindow(this);
1217 #if defined(_WIN32_WCE)
1219 // Unload wince aygshell library to prevent leak
1222 FreeLibrary(aygshell);
1228 for ( i=0; i < SDL_arraysize(SDL_modelist); ++i ) {
1229 if ( !SDL_modelist[i] ) {
1232 for ( j=0; SDL_modelist[i][j]; ++j ) {
1233 SDL_free(SDL_modelist[i][j]);
1235 SDL_free(SDL_modelist[i]);
1236 SDL_modelist[i] = NULL;
1237 SDL_nummodes[i] = 0;
1241 /* Exported for the windows message loop only */
1242 static void DIB_GrabStaticColors(HWND window)
1244 #if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE)
1247 hdc = GetDC(window);
1248 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC256);
1249 if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) {
1250 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
1252 ReleaseDC(window, hdc);
1255 static void DIB_ReleaseStaticColors(HWND window)
1257 #if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE)
1260 hdc = GetDC(window);
1261 SetSystemPaletteUse(hdc, SYSPAL_STATIC);
1262 ReleaseDC(window, hdc);
1265 static void DIB_Activate(_THIS, BOOL active, BOOL minimized)
1267 if ( grab_palette ) {
1269 DIB_ReleaseStaticColors(SDL_Window);
1270 DIB_RealizePalette(this);
1271 } else if ( !minimized ) {
1272 DIB_GrabStaticColors(SDL_Window);
1273 DIB_RealizePalette(this);
1277 static void DIB_RealizePalette(_THIS)
1279 if ( screen_pal != NULL ) {
1282 hdc = GetDC(SDL_Window);
1284 UnrealizeObject(screen_pal);
1286 SelectPalette(hdc, screen_pal, FALSE);
1287 if ( RealizePalette(hdc) ) {
1288 InvalidateRect(SDL_Window, NULL, FALSE);
1290 ReleaseDC(SDL_Window, hdc);
1293 static void DIB_PaletteChanged(_THIS, HWND window)
1295 if ( window != SDL_Window ) {
1296 DIB_RealizePalette(this);
1300 /* Exported for the windows message loop only */
1301 static void DIB_WinPAINT(_THIS, HDC hdc)
1306 SelectPalette(hdc, screen_pal, FALSE);
1308 mdc = CreateCompatibleDC(hdc);
1309 SelectObject(mdc, screen_bmp);
1310 BitBlt(hdc, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h,
1311 mdc, 0, 0, SRCCOPY);
1315 /* Stub in case DirectX isn't available */
1316 #if !SDL_AUDIO_DRIVER_DSOUND
1317 void DX5_SoundFocus(HWND hwnd)