src/video/windx5/SDL_dx5video.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 29 May 2006 04:04:35 +0000
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
child 1705 fc731a7d83ed
permissions -rw-r--r--
more tweaking indent options
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "directx.h"
    25 
    26 /* Not yet in the mingw32 cross-compile headers */
    27 #ifndef CDS_FULLSCREEN
    28 #define CDS_FULLSCREEN	4
    29 #endif
    30 
    31 #include "SDL_timer.h"
    32 #include "SDL_events.h"
    33 #include "SDL_syswm.h"
    34 #include "../SDL_sysvideo.h"
    35 #include "../SDL_blit.h"
    36 #include "../SDL_pixels_c.h"
    37 #include "SDL_dx5video.h"
    38 #include "../wincommon/SDL_syswm_c.h"
    39 #include "../wincommon/SDL_sysmouse_c.h"
    40 #include "SDL_dx5events_c.h"
    41 #include "SDL_dx5yuv_c.h"
    42 #include "../wincommon/SDL_wingl_c.h"
    43 
    44 #ifdef _WIN32_WCE
    45 #define NO_CHANGEDISPLAYSETTINGS
    46 #endif
    47 #ifndef WS_MAXIMIZE
    48 #define WS_MAXIMIZE		0
    49 #endif
    50 #ifndef SWP_NOCOPYBITS
    51 #define SWP_NOCOPYBITS	0
    52 #endif
    53 #ifndef PC_NOCOLLAPSE
    54 #define PC_NOCOLLAPSE	0
    55 #endif
    56 
    57 
    58 /* DirectX function pointers for video and events */
    59 HRESULT(WINAPI * DDrawCreate) (GUID FAR * lpGUID, LPDIRECTDRAW FAR * lplpDD,
    60                                IUnknown FAR * pUnkOuter);
    61 HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
    62                                 LPDIRECTINPUT * ppDI, LPUNKNOWN punkOuter);
    63 
    64 /* This is the rect EnumModes2 uses */
    65 struct DX5EnumRect
    66 {
    67     SDL_Rect r;
    68     int refreshRate;
    69     struct DX5EnumRect *next;
    70 };
    71 static struct DX5EnumRect *enumlists[NUM_MODELISTS];
    72 
    73 /*
    74  * Experimentally determined values for c_cfDI* constants used in DirectX 5.0
    75  */
    76 
    77 /* Keyboard */
    78 
    79 static DIOBJECTDATAFORMAT KBD_fmt[] = {
    80     {&GUID_Key, 0, 0x8000000C, 0x00000000},
    81     {&GUID_Key, 1, 0x8000010C, 0x00000000},
    82     {&GUID_Key, 2, 0x8000020C, 0x00000000},
    83     {&GUID_Key, 3, 0x8000030C, 0x00000000},
    84     {&GUID_Key, 4, 0x8000040C, 0x00000000},
    85     {&GUID_Key, 5, 0x8000050C, 0x00000000},
    86     {&GUID_Key, 6, 0x8000060C, 0x00000000},
    87     {&GUID_Key, 7, 0x8000070C, 0x00000000},
    88     {&GUID_Key, 8, 0x8000080C, 0x00000000},
    89     {&GUID_Key, 9, 0x8000090C, 0x00000000},
    90     {&GUID_Key, 10, 0x80000A0C, 0x00000000},
    91     {&GUID_Key, 11, 0x80000B0C, 0x00000000},
    92     {&GUID_Key, 12, 0x80000C0C, 0x00000000},
    93     {&GUID_Key, 13, 0x80000D0C, 0x00000000},
    94     {&GUID_Key, 14, 0x80000E0C, 0x00000000},
    95     {&GUID_Key, 15, 0x80000F0C, 0x00000000},
    96     {&GUID_Key, 16, 0x8000100C, 0x00000000},
    97     {&GUID_Key, 17, 0x8000110C, 0x00000000},
    98     {&GUID_Key, 18, 0x8000120C, 0x00000000},
    99     {&GUID_Key, 19, 0x8000130C, 0x00000000},
   100     {&GUID_Key, 20, 0x8000140C, 0x00000000},
   101     {&GUID_Key, 21, 0x8000150C, 0x00000000},
   102     {&GUID_Key, 22, 0x8000160C, 0x00000000},
   103     {&GUID_Key, 23, 0x8000170C, 0x00000000},
   104     {&GUID_Key, 24, 0x8000180C, 0x00000000},
   105     {&GUID_Key, 25, 0x8000190C, 0x00000000},
   106     {&GUID_Key, 26, 0x80001A0C, 0x00000000},
   107     {&GUID_Key, 27, 0x80001B0C, 0x00000000},
   108     {&GUID_Key, 28, 0x80001C0C, 0x00000000},
   109     {&GUID_Key, 29, 0x80001D0C, 0x00000000},
   110     {&GUID_Key, 30, 0x80001E0C, 0x00000000},
   111     {&GUID_Key, 31, 0x80001F0C, 0x00000000},
   112     {&GUID_Key, 32, 0x8000200C, 0x00000000},
   113     {&GUID_Key, 33, 0x8000210C, 0x00000000},
   114     {&GUID_Key, 34, 0x8000220C, 0x00000000},
   115     {&GUID_Key, 35, 0x8000230C, 0x00000000},
   116     {&GUID_Key, 36, 0x8000240C, 0x00000000},
   117     {&GUID_Key, 37, 0x8000250C, 0x00000000},
   118     {&GUID_Key, 38, 0x8000260C, 0x00000000},
   119     {&GUID_Key, 39, 0x8000270C, 0x00000000},
   120     {&GUID_Key, 40, 0x8000280C, 0x00000000},
   121     {&GUID_Key, 41, 0x8000290C, 0x00000000},
   122     {&GUID_Key, 42, 0x80002A0C, 0x00000000},
   123     {&GUID_Key, 43, 0x80002B0C, 0x00000000},
   124     {&GUID_Key, 44, 0x80002C0C, 0x00000000},
   125     {&GUID_Key, 45, 0x80002D0C, 0x00000000},
   126     {&GUID_Key, 46, 0x80002E0C, 0x00000000},
   127     {&GUID_Key, 47, 0x80002F0C, 0x00000000},
   128     {&GUID_Key, 48, 0x8000300C, 0x00000000},
   129     {&GUID_Key, 49, 0x8000310C, 0x00000000},
   130     {&GUID_Key, 50, 0x8000320C, 0x00000000},
   131     {&GUID_Key, 51, 0x8000330C, 0x00000000},
   132     {&GUID_Key, 52, 0x8000340C, 0x00000000},
   133     {&GUID_Key, 53, 0x8000350C, 0x00000000},
   134     {&GUID_Key, 54, 0x8000360C, 0x00000000},
   135     {&GUID_Key, 55, 0x8000370C, 0x00000000},
   136     {&GUID_Key, 56, 0x8000380C, 0x00000000},
   137     {&GUID_Key, 57, 0x8000390C, 0x00000000},
   138     {&GUID_Key, 58, 0x80003A0C, 0x00000000},
   139     {&GUID_Key, 59, 0x80003B0C, 0x00000000},
   140     {&GUID_Key, 60, 0x80003C0C, 0x00000000},
   141     {&GUID_Key, 61, 0x80003D0C, 0x00000000},
   142     {&GUID_Key, 62, 0x80003E0C, 0x00000000},
   143     {&GUID_Key, 63, 0x80003F0C, 0x00000000},
   144     {&GUID_Key, 64, 0x8000400C, 0x00000000},
   145     {&GUID_Key, 65, 0x8000410C, 0x00000000},
   146     {&GUID_Key, 66, 0x8000420C, 0x00000000},
   147     {&GUID_Key, 67, 0x8000430C, 0x00000000},
   148     {&GUID_Key, 68, 0x8000440C, 0x00000000},
   149     {&GUID_Key, 69, 0x8000450C, 0x00000000},
   150     {&GUID_Key, 70, 0x8000460C, 0x00000000},
   151     {&GUID_Key, 71, 0x8000470C, 0x00000000},
   152     {&GUID_Key, 72, 0x8000480C, 0x00000000},
   153     {&GUID_Key, 73, 0x8000490C, 0x00000000},
   154     {&GUID_Key, 74, 0x80004A0C, 0x00000000},
   155     {&GUID_Key, 75, 0x80004B0C, 0x00000000},
   156     {&GUID_Key, 76, 0x80004C0C, 0x00000000},
   157     {&GUID_Key, 77, 0x80004D0C, 0x00000000},
   158     {&GUID_Key, 78, 0x80004E0C, 0x00000000},
   159     {&GUID_Key, 79, 0x80004F0C, 0x00000000},
   160     {&GUID_Key, 80, 0x8000500C, 0x00000000},
   161     {&GUID_Key, 81, 0x8000510C, 0x00000000},
   162     {&GUID_Key, 82, 0x8000520C, 0x00000000},
   163     {&GUID_Key, 83, 0x8000530C, 0x00000000},
   164     {&GUID_Key, 84, 0x8000540C, 0x00000000},
   165     {&GUID_Key, 85, 0x8000550C, 0x00000000},
   166     {&GUID_Key, 86, 0x8000560C, 0x00000000},
   167     {&GUID_Key, 87, 0x8000570C, 0x00000000},
   168     {&GUID_Key, 88, 0x8000580C, 0x00000000},
   169     {&GUID_Key, 89, 0x8000590C, 0x00000000},
   170     {&GUID_Key, 90, 0x80005A0C, 0x00000000},
   171     {&GUID_Key, 91, 0x80005B0C, 0x00000000},
   172     {&GUID_Key, 92, 0x80005C0C, 0x00000000},
   173     {&GUID_Key, 93, 0x80005D0C, 0x00000000},
   174     {&GUID_Key, 94, 0x80005E0C, 0x00000000},
   175     {&GUID_Key, 95, 0x80005F0C, 0x00000000},
   176     {&GUID_Key, 96, 0x8000600C, 0x00000000},
   177     {&GUID_Key, 97, 0x8000610C, 0x00000000},
   178     {&GUID_Key, 98, 0x8000620C, 0x00000000},
   179     {&GUID_Key, 99, 0x8000630C, 0x00000000},
   180     {&GUID_Key, 100, 0x8000640C, 0x00000000},
   181     {&GUID_Key, 101, 0x8000650C, 0x00000000},
   182     {&GUID_Key, 102, 0x8000660C, 0x00000000},
   183     {&GUID_Key, 103, 0x8000670C, 0x00000000},
   184     {&GUID_Key, 104, 0x8000680C, 0x00000000},
   185     {&GUID_Key, 105, 0x8000690C, 0x00000000},
   186     {&GUID_Key, 106, 0x80006A0C, 0x00000000},
   187     {&GUID_Key, 107, 0x80006B0C, 0x00000000},
   188     {&GUID_Key, 108, 0x80006C0C, 0x00000000},
   189     {&GUID_Key, 109, 0x80006D0C, 0x00000000},
   190     {&GUID_Key, 110, 0x80006E0C, 0x00000000},
   191     {&GUID_Key, 111, 0x80006F0C, 0x00000000},
   192     {&GUID_Key, 112, 0x8000700C, 0x00000000},
   193     {&GUID_Key, 113, 0x8000710C, 0x00000000},
   194     {&GUID_Key, 114, 0x8000720C, 0x00000000},
   195     {&GUID_Key, 115, 0x8000730C, 0x00000000},
   196     {&GUID_Key, 116, 0x8000740C, 0x00000000},
   197     {&GUID_Key, 117, 0x8000750C, 0x00000000},
   198     {&GUID_Key, 118, 0x8000760C, 0x00000000},
   199     {&GUID_Key, 119, 0x8000770C, 0x00000000},
   200     {&GUID_Key, 120, 0x8000780C, 0x00000000},
   201     {&GUID_Key, 121, 0x8000790C, 0x00000000},
   202     {&GUID_Key, 122, 0x80007A0C, 0x00000000},
   203     {&GUID_Key, 123, 0x80007B0C, 0x00000000},
   204     {&GUID_Key, 124, 0x80007C0C, 0x00000000},
   205     {&GUID_Key, 125, 0x80007D0C, 0x00000000},
   206     {&GUID_Key, 126, 0x80007E0C, 0x00000000},
   207     {&GUID_Key, 127, 0x80007F0C, 0x00000000},
   208     {&GUID_Key, 128, 0x8000800C, 0x00000000},
   209     {&GUID_Key, 129, 0x8000810C, 0x00000000},
   210     {&GUID_Key, 130, 0x8000820C, 0x00000000},
   211     {&GUID_Key, 131, 0x8000830C, 0x00000000},
   212     {&GUID_Key, 132, 0x8000840C, 0x00000000},
   213     {&GUID_Key, 133, 0x8000850C, 0x00000000},
   214     {&GUID_Key, 134, 0x8000860C, 0x00000000},
   215     {&GUID_Key, 135, 0x8000870C, 0x00000000},
   216     {&GUID_Key, 136, 0x8000880C, 0x00000000},
   217     {&GUID_Key, 137, 0x8000890C, 0x00000000},
   218     {&GUID_Key, 138, 0x80008A0C, 0x00000000},
   219     {&GUID_Key, 139, 0x80008B0C, 0x00000000},
   220     {&GUID_Key, 140, 0x80008C0C, 0x00000000},
   221     {&GUID_Key, 141, 0x80008D0C, 0x00000000},
   222     {&GUID_Key, 142, 0x80008E0C, 0x00000000},
   223     {&GUID_Key, 143, 0x80008F0C, 0x00000000},
   224     {&GUID_Key, 144, 0x8000900C, 0x00000000},
   225     {&GUID_Key, 145, 0x8000910C, 0x00000000},
   226     {&GUID_Key, 146, 0x8000920C, 0x00000000},
   227     {&GUID_Key, 147, 0x8000930C, 0x00000000},
   228     {&GUID_Key, 148, 0x8000940C, 0x00000000},
   229     {&GUID_Key, 149, 0x8000950C, 0x00000000},
   230     {&GUID_Key, 150, 0x8000960C, 0x00000000},
   231     {&GUID_Key, 151, 0x8000970C, 0x00000000},
   232     {&GUID_Key, 152, 0x8000980C, 0x00000000},
   233     {&GUID_Key, 153, 0x8000990C, 0x00000000},
   234     {&GUID_Key, 154, 0x80009A0C, 0x00000000},
   235     {&GUID_Key, 155, 0x80009B0C, 0x00000000},
   236     {&GUID_Key, 156, 0x80009C0C, 0x00000000},
   237     {&GUID_Key, 157, 0x80009D0C, 0x00000000},
   238     {&GUID_Key, 158, 0x80009E0C, 0x00000000},
   239     {&GUID_Key, 159, 0x80009F0C, 0x00000000},
   240     {&GUID_Key, 160, 0x8000A00C, 0x00000000},
   241     {&GUID_Key, 161, 0x8000A10C, 0x00000000},
   242     {&GUID_Key, 162, 0x8000A20C, 0x00000000},
   243     {&GUID_Key, 163, 0x8000A30C, 0x00000000},
   244     {&GUID_Key, 164, 0x8000A40C, 0x00000000},
   245     {&GUID_Key, 165, 0x8000A50C, 0x00000000},
   246     {&GUID_Key, 166, 0x8000A60C, 0x00000000},
   247     {&GUID_Key, 167, 0x8000A70C, 0x00000000},
   248     {&GUID_Key, 168, 0x8000A80C, 0x00000000},
   249     {&GUID_Key, 169, 0x8000A90C, 0x00000000},
   250     {&GUID_Key, 170, 0x8000AA0C, 0x00000000},
   251     {&GUID_Key, 171, 0x8000AB0C, 0x00000000},
   252     {&GUID_Key, 172, 0x8000AC0C, 0x00000000},
   253     {&GUID_Key, 173, 0x8000AD0C, 0x00000000},
   254     {&GUID_Key, 174, 0x8000AE0C, 0x00000000},
   255     {&GUID_Key, 175, 0x8000AF0C, 0x00000000},
   256     {&GUID_Key, 176, 0x8000B00C, 0x00000000},
   257     {&GUID_Key, 177, 0x8000B10C, 0x00000000},
   258     {&GUID_Key, 178, 0x8000B20C, 0x00000000},
   259     {&GUID_Key, 179, 0x8000B30C, 0x00000000},
   260     {&GUID_Key, 180, 0x8000B40C, 0x00000000},
   261     {&GUID_Key, 181, 0x8000B50C, 0x00000000},
   262     {&GUID_Key, 182, 0x8000B60C, 0x00000000},
   263     {&GUID_Key, 183, 0x8000B70C, 0x00000000},
   264     {&GUID_Key, 184, 0x8000B80C, 0x00000000},
   265     {&GUID_Key, 185, 0x8000B90C, 0x00000000},
   266     {&GUID_Key, 186, 0x8000BA0C, 0x00000000},
   267     {&GUID_Key, 187, 0x8000BB0C, 0x00000000},
   268     {&GUID_Key, 188, 0x8000BC0C, 0x00000000},
   269     {&GUID_Key, 189, 0x8000BD0C, 0x00000000},
   270     {&GUID_Key, 190, 0x8000BE0C, 0x00000000},
   271     {&GUID_Key, 191, 0x8000BF0C, 0x00000000},
   272     {&GUID_Key, 192, 0x8000C00C, 0x00000000},
   273     {&GUID_Key, 193, 0x8000C10C, 0x00000000},
   274     {&GUID_Key, 194, 0x8000C20C, 0x00000000},
   275     {&GUID_Key, 195, 0x8000C30C, 0x00000000},
   276     {&GUID_Key, 196, 0x8000C40C, 0x00000000},
   277     {&GUID_Key, 197, 0x8000C50C, 0x00000000},
   278     {&GUID_Key, 198, 0x8000C60C, 0x00000000},
   279     {&GUID_Key, 199, 0x8000C70C, 0x00000000},
   280     {&GUID_Key, 200, 0x8000C80C, 0x00000000},
   281     {&GUID_Key, 201, 0x8000C90C, 0x00000000},
   282     {&GUID_Key, 202, 0x8000CA0C, 0x00000000},
   283     {&GUID_Key, 203, 0x8000CB0C, 0x00000000},
   284     {&GUID_Key, 204, 0x8000CC0C, 0x00000000},
   285     {&GUID_Key, 205, 0x8000CD0C, 0x00000000},
   286     {&GUID_Key, 206, 0x8000CE0C, 0x00000000},
   287     {&GUID_Key, 207, 0x8000CF0C, 0x00000000},
   288     {&GUID_Key, 208, 0x8000D00C, 0x00000000},
   289     {&GUID_Key, 209, 0x8000D10C, 0x00000000},
   290     {&GUID_Key, 210, 0x8000D20C, 0x00000000},
   291     {&GUID_Key, 211, 0x8000D30C, 0x00000000},
   292     {&GUID_Key, 212, 0x8000D40C, 0x00000000},
   293     {&GUID_Key, 213, 0x8000D50C, 0x00000000},
   294     {&GUID_Key, 214, 0x8000D60C, 0x00000000},
   295     {&GUID_Key, 215, 0x8000D70C, 0x00000000},
   296     {&GUID_Key, 216, 0x8000D80C, 0x00000000},
   297     {&GUID_Key, 217, 0x8000D90C, 0x00000000},
   298     {&GUID_Key, 218, 0x8000DA0C, 0x00000000},
   299     {&GUID_Key, 219, 0x8000DB0C, 0x00000000},
   300     {&GUID_Key, 220, 0x8000DC0C, 0x00000000},
   301     {&GUID_Key, 221, 0x8000DD0C, 0x00000000},
   302     {&GUID_Key, 222, 0x8000DE0C, 0x00000000},
   303     {&GUID_Key, 223, 0x8000DF0C, 0x00000000},
   304     {&GUID_Key, 224, 0x8000E00C, 0x00000000},
   305     {&GUID_Key, 225, 0x8000E10C, 0x00000000},
   306     {&GUID_Key, 226, 0x8000E20C, 0x00000000},
   307     {&GUID_Key, 227, 0x8000E30C, 0x00000000},
   308     {&GUID_Key, 228, 0x8000E40C, 0x00000000},
   309     {&GUID_Key, 229, 0x8000E50C, 0x00000000},
   310     {&GUID_Key, 230, 0x8000E60C, 0x00000000},
   311     {&GUID_Key, 231, 0x8000E70C, 0x00000000},
   312     {&GUID_Key, 232, 0x8000E80C, 0x00000000},
   313     {&GUID_Key, 233, 0x8000E90C, 0x00000000},
   314     {&GUID_Key, 234, 0x8000EA0C, 0x00000000},
   315     {&GUID_Key, 235, 0x8000EB0C, 0x00000000},
   316     {&GUID_Key, 236, 0x8000EC0C, 0x00000000},
   317     {&GUID_Key, 237, 0x8000ED0C, 0x00000000},
   318     {&GUID_Key, 238, 0x8000EE0C, 0x00000000},
   319     {&GUID_Key, 239, 0x8000EF0C, 0x00000000},
   320     {&GUID_Key, 240, 0x8000F00C, 0x00000000},
   321     {&GUID_Key, 241, 0x8000F10C, 0x00000000},
   322     {&GUID_Key, 242, 0x8000F20C, 0x00000000},
   323     {&GUID_Key, 243, 0x8000F30C, 0x00000000},
   324     {&GUID_Key, 244, 0x8000F40C, 0x00000000},
   325     {&GUID_Key, 245, 0x8000F50C, 0x00000000},
   326     {&GUID_Key, 246, 0x8000F60C, 0x00000000},
   327     {&GUID_Key, 247, 0x8000F70C, 0x00000000},
   328     {&GUID_Key, 248, 0x8000F80C, 0x00000000},
   329     {&GUID_Key, 249, 0x8000F90C, 0x00000000},
   330     {&GUID_Key, 250, 0x8000FA0C, 0x00000000},
   331     {&GUID_Key, 251, 0x8000FB0C, 0x00000000},
   332     {&GUID_Key, 252, 0x8000FC0C, 0x00000000},
   333     {&GUID_Key, 253, 0x8000FD0C, 0x00000000},
   334     {&GUID_Key, 254, 0x8000FE0C, 0x00000000},
   335     {&GUID_Key, 255, 0x8000FF0C, 0x00000000},
   336 };
   337 
   338 const DIDATAFORMAT c_dfDIKeyboard = { 24, 16, 0x00000002, 256, 256, KBD_fmt };
   339 
   340 
   341 /* Mouse */
   342 
   343 static DIOBJECTDATAFORMAT PTR_fmt[] = {
   344     {&GUID_XAxis, 0, 0x00FFFF03, 0x00000000},
   345     {&GUID_YAxis, 4, 0x00FFFF03, 0x00000000},
   346     {&GUID_ZAxis, 8, 0x80FFFF03, 0x00000000},
   347     {NULL, 12, 0x00FFFF0C, 0x00000000},
   348     {NULL, 13, 0x00FFFF0C, 0x00000000},
   349     {NULL, 14, 0x80FFFF0C, 0x00000000},
   350     {NULL, 15, 0x80FFFF0C, 0x00000000},
   351 };
   352 
   353 const DIDATAFORMAT c_dfDIMouse = { 24, 16, 0x00000002, 16, 7, PTR_fmt };
   354 
   355 
   356 /* Joystick */
   357 
   358 static DIOBJECTDATAFORMAT JOY_fmt[] = {
   359     {&GUID_XAxis, 0, 0x80FFFF03, 0x00000100},
   360     {&GUID_YAxis, 4, 0x80FFFF03, 0x00000100},
   361     {&GUID_ZAxis, 8, 0x80FFFF03, 0x00000100},
   362     {&GUID_RxAxis, 12, 0x80FFFF03, 0x00000100},
   363     {&GUID_RyAxis, 16, 0x80FFFF03, 0x00000100},
   364     {&GUID_RzAxis, 20, 0x80FFFF03, 0x00000100},
   365     {&GUID_Slider, 24, 0x80FFFF03, 0x00000100},
   366     {&GUID_Slider, 28, 0x80FFFF03, 0x00000100},
   367     {&GUID_POV, 32, 0x80FFFF10, 0x00000000},
   368     {&GUID_POV, 36, 0x80FFFF10, 0x00000000},
   369     {&GUID_POV, 40, 0x80FFFF10, 0x00000000},
   370     {&GUID_POV, 44, 0x80FFFF10, 0x00000000},
   371     {NULL, 48, 0x80FFFF0C, 0x00000000},
   372     {NULL, 49, 0x80FFFF0C, 0x00000000},
   373     {NULL, 50, 0x80FFFF0C, 0x00000000},
   374     {NULL, 51, 0x80FFFF0C, 0x00000000},
   375     {NULL, 52, 0x80FFFF0C, 0x00000000},
   376     {NULL, 53, 0x80FFFF0C, 0x00000000},
   377     {NULL, 54, 0x80FFFF0C, 0x00000000},
   378     {NULL, 55, 0x80FFFF0C, 0x00000000},
   379     {NULL, 56, 0x80FFFF0C, 0x00000000},
   380     {NULL, 57, 0x80FFFF0C, 0x00000000},
   381     {NULL, 58, 0x80FFFF0C, 0x00000000},
   382     {NULL, 59, 0x80FFFF0C, 0x00000000},
   383     {NULL, 60, 0x80FFFF0C, 0x00000000},
   384     {NULL, 61, 0x80FFFF0C, 0x00000000},
   385     {NULL, 62, 0x80FFFF0C, 0x00000000},
   386     {NULL, 63, 0x80FFFF0C, 0x00000000},
   387     {NULL, 64, 0x80FFFF0C, 0x00000000},
   388     {NULL, 65, 0x80FFFF0C, 0x00000000},
   389     {NULL, 66, 0x80FFFF0C, 0x00000000},
   390     {NULL, 67, 0x80FFFF0C, 0x00000000},
   391     {NULL, 68, 0x80FFFF0C, 0x00000000},
   392     {NULL, 69, 0x80FFFF0C, 0x00000000},
   393     {NULL, 70, 0x80FFFF0C, 0x00000000},
   394     {NULL, 71, 0x80FFFF0C, 0x00000000},
   395     {NULL, 72, 0x80FFFF0C, 0x00000000},
   396     {NULL, 73, 0x80FFFF0C, 0x00000000},
   397     {NULL, 74, 0x80FFFF0C, 0x00000000},
   398     {NULL, 75, 0x80FFFF0C, 0x00000000},
   399     {NULL, 76, 0x80FFFF0C, 0x00000000},
   400     {NULL, 77, 0x80FFFF0C, 0x00000000},
   401     {NULL, 78, 0x80FFFF0C, 0x00000000},
   402     {NULL, 79, 0x80FFFF0C, 0x00000000},
   403 };
   404 
   405 const DIDATAFORMAT c_dfDIJoystick = { 24, 16, 0x00000001, 80, 44, JOY_fmt };
   406 
   407 
   408 /* Initialization/Query functions */
   409 static int DX5_VideoInit(_THIS, SDL_PixelFormat * vformat);
   410 static SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat * format,
   411                                 Uint32 flags);
   412 static SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface * current, int width,
   413                                      int height, int bpp, Uint32 flags);
   414 static int DX5_SetColors(_THIS, int firstcolor, int ncolors,
   415                          SDL_Color * colors);
   416 static int DX5_SetGammaRamp(_THIS, Uint16 * ramp);
   417 static int DX5_GetGammaRamp(_THIS, Uint16 * ramp);
   418 static void DX5_VideoQuit(_THIS);
   419 
   420 /* Hardware surface functions */
   421 static int DX5_AllocHWSurface(_THIS, SDL_Surface * surface);
   422 static int DX5_CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst);
   423 static int DX5_FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * dstrect,
   424                           Uint32 color);
   425 static int DX5_SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key);
   426 static int DX5_SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 alpha);
   427 static int DX5_LockHWSurface(_THIS, SDL_Surface * surface);
   428 static void DX5_UnlockHWSurface(_THIS, SDL_Surface * surface);
   429 static int DX5_FlipHWSurface(_THIS, SDL_Surface * surface);
   430 static void DX5_FreeHWSurface(_THIS, SDL_Surface * surface);
   431 
   432 static int DX5_AllocDDSurface(_THIS, SDL_Surface * surface,
   433                               LPDIRECTDRAWSURFACE3 requested, Uint32 flag);
   434 
   435 /* Windows message handling functions */
   436 static void DX5_RealizePalette(_THIS);
   437 static void DX5_PaletteChanged(_THIS, HWND window);
   438 static void DX5_WinPAINT(_THIS, HDC hdc);
   439 
   440 /* WinDIB driver functions for manipulating gamma ramps */
   441 extern int DIB_SetGammaRamp(_THIS, Uint16 * ramp);
   442 extern int DIB_GetGammaRamp(_THIS, Uint16 * ramp);
   443 extern void DIB_QuitGamma(_THIS);
   444 
   445 /* Functions for loading the DirectX functions dynamically */
   446 static int DX5_loaded = 0;
   447 static HINSTANCE DDrawDLL = NULL;
   448 static HINSTANCE DInputDLL = NULL;
   449 
   450 void
   451 DX5_Unload(void)
   452 {
   453     if (--DX5_loaded == 0) {
   454         if (DDrawDLL != NULL) {
   455             FreeLibrary(DDrawDLL);
   456             DDrawCreate = NULL;
   457             DDrawDLL = NULL;
   458         }
   459         if (DInputDLL != NULL) {
   460             FreeLibrary(DInputDLL);
   461             DInputCreate = NULL;
   462             DInputDLL = NULL;
   463         }
   464     }
   465 }
   466 int
   467 DX5_Load(void)
   468 {
   469     int status = 0;
   470 
   471     if (++DX5_loaded == 1) {
   472         DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL"));
   473         if (DDrawDLL != NULL) {
   474             DDrawCreate = (void *) GetProcAddress(DDrawDLL,
   475                                                   TEXT("DirectDrawCreate"));
   476         }
   477         DInputDLL = LoadLibrary(TEXT("DINPUT.DLL"));
   478         if (DInputDLL != NULL) {
   479             DInputCreate = (void *) GetProcAddress(DInputDLL,
   480                                                    TEXT
   481                                                    ("DirectInputCreateA"));
   482         }
   483         if (DDrawDLL && DDrawCreate && DInputDLL && DInputCreate) {
   484             status = 0;
   485         } else {
   486             DX5_Unload();
   487             status = -1;
   488         }
   489     }
   490     return status;
   491 }
   492 
   493 /* DX5 driver bootstrap functions */
   494 
   495 static int
   496 DX5_Available(void)
   497 {
   498     int ddraw_ok = 0;
   499     HRESULT(WINAPI * DDrawCreate) (GUID *, LPDIRECTDRAW *, IUnknown *);
   500     LPDIRECTDRAW DDraw;
   501 
   502     /* Version check DINPUT.DLL and DDRAW.DLL (Is DirectX okay?) */
   503     if (DX5_Load() < 0) {
   504         return -1;
   505     }
   506 
   507     /* Try to create a valid DirectDraw object */
   508     DDrawCreate = (void *) GetProcAddress(DDrawDLL, TEXT("DirectDrawCreate"));
   509     if ((DDrawCreate != NULL) && !FAILED(DDrawCreate(NULL, &DDraw, NULL))) {
   510         if (!FAILED(IDirectDraw_SetCooperativeLevel(DDraw,
   511                                                     NULL, DDSCL_NORMAL))) {
   512             DDSURFACEDESC desc;
   513             LPDIRECTDRAWSURFACE DDrawSurf;
   514             LPDIRECTDRAWSURFACE3 DDrawSurf3;
   515 
   516             /* Try to create a DirectDrawSurface3 object */
   517             SDL_memset(&desc, 0, sizeof(desc));
   518             desc.dwSize = sizeof(desc);
   519             desc.dwFlags = DDSD_CAPS;
   520             desc.ddsCaps.dwCaps =
   521                 DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
   522             if (!FAILED
   523                 (IDirectDraw_CreateSurface(DDraw, &desc, &DDrawSurf, NULL))) {
   524                 if (!FAILED
   525                     (IDirectDrawSurface_QueryInterface
   526                      (DDrawSurf, &IID_IDirectDrawSurface3,
   527                       (LPVOID *) & DDrawSurf3))) {
   528                     /* Yay! */
   529                     ddraw_ok = 1;
   530 
   531                     /* Clean up.. */
   532                     IDirectDrawSurface3_Release(DDrawSurf3);
   533                 }
   534                 IDirectDrawSurface_Release(DDrawSurf);
   535             }
   536         }
   537         IDirectDraw_Release(DDraw);
   538     }
   539 
   540     DX5_Unload();
   541 
   542     return ddraw_ok;
   543 }
   544 
   545 static void
   546 DX5_DeleteDevice(SDL_VideoDevice * this)
   547 {
   548     /* Free DirectDraw object */
   549     if (ddraw2 != NULL) {
   550         IDirectDraw2_Release(ddraw2);
   551     }
   552     DX5_Unload();
   553 
   554     if (this) {
   555         if (this->hidden) {
   556             SDL_free(this->hidden);
   557         }
   558         if (this->gl_data) {
   559             SDL_free(this->gl_data);
   560         }
   561         SDL_free(this);
   562     }
   563 }
   564 
   565 static SDL_VideoDevice *
   566 DX5_CreateDevice(int devindex)
   567 {
   568     SDL_VideoDevice *device;
   569 
   570     /* Load DirectX */
   571     if (DX5_Load() < 0) {
   572         return (NULL);
   573     }
   574 
   575     /* Initialize all variables that we clean on shutdown */
   576     device = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice));
   577     if (device) {
   578         SDL_memset(device, 0, (sizeof *device));
   579         device->hidden = (struct SDL_PrivateVideoData *)
   580             SDL_malloc((sizeof *device->hidden));
   581         device->gl_data = (struct SDL_PrivateGLData *)
   582             SDL_malloc((sizeof *device->gl_data));
   583     }
   584     if ((device == NULL) || (device->hidden == NULL) ||
   585         (device->gl_data == NULL)) {
   586         SDL_OutOfMemory();
   587         DX5_DeleteDevice(device);
   588         return (NULL);
   589     }
   590     SDL_memset(device->hidden, 0, (sizeof *device->hidden));
   591     SDL_memset(device->gl_data, 0, (sizeof *device->gl_data));
   592 
   593     /* Set the function pointers */
   594     device->VideoInit = DX5_VideoInit;
   595     device->ListModes = DX5_ListModes;
   596     device->SetVideoMode = DX5_SetVideoMode;
   597     device->UpdateMouse = WIN_UpdateMouse;
   598     device->CreateYUVOverlay = DX5_CreateYUVOverlay;
   599     device->SetColors = DX5_SetColors;
   600     device->UpdateRects = NULL;
   601     device->VideoQuit = DX5_VideoQuit;
   602     device->AllocHWSurface = DX5_AllocHWSurface;
   603     device->CheckHWBlit = DX5_CheckHWBlit;
   604     device->FillHWRect = DX5_FillHWRect;
   605     device->SetHWColorKey = DX5_SetHWColorKey;
   606     device->SetHWAlpha = DX5_SetHWAlpha;
   607     device->LockHWSurface = DX5_LockHWSurface;
   608     device->UnlockHWSurface = DX5_UnlockHWSurface;
   609     device->FlipHWSurface = DX5_FlipHWSurface;
   610     device->FreeHWSurface = DX5_FreeHWSurface;
   611     device->SetGammaRamp = DX5_SetGammaRamp;
   612     device->GetGammaRamp = DX5_GetGammaRamp;
   613 #if SDL_VIDEO_OPENGL
   614     device->GL_LoadLibrary = WIN_GL_LoadLibrary;
   615     device->GL_GetProcAddress = WIN_GL_GetProcAddress;
   616     device->GL_GetAttribute = WIN_GL_GetAttribute;
   617     device->GL_MakeCurrent = WIN_GL_MakeCurrent;
   618     device->GL_SwapBuffers = WIN_GL_SwapBuffers;
   619 #endif
   620     device->SetCaption = WIN_SetWMCaption;
   621     device->SetIcon = WIN_SetWMIcon;
   622     device->IconifyWindow = WIN_IconifyWindow;
   623     device->GrabInput = WIN_GrabInput;
   624     device->GetWMInfo = WIN_GetWMInfo;
   625     device->FreeWMCursor = WIN_FreeWMCursor;
   626     device->CreateWMCursor = WIN_CreateWMCursor;
   627     device->ShowWMCursor = WIN_ShowWMCursor;
   628     device->WarpWMCursor = WIN_WarpWMCursor;
   629     device->CheckMouseMode = WIN_CheckMouseMode;
   630     device->InitOSKeymap = DX5_InitOSKeymap;
   631     device->PumpEvents = DX5_PumpEvents;
   632 
   633     /* Set up the windows message handling functions */
   634     WIN_RealizePalette = DX5_RealizePalette;
   635     WIN_PaletteChanged = DX5_PaletteChanged;
   636     WIN_WinPAINT = DX5_WinPAINT;
   637     HandleMessage = DX5_HandleMessage;
   638 
   639     device->free = DX5_DeleteDevice;
   640 
   641     /* We're finally ready */
   642     return device;
   643 }
   644 
   645 VideoBootStrap DIRECTX_bootstrap = {
   646     "directx", "Win95/98/2000 DirectX",
   647     DX5_Available, DX5_CreateDevice
   648 };
   649 
   650 static int
   651 cmpmodes(const void *va, const void *vb)
   652 {
   653     SDL_Rect *a = *(SDL_Rect **) va;
   654     SDL_Rect *b = *(SDL_Rect **) vb;
   655     if (a->w == b->w)
   656         return b->h - a->h;
   657     else
   658         return b->w - a->w;
   659 }
   660 
   661 static HRESULT WINAPI
   662 EnumModes2(DDSURFACEDESC * desc, VOID * udata)
   663 {
   664     SDL_VideoDevice *this = (SDL_VideoDevice *) udata;
   665     struct DX5EnumRect *enumrect;
   666 #if defined(NONAMELESSUNION)
   667     int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount;
   668     int refreshRate = desc->u2.dwRefreshRate;
   669 #else
   670     int bpp = desc->ddpfPixelFormat.dwRGBBitCount;
   671     int refreshRate = desc->dwRefreshRate;
   672 #endif
   673     int maxRefreshRate;
   674 
   675     if (desc->dwWidth <= SDL_desktop_mode.dmPelsWidth &&
   676         desc->dwHeight <= SDL_desktop_mode.dmPelsHeight) {
   677         maxRefreshRate = SDL_desktop_mode.dmDisplayFrequency;
   678     } else {
   679         maxRefreshRate = 85;    /* safe value? */
   680     }
   681 
   682     switch (bpp) {
   683     case 8:
   684     case 16:
   685     case 24:
   686     case 32:
   687         bpp /= 8;
   688         --bpp;
   689         if (enumlists[bpp] &&
   690             enumlists[bpp]->r.w == (Uint16) desc->dwWidth &&
   691             enumlists[bpp]->r.h == (Uint16) desc->dwHeight) {
   692             if (refreshRate > enumlists[bpp]->refreshRate &&
   693                 refreshRate <= maxRefreshRate) {
   694                 enumlists[bpp]->refreshRate = refreshRate;
   695 #ifdef DDRAW_DEBUG
   696                 fprintf(stderr,
   697                         "New refresh rate for %d bpp: %dx%d at %d Hz\n",
   698                         (bpp + 1) * 8, (int) desc->dwWidth,
   699                         (int) desc->dwHeight, refreshRate);
   700 #endif
   701             }
   702             break;
   703         }
   704         ++SDL_nummodes[bpp];
   705         enumrect =
   706             (struct DX5EnumRect *) SDL_malloc(sizeof(struct DX5EnumRect));
   707         if (!enumrect) {
   708             SDL_OutOfMemory();
   709             return (DDENUMRET_CANCEL);
   710         }
   711         enumrect->refreshRate = refreshRate;
   712         enumrect->r.x = 0;
   713         enumrect->r.y = 0;
   714         enumrect->r.w = (Uint16) desc->dwWidth;
   715         enumrect->r.h = (Uint16) desc->dwHeight;
   716         enumrect->next = enumlists[bpp];
   717         enumlists[bpp] = enumrect;
   718 #ifdef DDRAW_DEBUG
   719         fprintf(stderr, "New mode for %d bpp: %dx%d at %d Hz\n",
   720                 (bpp + 1) * 8, (int) desc->dwWidth, (int) desc->dwHeight,
   721                 refreshRate);
   722 #endif
   723         break;
   724     }
   725 
   726     return (DDENUMRET_OK);
   727 }
   728 
   729 void
   730 SetDDerror(const char *function, int code)
   731 {
   732     static char *error;
   733     static char errbuf[1024];
   734 
   735     errbuf[0] = 0;
   736     switch (code) {
   737     case DDERR_GENERIC:
   738         error = "Undefined error!";
   739         break;
   740     case DDERR_EXCEPTION:
   741         error = "Exception encountered";
   742         break;
   743     case DDERR_INVALIDOBJECT:
   744         error = "Invalid object";
   745         break;
   746     case DDERR_INVALIDPARAMS:
   747         error = "Invalid parameters";
   748         break;
   749     case DDERR_NOTFOUND:
   750         error = "Object not found";
   751         break;
   752     case DDERR_INVALIDRECT:
   753         error = "Invalid rectangle";
   754         break;
   755     case DDERR_INVALIDCAPS:
   756         error = "Invalid caps member";
   757         break;
   758     case DDERR_INVALIDPIXELFORMAT:
   759         error = "Invalid pixel format";
   760         break;
   761     case DDERR_OUTOFMEMORY:
   762         error = "Out of memory";
   763         break;
   764     case DDERR_OUTOFVIDEOMEMORY:
   765         error = "Out of video memory";
   766         break;
   767     case DDERR_SURFACEBUSY:
   768         error = "Surface busy";
   769         break;
   770     case DDERR_SURFACELOST:
   771         error = "Surface was lost";
   772         break;
   773     case DDERR_WASSTILLDRAWING:
   774         error = "DirectDraw is still drawing";
   775         break;
   776     case DDERR_INVALIDSURFACETYPE:
   777         error = "Invalid surface type";
   778         break;
   779     case DDERR_NOEXCLUSIVEMODE:
   780         error = "Not in exclusive access mode";
   781         break;
   782     case DDERR_NOPALETTEATTACHED:
   783         error = "No palette attached";
   784         break;
   785     case DDERR_NOPALETTEHW:
   786         error = "No palette hardware";
   787         break;
   788     case DDERR_NOT8BITCOLOR:
   789         error = "Not 8-bit color";
   790         break;
   791     case DDERR_EXCLUSIVEMODEALREADYSET:
   792         error = "Exclusive mode was already set";
   793         break;
   794     case DDERR_HWNDALREADYSET:
   795         error = "Window handle already set";
   796         break;
   797     case DDERR_HWNDSUBCLASSED:
   798         error = "Window handle is subclassed";
   799         break;
   800     case DDERR_NOBLTHW:
   801         error = "No blit hardware";
   802         break;
   803     case DDERR_IMPLICITLYCREATED:
   804         error = "Surface was implicitly created";
   805         break;
   806     case DDERR_INCOMPATIBLEPRIMARY:
   807         error = "Incompatible primary surface";
   808         break;
   809     case DDERR_NOCOOPERATIVELEVELSET:
   810         error = "No cooperative level set";
   811         break;
   812     case DDERR_NODIRECTDRAWHW:
   813         error = "No DirectDraw hardware";
   814         break;
   815     case DDERR_NOEMULATION:
   816         error = "No emulation available";
   817         break;
   818     case DDERR_NOFLIPHW:
   819         error = "No flip hardware";
   820         break;
   821     case DDERR_NOTFLIPPABLE:
   822         error = "Surface not flippable";
   823         break;
   824     case DDERR_PRIMARYSURFACEALREADYEXISTS:
   825         error = "Primary surface already exists";
   826         break;
   827     case DDERR_UNSUPPORTEDMODE:
   828         error = "Unsupported mode";
   829         break;
   830     case DDERR_WRONGMODE:
   831         error = "Surface created in different mode";
   832         break;
   833     case DDERR_UNSUPPORTED:
   834         error = "Operation not supported";
   835         break;
   836     case E_NOINTERFACE:
   837         error = "Interface not present";
   838         break;
   839     default:
   840         SDL_snprintf(errbuf, SDL_arraysize(errbuf),
   841                      "%s: Unknown DirectDraw error: 0x%x", function, code);
   842         break;
   843     }
   844     if (!errbuf[0]) {
   845         SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function,
   846                      error);
   847     }
   848     SDL_SetError("%s", errbuf);
   849     return;
   850 }
   851 
   852 
   853 static int
   854 DX5_UpdateVideoInfo(_THIS)
   855 {
   856     /* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */
   857 #if DIRECTDRAW_VERSION <= 0x300
   858 #error Your version of DirectX must be greater than or equal to 5.0
   859 #endif
   860 #ifndef IDirectDrawGammaControl_SetGammaRamp
   861     /*if gamma is undefined then we really have directx <= 0x500 */
   862     DDCAPS DDCaps;
   863 #else
   864     DDCAPS_DX5 DDCaps;
   865 #endif
   866     HRESULT result;
   867 
   868     /* Fill in our hardware acceleration capabilities */
   869     SDL_memset(&DDCaps, 0, sizeof(DDCaps));
   870     DDCaps.dwSize = sizeof(DDCaps);
   871     result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *) & DDCaps, NULL);
   872     if (result != DD_OK) {
   873         SetDDerror("DirectDraw2::GetCaps", result);
   874         return (-1);
   875     }
   876     this->info.hw_available = 1;
   877     if ((DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT) {
   878         this->info.blit_hw = 1;
   879     }
   880     if (((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) &&
   881         ((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT)) {
   882         this->info.blit_hw_CC = 1;
   883     }
   884     if ((DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA) {
   885         /* This is only for alpha channel, and DirectX 6
   886            doesn't support 2D alpha blits yet, so set it 0
   887          */
   888         this->info.blit_hw_A = 0;
   889     }
   890     if ((DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM) {
   891         this->info.blit_sw = 1;
   892         /* This isn't necessarily true, but the HEL will cover us */
   893         this->info.blit_sw_CC = this->info.blit_hw_CC;
   894         this->info.blit_sw_A = this->info.blit_hw_A;
   895     }
   896     if ((DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL) {
   897         this->info.blit_fill = 1;
   898     }
   899 
   900     /* Find out how much video memory is available */
   901     {
   902         DDSCAPS ddsCaps;
   903         DWORD total_mem;
   904         ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
   905         result = IDirectDraw2_GetAvailableVidMem(ddraw2,
   906                                                  &ddsCaps, &total_mem, NULL);
   907         if (result != DD_OK) {
   908             total_mem = DDCaps.dwVidMemTotal;
   909         }
   910         this->info.video_mem = total_mem / 1024;
   911     }
   912     return (0);
   913 }
   914 
   915 int
   916 DX5_VideoInit(_THIS, SDL_PixelFormat * vformat)
   917 {
   918     HRESULT result;
   919     LPDIRECTDRAW ddraw;
   920     int i, j;
   921     HDC hdc;
   922 
   923     /* Intialize everything */
   924     ddraw2 = NULL;
   925     SDL_primary = NULL;
   926     SDL_clipper = NULL;
   927     SDL_palette = NULL;
   928     for (i = 0; i < NUM_MODELISTS; ++i) {
   929         SDL_nummodes[i] = 0;
   930         SDL_modelist[i] = NULL;
   931         SDL_modeindex[i] = 0;
   932     }
   933     colorchange_expected = 0;
   934 
   935     /* Create the window */
   936     if (DX5_CreateWindow(this) < 0) {
   937         return (-1);
   938     }
   939 #if !SDL_AUDIO_DISABLED
   940     DX5_SoundFocus(SDL_Window);
   941 #endif
   942 
   943     /* Create the DirectDraw object */
   944     result = DDrawCreate(NULL, &ddraw, NULL);
   945     if (result != DD_OK) {
   946         SetDDerror("DirectDrawCreate", result);
   947         return (-1);
   948     }
   949     result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2,
   950                                         (LPVOID *) & ddraw2);
   951     IDirectDraw_Release(ddraw);
   952     if (result != DD_OK) {
   953         SetDDerror("DirectDraw::QueryInterface", result);
   954         return (-1);
   955     }
   956 
   957     /* Determine the screen depth */
   958     hdc = GetDC(SDL_Window);
   959     vformat->BitsPerPixel = GetDeviceCaps(hdc, PLANES) *
   960         GetDeviceCaps(hdc, BITSPIXEL);
   961     ReleaseDC(SDL_Window, hdc);
   962 
   963 #ifndef NO_CHANGEDISPLAYSETTINGS
   964     /* Query for the desktop resolution */
   965     EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode);
   966     this->info.current_w = SDL_desktop_mode.dmPelsWidth;
   967     this->info.current_h = SDL_desktop_mode.dmPelsHeight;
   968 #endif
   969 
   970     /* Enumerate the available fullscreen modes */
   971     for (i = 0; i < NUM_MODELISTS; ++i)
   972         enumlists[i] = NULL;
   973 
   974     result =
   975         IDirectDraw2_EnumDisplayModes(ddraw2, DDEDM_REFRESHRATES, NULL, this,
   976                                       EnumModes2);
   977     if (result != DD_OK) {
   978         SetDDerror("DirectDraw2::EnumDisplayModes", result);
   979         return (-1);
   980     }
   981     for (i = 0; i < NUM_MODELISTS; ++i) {
   982         struct DX5EnumRect *rect;
   983         SDL_modelist[i] = (SDL_Rect **)
   984             SDL_malloc((SDL_nummodes[i] + 1) * sizeof(SDL_Rect *));
   985         if (SDL_modelist[i] == NULL) {
   986             SDL_OutOfMemory();
   987             return (-1);
   988         }
   989         for (j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next) {
   990             SDL_modelist[i][j] = &rect->r;
   991         }
   992         SDL_modelist[i][j] = NULL;
   993 
   994         if (SDL_nummodes[i] > 0) {
   995             SDL_qsort(SDL_modelist[i], SDL_nummodes[i],
   996                       sizeof *SDL_modelist[i], cmpmodes);
   997         }
   998     }
   999 
  1000     /* Fill in some window manager capabilities */
  1001     this->info.wm_available = 1;
  1002 
  1003     /* Fill in the video hardware capabilities */
  1004     DX5_UpdateVideoInfo(this);
  1005 
  1006     return (0);
  1007 }
  1008 
  1009 SDL_Rect **
  1010 DX5_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
  1011 {
  1012     int bpp;
  1013 
  1014     bpp = format->BitsPerPixel;
  1015     if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
  1016         /* FIXME:  No support for 1 bpp or 4 bpp formats */
  1017         switch (bpp) {          /* Does windows support other BPP? */
  1018         case 8:
  1019         case 16:
  1020         case 24:
  1021         case 32:
  1022             bpp = (bpp / 8) - 1;
  1023             if (SDL_nummodes[bpp] > 0)
  1024                 return (SDL_modelist[bpp]);
  1025             /* Fall through */
  1026         default:
  1027             return ((SDL_Rect **) 0);
  1028         }
  1029     } else {
  1030         if (this->screen->format->BitsPerPixel == bpp) {
  1031             return ((SDL_Rect **) - 1);
  1032         } else {
  1033             return ((SDL_Rect **) 0);
  1034         }
  1035     }
  1036 }
  1037 
  1038 /* Various screen update functions available */
  1039 static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect * rects);
  1040 static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect * rects);
  1041 
  1042 SDL_Surface *
  1043 DX5_SetVideoMode(_THIS, SDL_Surface * current,
  1044                  int width, int height, int bpp, Uint32 flags)
  1045 {
  1046     SDL_Surface *video;
  1047     HRESULT result;
  1048     DWORD sharemode;
  1049     DWORD style;
  1050     const DWORD directstyle = (WS_POPUP);
  1051     const DWORD windowstyle =
  1052         (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
  1053     const DWORD resizestyle = (WS_THICKFRAME | WS_MAXIMIZEBOX);
  1054     DDSURFACEDESC ddsd;
  1055     LPDIRECTDRAWSURFACE dd_surface1;
  1056     LPDIRECTDRAWSURFACE3 dd_surface3;
  1057 
  1058     SDL_resizing = 1;
  1059 #ifdef DDRAW_DEBUG
  1060     fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp);
  1061 #endif
  1062     /* Clean up any previous DirectDraw surfaces */
  1063     if (current->hwdata) {
  1064         this->FreeHWSurface(this, current);
  1065         current->hwdata = NULL;
  1066     }
  1067     if (SDL_primary != NULL) {
  1068         IDirectDrawSurface3_Release(SDL_primary);
  1069         SDL_primary = NULL;
  1070     }
  1071 #ifndef NO_CHANGEDISPLAYSETTINGS
  1072     /* Unset any previous OpenGL fullscreen mode */
  1073     if ((current->flags & (SDL_INTERNALOPENGL | SDL_FULLSCREEN)) ==
  1074         (SDL_INTERNALOPENGL | SDL_FULLSCREEN)) {
  1075         ChangeDisplaySettings(NULL, 0);
  1076     }
  1077 #endif
  1078 
  1079     /* Clean up any GL context that may be hanging around */
  1080     if (current->flags & SDL_INTERNALOPENGL) {
  1081         WIN_GL_ShutDown(this);
  1082     }
  1083 
  1084     /* If we are setting a GL mode, use GDI, not DirectX (yuck) */
  1085     if (flags & SDL_INTERNALOPENGL) {
  1086         Uint32 Rmask, Gmask, Bmask;
  1087 
  1088         /* Recalculate the bitmasks if necessary */
  1089         if (bpp == current->format->BitsPerPixel) {
  1090             video = current;
  1091         } else {
  1092             switch (bpp) {
  1093             case 15:
  1094             case 16:
  1095                 if (0 /*DIB_SussScreenDepth() == 15 */ ) {
  1096                     /* 5-5-5 */
  1097                     Rmask = 0x00007c00;
  1098                     Gmask = 0x000003e0;
  1099                     Bmask = 0x0000001f;
  1100                 } else {
  1101                     /* 5-6-5 */
  1102                     Rmask = 0x0000f800;
  1103                     Gmask = 0x000007e0;
  1104                     Bmask = 0x0000001f;
  1105                 }
  1106                 break;
  1107             case 24:
  1108             case 32:
  1109                 /* GDI defined as 8-8-8 */
  1110                 Rmask = 0x00ff0000;
  1111                 Gmask = 0x0000ff00;
  1112                 Bmask = 0x000000ff;
  1113                 break;
  1114             default:
  1115                 Rmask = 0x00000000;
  1116                 Gmask = 0x00000000;
  1117                 Bmask = 0x00000000;
  1118                 break;
  1119             }
  1120             video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp,
  1121                                          Rmask, Gmask, Bmask, 0);
  1122             if (video == NULL) {
  1123                 SDL_OutOfMemory();
  1124                 return (NULL);
  1125             }
  1126         }
  1127 
  1128         /* Fill in part of the video surface */
  1129         video->flags = 0;       /* Clear flags */
  1130         video->w = width;
  1131         video->h = height;
  1132         video->pitch = SDL_CalculatePitch(video);
  1133 
  1134 #ifndef NO_CHANGEDISPLAYSETTINGS
  1135         /* Set fullscreen mode if appropriate.
  1136            Ugh, since our list of valid video modes comes from
  1137            the DirectX driver, we may not actually be able to
  1138            change to the desired resolution here.
  1139            FIXME: Should we do a closest match?
  1140          */
  1141         if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
  1142             DEVMODE settings;
  1143             BOOL changed;
  1144 
  1145             SDL_memset(&settings, 0, sizeof(DEVMODE));
  1146             settings.dmSize = sizeof(DEVMODE);
  1147             settings.dmBitsPerPel = video->format->BitsPerPixel;
  1148             settings.dmPelsWidth = width;
  1149             settings.dmPelsHeight = height;
  1150             settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
  1151             if (width <= (int) SDL_desktop_mode.dmPelsWidth
  1152                 && height <= (int) SDL_desktop_mode.dmPelsHeight) {
  1153                 settings.dmDisplayFrequency =
  1154                     SDL_desktop_mode.dmDisplayFrequency;
  1155                 settings.dmFields |= DM_DISPLAYFREQUENCY;
  1156             }
  1157             changed =
  1158                 (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) ==
  1159                  DISP_CHANGE_SUCCESSFUL);
  1160             if (!changed && (settings.dmFields & DM_DISPLAYFREQUENCY)) {
  1161                 settings.dmFields &= ~DM_DISPLAYFREQUENCY;
  1162                 changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN)
  1163                            == DISP_CHANGE_SUCCESSFUL);
  1164             }
  1165             if (changed) {
  1166                 video->flags |= SDL_FULLSCREEN;
  1167                 SDL_fullscreen_mode = settings;
  1168             }
  1169         }
  1170 #endif /* !NO_CHANGEDISPLAYSETTINGS */
  1171 
  1172         style = GetWindowLong(SDL_Window, GWL_STYLE);
  1173         style &= ~(resizestyle | WS_MAXIMIZE);
  1174         if (video->flags & SDL_FULLSCREEN) {
  1175             style &= ~windowstyle;
  1176             style |= directstyle;
  1177         } else {
  1178             if (flags & SDL_NOFRAME) {
  1179                 style &= ~windowstyle;
  1180                 style |= directstyle;
  1181                 video->flags |= SDL_NOFRAME;
  1182             } else {
  1183                 style &= ~directstyle;
  1184                 style |= windowstyle;
  1185                 if (flags & SDL_RESIZABLE) {
  1186                     style |= resizestyle;
  1187                     video->flags |= SDL_RESIZABLE;
  1188                 }
  1189             }
  1190 #if WS_MAXIMIZE
  1191             if (IsZoomed(SDL_Window))
  1192                 style |= WS_MAXIMIZE;
  1193 #endif
  1194         }
  1195 
  1196         /* DJM: Don't piss of anyone who has setup his own window */
  1197         if (!SDL_windowid)
  1198             SetWindowLong(SDL_Window, GWL_STYLE, style);
  1199 
  1200         /* Resize the window (copied from SDL WinDIB driver) */
  1201         if (!SDL_windowid && !IsZoomed(SDL_Window)) {
  1202             RECT bounds;
  1203             int x, y;
  1204             HWND top;
  1205             UINT swp_flags;
  1206             const char *window = NULL;
  1207             const char *center = NULL;
  1208 
  1209             if (!SDL_windowX && !SDL_windowY) {
  1210                 window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
  1211                 center = SDL_getenv("SDL_VIDEO_CENTERED");
  1212                 if (window) {
  1213                     if (SDL_sscanf(window, "%d,%d", &x, &y) == 2) {
  1214                         SDL_windowX = x;
  1215                         SDL_windowY = y;
  1216                     }
  1217                     if (SDL_strcmp(window, "center") == 0) {
  1218                         center = window;
  1219                     }
  1220                 }
  1221             }
  1222             swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW);
  1223 
  1224             bounds.left = SDL_windowX;
  1225             bounds.top = SDL_windowY;
  1226             bounds.right = SDL_windowX + video->w;
  1227             bounds.bottom = SDL_windowY + video->h;
  1228             AdjustWindowRectEx(&bounds,
  1229                                GetWindowLong(SDL_Window, GWL_STYLE),
  1230                                FALSE, 0);
  1231             width = bounds.right - bounds.left;
  1232             height = bounds.bottom - bounds.top;
  1233             if ((flags & SDL_FULLSCREEN)) {
  1234                 x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
  1235                 y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
  1236             } else if (center) {
  1237                 x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
  1238                 y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
  1239             } else if (SDL_windowX || SDL_windowY || window) {
  1240                 x = bounds.left;
  1241                 y = bounds.top;
  1242             } else {
  1243                 x = y = -1;
  1244                 swp_flags |= SWP_NOMOVE;
  1245             }
  1246             if (flags & SDL_FULLSCREEN) {
  1247                 top = HWND_TOPMOST;
  1248             } else {
  1249                 top = HWND_NOTOPMOST;
  1250             }
  1251             SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
  1252             if (!(flags & SDL_FULLSCREEN)) {
  1253                 SDL_windowX = SDL_bounds.left;
  1254                 SDL_windowY = SDL_bounds.top;
  1255             }
  1256             SetForegroundWindow(SDL_Window);
  1257         }
  1258         SDL_resizing = 0;
  1259 
  1260         /* Set up for OpenGL */
  1261         if (WIN_GL_SetupWindow(this) < 0) {
  1262             return (NULL);
  1263         }
  1264         video->flags |= SDL_INTERNALOPENGL;
  1265         return (video);
  1266     }
  1267 
  1268     /* Set the appropriate window style */
  1269     style = GetWindowLong(SDL_Window, GWL_STYLE);
  1270     style &= ~(resizestyle | WS_MAXIMIZE);
  1271     if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
  1272         style &= ~windowstyle;
  1273         style |= directstyle;
  1274     } else {
  1275         if (flags & SDL_NOFRAME) {
  1276             style &= ~windowstyle;
  1277             style |= directstyle;
  1278         } else {
  1279             style &= ~directstyle;
  1280             style |= windowstyle;
  1281             if (flags & SDL_RESIZABLE) {
  1282                 style |= resizestyle;
  1283             }
  1284         }
  1285 #if WS_MAXIMIZE
  1286         if (IsZoomed(SDL_Window))
  1287             style |= WS_MAXIMIZE;
  1288 #endif
  1289     }
  1290     /* DJM: Don't piss of anyone who has setup his own window */
  1291     if (!SDL_windowid)
  1292         SetWindowLong(SDL_Window, GWL_STYLE, style);
  1293 
  1294     /* Set DirectDraw sharing mode.. exclusive when fullscreen */
  1295     if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
  1296         sharemode = DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT;
  1297     } else {
  1298         sharemode = DDSCL_NORMAL;
  1299     }
  1300     result = IDirectDraw2_SetCooperativeLevel(ddraw2, SDL_Window, sharemode);
  1301     if (result != DD_OK) {
  1302         SetDDerror("DirectDraw2::SetCooperativeLevel", result);
  1303         return (NULL);
  1304     }
  1305 
  1306     /* Set the display mode, if we are in fullscreen mode */
  1307     if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
  1308         RECT bounds;
  1309         struct DX5EnumRect *rect;
  1310         int maxRefreshRate;
  1311 
  1312         /* Cover up desktop during mode change */
  1313         bounds.left = 0;
  1314         bounds.top = 0;
  1315         bounds.right = GetSystemMetrics(SM_CXSCREEN);
  1316         bounds.bottom = GetSystemMetrics(SM_CYSCREEN);
  1317         AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE),
  1318                            FALSE, 0);
  1319         SetWindowPos(SDL_Window, HWND_TOPMOST, bounds.left, bounds.top,
  1320                      bounds.right - bounds.left,
  1321                      bounds.bottom - bounds.top, SWP_NOCOPYBITS);
  1322         ShowWindow(SDL_Window, SW_SHOW);
  1323         while (GetForegroundWindow() != SDL_Window) {
  1324             SetForegroundWindow(SDL_Window);
  1325             SDL_Delay(100);
  1326         }
  1327 
  1328         /* find maximum monitor refresh rate for this resolution */
  1329         /* Dmitry Yakimov ftech@tula.net */
  1330         maxRefreshRate = 0;     /* system default */
  1331         for (rect = enumlists[bpp / 8 - 1]; rect; rect = rect->next) {
  1332             if ((width == rect->r.w) && (height == rect->r.h)) {
  1333                 maxRefreshRate = rect->refreshRate;
  1334                 break;
  1335             }
  1336         }
  1337 #ifdef DDRAW_DEBUG
  1338         fprintf(stderr, "refresh rate = %d Hz\n", maxRefreshRate);
  1339 #endif
  1340 
  1341         result =
  1342             IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp,
  1343                                         maxRefreshRate, 0);
  1344         if (result != DD_OK) {
  1345             result =
  1346                 IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, 0, 0);
  1347             if (result != DD_OK) {
  1348                 /* We couldn't set fullscreen mode, try window */
  1349                 return (DX5_SetVideoMode
  1350                         (this, current, width, height, bpp,
  1351                          flags & ~SDL_FULLSCREEN));
  1352             }
  1353         }
  1354         DX5_DInputReset(this, 1);
  1355     } else {
  1356         DX5_DInputReset(this, 0);
  1357     }
  1358     DX5_UpdateVideoInfo(this);
  1359 
  1360     /* Create a primary DirectDraw surface */
  1361     SDL_memset(&ddsd, 0, sizeof(ddsd));
  1362     ddsd.dwSize = sizeof(ddsd);
  1363     ddsd.dwFlags = DDSD_CAPS;
  1364     ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY);
  1365     if ((flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) {
  1366         /* There's no windowed double-buffering */
  1367         flags &= ~SDL_DOUBLEBUF;
  1368     }
  1369     if ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
  1370         ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
  1371         ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX | DDSCAPS_FLIP);
  1372         ddsd.dwBackBufferCount = 1;
  1373     }
  1374     result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL);
  1375     if ((result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)) {
  1376         ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
  1377         ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX | DDSCAPS_FLIP);
  1378         ddsd.dwBackBufferCount = 0;
  1379         result = IDirectDraw2_CreateSurface(ddraw2,
  1380                                             &ddsd, &dd_surface1, NULL);
  1381     }
  1382     if (result != DD_OK) {
  1383         SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result);
  1384         return (NULL);
  1385     }
  1386     result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1387                                                &IID_IDirectDrawSurface3,
  1388                                                (LPVOID *) & SDL_primary);
  1389     if (result != DD_OK) {
  1390         SetDDerror("DirectDrawSurface::QueryInterface", result);
  1391         return (NULL);
  1392     }
  1393     IDirectDrawSurface_Release(dd_surface1);
  1394 
  1395     /* Get the format of the primary DirectDraw surface */
  1396     SDL_memset(&ddsd, 0, sizeof(ddsd));
  1397     ddsd.dwSize = sizeof(ddsd);
  1398     ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
  1399     result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
  1400     if (result != DD_OK) {
  1401         SetDDerror("DirectDrawSurface::GetSurfaceDesc", result);
  1402         return (NULL);
  1403     }
  1404     if (!(ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB)) {
  1405         SDL_SetError("Primary DDRAW surface is not RGB format");
  1406         return (NULL);
  1407     }
  1408 
  1409     /* Free old palette and create a new one if we're in 8-bit mode */
  1410     if (SDL_palette != NULL) {
  1411         IDirectDrawPalette_Release(SDL_palette);
  1412         SDL_palette = NULL;
  1413     }
  1414 #if defined(NONAMELESSUNION)
  1415     if (ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8) {
  1416 #else
  1417     if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) {
  1418 #endif
  1419         int i;
  1420 
  1421         if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
  1422             /* We have access to the entire palette */
  1423             for (i = 0; i < 256; ++i) {
  1424                 SDL_colors[i].peFlags = (PC_NOCOLLAPSE | PC_RESERVED);
  1425                 SDL_colors[i].peRed = 0;
  1426                 SDL_colors[i].peGreen = 0;
  1427                 SDL_colors[i].peBlue = 0;
  1428             }
  1429         } else {
  1430             /* First 10 colors are reserved by Windows */
  1431             for (i = 0; i < 10; ++i) {
  1432                 SDL_colors[i].peFlags = PC_EXPLICIT;
  1433                 SDL_colors[i].peRed = i;
  1434                 SDL_colors[i].peGreen = 0;
  1435                 SDL_colors[i].peBlue = 0;
  1436             }
  1437             for (i = 10; i < (10 + 236); ++i) {
  1438                 SDL_colors[i].peFlags = PC_NOCOLLAPSE;
  1439                 SDL_colors[i].peRed = 0;
  1440                 SDL_colors[i].peGreen = 0;
  1441                 SDL_colors[i].peBlue = 0;
  1442             }
  1443             /* Last 10 colors are reserved by Windows */
  1444             for (i = 246; i < 256; ++i) {
  1445                 SDL_colors[i].peFlags = PC_EXPLICIT;
  1446                 SDL_colors[i].peRed = i;
  1447                 SDL_colors[i].peGreen = 0;
  1448                 SDL_colors[i].peBlue = 0;
  1449             }
  1450         }
  1451         result = IDirectDraw2_CreatePalette(ddraw2,
  1452                                             (DDPCAPS_8BIT |
  1453                                              DDPCAPS_ALLOW256), SDL_colors,
  1454                                             &SDL_palette, NULL);
  1455         if (result != DD_OK) {
  1456             SetDDerror("DirectDraw2::CreatePalette", result);
  1457             return (NULL);
  1458         }
  1459         result = IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
  1460         if (result != DD_OK) {
  1461             SetDDerror("DirectDrawSurface3::SetPalette", result);
  1462             return (NULL);
  1463         }
  1464     }
  1465 
  1466     /* Create our video surface using the same pixel format */
  1467     video = current;
  1468     if ((width != video->w) || (height != video->h)
  1469         || (video->format->BitsPerPixel !=
  1470 #if defined(NONAMELESSUNION)
  1471             ddsd.ddpfPixelFormat.u1.dwRGBBitCount)) {
  1472 #else
  1473             ddsd.ddpfPixelFormat.dwRGBBitCount)) {
  1474 #endif
  1475         SDL_FreeSurface(video);
  1476         video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
  1477 #if defined(NONAMELESSUNION)
  1478                                      ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
  1479                                      ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1480                                      ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1481                                      ddsd.ddpfPixelFormat.u4.dwBBitMask,
  1482 #else
  1483                                      ddsd.ddpfPixelFormat.dwRGBBitCount,
  1484                                      ddsd.ddpfPixelFormat.dwRBitMask,
  1485                                      ddsd.ddpfPixelFormat.dwGBitMask,
  1486                                      ddsd.ddpfPixelFormat.dwBBitMask,
  1487 #endif
  1488                                      0);
  1489         if (video == NULL) {
  1490             SDL_OutOfMemory();
  1491             return (NULL);
  1492         }
  1493         video->w = width;
  1494         video->h = height;
  1495         video->pitch = 0;
  1496     }
  1497     video->flags = 0;           /* Clear flags */
  1498 
  1499     /* If not fullscreen, locking is possible, but it doesn't do what 
  1500        the caller really expects -- if the locked surface is written to,
  1501        the appropriate portion of the entire screen is modified, not 
  1502        the application window, as we would like.
  1503        Note that it is still possible to write directly to display
  1504        memory, but the application must respect the clip list of
  1505        the surface.  There might be some odd timing interactions
  1506        involving clip list updates and background refreshing as
  1507        Windows moves other windows across our window.
  1508        We currently don't support this, even though it might be a
  1509        good idea since BeOS has an implementation of BDirectWindow
  1510        that does the same thing.  This would be most useful for
  1511        applications that do complete screen updates every frame.
  1512        -- Fixme?
  1513      */
  1514     if ((flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) {
  1515         /* Necessary if we're going from fullscreen to window */
  1516         if (video->pixels == NULL) {
  1517             video->pitch = (width * video->format->BytesPerPixel);
  1518             /* Pitch needs to be QWORD (8-byte) aligned */
  1519             video->pitch = (video->pitch + 7) & ~7;
  1520             video->pixels = (void *) SDL_malloc(video->h * video->pitch);
  1521             if (video->pixels == NULL) {
  1522                 if (video != current) {
  1523                     SDL_FreeSurface(video);
  1524                 }
  1525                 SDL_OutOfMemory();
  1526                 return (NULL);
  1527             }
  1528         }
  1529         dd_surface3 = NULL;
  1530 #if 0                           /* FIXME: enable this when SDL consistently reports lost surfaces */
  1531         if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
  1532             video->flags |= SDL_HWSURFACE;
  1533         } else {
  1534             video->flags |= SDL_SWSURFACE;
  1535         }
  1536 #else
  1537         video->flags |= SDL_SWSURFACE;
  1538 #endif
  1539         if ((flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME)) {
  1540             video->flags |= SDL_RESIZABLE;
  1541         }
  1542         if (flags & SDL_NOFRAME) {
  1543             video->flags |= SDL_NOFRAME;
  1544         }
  1545     } else {
  1546         /* Necessary if we're going from window to fullscreen */
  1547         if (video->pixels != NULL) {
  1548             SDL_free(video->pixels);
  1549             video->pixels = NULL;
  1550         }
  1551         dd_surface3 = SDL_primary;
  1552         video->flags |= SDL_HWSURFACE;
  1553     }
  1554 
  1555     /* See if the primary surface has double-buffering enabled */
  1556     if ((ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP) {
  1557         video->flags |= SDL_DOUBLEBUF;
  1558     }
  1559 
  1560     /* Allocate the SDL surface associated with the primary surface */
  1561     if (DX5_AllocDDSurface(this, video, dd_surface3,
  1562                            video->flags & SDL_HWSURFACE) < 0) {
  1563         if (video != current) {
  1564             SDL_FreeSurface(video);
  1565         }
  1566         return (NULL);
  1567     }
  1568 
  1569     /* Use the appropriate blitting function */
  1570     if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
  1571         video->flags |= SDL_FULLSCREEN;
  1572         if (video->format->palette != NULL) {
  1573             video->flags |= SDL_HWPALETTE;
  1574         }
  1575         this->UpdateRects = DX5_DirectUpdate;
  1576     } else {
  1577         this->UpdateRects = DX5_WindowUpdate;
  1578     }
  1579 
  1580     /* Make our window the proper size, set the clipper, then show it */
  1581     if ((flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) {
  1582         /* Create and set a clipper on our primary surface */
  1583         if (SDL_clipper == NULL) {
  1584             result = IDirectDraw2_CreateClipper(ddraw2,
  1585                                                 0, &SDL_clipper, NULL);
  1586             if (result != DD_OK) {
  1587                 if (video != current) {
  1588                     SDL_FreeSurface(video);
  1589                 }
  1590                 SetDDerror("DirectDraw2::CreateClipper", result);
  1591                 return (NULL);
  1592             }
  1593         }
  1594         result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
  1595         if (result != DD_OK) {
  1596             if (video != current) {
  1597                 SDL_FreeSurface(video);
  1598             }
  1599             SetDDerror("DirectDrawClipper::SetHWnd", result);
  1600             return (NULL);
  1601         }
  1602         result = IDirectDrawSurface3_SetClipper(SDL_primary, SDL_clipper);
  1603         if (result != DD_OK) {
  1604             if (video != current) {
  1605                 SDL_FreeSurface(video);
  1606             }
  1607             SetDDerror("DirectDrawSurface3::SetClipper", result);
  1608             return (NULL);
  1609         }
  1610 
  1611         /* Resize the window (copied from SDL WinDIB driver) */
  1612         if (!SDL_windowid && !IsZoomed(SDL_Window)) {
  1613             RECT bounds;
  1614             int x, y;
  1615             UINT swp_flags;
  1616             const char *window = NULL;
  1617             const char *center = NULL;
  1618 
  1619             if (!SDL_windowX && !SDL_windowY) {
  1620                 window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
  1621                 center = SDL_getenv("SDL_VIDEO_CENTERED");
  1622                 if (window) {
  1623                     if (SDL_sscanf(window, "%d,%d", &x, &y) == 2) {
  1624                         SDL_windowX = x;
  1625                         SDL_windowY = y;
  1626                     }
  1627                     if (SDL_strcmp(window, "center") == 0) {
  1628                         center = window;
  1629                     }
  1630                 }
  1631             }
  1632             swp_flags = SWP_NOCOPYBITS;
  1633 
  1634             bounds.left = SDL_windowX;
  1635             bounds.top = SDL_windowY;
  1636             bounds.right = SDL_windowX + video->w;
  1637             bounds.bottom = SDL_windowY + video->h;
  1638             AdjustWindowRectEx(&bounds,
  1639                                GetWindowLong(SDL_Window, GWL_STYLE),
  1640                                FALSE, 0);
  1641             width = bounds.right - bounds.left;
  1642             height = bounds.bottom - bounds.top;
  1643             if (center) {
  1644                 x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
  1645                 y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
  1646             } else if (SDL_windowX || SDL_windowY || window) {
  1647                 x = bounds.left;
  1648                 y = bounds.top;
  1649             } else {
  1650                 x = y = -1;
  1651                 swp_flags |= SWP_NOMOVE;
  1652             }
  1653             SetWindowPos(SDL_Window, HWND_NOTOPMOST, x, y, width, height,
  1654                          swp_flags);
  1655             SDL_windowX = SDL_bounds.left;
  1656             SDL_windowY = SDL_bounds.top;
  1657         }
  1658 
  1659     }
  1660     ShowWindow(SDL_Window, SW_SHOW);
  1661     SetForegroundWindow(SDL_Window);
  1662     SDL_resizing = 0;
  1663 
  1664     /* JC 14 Mar 2006
  1665        Flush the message loop or this can cause big problems later
  1666        Especially if the user decides to use dialog boxes or assert()!
  1667      */
  1668     WIN_FlushMessageQueue();
  1669 
  1670     /* We're live! */
  1671     return (video);
  1672 }
  1673 
  1674 struct private_hwdata
  1675 {
  1676     LPDIRECTDRAWSURFACE3 dd_surface;
  1677     LPDIRECTDRAWSURFACE3 dd_writebuf;
  1678 };
  1679 
  1680 static int
  1681 DX5_AllocDDSurface(_THIS, SDL_Surface * surface,
  1682                    LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
  1683 {
  1684     LPDIRECTDRAWSURFACE dd_surface1;
  1685     LPDIRECTDRAWSURFACE3 dd_surface3;
  1686     DDSURFACEDESC ddsd;
  1687     HRESULT result;
  1688 
  1689     /* Clear the hardware flag, in case we fail */
  1690     surface->flags &= ~flag;
  1691 
  1692     /* Allocate the hardware acceleration data */
  1693     surface->hwdata = (struct private_hwdata *)
  1694         SDL_malloc(sizeof(*surface->hwdata));
  1695     if (surface->hwdata == NULL) {
  1696         SDL_OutOfMemory();
  1697         return (-1);
  1698     }
  1699     dd_surface3 = NULL;
  1700 
  1701     /* Set up the surface description */
  1702     SDL_memset(&ddsd, 0, sizeof(ddsd));
  1703     ddsd.dwSize = sizeof(ddsd);
  1704     ddsd.dwFlags = (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS |
  1705                     DDSD_PITCH | DDSD_PIXELFORMAT);
  1706     ddsd.dwWidth = surface->w;
  1707     ddsd.dwHeight = surface->h;
  1708 #if defined(NONAMELESSUNION)
  1709     ddsd.u1.lPitch = surface->pitch;
  1710 #else
  1711     ddsd.lPitch = surface->pitch;
  1712 #endif
  1713     if ((flag & SDL_HWSURFACE) == SDL_HWSURFACE) {
  1714         ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY);
  1715     } else {
  1716         ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);
  1717     }
  1718     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
  1719     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  1720     if (surface->format->palette) {
  1721         ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
  1722     }
  1723 #if defined(NONAMELESSUNION)
  1724     ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
  1725     ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
  1726     ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
  1727     ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
  1728 #else
  1729     ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
  1730     ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
  1731     ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
  1732     ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
  1733 #endif
  1734 
  1735     /* Create the DirectDraw video surface */
  1736     if (requested != NULL) {
  1737         dd_surface3 = requested;
  1738     } else {
  1739         result = IDirectDraw2_CreateSurface(ddraw2,
  1740                                             &ddsd, &dd_surface1, NULL);
  1741         if (result != DD_OK) {
  1742             SetDDerror("DirectDraw2::CreateSurface", result);
  1743             goto error_end;
  1744         }
  1745         result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1746                                                    &IID_IDirectDrawSurface3,
  1747                                                    (LPVOID *) & dd_surface3);
  1748         IDirectDrawSurface_Release(dd_surface1);
  1749         if (result != DD_OK) {
  1750             SetDDerror("DirectDrawSurface::QueryInterface", result);
  1751             goto error_end;
  1752         }
  1753     }
  1754 
  1755     if ((flag & SDL_HWSURFACE) == SDL_HWSURFACE) {
  1756         /* Check to see whether the surface actually ended up
  1757            in video memory, and fail if not.  We expect the
  1758            surfaces we create here to actually be in hardware!
  1759          */
  1760         result = IDirectDrawSurface3_GetCaps(dd_surface3, &ddsd.ddsCaps);
  1761         if (result != DD_OK) {
  1762             SetDDerror("DirectDrawSurface3::GetCaps", result);
  1763             goto error_end;
  1764         }
  1765         if ((ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) !=
  1766             DDSCAPS_VIDEOMEMORY) {
  1767             SDL_SetError("No room in video memory");
  1768             goto error_end;
  1769         }
  1770     } else {
  1771         /* Try to hook our surface memory */
  1772         ddsd.dwFlags = DDSD_LPSURFACE;
  1773         ddsd.lpSurface = surface->pixels;
  1774         result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3, &ddsd, 0);
  1775         if (result != DD_OK) {
  1776             SetDDerror("DirectDraw2::SetSurfaceDesc", result);
  1777             goto error_end;
  1778         }
  1779 
  1780     }
  1781 
  1782     /* Make sure the surface format was set properly */
  1783     SDL_memset(&ddsd, 0, sizeof(ddsd));
  1784     ddsd.dwSize = sizeof(ddsd);
  1785     result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
  1786                                       &ddsd,
  1787                                       (DDLOCK_NOSYSLOCK | DDLOCK_WAIT), NULL);
  1788     if (result != DD_OK) {
  1789         SetDDerror("DirectDrawSurface3::Lock", result);
  1790         goto error_end;
  1791     }
  1792     IDirectDrawSurface3_Unlock(dd_surface3, NULL);
  1793 
  1794     if ((flag & SDL_HWSURFACE) == SDL_SWSURFACE) {
  1795         if (ddsd.lpSurface != surface->pixels) {
  1796             SDL_SetError("DDraw didn't use SDL surface memory");
  1797             goto error_end;
  1798         }
  1799         if (
  1800 #if defined(NONAMELESSUNION)
  1801                ddsd.u1.lPitch
  1802 #else
  1803                ddsd.lPitch
  1804 #endif
  1805                != (LONG) surface->pitch) {
  1806             SDL_SetError("DDraw created surface with wrong pitch");
  1807             goto error_end;
  1808         }
  1809     } else {
  1810 #if defined(NONAMELESSUNION)
  1811         surface->pitch = (Uint16) ddsd.u1.lPitch;
  1812 #else
  1813         surface->pitch = (Uint16) ddsd.lPitch;
  1814 #endif
  1815     }
  1816 #if defined(NONAMELESSUNION)
  1817     if ((ddsd.ddpfPixelFormat.u1.dwRGBBitCount !=
  1818          surface->format->BitsPerPixel) ||
  1819         (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
  1820         (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
  1821         (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask)) {
  1822 #else
  1823     if ((ddsd.ddpfPixelFormat.dwRGBBitCount !=
  1824          surface->format->BitsPerPixel) ||
  1825         (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
  1826         (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
  1827         (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask)) {
  1828 #endif
  1829         SDL_SetError("DDraw didn't use SDL surface description");
  1830         goto error_end;
  1831     }
  1832     if ((ddsd.dwWidth != (DWORD) surface->w) ||
  1833         (ddsd.dwHeight != (DWORD) surface->h)) {
  1834         SDL_SetError("DDraw created surface with wrong size");
  1835         goto error_end;
  1836     }
  1837 
  1838     /* Set the surface private data */
  1839     surface->flags |= flag;
  1840     surface->hwdata->dd_surface = dd_surface3;
  1841     if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
  1842         LPDIRECTDRAWSURFACE3 dd_writebuf;
  1843 
  1844         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
  1845         result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
  1846                                                         &ddsd.ddsCaps,
  1847                                                         &dd_writebuf);
  1848         if (result != DD_OK) {
  1849             SetDDerror("DirectDrawSurface3::GetAttachedSurface", result);
  1850         } else {
  1851             dd_surface3 = dd_writebuf;
  1852         }
  1853     }
  1854     surface->hwdata->dd_writebuf = dd_surface3;
  1855 
  1856     /* We're ready to go! */
  1857     return (0);
  1858 
  1859     /* Okay, so goto's are cheesy, but there are so many possible
  1860        errors in this function, and the cleanup is the same in 
  1861        every single case.  Is there a better way, other than deeply
  1862        nesting the code?
  1863      */
  1864   error_end:
  1865     if ((dd_surface3 != NULL) && (dd_surface3 != requested)) {
  1866         IDirectDrawSurface_Release(dd_surface3);
  1867     }
  1868     SDL_free(surface->hwdata);
  1869     surface->hwdata = NULL;
  1870     return (-1);
  1871 }
  1872 
  1873 static int
  1874 DX5_AllocHWSurface(_THIS, SDL_Surface * surface)
  1875 {
  1876     /* DDraw limitation -- you need to set cooperative level first */
  1877     if (SDL_primary == NULL) {
  1878         SDL_SetError("You must set a non-GL video mode first");
  1879         return (-1);
  1880     }
  1881     return (DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
  1882 }
  1883 
  1884 #ifdef DDRAW_DEBUG
  1885 void
  1886 PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
  1887 {
  1888     DDSURFACEDESC ddsd;
  1889 
  1890     /* Lock and load! */
  1891     SDL_memset(&ddsd, 0, sizeof(ddsd));
  1892     ddsd.dwSize = sizeof(ddsd);
  1893     if (IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
  1894                                  (DDLOCK_NOSYSLOCK | DDLOCK_WAIT),
  1895                                  NULL) != DD_OK) {
  1896         return;
  1897     }
  1898     IDirectDrawSurface3_Unlock(surface, NULL);
  1899 
  1900     fprintf(stderr, "%s:\n", title);
  1901     fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n",
  1902             ddsd.dwWidth, ddsd.dwHeight,
  1903             (flags & SDL_HWSURFACE) ? "hardware" : "software",
  1904 #if defined(NONAMELESSUNION)
  1905             ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
  1906 #else
  1907             ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
  1908 #endif
  1909     fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n",
  1910 #if defined(NONAMELESSUNION)
  1911             ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1912             ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1913             ddsd.ddpfPixelFormat.u4.dwBBitMask);
  1914 #else
  1915             ddsd.ddpfPixelFormat.dwRBitMask,
  1916             ddsd.ddpfPixelFormat.dwGBitMask, ddsd.ddpfPixelFormat.dwBBitMask);
  1917 #endif
  1918 }
  1919 #endif /* DDRAW_DEBUG */
  1920 
  1921 static int
  1922 DX5_HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect,
  1923                 SDL_Surface * dst, SDL_Rect * dstrect)
  1924 {
  1925     LPDIRECTDRAWSURFACE3 src_surface;
  1926     LPDIRECTDRAWSURFACE3 dst_surface;
  1927     DWORD flags;
  1928     RECT rect;
  1929     HRESULT result;
  1930 
  1931     /* Set it up.. the desination must have a DDRAW surface */
  1932     src_surface = src->hwdata->dd_writebuf;
  1933     dst_surface = dst->hwdata->dd_writebuf;
  1934     rect.top = (LONG) srcrect->y;
  1935     rect.bottom = (LONG) srcrect->y + srcrect->h;
  1936     rect.left = (LONG) srcrect->x;
  1937     rect.right = (LONG) srcrect->x + srcrect->w;
  1938     if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY)
  1939         flags = DDBLTFAST_SRCCOLORKEY;
  1940     else
  1941         flags = DDBLTFAST_NOCOLORKEY;
  1942     /* FIXME:  We can remove this flag for _really_ fast blit queuing,
  1943        but it will affect the return values of locks and flips.
  1944      */
  1945     flags |= DDBLTFAST_WAIT;
  1946 
  1947     /* Do the blit! */
  1948     result = IDirectDrawSurface3_BltFast(dst_surface,
  1949                                          dstrect->x, dstrect->y, src_surface,
  1950                                          &rect, flags);
  1951     if (result != DD_OK) {
  1952         if (result == DDERR_SURFACELOST) {
  1953             result = IDirectDrawSurface3_Restore(src_surface);
  1954             result = IDirectDrawSurface3_Restore(dst_surface);
  1955             /* The surfaces need to be reloaded with artwork */
  1956             SDL_SetError("Blit surfaces were lost, reload them");
  1957             return (-2);
  1958         }
  1959         SetDDerror("IDirectDrawSurface3::BltFast", result);
  1960 #ifdef DDRAW_DEBUG
  1961         fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w,
  1962                 dstrect->h, dstrect->x, dstrect->y);
  1963         fprintf(stderr,
  1964                 "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n",
  1965                 (src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src,
  1966                 dst, dstrect->x, dstrect->y);
  1967         PrintSurface("SRC", src_surface, src->flags);
  1968         PrintSurface("DST", dst_surface, dst->flags);
  1969         fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n",
  1970                 rect.left, rect.top, rect.right, rect.bottom);
  1971 #endif
  1972         /* Unexpected error, fall back to software blit */
  1973         return (src->map->sw_blit(src, srcrect, dst, dstrect));
  1974     }
  1975     return (0);
  1976 }
  1977 
  1978 static int
  1979 DX5_CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst)
  1980 {
  1981     int accelerated;
  1982 
  1983     /* We need to have a DDraw surface for HW blits */
  1984     if ((src->flags & SDL_HWSURFACE) == SDL_SWSURFACE) {
  1985         /* Allocate a DDraw surface for the blit */
  1986         if (src->hwdata == NULL) {
  1987             DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
  1988         }
  1989     }
  1990     if (src->hwdata == NULL) {
  1991         return (0);
  1992     }
  1993 
  1994     /* Set initial acceleration on */
  1995     src->flags |= SDL_HWACCEL;
  1996 
  1997     /* Set the surface attributes */
  1998     if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
  1999         if (DX5_SetHWColorKey(this, src, src->format->colorkey) < 0) {
  2000             src->flags &= ~SDL_HWACCEL;
  2001         }
  2002     }
  2003     if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
  2004         if (DX5_SetHWAlpha(this, src, src->format->alpha) < 0) {
  2005             src->flags &= ~SDL_HWACCEL;
  2006         }
  2007     }
  2008 
  2009     /* Check to see if final surface blit is accelerated */
  2010     accelerated = !!(src->flags & SDL_HWACCEL);
  2011     if (accelerated) {
  2012 #ifdef DDRAW_DEBUG
  2013         fprintf(stderr, "Setting accelerated blit on 0x%p\n", src);
  2014 #endif
  2015         src->map->hw_blit = DX5_HWAccelBlit;
  2016     }
  2017     return (accelerated);
  2018 }
  2019 
  2020 static int
  2021 DX5_FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
  2022 {
  2023     LPDIRECTDRAWSURFACE3 dst_surface;
  2024     RECT area;
  2025     DDBLTFX bltfx;
  2026     HRESULT result;
  2027 
  2028 #ifdef DDRAW_DEBUG
  2029     fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x,
  2030             dstrect->y);
  2031 #endif
  2032     dst_surface = dst->hwdata->dd_writebuf;
  2033     area.top = (LONG) dstrect->y;
  2034     area.bottom = (LONG) dstrect->y + dstrect->h;
  2035     area.left = (LONG) dstrect->x;
  2036     area.right = (LONG) dstrect->x + dstrect->w;
  2037     bltfx.dwSize = sizeof(bltfx);
  2038 #if defined(NONAMELESSUNION)
  2039     bltfx.u5.dwFillColor = color;
  2040 #else
  2041     bltfx.dwFillColor = color;
  2042 #endif
  2043     result = IDirectDrawSurface3_Blt(dst_surface,
  2044                                      &area, NULL, NULL,
  2045                                      DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
  2046     if (result == DDERR_SURFACELOST) {
  2047         IDirectDrawSurface3_Restore(dst_surface);
  2048         result = IDirectDrawSurface3_Blt(dst_surface,
  2049                                          &area, NULL, NULL,
  2050                                          DDBLT_COLORFILL | DDBLT_WAIT,
  2051                                          &bltfx);
  2052     }
  2053     if (result != DD_OK) {
  2054         SetDDerror("IDirectDrawSurface3::Blt", result);
  2055         return (-1);
  2056     }
  2057     return (0);
  2058 }
  2059 
  2060 static int
  2061 DX5_SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key)
  2062 {
  2063     DDCOLORKEY colorkey;
  2064     HRESULT result;
  2065 
  2066     /* Set the surface colorkey */
  2067     colorkey.dwColorSpaceLowValue = key;
  2068     colorkey.dwColorSpaceHighValue = key;
  2069     result =
  2070         IDirectDrawSurface3_SetColorKey(surface->hwdata->dd_surface,
  2071                                         DDCKEY_SRCBLT, &colorkey);
  2072     if (result != DD_OK) {
  2073         SetDDerror("IDirectDrawSurface3::SetColorKey", result);
  2074         return (-1);
  2075     }
  2076     return (0);
  2077 }
  2078 static int
  2079 DX5_SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 alpha)
  2080 {
  2081     return (-1);
  2082 }
  2083 
  2084 static int
  2085 DX5_LockHWSurface(_THIS, SDL_Surface * surface)
  2086 {
  2087     HRESULT result;
  2088     LPDIRECTDRAWSURFACE3 dd_surface;
  2089     DDSURFACEDESC ddsd;
  2090 
  2091     /* Lock and load! */
  2092     dd_surface = surface->hwdata->dd_writebuf;
  2093     SDL_memset(&ddsd, 0, sizeof(ddsd));
  2094     ddsd.dwSize = sizeof(ddsd);
  2095     result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
  2096                                       (DDLOCK_NOSYSLOCK | DDLOCK_WAIT), NULL);
  2097     if (result == DDERR_SURFACELOST) {
  2098         result = IDirectDrawSurface3_Restore(surface->hwdata->dd_surface);
  2099         result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
  2100                                           (DDLOCK_NOSYSLOCK | DDLOCK_WAIT),
  2101                                           NULL);
  2102     }
  2103     if (result != DD_OK) {
  2104         SetDDerror("DirectDrawSurface3::Lock", result);
  2105         return (-1);
  2106     }
  2107     /* Pitch might have changed -- recalculate pitch and offset */
  2108 #if defined(NONAMELESSUNION)
  2109     if (surface->pitch != ddsd.u1.lPitch) {
  2110         surface->pitch = ddsd.u1.lPitch;
  2111 #else
  2112     if (surface->pitch != ddsd.lPitch) {
  2113         surface->pitch = (Uint16) ddsd.lPitch;
  2114 #endif
  2115         surface->offset =
  2116             ((ddsd.dwHeight - surface->h) / 2) * surface->pitch +
  2117             ((ddsd.dwWidth - surface->w) / 2) *
  2118             surface->format->BytesPerPixel;
  2119     }
  2120     surface->pixels = ddsd.lpSurface;
  2121     return (0);
  2122 }
  2123 
  2124 static void
  2125 DX5_UnlockHWSurface(_THIS, SDL_Surface * surface)
  2126 {
  2127     IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
  2128     surface->pixels = NULL;
  2129 }
  2130 
  2131 static int
  2132 DX5_FlipHWSurface(_THIS, SDL_Surface * surface)
  2133 {
  2134     HRESULT result;
  2135     LPDIRECTDRAWSURFACE3 dd_surface;
  2136 
  2137     dd_surface = surface->hwdata->dd_surface;
  2138 
  2139     /* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */
  2140     /* Dmitry Yakimov (ftech@tula.net) */
  2141     while (IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) ==
  2142            DDERR_WASSTILLDRAWING);
  2143 
  2144     result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
  2145     if (result == DDERR_SURFACELOST) {
  2146         result = IDirectDrawSurface3_Restore(surface->hwdata->dd_surface);
  2147         while (IDirectDrawSurface3_GetFlipStatus
  2148                (dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
  2149         result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
  2150     }
  2151     if (result != DD_OK) {
  2152         SetDDerror("DirectDrawSurface3::Flip", result);
  2153         return (-1);
  2154     }
  2155     return (0);
  2156 }
  2157 
  2158 static void
  2159 DX5_FreeHWSurface(_THIS, SDL_Surface * surface)
  2160 {
  2161     if (surface->hwdata) {
  2162         if (surface->hwdata->dd_surface != SDL_primary) {
  2163             IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
  2164         }
  2165         SDL_free(surface->hwdata);
  2166         surface->hwdata = NULL;
  2167     }
  2168 }
  2169 
  2170 void
  2171 DX5_WindowUpdate(_THIS, int numrects, SDL_Rect * rects)
  2172 {
  2173     HRESULT result;
  2174     int i;
  2175     RECT src, dst;
  2176 
  2177     for (i = 0; i < numrects; ++i) {
  2178         src.top = (LONG) rects[i].y;
  2179         src.bottom = (LONG) rects[i].y + rects[i].h;
  2180         src.left = (LONG) rects[i].x;
  2181         src.right = (LONG) rects[i].x + rects[i].w;
  2182         dst.top = SDL_bounds.top + src.top;
  2183         dst.left = SDL_bounds.left + src.left;
  2184         dst.bottom = SDL_bounds.top + src.bottom;
  2185         dst.right = SDL_bounds.left + src.right;
  2186         result = IDirectDrawSurface3_Blt(SDL_primary, &dst,
  2187                                          this->screen->hwdata->dd_surface,
  2188                                          &src, DDBLT_WAIT, NULL);
  2189         /* Doh!  Check for lost surface and restore it */
  2190         if (result == DDERR_SURFACELOST) {
  2191             IDirectDrawSurface3_Restore(SDL_primary);
  2192             IDirectDrawSurface3_Blt(SDL_primary, &dst,
  2193                                     this->screen->hwdata->dd_surface,
  2194                                     &src, DDBLT_WAIT, NULL);
  2195         }
  2196     }
  2197 }
  2198 
  2199 void
  2200 DX5_DirectUpdate(_THIS, int numrects, SDL_Rect * rects)
  2201 {
  2202 }
  2203 
  2204 /* Compress a full palette into the limited number of colors given to us
  2205    by windows.
  2206 
  2207    The "best" way to do this is to sort the colors by diversity and place
  2208    the most diverse colors into the limited palette.  Unfortunately this
  2209    results in widely varying colors being displayed in the interval during
  2210    which the windows palette has been set, and the mapping of the shadow
  2211    surface to the new palette.  This is especially noticeable during fades.
  2212 
  2213    To deal with this problem, we can copy a predetermined portion of the
  2214    full palette, and use that as the limited palette.  This allows colors
  2215    to fade smoothly as the remapping is very similar on each palette change.
  2216    Unfortunately, this breaks applications which partition the palette into
  2217    distinct and widely varying areas, expecting all colors to be available.
  2218 
  2219    I'm making them both available, chosen at compile time.
  2220    If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
  2221    otherwise the sort-by-diversity algorithm will be used.
  2222 */
  2223 #define SIMPLE_COMPRESSION
  2224 #define CS_CS_DIST(A, B) ({						\
  2225 	int r = (A.r - B.r);						\
  2226 	int g = (A.g - B.g);						\
  2227 	int b = (A.b - B.b);						\
  2228 	(r*r + g*g + b*b);						\
  2229 })
  2230 static void
  2231 DX5_CompressPalette(_THIS, SDL_Color * colors, int ncolors, int maxcolors)
  2232 {
  2233 #ifdef SIMPLE_COMPRESSION
  2234     int i, j;
  2235 #else
  2236     static SDL_Color zero = { 0, 0, 0, 0 };
  2237     int i, j;
  2238     int max, dist;
  2239     int prev, next;
  2240     int *pool;
  2241     int *seen, *order;
  2242 #endif
  2243 
  2244     /* Does this happen? */
  2245     if (maxcolors > ncolors) {
  2246         maxcolors = ncolors;
  2247     }
  2248 #ifdef SIMPLE_COMPRESSION
  2249     /* Just copy the first "maxcolors" colors */
  2250     for (j = 10, i = 0; i < maxcolors; ++i, ++j) {
  2251         SDL_colors[j].peRed = colors[i].r;
  2252         SDL_colors[j].peGreen = colors[i].g;
  2253         SDL_colors[j].peBlue = colors[i].b;
  2254     }
  2255 #else
  2256     /* Allocate memory for the arrays we use */
  2257     pool = SDL_stack_alloc(int, 2 * ncolors);
  2258     if (pool == NULL) {
  2259         /* No worries, just return */ ;
  2260         return;
  2261     }
  2262     seen = pool;
  2263     SDL_memset(seen, 0, ncolors * sizeof(int));
  2264     order = pool + ncolors;
  2265 
  2266     /* Start with the brightest color */
  2267     max = 0;
  2268     for (i = 0; i < ncolors; ++i) {
  2269         dist = CS_CS_DIST(zero, colors[i]);
  2270         if (dist >= max) {
  2271             max = dist;
  2272             next = i;
  2273         }
  2274     }
  2275     j = 0;
  2276     order[j++] = next;
  2277     seen[next] = 1;
  2278     prev = next;
  2279 
  2280     /* Keep going through all the colors */
  2281     while (j < maxcolors) {
  2282         max = 0;
  2283         for (i = 0; i < ncolors; ++i) {
  2284             if (seen[i]) {
  2285                 continue;
  2286             }
  2287             dist = CS_CS_DIST(colors[i], colors[prev]);
  2288             if (dist >= max) {
  2289                 max = dist;
  2290                 next = i;
  2291             }
  2292         }
  2293         order[j++] = next;
  2294         seen[next] = 1;
  2295         prev = next;
  2296     }
  2297 
  2298     /* Compress the colors to the palette */
  2299     for (j = 10, i = 0; i < maxcolors; ++i, ++j) {
  2300         SDL_colors[j].peRed = colors[order[i]].r;
  2301         SDL_colors[j].peGreen = colors[order[i]].g;
  2302         SDL_colors[j].peBlue = colors[order[i]].b;
  2303     }
  2304     SDL_stack_free(pool);
  2305 #endif /* SIMPLE_COMPRESSION */
  2306 }
  2307 
  2308 /* Set the system colormap in both fullscreen and windowed modes */
  2309 int
  2310 DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
  2311 {
  2312     int i;
  2313     int alloct_all;
  2314 
  2315     /* Copy palette colors into display palette */
  2316     alloct_all = 0;
  2317     if (SDL_palette != NULL) {
  2318         if ((this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
  2319             /* We can set all entries explicitly */
  2320             for (i = 0; i < ncolors; ++i) {
  2321                 int j = firstcolor + i;
  2322                 SDL_colors[j].peRed = colors[i].r;
  2323                 SDL_colors[j].peGreen = colors[i].g;
  2324                 SDL_colors[j].peBlue = colors[i].b;
  2325             }
  2326             IDirectDrawPalette_SetEntries(SDL_palette, 0,
  2327                                           firstcolor, ncolors,
  2328                                           &SDL_colors[firstcolor]);
  2329             alloct_all = 1;
  2330         } else {
  2331             /* Grab the 236 most diverse colors in the palette */
  2332             DX5_CompressPalette(this, colors, ncolors, 236);
  2333             /* This sends an WM_PALETTECHANGED message to us */
  2334             colorchange_expected = 1;
  2335             IDirectDrawPalette_SetEntries(SDL_palette, 0, 0, 256, SDL_colors);
  2336         }
  2337     }
  2338     return (alloct_all);
  2339 }
  2340 
  2341 /* Gamma code is only available on DirectX 7 and newer */
  2342 static int
  2343 DX5_SetGammaRamp(_THIS, Uint16 * ramp)
  2344 {
  2345 #ifdef IDirectDrawGammaControl_SetGammaRamp
  2346     LPDIRECTDRAWGAMMACONTROL gamma;
  2347     DDGAMMARAMP gamma_ramp;
  2348     HRESULT result;
  2349 #endif
  2350 
  2351     /* In windowed or OpenGL mode, use windib gamma code */
  2352     if (!DDRAW_FULLSCREEN()) {
  2353         return DIB_SetGammaRamp(this, ramp);
  2354     }
  2355 #ifndef IDirectDrawGammaControl_SetGammaRamp
  2356     SDL_SetError("SDL compiled without DirectX gamma ramp support");
  2357     return -1;
  2358 #else
  2359     /* Check for a video mode! */
  2360     if (!SDL_primary) {
  2361         SDL_SetError("A video mode must be set for gamma correction");
  2362         return (-1);
  2363     }
  2364 
  2365     /* Get the gamma control object */
  2366     result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  2367                                                 &IID_IDirectDrawGammaControl,
  2368                                                 (LPVOID *) & gamma);
  2369     if (result != DD_OK) {
  2370         SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  2371         return (-1);
  2372     }
  2373 
  2374     /* Set up the gamma ramp */
  2375     SDL_memcpy(gamma_ramp.red, &ramp[0 * 256], 256 * sizeof(*ramp));
  2376     SDL_memcpy(gamma_ramp.green, &ramp[1 * 256], 256 * sizeof(*ramp));
  2377     SDL_memcpy(gamma_ramp.blue, &ramp[2 * 256], 256 * sizeof(*ramp));
  2378     result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp);
  2379     if (result != DD_OK) {
  2380         SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result);
  2381     }
  2382 
  2383     /* Release the interface and return */
  2384     IDirectDrawGammaControl_Release(gamma);
  2385     return (result == DD_OK) ? 0 : -1;
  2386 #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2387 }
  2388 
  2389 static int
  2390 DX5_GetGammaRamp(_THIS, Uint16 * ramp)
  2391 {
  2392 #ifdef IDirectDrawGammaControl_SetGammaRamp
  2393     LPDIRECTDRAWGAMMACONTROL gamma;
  2394     DDGAMMARAMP gamma_ramp;
  2395     HRESULT result;
  2396 #endif
  2397 
  2398     /* In windowed or OpenGL mode, use windib gamma code */
  2399     if (!DDRAW_FULLSCREEN()) {
  2400         return DIB_GetGammaRamp(this, ramp);
  2401     }
  2402 #ifndef IDirectDrawGammaControl_SetGammaRamp
  2403     SDL_SetError("SDL compiled without DirectX gamma ramp support");
  2404     return -1;
  2405 #else
  2406     /* Check for a video mode! */
  2407     if (!SDL_primary) {
  2408         SDL_SetError("A video mode must be set for gamma correction");
  2409         return (-1);
  2410     }
  2411 
  2412     /* Get the gamma control object */
  2413     result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  2414                                                 &IID_IDirectDrawGammaControl,
  2415                                                 (LPVOID *) & gamma);
  2416     if (result != DD_OK) {
  2417         SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  2418         return (-1);
  2419     }
  2420 
  2421     /* Set up the gamma ramp */
  2422     result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp);
  2423     if (result == DD_OK) {
  2424         SDL_memcpy(&ramp[0 * 256], gamma_ramp.red, 256 * sizeof(*ramp));
  2425         SDL_memcpy(&ramp[1 * 256], gamma_ramp.green, 256 * sizeof(*ramp));
  2426         SDL_memcpy(&ramp[2 * 256], gamma_ramp.blue, 256 * sizeof(*ramp));
  2427     } else {
  2428         SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result);
  2429     }
  2430 
  2431     /* Release the interface and return */
  2432     IDirectDrawGammaControl_Release(gamma);
  2433     return (result == DD_OK) ? 0 : -1;
  2434 #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2435 }
  2436 
  2437 void
  2438 DX5_VideoQuit(_THIS)
  2439 {
  2440     int i, j;
  2441 
  2442     /* If we're fullscreen GL, we need to reset the display */
  2443     if (this->screen != NULL) {
  2444 #ifndef NO_CHANGEDISPLAYSETTINGS
  2445         if ((this->screen->flags & (SDL_INTERNALOPENGL | SDL_FULLSCREEN)) ==
  2446             (SDL_INTERNALOPENGL | SDL_FULLSCREEN)) {
  2447             ChangeDisplaySettings(NULL, 0);
  2448             ShowWindow(SDL_Window, SW_HIDE);
  2449         }
  2450 #endif
  2451         if (this->screen->flags & SDL_INTERNALOPENGL) {
  2452             WIN_GL_ShutDown(this);
  2453         }
  2454     }
  2455 
  2456     /* Free any palettes we used */
  2457     if (SDL_palette != NULL) {
  2458         IDirectDrawPalette_Release(SDL_palette);
  2459         SDL_palette = NULL;
  2460     }
  2461 
  2462     /* Allow the primary surface to be freed */
  2463     if (SDL_primary != NULL) {
  2464         SDL_primary = NULL;
  2465     }
  2466 
  2467     /* Free video mode lists */
  2468     for (i = 0; i < NUM_MODELISTS; ++i) {
  2469         if (SDL_modelist[i] != NULL) {
  2470             for (j = 0; SDL_modelist[i][j]; ++j)
  2471                 SDL_free(SDL_modelist[i][j]);
  2472             SDL_free(SDL_modelist[i]);
  2473             SDL_modelist[i] = NULL;
  2474         }
  2475     }
  2476 
  2477     /* Free the window */
  2478     DIB_QuitGamma(this);
  2479     if (SDL_Window) {
  2480         DX5_DestroyWindow(this);
  2481     }
  2482 
  2483     /* Free our window icon */
  2484     if (screen_icn) {
  2485         DestroyIcon(screen_icn);
  2486         screen_icn = NULL;
  2487     }
  2488 }
  2489 
  2490 /* Exported for the windows message loop only */
  2491 void
  2492 DX5_RealizePalette(_THIS)
  2493 {
  2494     if (SDL_palette) {
  2495         IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
  2496     }
  2497 }
  2498 static void
  2499 DX5_Recolor8Bit(_THIS, SDL_Surface * surface, Uint8 * mapping)
  2500 {
  2501     int row, col;
  2502     Uint8 *pixels;
  2503 
  2504     if (surface->w && surface->h) {
  2505         if ((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
  2506             if (this->LockHWSurface(this, surface) < 0) {
  2507                 return;
  2508             }
  2509         }
  2510         for (row = 0; row < surface->h; ++row) {
  2511             pixels = (Uint8 *) surface->pixels + row * surface->pitch;
  2512             for (col = 0; col < surface->w; ++col, ++pixels) {
  2513                 *pixels = mapping[*pixels];
  2514             }
  2515         }
  2516         if ((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
  2517             this->UnlockHWSurface(this, surface);
  2518         }
  2519         SDL_UpdateRect(surface, 0, 0, 0, 0);
  2520     }
  2521 }
  2522 void
  2523 DX5_PaletteChanged(_THIS, HWND window)
  2524 {
  2525     SDL_Palette *palette;
  2526     SDL_Color *saved = NULL;
  2527     HDC hdc;
  2528     int i;
  2529     PALETTEENTRY *entries;
  2530 
  2531     /* This is true when the window is closing */
  2532     if ((SDL_primary == NULL) || (SDL_VideoSurface == NULL))
  2533         return;
  2534 
  2535     /* We need to get the colors as they were set */
  2536     palette = this->physpal;
  2537     if (!palette)
  2538         palette = SDL_VideoSurface->format->palette;
  2539     if (palette == NULL) {      /* Sometimes we don't have a palette */
  2540         return;
  2541     }
  2542     entries = SDL_stack_alloc(PALETTEENTRY, palette->ncolors);
  2543     hdc = GetDC(window);
  2544     GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries);
  2545     ReleaseDC(window, hdc);
  2546     if (!colorchange_expected) {
  2547         saved = SDL_stack_alloc(SDL_Color, palette->ncolors);
  2548         SDL_memcpy(saved, palette->colors,
  2549                    palette->ncolors * sizeof(SDL_Color));
  2550     }
  2551     for (i = 0; i < palette->ncolors; ++i) {
  2552         palette->colors[i].r = entries[i].peRed;
  2553         palette->colors[i].g = entries[i].peGreen;
  2554         palette->colors[i].b = entries[i].peBlue;
  2555     }
  2556     SDL_stack_free(entries);
  2557     if (!colorchange_expected) {
  2558         Uint8 mapping[256];
  2559 
  2560         SDL_memset(mapping, 0, sizeof(mapping));
  2561         for (i = 0; i < palette->ncolors; ++i) {
  2562             mapping[i] = SDL_FindColor(palette,
  2563                                        saved[i].r, saved[i].g, saved[i].b);
  2564         }
  2565         DX5_Recolor8Bit(this, SDL_VideoSurface, mapping);
  2566         SDL_stack_free(saved);
  2567     }
  2568     colorchange_expected = 0;
  2569 
  2570     /* Notify all mapped surfaces of the change */
  2571     SDL_FormatChanged(SDL_VideoSurface);
  2572 }
  2573 
  2574 /* Exported for the windows message loop only */
  2575 void
  2576 DX5_WinPAINT(_THIS, HDC hdc)
  2577 {
  2578     SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
  2579 }
  2580 
  2581 /* vi: set ts=4 sw=4 expandtab: */