winengine.c revision 9ace9065
1/* 2 *Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved. 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 *"Software"), to deal in the Software without restriction, including 7 *without limitation the rights to use, copy, modify, merge, publish, 8 *distribute, sublicense, and/or sell copies of the Software, and to 9 *permit persons to whom the Software is furnished to do so, subject to 10 *the following conditions: 11 * 12 *The above copyright notice and this permission notice shall be 13 *included in all copies or substantial portions of the Software. 14 * 15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR 19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 *Except as contained in this notice, the name of Harold L Hunt II 24 *shall not be used in advertising or otherwise to promote the sale, use 25 *or other dealings in this Software without prior written authorization 26 *from Harold L Hunt II. 27 * 28 * Authors: Harold L Hunt II 29 */ 30 31#ifdef HAVE_XWIN_CONFIG_H 32#include <xwin-config.h> 33#endif 34#include "win.h" 35#include "winmsg.h" 36 37/* 38 * Global variables for function pointers into 39 * dynamically loaded libraries 40 */ 41FARPROC g_fpDirectDrawCreate = NULL; 42FARPROC g_fpDirectDrawCreateClipper = NULL; 43 44/* 45 module handle for dynamically loaded directdraw library 46*/ 47static HMODULE g_hmodDirectDraw = NULL; 48 49/* 50 * Detect engines supported by current Windows version 51 * DirectDraw version and hardware 52 */ 53 54void 55winDetectSupportedEngines (void) 56{ 57 OSVERSIONINFO osvi; 58 59 /* Initialize the engine support flags */ 60 g_dwEnginesSupported = WIN_SERVER_SHADOW_GDI; 61 62#ifdef XWIN_NATIVEGDI 63 g_dwEnginesSupported |= WIN_SERVER_NATIVE_GDI; 64#endif 65 66 /* Get operating system version information */ 67 ZeroMemory (&osvi, sizeof (osvi)); 68 osvi.dwOSVersionInfoSize = sizeof (osvi); 69 GetVersionEx (&osvi); 70 71 /* Branch on platform ID */ 72 switch (osvi.dwPlatformId) 73 { 74 case VER_PLATFORM_WIN32_NT: 75 /* Engine 4 is supported on NT only */ 76 winErrorFVerb (2, "winDetectSupportedEngines - Windows NT/2000/XP\n"); 77 break; 78 79 case VER_PLATFORM_WIN32_WINDOWS: 80 /* Engine 4 is supported on NT only */ 81 winErrorFVerb (2, "winDetectSupportedEngines - Windows 95/98/Me\n"); 82 break; 83 } 84 85 /* Do we have DirectDraw? */ 86 if (g_hmodDirectDraw != NULL) 87 { 88 LPDIRECTDRAW lpdd = NULL; 89 LPDIRECTDRAW4 lpdd4 = NULL; 90 HRESULT ddrval; 91 92 /* Was the DirectDrawCreate function found? */ 93 if (g_fpDirectDrawCreate == NULL) 94 { 95 /* No DirectDraw support */ 96 return; 97 } 98 99 /* DirectDrawCreate exists, try to call it */ 100 /* Create a DirectDraw object, store the address at lpdd */ 101 ddrval = (*g_fpDirectDrawCreate) (NULL, 102 (void**) &lpdd, 103 NULL); 104 if (FAILED (ddrval)) 105 { 106 /* No DirectDraw support */ 107 winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw not installed\n"); 108 return; 109 } 110 else 111 { 112 /* We have DirectDraw */ 113 winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw installed\n"); 114 g_dwEnginesSupported |= WIN_SERVER_SHADOW_DD; 115 116#ifdef XWIN_PRIMARYFB 117 /* Allow PrimaryDD engine if NT */ 118 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) 119 { 120 g_dwEnginesSupported |= WIN_SERVER_PRIMARY_DD; 121 winErrorFVerb (2, "winDetectSupportedEngines - Allowing PrimaryDD\n"); 122 } 123#endif 124 } 125 126 /* Try to query for DirectDraw4 interface */ 127 ddrval = IDirectDraw_QueryInterface (lpdd, 128 &IID_IDirectDraw4, 129 (LPVOID*) &lpdd4); 130 if (SUCCEEDED (ddrval)) 131 { 132 /* We have DirectDraw4 */ 133 winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw4 installed\n"); 134 g_dwEnginesSupported |= WIN_SERVER_SHADOW_DDNL; 135 } 136 137 /* Cleanup DirectDraw interfaces */ 138 if (lpdd4 != NULL) 139 IDirectDraw_Release (lpdd4); 140 if (lpdd != NULL) 141 IDirectDraw_Release (lpdd); 142 } 143 144 winErrorFVerb (2, "winDetectSupportedEngines - Returning, supported engines %08x\n", 145 (unsigned int) g_dwEnginesSupported); 146} 147 148 149/* 150 * Set the engine type, depending on the engines 151 * supported for this screen, and whether the user 152 * suggested an engine type 153 */ 154 155Bool 156winSetEngine (ScreenPtr pScreen) 157{ 158 winScreenPriv(pScreen); 159 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 160 HDC hdc; 161 DWORD dwBPP; 162 163 /* Get a DC */ 164 hdc = GetDC (NULL); 165 if (hdc == NULL) 166 { 167 ErrorF ("winSetEngine - Couldn't get an HDC\n"); 168 return FALSE; 169 } 170 171 /* 172 * pScreenInfo->dwBPP may be 0 to indicate that the current screen 173 * depth is to be used. Thus, we must query for the current display 174 * depth here. 175 */ 176 dwBPP = GetDeviceCaps (hdc, BITSPIXEL); 177 178 /* Release the DC */ 179 ReleaseDC (NULL, hdc); 180 hdc = NULL; 181 182 /* ShadowGDI is the only engine that supports windowed PseudoColor */ 183 if (dwBPP == 8 && !pScreenInfo->fFullScreen) 184 { 185 winErrorFVerb (2, "winSetEngine - Windowed && PseudoColor => ShadowGDI\n"); 186 pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI; 187 188 /* Set engine function pointers */ 189 winSetEngineFunctionsShadowGDI (pScreen); 190 return TRUE; 191 } 192 193 /* ShadowGDI is the only engine that supports Multi Window Mode */ 194 if ( 195#ifdef XWIN_MULTIWINDOWEXTWM 196 pScreenInfo->fMWExtWM 197#else 198 FALSE 199#endif 200#ifdef XWIN_MULTIWINDOW 201 || pScreenInfo->fMultiWindow 202#else 203 || FALSE 204#endif 205 ) 206 { 207 winErrorFVerb (2, "winSetEngine - Multi Window or Rootless => ShadowGDI\n"); 208 pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI; 209 210 /* Set engine function pointers */ 211 winSetEngineFunctionsShadowGDI (pScreen); 212 return TRUE; 213 } 214 215 /* If the user's choice is supported, we'll use that */ 216 if (g_dwEnginesSupported & pScreenInfo->dwEnginePreferred) 217 { 218 winErrorFVerb (2, "winSetEngine - Using user's preference: %d\n", 219 (int) pScreenInfo->dwEnginePreferred); 220 pScreenInfo->dwEngine = pScreenInfo->dwEnginePreferred; 221 222 /* Setup engine function pointers */ 223 switch (pScreenInfo->dwEngine) 224 { 225 case WIN_SERVER_SHADOW_GDI: 226 winSetEngineFunctionsShadowGDI (pScreen); 227 break; 228 case WIN_SERVER_SHADOW_DD: 229 winSetEngineFunctionsShadowDD (pScreen); 230 break; 231 case WIN_SERVER_SHADOW_DDNL: 232 winSetEngineFunctionsShadowDDNL (pScreen); 233 break; 234#ifdef XWIN_PRIMARYFB 235 case WIN_SERVER_PRIMARY_DD: 236 winSetEngineFunctionsPrimaryDD (pScreen); 237 break; 238#endif 239#ifdef XWIN_NATIVEGDI 240 case WIN_SERVER_NATIVE_GDI: 241 winSetEngineFunctionsNativeGDI (pScreen); 242 break; 243#endif 244 default: 245 FatalError ("winSetEngine - Invalid engine type\n"); 246 } 247 return TRUE; 248 } 249 250 /* ShadowDDNL has good performance, so why not */ 251 if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DDNL) 252 { 253 winErrorFVerb (2, "winSetEngine - Using Shadow DirectDraw NonLocking\n"); 254 pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DDNL; 255 256 /* Set engine function pointers */ 257 winSetEngineFunctionsShadowDDNL (pScreen); 258 return TRUE; 259 } 260 261 /* ShadowDD is next in line */ 262 if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DD) 263 { 264 winErrorFVerb (2, "winSetEngine - Using Shadow DirectDraw\n"); 265 pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DD; 266 267 /* Set engine function pointers */ 268 winSetEngineFunctionsShadowDD (pScreen); 269 return TRUE; 270 } 271 272 /* ShadowGDI is next in line */ 273 if (g_dwEnginesSupported & WIN_SERVER_SHADOW_GDI) 274 { 275 winErrorFVerb (2, "winSetEngine - Using Shadow GDI DIB\n"); 276 pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI; 277 278 /* Set engine function pointers */ 279 winSetEngineFunctionsShadowGDI (pScreen); 280 return TRUE; 281 } 282 283 return TRUE; 284} 285 286 287/* 288 * Get procedure addresses for DirectDrawCreate and DirectDrawCreateClipper 289 */ 290 291Bool 292winGetDDProcAddresses (void) 293{ 294 Bool fReturn = TRUE; 295 296 /* Load the DirectDraw library */ 297 g_hmodDirectDraw = LoadLibraryEx ("ddraw.dll", NULL, 0); 298 if (g_hmodDirectDraw == NULL) 299 { 300 ErrorF ("winGetDDProcAddresses - Could not load ddraw.dll\n"); 301 fReturn = TRUE; 302 goto winGetDDProcAddresses_Exit; 303 } 304 305 /* Try to get the DirectDrawCreate address */ 306 g_fpDirectDrawCreate = GetProcAddress (g_hmodDirectDraw, 307 "DirectDrawCreate"); 308 if (g_fpDirectDrawCreate == NULL) 309 { 310 ErrorF ("winGetDDProcAddresses - Could not get DirectDrawCreate " 311 "address\n"); 312 fReturn = TRUE; 313 goto winGetDDProcAddresses_Exit; 314 } 315 316 /* Try to get the DirectDrawCreateClipper address */ 317 g_fpDirectDrawCreateClipper = GetProcAddress (g_hmodDirectDraw, 318 "DirectDrawCreateClipper"); 319 if (g_fpDirectDrawCreateClipper == NULL) 320 { 321 ErrorF ("winGetDDProcAddresses - Could not get " 322 "DirectDrawCreateClipper address\n"); 323 fReturn = FALSE; 324 goto winGetDDProcAddresses_Exit; 325 } 326 327 /* 328 * Note: Do not unload ddraw.dll here. Do it in GiveUp 329 */ 330 331 winGetDDProcAddresses_Exit: 332 /* Unload the DirectDraw library if we failed to initialize */ 333 if (!fReturn && g_hmodDirectDraw != NULL) 334 { 335 FreeLibrary (g_hmodDirectDraw); 336 g_hmodDirectDraw = NULL; 337 } 338 339 return fReturn; 340} 341 342void 343winReleaseDDProcAddresses(void) 344{ 345 if (g_hmodDirectDraw != NULL) 346 { 347 FreeLibrary (g_hmodDirectDraw); 348 g_hmodDirectDraw = NULL; 349 g_fpDirectDrawCreate = NULL; 350 g_fpDirectDrawCreateClipper = NULL; 351 } 352} 353