| 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 | */ |
| 41 | FARPROC g_fpDirectDrawCreate = NULL; |
| 42 | FARPROC g_fpDirectDrawCreateClipper = NULL; |
| 43 | |
| 44 | /* |
| 45 | module handle for dynamically loaded directdraw library |
| 46 | */ |
| 47 | static HMODULE g_hmodDirectDraw = NULL; |
| 48 | |
| 49 | /* |
| 50 | * Detect engines supported by current Windows version |
| 51 | * DirectDraw version and hardware |
| 52 | */ |
| 53 | |
| 54 | void |
| 55 | winDetectSupportedEngines(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 | /* Do we have DirectDraw? */ |
| 72 | if (g_hmodDirectDraw != NULL) { |
| 73 | LPDIRECTDRAW lpdd = NULL; |
| 74 | LPDIRECTDRAW4 lpdd4 = NULL; |
| 75 | HRESULT ddrval; |
| 76 | |
| 77 | /* Was the DirectDrawCreate function found? */ |
| 78 | if (g_fpDirectDrawCreate == NULL) { |
| 79 | /* No DirectDraw support */ |
| 80 | return; |
| 81 | } |
| 82 | |
| 83 | /* DirectDrawCreate exists, try to call it */ |
| 84 | /* Create a DirectDraw object, store the address at lpdd */ |
| 85 | ddrval = (*g_fpDirectDrawCreate) (NULL, (void **) &lpdd, NULL); |
| 86 | if (FAILED(ddrval)) { |
| 87 | /* No DirectDraw support */ |
| 88 | winErrorFVerb(2, |
| 89 | "winDetectSupportedEngines - DirectDraw not installed\n"); |
| 90 | return; |
| 91 | } |
| 92 | else { |
| 93 | /* We have DirectDraw */ |
| 94 | winErrorFVerb(2, |
| 95 | "winDetectSupportedEngines - DirectDraw installed, allowing ShadowDD\n"); |
| 96 | g_dwEnginesSupported |= WIN_SERVER_SHADOW_DD; |
| 97 | |
| 98 | #ifdef XWIN_PRIMARYFB |
| 99 | /* Allow PrimaryDD engine if NT */ |
| 100 | if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { |
| 101 | g_dwEnginesSupported |= WIN_SERVER_PRIMARY_DD; |
| 102 | winErrorFVerb(2, |
| 103 | "winDetectSupportedEngines - Windows NT, allowing PrimaryDD\n"); |
| 104 | } |
| 105 | #endif |
| 106 | } |
| 107 | |
| 108 | /* Try to query for DirectDraw4 interface */ |
| 109 | ddrval = IDirectDraw_QueryInterface(lpdd, |
| 110 | &IID_IDirectDraw4, |
| 111 | (LPVOID *) &lpdd4); |
| 112 | if (SUCCEEDED(ddrval)) { |
| 113 | /* We have DirectDraw4 */ |
| 114 | winErrorFVerb(2, |
| 115 | "winDetectSupportedEngines - DirectDraw4 installed, allowing ShadowDDNL\n"); |
| 116 | g_dwEnginesSupported |= WIN_SERVER_SHADOW_DDNL; |
| 117 | } |
| 118 | |
| 119 | /* Cleanup DirectDraw interfaces */ |
| 120 | if (lpdd4 != NULL) |
| 121 | IDirectDraw_Release(lpdd4); |
| 122 | if (lpdd != NULL) |
| 123 | IDirectDraw_Release(lpdd); |
| 124 | } |
| 125 | |
| 126 | winErrorFVerb(2, |
| 127 | "winDetectSupportedEngines - Returning, supported engines %08x\n", |
| 128 | (unsigned int) g_dwEnginesSupported); |
| 129 | } |
| 130 | |
| 131 | /* |
| 132 | * Set the engine type, depending on the engines |
| 133 | * supported for this screen, and whether the user |
| 134 | * suggested an engine type |
| 135 | */ |
| 136 | |
| 137 | Bool |
| 138 | winSetEngine(ScreenPtr pScreen) |
| 139 | { |
| 140 | winScreenPriv(pScreen); |
| 141 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; |
| 142 | HDC hdc; |
| 143 | DWORD dwBPP; |
| 144 | |
| 145 | /* Get a DC */ |
| 146 | hdc = GetDC(NULL); |
| 147 | if (hdc == NULL) { |
| 148 | ErrorF("winSetEngine - Couldn't get an HDC\n"); |
| 149 | return FALSE; |
| 150 | } |
| 151 | |
| 152 | /* |
| 153 | * pScreenInfo->dwBPP may be 0 to indicate that the current screen |
| 154 | * depth is to be used. Thus, we must query for the current display |
| 155 | * depth here. |
| 156 | */ |
| 157 | dwBPP = GetDeviceCaps(hdc, BITSPIXEL); |
| 158 | |
| 159 | /* Release the DC */ |
| 160 | ReleaseDC(NULL, hdc); |
| 161 | hdc = NULL; |
| 162 | |
| 163 | /* ShadowGDI is the only engine that supports windowed PseudoColor */ |
| 164 | if (dwBPP == 8 && !pScreenInfo->fFullScreen) { |
| 165 | winErrorFVerb(2, |
| 166 | "winSetEngine - Windowed && PseudoColor => ShadowGDI\n"); |
| 167 | pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI; |
| 168 | |
| 169 | /* Set engine function pointers */ |
| 170 | winSetEngineFunctionsShadowGDI(pScreen); |
| 171 | return TRUE; |
| 172 | } |
| 173 | |
| 174 | /* ShadowGDI is the only engine that supports Multi Window Mode */ |
| 175 | if (FALSE |
| 176 | #ifdef XWIN_MULTIWINDOWEXTWM |
| 177 | || pScreenInfo->fMWExtWM |
| 178 | #endif |
| 179 | #ifdef XWIN_MULTIWINDOW |
| 180 | || pScreenInfo->fMultiWindow |
| 181 | #endif |
| 182 | ) { |
| 183 | winErrorFVerb(2, |
| 184 | "winSetEngine - Multi Window or Rootless => ShadowGDI\n"); |
| 185 | pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI; |
| 186 | |
| 187 | /* Set engine function pointers */ |
| 188 | winSetEngineFunctionsShadowGDI(pScreen); |
| 189 | return TRUE; |
| 190 | } |
| 191 | |
| 192 | /* If the user's choice is supported, we'll use that */ |
| 193 | if (g_dwEnginesSupported & pScreenInfo->dwEnginePreferred) { |
| 194 | winErrorFVerb(2, "winSetEngine - Using user's preference: %d\n", |
| 195 | (int) pScreenInfo->dwEnginePreferred); |
| 196 | pScreenInfo->dwEngine = pScreenInfo->dwEnginePreferred; |
| 197 | |
| 198 | /* Setup engine function pointers */ |
| 199 | switch (pScreenInfo->dwEngine) { |
| 200 | case WIN_SERVER_SHADOW_GDI: |
| 201 | winSetEngineFunctionsShadowGDI(pScreen); |
| 202 | break; |
| 203 | case WIN_SERVER_SHADOW_DD: |
| 204 | winSetEngineFunctionsShadowDD(pScreen); |
| 205 | break; |
| 206 | case WIN_SERVER_SHADOW_DDNL: |
| 207 | winSetEngineFunctionsShadowDDNL(pScreen); |
| 208 | break; |
| 209 | #ifdef XWIN_PRIMARYFB |
| 210 | case WIN_SERVER_PRIMARY_DD: |
| 211 | winSetEngineFunctionsPrimaryDD(pScreen); |
| 212 | break; |
| 213 | #endif |
| 214 | #ifdef XWIN_NATIVEGDI |
| 215 | case WIN_SERVER_NATIVE_GDI: |
| 216 | winSetEngineFunctionsNativeGDI(pScreen); |
| 217 | break; |
| 218 | #endif |
| 219 | default: |
| 220 | FatalError("winSetEngine - Invalid engine type\n"); |
| 221 | } |
| 222 | return TRUE; |
| 223 | } |
| 224 | |
| 225 | /* ShadowDDNL has good performance, so why not */ |
| 226 | if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DDNL) { |
| 227 | winErrorFVerb(2, "winSetEngine - Using Shadow DirectDraw NonLocking\n"); |
| 228 | pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DDNL; |
| 229 | |
| 230 | /* Set engine function pointers */ |
| 231 | winSetEngineFunctionsShadowDDNL(pScreen); |
| 232 | return TRUE; |
| 233 | } |
| 234 | |
| 235 | /* ShadowDD is next in line */ |
| 236 | if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DD) { |
| 237 | winErrorFVerb(2, "winSetEngine - Using Shadow DirectDraw\n"); |
| 238 | pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DD; |
| 239 | |
| 240 | /* Set engine function pointers */ |
| 241 | winSetEngineFunctionsShadowDD(pScreen); |
| 242 | return TRUE; |
| 243 | } |
| 244 | |
| 245 | /* ShadowGDI is next in line */ |
| 246 | if (g_dwEnginesSupported & WIN_SERVER_SHADOW_GDI) { |
| 247 | winErrorFVerb(2, "winSetEngine - Using Shadow GDI DIB\n"); |
| 248 | pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI; |
| 249 | |
| 250 | /* Set engine function pointers */ |
| 251 | winSetEngineFunctionsShadowGDI(pScreen); |
| 252 | return TRUE; |
| 253 | } |
| 254 | |
| 255 | return TRUE; |
| 256 | } |
| 257 | |
| 258 | /* |
| 259 | * Get procedure addresses for DirectDrawCreate and DirectDrawCreateClipper |
| 260 | */ |
| 261 | |
| 262 | Bool |
| 263 | winGetDDProcAddresses(void) |
| 264 | { |
| 265 | Bool fReturn = TRUE; |
| 266 | |
| 267 | /* Load the DirectDraw library */ |
| 268 | g_hmodDirectDraw = LoadLibraryEx("ddraw.dll", NULL, 0); |
| 269 | if (g_hmodDirectDraw == NULL) { |
| 270 | ErrorF("winGetDDProcAddresses - Could not load ddraw.dll\n"); |
| 271 | fReturn = TRUE; |
| 272 | goto winGetDDProcAddresses_Exit; |
| 273 | } |
| 274 | |
| 275 | /* Try to get the DirectDrawCreate address */ |
| 276 | g_fpDirectDrawCreate = GetProcAddress(g_hmodDirectDraw, "DirectDrawCreate"); |
| 277 | if (g_fpDirectDrawCreate == NULL) { |
| 278 | ErrorF("winGetDDProcAddresses - Could not get DirectDrawCreate " |
| 279 | "address\n"); |
| 280 | fReturn = TRUE; |
| 281 | goto winGetDDProcAddresses_Exit; |
| 282 | } |
| 283 | |
| 284 | /* Try to get the DirectDrawCreateClipper address */ |
| 285 | g_fpDirectDrawCreateClipper = GetProcAddress(g_hmodDirectDraw, |
| 286 | "DirectDrawCreateClipper"); |
| 287 | if (g_fpDirectDrawCreateClipper == NULL) { |
| 288 | ErrorF("winGetDDProcAddresses - Could not get " |
| 289 | "DirectDrawCreateClipper address\n"); |
| 290 | fReturn = FALSE; |
| 291 | goto winGetDDProcAddresses_Exit; |
| 292 | } |
| 293 | |
| 294 | /* |
| 295 | * Note: Do not unload ddraw.dll here. Do it in GiveUp |
| 296 | */ |
| 297 | |
| 298 | winGetDDProcAddresses_Exit: |
| 299 | /* Unload the DirectDraw library if we failed to initialize */ |
| 300 | if (!fReturn && g_hmodDirectDraw != NULL) { |
| 301 | FreeLibrary(g_hmodDirectDraw); |
| 302 | g_hmodDirectDraw = NULL; |
| 303 | } |
| 304 | |
| 305 | return fReturn; |
| 306 | } |
| 307 | |
| 308 | void |
| 309 | winReleaseDDProcAddresses(void) |
| 310 | { |
| 311 | if (g_hmodDirectDraw != NULL) { |
| 312 | FreeLibrary(g_hmodDirectDraw); |
| 313 | g_hmodDirectDraw = NULL; |
| 314 | g_fpDirectDrawCreate = NULL; |
| 315 | g_fpDirectDrawCreateClipper = NULL; |
| 316 | } |
| 317 | } |