SDL-1.2.14
[sdl_omap.git] / src / video / windib / SDL_dibvideo.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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 #define WIN32_LEAN_AND_MEAN
25 #include <windows.h>
26
27 /* Not yet in the mingw32 cross-compile headers */
28 #ifndef CDS_FULLSCREEN
29 #define CDS_FULLSCREEN  4
30 #endif
31
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"
43
44 #ifdef _WIN32_WCE
45
46 #ifndef DM_DISPLAYORIENTATION
47 #define DM_DISPLAYORIENTATION 0x00800000L
48 #endif
49 #ifndef DM_DISPLAYQUERYORIENTATION 
50 #define DM_DISPLAYQUERYORIENTATION 0x01000000L
51 #endif
52 #ifndef DMDO_0
53 #define DMDO_0      0
54 #endif
55 #ifndef DMDO_90
56 #define DMDO_90     1
57 #endif
58 #ifndef DMDO_180
59 #define DMDO_180    2
60 #endif
61 #ifndef DMDO_270
62 #define DMDO_270    4
63 #endif
64
65 #define NO_GETDIBITS
66 #define NO_GAMMA_SUPPORT
67   #if _WIN32_WCE < 420
68     #define NO_CHANGEDISPLAYSETTINGS
69   #else
70     #define ChangeDisplaySettings(lpDevMode, dwFlags) ChangeDisplaySettingsEx(NULL, (lpDevMode), 0, (dwFlags), 0)
71   #endif
72 #endif
73 #ifndef WS_MAXIMIZE
74 #define WS_MAXIMIZE     0
75 #endif
76 #ifndef WS_THICKFRAME
77 #define WS_THICKFRAME   0
78 #endif
79 #ifndef SWP_NOCOPYBITS
80 #define SWP_NOCOPYBITS  0
81 #endif
82 #ifndef PC_NOCOLLAPSE
83 #define PC_NOCOLLAPSE   0
84 #endif
85
86 #ifdef _WIN32_WCE
87 // defined and used in SDL_sysevents.c
88 extern HINSTANCE aygshell;
89 #endif
90
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,
96                          SDL_Color *colors);
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);
103
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);
109
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);
117
118 /* helper fn */
119 static int DIB_SussScreenDepth();
120
121 /* DIB driver bootstrap functions */
122
123 static int DIB_Available(void)
124 {
125         return(1);
126 }
127
128 static void DIB_DeleteDevice(SDL_VideoDevice *device)
129 {
130         if ( device ) {
131                 if ( device->hidden ) {
132                         if ( device->hidden->dibInfo ) {
133                                 SDL_free( device->hidden->dibInfo );
134                         }
135                         SDL_free(device->hidden);
136                 }
137                 if ( device->gl_data ) {
138                         SDL_free(device->gl_data);
139                 }
140                 SDL_free(device);
141         }
142 }
143
144 static SDL_VideoDevice *DIB_CreateDevice(int devindex)
145 {
146         SDL_VideoDevice *device;
147
148         /* Initialize all variables that we clean on shutdown */
149         device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
150         if ( device ) {
151                 SDL_memset(device, 0, (sizeof *device));
152                 device->hidden = (struct SDL_PrivateVideoData *)
153                                 SDL_malloc((sizeof *device->hidden));
154                 if(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)
158                         {
159                                 SDL_free(device->hidden);
160                                 device->hidden = NULL;
161                         }
162                 }
163                 
164                 device->gl_data = (struct SDL_PrivateGLData *)
165                                 SDL_malloc((sizeof *device->gl_data));
166         }
167         if ( (device == NULL) || (device->hidden == NULL) ||
168                                  (device->gl_data == NULL) ) {
169                 SDL_OutOfMemory();
170                 DIB_DeleteDevice(device);
171                 return(NULL);
172         }
173         SDL_memset(device->hidden->dibInfo, 0, (sizeof *device->hidden->dibInfo));
174         SDL_memset(device->gl_data, 0, (sizeof *device->gl_data));
175
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;
195 #if SDL_VIDEO_OPENGL
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;
201 #endif
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;
214
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;
221
222         device->free = DIB_DeleteDevice;
223
224         /* We're finally ready */
225         return device;
226 }
227
228 VideoBootStrap WINDIB_bootstrap = {
229         "windib", "Win95/98/NT/2000/CE GDI",
230         DIB_Available, DIB_CreateDevice
231 };
232
233 static int cmpmodes(const void *va, const void *vb)
234 {
235     SDL_Rect *a = *(SDL_Rect **)va;
236     SDL_Rect *b = *(SDL_Rect **)vb;
237     if ( a->w == b->w )
238         return b->h - a->h;
239     else
240         return b->w - a->w;
241 }
242
243 static int DIB_AddMode(_THIS, int bpp, int w, int h)
244 {
245         SDL_Rect *mode;
246         int i, index;
247         int next_mode;
248
249         /* Check to see if we already have this mode */
250         if ( bpp < 8 || bpp > 32 ) {  /* Not supported */
251                 return(0);
252         }
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) ) {
257                         return(0);
258                 }
259         }
260
261         /* Set up the new video mode rectangle */
262         mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
263         if ( mode == NULL ) {
264                 SDL_OutOfMemory();
265                 return(-1);
266         }
267         mode->x = 0;
268         mode->y = 0;
269         mode->w = w;
270         mode->h = h;
271
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 ) {
277                 SDL_OutOfMemory();
278                 SDL_nummodes[index] = 0;
279                 SDL_free(mode);
280                 return(-1);
281         }
282         SDL_modelist[index][next_mode] = mode;
283         SDL_modelist[index][next_mode+1] = NULL;
284         SDL_nummodes[index]++;
285
286         return(0);
287 }
288
289 static void DIB_CreatePalette(_THIS, int bpp)
290 {
291 /*      RJR: March 28, 2000
292         moved palette creation here from "DIB_VideoInit" */
293
294         LOGPALETTE *palette;
295         HDC hdc;
296         int ncolors;
297
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;
308 }
309
310 int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat)
311 {
312         const char *env = NULL;
313 #ifndef NO_CHANGEDISPLAYSETTINGS
314         int i;
315         DEVMODE settings;
316 #endif
317
318         /* Create the window */
319         if ( DIB_CreateWindow(this) < 0 ) {
320                 return(-1);
321         }
322
323 #if !SDL_AUDIO_DISABLED
324         DX5_SoundFocus(SDL_Window);
325 #endif
326
327         /* Determine the screen depth */
328         vformat->BitsPerPixel = DIB_SussScreenDepth();
329         switch (vformat->BitsPerPixel) {
330                 case 15:
331                         vformat->Rmask = 0x00007c00;
332                         vformat->Gmask = 0x000003e0;
333                         vformat->Bmask = 0x0000001f;
334                         vformat->BitsPerPixel = 16;
335                         break;
336                 case 16:
337                         vformat->Rmask = 0x0000f800;
338                         vformat->Gmask = 0x000007e0;
339                         vformat->Bmask = 0x0000001f;
340                         break;
341                 case 24:
342                 case 32:
343                         /* GDI defined as 8-8-8 */
344                         vformat->Rmask = 0x00ff0000;
345                         vformat->Gmask = 0x0000ff00;
346                         vformat->Bmask = 0x000000ff;
347                         break;
348                 default:
349                         break;
350         }
351
352         /* See if gamma is supported on this screen */
353         DIB_CheckGamma(this);
354
355 #ifndef NO_CHANGEDISPLAYSETTINGS
356
357         settings.dmSize = sizeof(DEVMODE);
358         settings.dmDriverExtra = 0;
359 #ifdef _WIN32_WCE
360         settings.dmFields = DM_DISPLAYQUERYORIENTATION;
361         this->hidden->supportRotation = ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL;
362 #endif
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;
369
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);
374 #ifdef _WIN32_WCE               
375                 if( this->hidden->supportRotation )
376                         DIB_AddMode(this, settings.dmBitsPerPel,
377                                 settings.dmPelsHeight, settings.dmPelsWidth);
378 #endif
379         }
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);
384                 }
385         }
386 #else
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.
392
393         DIB_AddMode(this, vformat->BitsPerPixel,
394                         GetDeviceCaps(GetDC(NULL), HORZRES), 
395                         GetDeviceCaps(GetDC(NULL), VERTRES));
396
397 #endif /* !NO_CHANGEDISPLAYSETTINGS */
398
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);
404         }
405
406         /* Fill in some window manager capabilities */
407         this->info.wm_available = 1;
408
409 #ifdef _WIN32_WCE
410         this->hidden->origRotation = -1;
411 #endif
412
413         /* Allow environment override of screensaver disable. */
414         env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
415         if ( env ) {
416                 allow_screensaver = SDL_atoi(env);
417         } else {
418 #ifdef SDL_VIDEO_DISABLE_SCREENSAVER
419                 allow_screensaver = 0;
420 #else
421                 allow_screensaver = 1;
422 #endif
423         }
424
425         /* We're done! */
426         return(0);
427 }
428
429 /* We support any format at any dimension */
430 SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
431 {
432         if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
433                 return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
434         } else {
435                 return((SDL_Rect **)-1);
436         }
437 }
438
439
440 /*
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)
446 */
447 static int DIB_SussScreenDepth()
448 {
449 #ifdef NO_GETDIBITS
450         int depth;
451         HDC hdc;
452
453         hdc = GetDC(SDL_Window);
454         depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
455         ReleaseDC(SDL_Window, hdc);
456         return(depth);
457 #else
458     int depth;
459     int dib_size;
460     LPBITMAPINFOHEADER dib_hdr;
461     HDC hdc;
462     HBITMAP hbm;
463
464     /* Allocate enough space for a DIB header plus palette (for
465      * 8-bit modes) or bitfields (for 16- and 32-bit modes)
466      */
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);
471     
472     /* Get a device-dependent bitmap that's compatible with the
473        screen.
474      */
475     hdc = GetDC(NULL);
476     hbm = CreateCompatibleBitmap( hdc, 1, 1 );
477
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.
481      */
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);
484     DeleteObject(hbm);
485     ReleaseDC(NULL, hdc);
486
487     depth = 0;
488     switch( dib_hdr->biBitCount )
489     {
490     case 8:     depth = 8; break;
491     case 24:    depth = 24; break;
492     case 32:    depth = 32; break;
493     case 16:
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 */
499             }
500         }
501     }
502     SDL_free(dib_hdr);
503     return depth;
504 #endif /* NO_GETDIBITS */
505 }
506
507
508 /* Various screen update functions available */
509 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
510
511 static void DIB_ResizeWindow(_THIS, int width, int height, int prev_width, int prev_height, Uint32 flags)
512 {
513         RECT bounds;
514         int x, y;
515
516 #ifndef _WIN32_WCE
517         /* Resize the window */
518         if ( !SDL_windowid && !IsZoomed(SDL_Window) ) {
519 #else
520         if ( !SDL_windowid ) {
521 #endif
522                 HWND top;
523                 UINT swp_flags;
524                 const char *window = NULL;
525                 const char *center = NULL;
526
527                 if ( width != prev_width || height != prev_height ) {
528                         window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
529                         center = SDL_getenv("SDL_VIDEO_CENTERED");
530                         if ( window ) {
531                                 if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) {
532                                         SDL_windowX = x;
533                                         SDL_windowY = y;
534                                 }
535                                 if ( SDL_strcmp(window, "center") == 0 ) {
536                                         center = window;
537                                 }
538                         }
539                 }
540                 swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW);
541
542                 bounds.left = SDL_windowX;
543                 bounds.top = SDL_windowY;
544                 bounds.right = SDL_windowX+width;
545                 bounds.bottom = SDL_windowY+height;
546 #ifndef _WIN32_WCE
547                 AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0);
548 #else
549                 // The bMenu parameter must be FALSE; menu bars are not supported
550                 AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), 0, 0);
551 #endif
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 ) {
561                         x = bounds.left;
562                         y = bounds.top;
563                 } else {
564                         x = y = -1;
565                         swp_flags |= SWP_NOMOVE;
566                 }
567                 if ( flags & SDL_FULLSCREEN ) {
568                         top = HWND_TOPMOST;
569                 } else {
570                         top = HWND_NOTOPMOST;
571                 }
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;
576                 }
577                 SetForegroundWindow(SDL_Window);
578         }
579 }
580
581 SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current,
582                                 int width, int height, int bpp, Uint32 flags)
583 {
584         SDL_Surface *video;
585         int prev_w, prev_h;
586         Uint32 prev_flags;
587         DWORD style;
588         const DWORD directstyle =
589                         (WS_POPUP);
590         const DWORD windowstyle = 
591                         (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
592         const DWORD resizestyle =
593                         (WS_THICKFRAME|WS_MAXIMIZEBOX);
594         int binfo_size;
595         BITMAPINFO *binfo;
596         HDC hdc;
597         Uint32 Rmask, Gmask, Bmask;
598
599         prev_w = current->w;
600         prev_h = current->h;
601         prev_flags = current->flags;
602
603         /*
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.
611          */
612         if ( SDL_Window &&
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 */
617                 current->w = width;
618                 current->h = height;
619                 SDL_resizing = 1;
620                 DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags);
621                 SDL_resizing = 0;
622                 return current;
623         }
624
625         /* Clean up any GL context that may be hanging around */
626         if ( current->flags & SDL_OPENGL ) {
627                 WIN_GL_ShutDown(this);
628         }
629         SDL_resizing = 1;
630
631         /* Recalculate the bitmasks if necessary */
632         if ( bpp == current->format->BitsPerPixel ) {
633                 video = current;
634         } else {
635                 switch (bpp) {
636                         case 15:
637                         case 16:
638                                 if ( DIB_SussScreenDepth() == 15 ) {
639                                         /* 5-5-5 */
640                                         Rmask = 0x00007c00;
641                                         Gmask = 0x000003e0;
642                                         Bmask = 0x0000001f;
643                                 } else {
644                                         /* 5-6-5 */
645                                         Rmask = 0x0000f800;
646                                         Gmask = 0x000007e0;
647                                         Bmask = 0x0000001f;
648                                 }
649                                 break;
650                         case 24:
651                         case 32:
652                                 /* GDI defined as 8-8-8 */
653                                 Rmask = 0x00ff0000;
654                                 Gmask = 0x0000ff00;
655                                 Bmask = 0x000000ff;
656                                 break;
657                         default:
658                                 Rmask = 0x00000000;
659                                 Gmask = 0x00000000;
660                                 Bmask = 0x00000000;
661                                 break;
662                 }
663                 video = SDL_CreateRGBSurface(SDL_SWSURFACE,
664                                         0, 0, bpp, Rmask, Gmask, Bmask, 0);
665                 if ( video == NULL ) {
666                         SDL_OutOfMemory();
667                         return(NULL);
668                 }
669         }
670
671         /* Fill in part of the video surface */
672         video->flags = 0;       /* Clear flags */
673         video->w = width;
674         video->h = height;
675         video->pitch = SDL_CalculatePitch(video);
676
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
681         */
682         SDL_VideoSurface = video;
683
684 #if defined(_WIN32_WCE)
685         if ( flags & SDL_FULLSCREEN )
686                 video->flags |= SDL_FULLSCREEN;
687 #endif
688
689 #ifndef NO_CHANGEDISPLAYSETTINGS
690         /* Set fullscreen mode if appropriate */
691         if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
692                 DEVMODE settings;
693                 BOOL changed;
694
695                 SDL_memset(&settings, 0, sizeof(DEVMODE));
696                 settings.dmSize = sizeof(DEVMODE);
697
698 #ifdef _WIN32_WCE
699                 // try to rotate screen to fit requested resolution
700                 if( this->hidden->supportRotation )
701                 {
702                         DWORD rotation;
703
704                         // ask current mode
705                         settings.dmFields = DM_DISPLAYORIENTATION;
706                         ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL);
707                         rotation = settings.dmDisplayOrientation;
708
709                         if( (width > GetDeviceCaps(GetDC(NULL), HORZRES))
710                                 && (height < GetDeviceCaps(GetDC(NULL), VERTRES)))
711                         {
712                                 switch( rotation )
713                                 {
714                                 case DMDO_0:
715                                         settings.dmDisplayOrientation = DMDO_90;
716                                         break;
717                                 case DMDO_270:
718                                         settings.dmDisplayOrientation = DMDO_180;
719                                         break;
720                                 }
721                                 if( settings.dmDisplayOrientation != rotation )
722                                 {
723                                         // go to landscape
724                                         this->hidden->origRotation = rotation;
725                                         ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL);
726                                 }
727                         }
728                         if( (width < GetDeviceCaps(GetDC(NULL), HORZRES))
729                                 && (height > GetDeviceCaps(GetDC(NULL), VERTRES)))
730                         {
731                                 switch( rotation )
732                                 {
733                                 case DMDO_90:
734                                         settings.dmDisplayOrientation = DMDO_0;
735                                         break;
736                                 case DMDO_180:
737                                         settings.dmDisplayOrientation = DMDO_270;
738                                         break;
739                                 }
740                                 if( settings.dmDisplayOrientation != rotation )
741                                 {
742                                         // go to portrait
743                                         this->hidden->origRotation = rotation;
744                                         ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL);
745                                 }
746                         }
747
748                 }
749 #endif
750
751 #ifndef _WIN32_WCE
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;
760                 }
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);
765                 }
766 #else
767                 changed = 1;
768 #endif
769                 if ( changed ) {
770                         video->flags |= SDL_FULLSCREEN;
771                         SDL_fullscreen_mode = settings;
772                 }
773
774         }
775 #endif /* !NO_CHANGEDISPLAYSETTINGS */
776
777         /* Reset the palette and create a new one if necessary */
778         if ( grab_palette ) {
779                 DIB_ReleaseStaticColors(SDL_Window);
780                 grab_palette = FALSE;
781         }
782         if ( screen_pal != NULL ) {
783         /*      RJR: March 28, 2000
784                 delete identity palette if switching from a palettized mode */
785                 DeleteObject(screen_pal);
786                 screen_pal = NULL;
787         }
788         if ( screen_logpal != NULL ) {
789                 SDL_free(screen_logpal);
790                 screen_logpal = NULL;
791         }
792
793         if ( bpp <= 8 )
794         {
795         /*      RJR: March 28, 2000
796                 create identity palette switching to a palettized mode */
797                 DIB_CreatePalette(this, bpp);
798         }
799
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;
805         } else {
806 #ifndef NO_CHANGEDISPLAYSETTINGS
807                 if ( (prev_flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
808                         ChangeDisplaySettings(NULL, 0);
809                 }
810 #endif
811                 if ( flags & SDL_NOFRAME ) {
812                         style &= ~windowstyle;
813                         style |= directstyle;
814                         video->flags |= SDL_NOFRAME;
815                 } else {
816                         style &= ~directstyle;
817                         style |= windowstyle;
818                         if ( flags & SDL_RESIZABLE ) {
819                                 style |= resizestyle;
820                                 video->flags |= SDL_RESIZABLE;
821                         }
822                 }
823 #if WS_MAXIMIZE && !defined(_WIN32_WCE)
824                 if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
825 #endif
826         }
827
828         /* DJM: Don't piss of anyone who has setup his own window */
829         if ( !SDL_windowid )
830                 SetWindowLong(SDL_Window, GWL_STYLE, style);
831
832         /* Delete the old bitmap if necessary */
833         if ( screen_bmp != NULL ) {
834                 DeleteObject(screen_bmp);
835         }
836         if ( ! (flags & SDL_OPENGL) ) {
837                 BOOL is16bitmode = (video->format->BytesPerPixel == 2);
838
839                 /* Suss out the bitmap info header */
840                 binfo_size = sizeof(*binfo);
841                 if( is16bitmode ) {
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 *
846                                                         sizeof(RGBQUAD);
847                 }
848                 binfo = (BITMAPINFO *)SDL_malloc(binfo_size);
849                 if ( ! binfo ) {
850                         if ( video != current ) {
851                                 SDL_FreeSurface(video);
852                         }
853                         SDL_OutOfMemory();
854                         return(NULL);
855                 }
856
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;
867
868                 if ( is16bitmode ) {
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;
874                 } else {
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));
879                         }
880                 }
881
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);
887                 SDL_free(binfo);
888                 if ( screen_bmp == NULL ) {
889                         if ( video != current ) {
890                                 SDL_FreeSurface(video);
891                         }
892                         SDL_SetError("Couldn't create DIB section");
893                         return(NULL);
894                 }
895                 this->UpdateRects = DIB_NormalUpdate;
896
897                 /* Set video surface flags */
898                 if ( screen_pal && (flags & (SDL_FULLSCREEN|SDL_HWPALETTE)) ) {
899                         grab_palette = TRUE;
900                 }
901                 if ( screen_pal ) {
902                         /* BitBlt() maps colors for us */
903                         video->flags |= SDL_HWPALETTE;
904                 }
905         }
906         DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags);
907         SDL_resizing = 0;
908
909         /* Set up for OpenGL */
910         if ( flags & SDL_OPENGL ) {
911                 if ( WIN_GL_SetupWindow(this) < 0 ) {
912                         return(NULL);
913                 }
914                 video->flags |= SDL_OPENGL;
915         }
916
917         /* JC 14 Mar 2006
918                 Flush the message loop or this can cause big problems later
919                 Especially if the user decides to use dialog boxes or assert()!
920         */
921         WIN_FlushMessageQueue();
922
923         /* We're live! */
924         return(video);
925 }
926
927 /* We don't actually allow hardware surfaces in the DIB driver */
928 static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface)
929 {
930         return(-1);
931 }
932 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface)
933 {
934         return;
935 }
936 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface)
937 {
938         return(0);
939 }
940 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface)
941 {
942         return;
943 }
944
945 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
946 {
947         HDC hdc, mdc;
948         int i;
949
950         hdc = GetDC(SDL_Window);
951         if ( screen_pal ) {
952                 SelectPalette(hdc, screen_pal, FALSE);
953         }
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);
959         }
960         DeleteDC(mdc);
961         ReleaseDC(SDL_Window, hdc);
962 }
963
964 static int FindPaletteIndex(LOGPALETTE *pal, BYTE r, BYTE g, BYTE b)
965 {
966         PALETTEENTRY *entry;
967         int i;
968         int nentries = pal->palNumEntries;
969
970         for ( i = 0; i < nentries; ++i ) {
971                 entry = &pal->palPalEntry[i];
972                 if ( entry->peRed == r && entry->peGreen == g && entry->peBlue == b ) {
973                         return i;
974                 }
975         }
976         return -1;
977 }
978
979 static BOOL CheckPaletteEntry(LOGPALETTE *pal, int index, BYTE r, BYTE g, BYTE b)
980 {
981         PALETTEENTRY *entry;
982         BOOL moved = 0;
983
984         entry = &pal->palPalEntry[index];
985         if ( entry->peRed != r || entry->peGreen != g || entry->peBlue != b ) {
986                 int found = FindPaletteIndex(pal, r, g, b);
987                 if ( found >= 0 ) {
988                         pal->palPalEntry[found] = *entry;
989                 }
990                 entry->peRed = r;
991                 entry->peGreen = g;
992                 entry->peBlue = b;
993                 moved = 1;
994         }
995         entry->peFlags = 0;
996
997         return moved;
998 }
999
1000 int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
1001 {
1002 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
1003         HDC hdc, mdc;
1004         RGBQUAD *pal;
1005 #else
1006         HDC hdc;
1007 #endif
1008         int i;
1009         int moved_entries = 0;
1010
1011         /* Update the display palette */
1012         hdc = GetDC(SDL_Window);
1013         if ( screen_pal ) {
1014                 PALETTEENTRY *entry;
1015
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;
1022                 }
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);
1028                 }
1029                 /* FIXME:
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.
1034                  */
1035 #endif
1036
1037 #ifndef _WIN32_WCE
1038                 /* Copy the entries into the system palette */
1039                 UnrealizeObject(screen_pal);
1040 #endif
1041                 SetPaletteEntries(screen_pal, 0, screen_logpal->palNumEntries, screen_logpal->palPalEntry);
1042                 SelectPalette(hdc, screen_pal, FALSE);
1043                 RealizePalette(hdc);
1044         }
1045
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;
1054         }
1055
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);
1063         }
1064         DeleteDC(mdc);
1065         SDL_stack_free(pal);
1066 #endif
1067         ReleaseDC(SDL_Window, hdc);
1068         return(1);
1069 }
1070
1071
1072 static void DIB_CheckGamma(_THIS)
1073 {
1074 #ifndef NO_GAMMA_SUPPORT
1075         HDC hdc;
1076         WORD ramp[3*256];
1077
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;
1083         }
1084         ReleaseDC(SDL_Window, hdc);
1085 #endif /* !NO_GAMMA_SUPPORT */
1086 }
1087 void DIB_SwapGamma(_THIS)
1088 {
1089 #ifndef NO_GAMMA_SUPPORT
1090         HDC hdc;
1091
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);
1097                 } else {
1098                         /* About to enter active state, set game gamma */
1099                         GetDeviceGammaRamp(hdc, gamma_saved);
1100                         SetDeviceGammaRamp(hdc, this->gamma);
1101                 }
1102                 ReleaseDC(SDL_Window, hdc);
1103         }
1104 #endif /* !NO_GAMMA_SUPPORT */
1105 }
1106 void DIB_QuitGamma(_THIS)
1107 {
1108 #ifndef NO_GAMMA_SUPPORT
1109         if ( gamma_saved ) {
1110                 /* Restore the original gamma if necessary */
1111                 if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
1112                         HDC hdc;
1113
1114                         hdc = GetDC(SDL_Window);
1115                         SetDeviceGammaRamp(hdc, gamma_saved);
1116                         ReleaseDC(SDL_Window, hdc);
1117                 }
1118
1119                 /* Free the saved gamma memory */
1120                 SDL_free(gamma_saved);
1121                 gamma_saved = 0;
1122         }
1123 #endif /* !NO_GAMMA_SUPPORT */
1124 }
1125
1126 int DIB_SetGammaRamp(_THIS, Uint16 *ramp)
1127 {
1128 #ifdef NO_GAMMA_SUPPORT
1129         SDL_SetError("SDL compiled without gamma ramp support");
1130         return -1;
1131 #else
1132         HDC hdc;
1133         BOOL succeeded;
1134
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 ) {
1139                         SDL_OutOfMemory();
1140                         return -1;
1141                 }
1142                 hdc = GetDC(SDL_Window);
1143                 GetDeviceGammaRamp(hdc, gamma_saved);
1144                 ReleaseDC(SDL_Window, hdc);
1145         }
1146         if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
1147                 hdc = GetDC(SDL_Window);
1148                 succeeded = SetDeviceGammaRamp(hdc, ramp);
1149                 ReleaseDC(SDL_Window, hdc);
1150         } else {
1151                 succeeded = TRUE;
1152         }
1153         return succeeded ? 0 : -1;
1154 #endif /* !NO_GAMMA_SUPPORT */
1155 }
1156
1157 int DIB_GetGammaRamp(_THIS, Uint16 *ramp)
1158 {
1159 #ifdef NO_GAMMA_SUPPORT
1160         SDL_SetError("SDL compiled without gamma ramp support");
1161         return -1;
1162 #else
1163         HDC hdc;
1164         BOOL succeeded;
1165
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 */
1172 }
1173
1174 void DIB_VideoQuit(_THIS)
1175 {
1176         int i, j;
1177
1178         /* Destroy the window and everything associated with it */
1179         if ( SDL_Window ) {
1180                 /* Delete the screen bitmap (also frees screen->pixels) */
1181                 if ( this->screen ) {
1182                         if ( grab_palette ) {
1183                                 DIB_ReleaseStaticColors(SDL_Window);
1184                         }
1185 #ifndef NO_CHANGEDISPLAYSETTINGS
1186                         if ( this->screen->flags & SDL_FULLSCREEN ) {
1187                                 ChangeDisplaySettings(NULL, 0);
1188                                 ShowWindow(SDL_Window, SW_HIDE);
1189                         }
1190 #endif
1191                         if ( this->screen->flags & SDL_OPENGL ) {
1192                                 WIN_GL_ShutDown(this);
1193                         }
1194                         this->screen->pixels = NULL;
1195                 }
1196                 if ( screen_pal != NULL ) {
1197                         DeleteObject(screen_pal);
1198                         screen_pal = NULL;
1199                 }
1200                 if ( screen_logpal != NULL ) {
1201                         SDL_free(screen_logpal);
1202                         screen_logpal = NULL;
1203                 }
1204                 if ( screen_bmp ) {
1205                         DeleteObject(screen_bmp);
1206                         screen_bmp = NULL;
1207                 }
1208                 if ( screen_icn ) {
1209                         DestroyIcon(screen_icn);
1210                         screen_icn = NULL;
1211                 }
1212                 DIB_QuitGamma(this);
1213                 DIB_DestroyWindow(this);
1214
1215                 SDL_Window = NULL;
1216
1217 #if defined(_WIN32_WCE)
1218
1219 // Unload wince aygshell library to prevent leak
1220                 if( aygshell ) 
1221                 {
1222                         FreeLibrary(aygshell);
1223                         aygshell = NULL;
1224                 }
1225 #endif
1226         }
1227
1228         for ( i=0; i < SDL_arraysize(SDL_modelist); ++i ) {
1229                 if ( !SDL_modelist[i] ) {
1230                         continue;
1231                 }
1232                 for ( j=0; SDL_modelist[i][j]; ++j ) {
1233                         SDL_free(SDL_modelist[i][j]);
1234                 }
1235                 SDL_free(SDL_modelist[i]);
1236                 SDL_modelist[i] = NULL;
1237                 SDL_nummodes[i] = 0;
1238         }
1239 }
1240
1241 /* Exported for the windows message loop only */
1242 static void DIB_GrabStaticColors(HWND window)
1243 {
1244 #if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE)
1245         HDC hdc;
1246
1247         hdc = GetDC(window);
1248         SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC256);
1249         if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) {
1250                 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
1251         }
1252         ReleaseDC(window, hdc);
1253 #endif
1254 }
1255 static void DIB_ReleaseStaticColors(HWND window)
1256 {
1257 #if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE)
1258         HDC hdc;
1259
1260         hdc = GetDC(window);
1261         SetSystemPaletteUse(hdc, SYSPAL_STATIC);
1262         ReleaseDC(window, hdc);
1263 #endif
1264 }
1265 static void DIB_Activate(_THIS, BOOL active, BOOL minimized)
1266 {
1267         if ( grab_palette ) {
1268                 if ( !active ) {
1269                         DIB_ReleaseStaticColors(SDL_Window);
1270                         DIB_RealizePalette(this);
1271                 } else if ( !minimized ) {
1272                         DIB_GrabStaticColors(SDL_Window);
1273                         DIB_RealizePalette(this);
1274                 }
1275         }
1276 }
1277 static void DIB_RealizePalette(_THIS)
1278 {
1279         if ( screen_pal != NULL ) {
1280                 HDC hdc;
1281
1282                 hdc = GetDC(SDL_Window);
1283 #ifndef _WIN32_WCE
1284                 UnrealizeObject(screen_pal);
1285 #endif
1286                 SelectPalette(hdc, screen_pal, FALSE);
1287                 if ( RealizePalette(hdc) ) {
1288                         InvalidateRect(SDL_Window, NULL, FALSE);
1289                 }
1290                 ReleaseDC(SDL_Window, hdc);
1291         }
1292 }
1293 static void DIB_PaletteChanged(_THIS, HWND window)
1294 {
1295         if ( window != SDL_Window ) {
1296                 DIB_RealizePalette(this);
1297         }
1298 }
1299
1300 /* Exported for the windows message loop only */
1301 static void DIB_WinPAINT(_THIS, HDC hdc)
1302 {
1303         HDC mdc;
1304
1305         if ( screen_pal ) {
1306                 SelectPalette(hdc, screen_pal, FALSE);
1307         }
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);
1312         DeleteDC(mdc);
1313 }
1314
1315 /* Stub in case DirectX isn't available */
1316 #if !SDL_AUDIO_DRIVER_DSOUND
1317 void DX5_SoundFocus(HWND hwnd)
1318 {
1319         return;
1320 }
1321 #endif