Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

8262 lines
262 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddcreate.c
  6. * Content: DirectDraw create object.
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 31-dec-94 craige initial implementation
  11. * 13-jan-95 craige re-worked to updated spec + ongoing work
  12. * 21-jan-95 craige made 32-bit + ongoing work
  13. * 13-feb-94 craige allow 32-bit callbacks
  14. * 21-feb-95 craige disconnect anyone who forgot to do it themselves
  15. * 27-feb-95 craige new sync. macros
  16. * 06-mar-95 craige HEL integration
  17. * 08-mar-95 craige new APIs
  18. * 11-mar-95 craige palette stuff
  19. * 15-mar-95 craige more HEL integration
  20. * 19-mar-95 craige use HRESULTs, process termination cleanup fixes
  21. * 27-mar-95 craige linear or rectangular vidmem
  22. * 28-mar-95 craige removed Get/SetColorKey, added FlipToGDISurface
  23. * 29-mar-95 craige reorg to only call driver once per creation, and
  24. * to allow driver to load us first
  25. * 01-apr-95 craige happy fun joy updated header file
  26. * 06-apr-95 craige fill in free video memory
  27. * 09-apr-95 craige fixed deadlock situation with a process having a lock
  28. * on the primary surface while another process starts
  29. * 12-apr-95 craige bug when driver object freed (extra leave csect)
  30. * 13-apr-95 craige EricEng's little contribution to our being late
  31. * 15-apr-95 craige fail load if no DD components present
  32. * 06-may-95 craige use driver-level csects only
  33. * 09-may-95 craige escape call to get 32-bit DLL
  34. * 12-may-95 craige added DirectDrawEnumerate; use GUIDs in DirectDrawCreate
  35. * 14-may-95 craige call DoneExclusiveMode during CurrentProcessCleanup
  36. * 15-may-95 craige restore display mode on a per-process basis
  37. * 19-may-95 craige memory leak on mode change
  38. * 23-may-95 craige added Flush, GetBatchLimit, SetBatchLimit
  39. * 24-may-95 craige plugged another memory leak; allow fourcc codes &
  40. * number of vmem heaps to change
  41. * 26-may-95 craige some idiot freed the vmem heaps and then tried to
  42. * free the surfaces!
  43. * 28-may-95 craige unicode support; make sure blt means at least srccopy
  44. * 05-jun-95 craige removed GetVersion, FreeAllSurfaces, DefWindowProc;
  45. * change GarbageCollect to Compact
  46. * 06-jun-95 craige call RestoreDisplayMode
  47. * 07-jun-95 craige removed DCLIST
  48. * 12-jun-95 craige new process list stuff
  49. * 16-jun-95 craige new surface structure
  50. * 18-jun-95 craige specify pitch for rectangular memory; deadlock
  51. * with MemAlloc16 if we don't take the DLL lock
  52. * 25-jun-95 craige one ddraw mutex
  53. * 26-jun-95 craige reorganized surface structure
  54. * 27-jun-95 craige replaced batch limit/flush stuff with BltBatch
  55. * 28-jun-95 craige ENTER_DDRAW at very start of fns
  56. * 02-jul-95 craige new registry format
  57. * 03-jul-95 craige YEEHAW: new driver struct; SEH
  58. * 06-jul-95 craige RemoveFromDriverList was screwing up links
  59. * 07-jul-95 craige added pdevice stuff
  60. * 08-jul-95 craige call InvalidateAllSurfaces
  61. * 10-jul-95 craige support SetOverlayPosition
  62. * 11-jul-95 craige validate pdevice is from a dibeng mini driver;
  63. * fail aggregation calls; one ddraw object/process
  64. * 13-jul-95 craige ENTER_DDRAW is now the win16 lock; need to
  65. * leave Win16 lock while doing ExtEscape calls
  66. * 14-jul-95 craige allow driver to specify heap is already allocated
  67. * 15-jul-95 craige invalid HDC set in emulation only
  68. * 18-jul-95 craige need to initialize dwPreferredMode
  69. * 20-jul-95 craige internal reorg to prevent thunking during modeset
  70. * 20-jul-95 toddla zero DDHALINFO before thunking in case nobody home.
  71. * 22-jul-95 craige emulation only needs to initialize correctly
  72. * 29-jul-95 toddla added DEBUG code to clear driver caps
  73. * 31-jul-95 toddla added DD_HAL_VERSION
  74. * 31-jul-95 craige set DDCAPS_BANKSWITCHED
  75. * 01-aug-95 toddla added dwPDevice to DDRAWI_DIRECTDRAW_GBL
  76. * 10-aug-95 craige validate alignment fields
  77. * 13-aug-95 craige check DD_HAL_VERSION & set DDCAPS2_CERTIFIED
  78. * 21-aug-95 craige mode X support
  79. * 27-aug-95 craige bug 738: use GUID instead of IID
  80. * 05-sep-95 craige bug 814
  81. * 08-sep-95 craige bug 845: reset driver callbacks every time
  82. * 09-sep-95 craige bug 949: don't allow ddraw to run in 4bpp
  83. * bug 951: NULL out fn tables at reset
  84. * 10-sep-95 toddla dont allow DirectDrawCreate to work for < 8bpp mode.
  85. * 10-sep-95 toddla added Message box when DirectDrawCreate fails
  86. * 20-sep-95 craige made primary display desc. a string resource
  87. * 21-sep-95 craige bug 1215: let ddraw16 know about certified for modex
  88. * 21-nov-95 colinmc made Direct3D a queryable interface off DirectDraw
  89. * 27-nov-95 colinmc new member to return available vram of a given type
  90. * (defined by DDSCAPS)
  91. * 05-dec-95 colinmc changed DDSCAPS_TEXTUREMAP => DDSCAPS_TEXTURE for
  92. * consitency with Direct3D
  93. * 09-dec-95 colinmc execute buffer support
  94. * 15-dec-95 colinmc fixed bug setting HAL up for execute buffers
  95. * 25-dec-95 craige added InternalDirectDrawCreate for ClassFactory work
  96. * 31-dec-95 craige more ClassFactory work
  97. * 04-jan-96 kylej add driver interface structures
  98. * 22-jan-96 jeffno NT driver conversation in createSurface.
  99. * Since vidmem ptrs can legally be 0 for kernel, added
  100. * DDRAWISURFACEGBL_ISGDISURFACE and use that to find gdi
  101. * 02-feb-96 kylej Move HAL function pointers to local object
  102. * 28-feb-96 kylej Change DDHALINFO structure
  103. * 02-mar-96 colinmc Repulsive hack to support interim drivers
  104. * 06-mar-96 kylej init HEL even with non-display drivers
  105. * 13-mar-96 craige Bug 7528: hw that doesn't have modex
  106. * 13-mar-96 jeffno Dynamic mode switch support for NT
  107. * Register process IDs with NT kernel stuff
  108. * 16-mar-96 colinmc Callback tables now initialized in dllmain
  109. * 18-mar-96 colinmc Bug 13545: Independent clippers cleanup
  110. * 22-mar-96 colinmc Bug 13316: uninitialized interfaces
  111. * 23-mar-96 colinmc Bug 12252: Direct3D not cleaned up properly on crash
  112. * 14-apr-96 colinmc Bug 17736: No driver notification of flip to GDI
  113. * 16-apr-96 colinmc Bug 17921: Remove interim driver support
  114. * 19-apr-96 colinmc Bug 18059: New caps bit to indicate that driver
  115. * can't interleave 2D and 3D operations during scene
  116. * rendering
  117. * 11-may-96 colinmc Bug 22293: Now validate GUID passed to DirectDraw
  118. * Create in retail as well as debug
  119. * 16-may-96 colinmc Bug 23215: Not checking for a mode index of -1
  120. * on driver initialization
  121. * 27-may-96 kylej Bug 24595: Set Certified bit after call to
  122. * FakeDDCreateDriverObject.
  123. * 26-jun-96 colinmc Bug 2041: DirectDraw needs time bomb
  124. * 22-jul-96 colinmc Work Item: Minimal stackable driver support
  125. * 23-aug-96 craige registry entries for sw only and modex only
  126. * 31-aug-96 colinmc Removed erroneous time bomb
  127. * 03-sep-96 craige App compatibilty stuff
  128. * 01-oct-96 ketand added GetAvailVidMem entrypoint for driver callbacks
  129. * 05-sep-96 colinmc Work Item: Removing the restriction on taking Win16
  130. * lock on VRAM surfaces (not including the primary)
  131. * 10-oct-96 colinmc Refinements of the Win16 locking stuff
  132. * 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
  133. * memory usage
  134. * 15-oct-96 toddla support multimonitor
  135. * 09-nov-96 colinmc Fixed problem with old and new drivers not working
  136. * with DirectDraw
  137. * 17-nov-96 colinmc Added ability to use PrintScrn key to snapshot
  138. * DirectDraw applications.
  139. * 08-dec-96 colinmc Initial AGP support
  140. * 21-jan-97 ketand Added a rectMonitor to lpDD_gbl to allow for correct clipping
  141. * on multi-monitor systems.
  142. * 25-jan-97 nwilt Instance GUID in GetDriverInfo struct
  143. * Query for D3DCallbacks2 w/no deps on D3D
  144. * 27-jan-97 colinmc Fixed problem with multi-mon on emulated displays
  145. * 27-jan-97 ketand Multi-mon. Remove bad globals; pass them explicitly. Fix ATTENTIONs.
  146. * 29-jan-97 smac Removed old ring 0 code
  147. * 30-jan-97 colinmc Work item 4125: Add time bomb for beta
  148. * 30-jan-97 jeffno Allow surfaces wider than the primary
  149. * 30-jan-97 ketand Only enumerate secondaries for multi-mon systems.
  150. * 01-feb-97 colinmc Bug 5457: Fixed Win16 lock problem causing hang
  151. * with mutliple AMovie instances on old cards
  152. * 07-feb-97 ketand Zero DisplayDevice struct between calls to EnumDisplayDevices.
  153. * Fix memory leak w.r.t. GetAndValidateNewHalInfo
  154. * 24-feb-97 ketand Update Rects whenever a display change occurs.
  155. * 24-feb-97 ketand Add a dwContext to GetDriverInfoData
  156. * 03-mar-97 smac Added kernel mode interface
  157. * 03-mar-97 jeffno Work item: Extended surface memory alignment
  158. * 08-mar-97 colinmc Added support for DMA style AGP usage
  159. * 11-mar-97 jeffno Asynchronous DMA support
  160. * 11-mar-97 nwilt Fail driver create if driver exports some DrawPrimitive
  161. * exports without exporting all of them.
  162. * 13-mar-97 colinmc Bug 6533: Pass uncached flag to VMM correctly
  163. * 20-mar-97 nwilt #6625 and D3D extended caps
  164. * 24-mar-97 jeffno Optimized Surfaces
  165. * 13-may-97 colinmc AGP support on OSR 2.1 systems
  166. * 26-may-97 nwilt Fail driver create if driver sets D3DDEVCAPS_DRAWPRIMTLVERTEX
  167. * without exporting the callbacks.
  168. * 31-jul-97 jvanaken Bug 7093: Ensure unique HDC for each process/driver pair
  169. * in a multimonitor system.
  170. * 16-sep-97 jeffno DirectDrawEnumerateEx
  171. * 30-sep-97 jeffno IDirectDraw4
  172. * 31-oct-97 johnstep Persistent-content surfaces for Windows 9x
  173. * 05-nov-97 jvanaken Support for master sprite list in SetSpriteDisplayList
  174. * 24-may-00 RichGr IA64: Remove casts from pointer assignment, effectively
  175. * changing assignment from DWORD(32-bit only) to
  176. * ULONG_PTR(32/64-bit). Change debug output to use %p
  177. * format specifier instead of %x for 32/64-bit pointers.
  178. *
  179. ***************************************************************************/
  180. #include "ddrawpr.h"
  181. #include "dx8priv.h"
  182. #include "apphack.h"
  183. #ifdef WINNT
  184. #include <ddrawint.h>
  185. #include "ddrawgdi.h"
  186. #define BUILD_DDDDK
  187. #include "d3dhal.h"
  188. #endif
  189. #ifdef WIN95
  190. #include "d3dhal.h"
  191. #endif
  192. #ifdef DEBUG
  193. #define static
  194. #endif
  195. #define RESPATH_D3D "Software\\Microsoft\\Direct3D"
  196. #define DPF_MODNAME "DirectDrawObjectCreate"
  197. #define DISPLAY_STR "display"
  198. HMONITOR GetMonitorFromDeviceName(LPSTR szName);
  199. #ifdef WINNT
  200. DWORD GetNumberOfMonitorAttachedToDesktop(VOID);
  201. DWORD APIENTRY GetDriverInfo2(LPDDRAWI_DIRECTDRAW_GBL lpGbl,DWORD* pdwDrvRet,DWORD dwType,DWORD dwSize,void* pBuffer);
  202. #endif
  203. char g_szPrimaryDisplay[MAX_DRIVER_NAME] = "";
  204. void getPrimaryDisplayName(void);
  205. void convertV1DDHALINFO( LPDDHALINFO lpDDHALInfo );
  206. DWORD dwRegFlags; // registry flags
  207. // ATTENTION: Does this work for Multi-Mon??
  208. WORD dwFakeFlags = 0; // Magic flags for the PDevice??
  209. #ifdef WIN95
  210. /*
  211. * DDHELP's handle for communicating with the DirectSound VXD. We need this
  212. * when we are executing DDRAW code with one of DDHELP's threads.
  213. */
  214. HANDLE hHelperDDVxd = INVALID_HANDLE_VALUE;
  215. #define CLOSEVXD( hvxd ) CloseHandle( hvxd )
  216. #else /* WIN95 */
  217. #define CLOSEVXD( hvxd )
  218. #endif /* WIN95 */
  219. //#ifdef WIN95
  220. /*
  221. * initial HAL callbacks
  222. */
  223. #ifndef WINNT //don't want these just yet
  224. static DDHAL_DDCALLBACKS ddHALDD =
  225. {
  226. sizeof( DDHAL_DDCALLBACKS ),
  227. 0,
  228. _DDHAL_DestroyDriver,
  229. _DDHAL_CreateSurface,
  230. NULL, // _DDHAL_DrvSetColorKey
  231. _DDHAL_SetMode,
  232. _DDHAL_WaitForVerticalBlank,
  233. _DDHAL_CanCreateSurface,
  234. _DDHAL_CreatePalette,
  235. _DDHAL_GetScanLine,
  236. _DDHAL_SetExclusiveMode,
  237. _DDHAL_FlipToGDISurface
  238. };
  239. static DDHAL_DDSURFACECALLBACKS ddHALDDSurface =
  240. {
  241. sizeof( DDHAL_DDSURFACECALLBACKS ),
  242. 0,
  243. _DDHAL_DestroySurface,
  244. _DDHAL_Flip,
  245. _DDHAL_SetClipList,
  246. _DDHAL_Lock,
  247. _DDHAL_Unlock,
  248. _DDHAL_Blt,
  249. _DDHAL_SetColorKey,
  250. _DDHAL_AddAttachedSurface,
  251. _DDHAL_GetBltStatus,
  252. _DDHAL_GetFlipStatus,
  253. _DDHAL_UpdateOverlay,
  254. _DDHAL_SetOverlayPosition,
  255. NULL,
  256. _DDHAL_SetPalette
  257. };
  258. static DDHAL_DDPALETTECALLBACKS ddHALDDPalette =
  259. {
  260. sizeof( DDHAL_DDPALETTECALLBACKS ),
  261. 0,
  262. _DDHAL_DestroyPalette,
  263. _DDHAL_SetEntries
  264. };
  265. /*
  266. * NOTE: Currently don't support thunking for these babies. If
  267. * a driver does the execute buffer thing it must explicitly
  268. * export 32-bit functions to handle these calls.
  269. * !!! NOTE: Need to determine whether we will ever need to
  270. * support thunking for this HAL.
  271. */
  272. static DDHAL_DDEXEBUFCALLBACKS ddHALDDExeBuf =
  273. {
  274. sizeof( DDHAL_DDEXEBUFCALLBACKS ),
  275. 0,
  276. NULL, /* CanCreateExecuteBuffer */
  277. NULL, /* CreateExecuteBuffer */
  278. NULL, /* DestroyExecuteBuffer */
  279. NULL, /* LockExecuteBuffer */
  280. NULL /* UnlockExecuteBuffer */
  281. };
  282. /*
  283. * NOTE: Currently don't support thunking for these babies. If
  284. * a driver does the video port thing it must explicitly
  285. * export 32-bit functions to handle these calls.
  286. * !!! NOTE: Need to determine whether we will ever need to
  287. * support thunking for this HAL.
  288. */
  289. static DDHAL_DDVIDEOPORTCALLBACKS ddHALDDVideoPort =
  290. {
  291. sizeof( DDHAL_DDVIDEOPORTCALLBACKS ),
  292. 0,
  293. NULL, // CanCreateVideoPort
  294. NULL, // CreateVideoPort
  295. NULL, // FlipVideoPort
  296. NULL, // GetVideoPortBandwidthInfo
  297. NULL, // GetVideoPortInputFormats
  298. NULL, // GetVideoPortOutputFormats
  299. NULL, // GetCurrentAutoflipSurface
  300. NULL, // GetVideoPortField
  301. NULL, // GetVideoPortLine
  302. NULL, // GetVideoPortConnectInfo
  303. NULL, // DestroyVideoPort
  304. NULL, // GetVideoPortFlipStatus
  305. NULL, // UpdateVideoPort
  306. NULL, // WaitForVideoPortSync
  307. NULL, // GetVideoSignalStatus
  308. NULL // ColorControl
  309. };
  310. /*
  311. * NOTE: Currently don't support thunking for these babies. If
  312. * a driver has a kernel mode interface it must explicitly
  313. * export 32-bit functions to handle these calls.
  314. */
  315. static DDHAL_DDKERNELCALLBACKS ddHALDDKernel =
  316. {
  317. sizeof( DDHAL_DDKERNELCALLBACKS ),
  318. 0,
  319. NULL, // SyncSurfaceData
  320. NULL // SyncVideoPortData
  321. };
  322. static DDHAL_DDCOLORCONTROLCALLBACKS ddHALDDColorControl =
  323. {
  324. sizeof( DDHAL_DDSURFACECALLBACKS ),
  325. 0,
  326. _DDHAL_ColorControl
  327. };
  328. #endif //not defined winnt
  329. //#endif //defined(WIN95)
  330. #ifndef WIN16_SEPARATE
  331. #ifdef WIN95
  332. CRITICAL_SECTION ddcCS = {0};
  333. #define ENTER_CSDDC() EnterCriticalSection( &ddcCS )
  334. #define LEAVE_CSDDC() LeaveCriticalSection( &ddcCS )
  335. #else
  336. #define ENTER_CSDDC()
  337. #define LEAVE_CSDDC()
  338. #endif
  339. #else
  340. #define ENTER_CSDDC()
  341. #define LEAVE_CSDDC()
  342. #endif
  343. // DisplayGUID - GUID used to enumerate secondary displays.
  344. //
  345. // {67685559-3106-11d0-B971-00AA00342F9F}
  346. //
  347. // we use this GUID and the next 32 for enumerating devices
  348. // returned via EnumDisplayDevices
  349. //
  350. static const GUID DisplayGUID =
  351. {0x67685559,0x3106,0x11d0,{0xb9,0x71,0x0,0xaa,0x0,0x34,0x2f,0x9f}};
  352. /*
  353. * DISPLAY_DEVICEA
  354. *
  355. * define a local copy of the structures and constants needed
  356. * to call EnumDisplayDevices
  357. *
  358. */
  359. #ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
  360. #define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
  361. #define DISPLAY_DEVICE_MULTI_DRIVER 0x00000002
  362. #define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
  363. #define DISPLAY_DEVICE_MIRRORING_DRIVER 0x00000008
  364. #define DISPLAY_DEVICE_VGA 0x00000010
  365. typedef struct {
  366. DWORD cb;
  367. CHAR DeviceName[MAX_DRIVER_NAME];
  368. CHAR DeviceString[128];
  369. DWORD StateFlags;
  370. } DISPLAY_DEVICEA;
  371. #endif
  372. /*
  373. * xxxEnumDisplayDevices
  374. *
  375. * wrapper around the new Win32 API EnumDisplayDevices
  376. * uses GetProcAddress() so we run on Win95.
  377. *
  378. * this function exists in NT 4.0 and Win97 (Memphis) but not Win95
  379. *
  380. */
  381. BOOL xxxEnumDisplayDevicesA(LPVOID lpUnused, DWORD iDevice, DISPLAY_DEVICEA *pdd, DWORD dwFlags)
  382. {
  383. HANDLE h = GetModuleHandle("USER32");
  384. BOOL (WINAPI *pfnEnumDisplayDevices)(LPVOID, DWORD, DISPLAY_DEVICEA *, DWORD);
  385. (FARPROC)pfnEnumDisplayDevices = GetProcAddress(h,"EnumDisplayDevicesA");
  386. //
  387. // NT 4.0 had a EnumDisplayDevicesA but it does not have the same
  388. // number of params, so ignore it unless a GetMonitorInfoA exists too.
  389. //
  390. if (GetProcAddress(h,"GetMonitorInfoA") == NULL)
  391. pfnEnumDisplayDevices = NULL;
  392. if (pfnEnumDisplayDevices)
  393. {
  394. return (*pfnEnumDisplayDevices)(lpUnused, iDevice, pdd, dwFlags);
  395. }
  396. return FALSE;
  397. }
  398. /*
  399. * xxxChangeDisplaySettingsEx
  400. *
  401. * wrapper around the new Win32 API ChangeDisplaySettingsEx
  402. * uses GetProcAddress() so we run on Win95.
  403. *
  404. * this function exists in NT 4.0 and Win97 (Memphis) but not Win95
  405. *
  406. */
  407. LONG xxxChangeDisplaySettingsExA(LPCSTR szDevice, LPDEVMODEA pdm, HWND hwnd, DWORD dwFlags,LPVOID lParam)
  408. {
  409. // We don't use ChangeDisplaySettingsEx on WIN95 because there is a magic
  410. // bit in DDraw16 that needs to be set/unset for us to correctly distinguish
  411. // between our own mode sets and external mode sets. (We need to know because
  412. // of RestoreMode state.)
  413. #ifdef WINNT
  414. HANDLE h = GetModuleHandle("USER32");
  415. LONG (WINAPI *pfnChangeDisplaySettingsExA)(LPCSTR,LPDEVMODEA,HWND,DWORD,LPVOID);
  416. (FARPROC)pfnChangeDisplaySettingsExA = GetProcAddress(h,"ChangeDisplaySettingsExA");
  417. if (pfnChangeDisplaySettingsExA)
  418. {
  419. LONG lRet;
  420. NotifyDriverToDeferFrees();
  421. lRet = (*pfnChangeDisplaySettingsExA)(szDevice, pdm, hwnd, dwFlags, lParam);
  422. if (lRet != DISP_CHANGE_SUCCESSFUL)
  423. {
  424. NotifyDriverOfFreeAliasedLocks();
  425. }
  426. return lRet;
  427. }
  428. else
  429. #endif
  430. if (szDevice == NULL)
  431. {
  432. return DD16_ChangeDisplaySettings(pdm, dwFlags);
  433. }
  434. #ifdef WIN95
  435. else
  436. {
  437. // This method works on Win95 for mode-setting other
  438. // devices. We're not yet sure whether the equivalent would
  439. // work for NT; so we'd rather call the 'approved' API (ChangeDisplaySettingsExA above.)
  440. if (pdm != NULL)
  441. {
  442. lstrcpy(pdm->dmDeviceName,szDevice);
  443. }
  444. return DD16_ChangeDisplaySettings(pdm, dwFlags);
  445. }
  446. #else
  447. else
  448. {
  449. return DISP_CHANGE_FAILED;
  450. }
  451. #endif
  452. }
  453. // Multi-monitor defines; these are wrong in the TRANGO tree;
  454. // so I need to define them here explicitly. When we move to
  455. // something that matches Memphis/NT5 then we can remove these
  456. #undef SM_XVIRTUALSCREEN
  457. #undef SM_YVIRTUALSCREEN
  458. #undef SM_CXVIRTUALSCREEN
  459. #undef SM_CYVIRTUALSCREEN
  460. #undef SM_CMONITORS
  461. #define SM_XVIRTUALSCREEN 76
  462. #define SM_YVIRTUALSCREEN 77
  463. #define SM_CXVIRTUALSCREEN 78
  464. #define SM_CYVIRTUALSCREEN 79
  465. #define SM_CMONITORS 80
  466. #ifndef ENUM_CURRENT_SETTINGS
  467. #define ENUM_CURRENT_SETTINGS ((DWORD)-1)
  468. #endif
  469. // This function walks through all GBLs and calls update rect on them
  470. // This is called by DDHELP when it receives a message regarding WM_DISPLAYCHANGE
  471. void UpdateAllDeviceRects( void )
  472. {
  473. LPDDRAWI_DIRECTDRAW_LCL tmp_lcl;
  474. ENTER_DDRAW();
  475. DPF( 1, W, "WM_DISPLAYCHANGE being processed by DDraw" );
  476. tmp_lcl = lpDriverLocalList;
  477. while( tmp_lcl )
  478. {
  479. // This interface may be "uninitialized" in which case
  480. // it doesn't point to a global object yet.
  481. if( tmp_lcl->lpGbl )
  482. {
  483. DPF( 4, W, "Updating rect for %s", tmp_lcl->lpGbl->cDriverName );
  484. UpdateRectFromDevice( tmp_lcl->lpGbl );
  485. }
  486. tmp_lcl = tmp_lcl->lpLink;
  487. }
  488. LEAVE_DDRAW();
  489. return;
  490. }
  491. #ifdef WINNT
  492. // This function gets the device rect by calling GetMonitorInfo.
  493. // On Win98, we got this by calling EnumDisplaySettings, but this
  494. // doesn't work on NT5 and reading the documentation, it never
  495. // indicates that it should work, so we'll just do it the documented
  496. // way.
  497. HRESULT GetNTDeviceRect( LPSTR pDriverName, LPRECT lpRect )
  498. {
  499. MONITORINFO MonInfo;
  500. HMONITOR hMon;
  501. MonInfo.cbSize = sizeof( MONITORINFO );
  502. if( _stricmp( pDriverName, DISPLAY_STR ) == 0 )
  503. {
  504. hMon = GetMonitorFromDeviceName( g_szPrimaryDisplay );
  505. }
  506. else
  507. {
  508. hMon = GetMonitorFromDeviceName( pDriverName );
  509. }
  510. if( hMon != NULL )
  511. {
  512. if( GetMonitorInfo( hMon, &MonInfo ) != 0 )
  513. {
  514. CopyMemory( lpRect, &MonInfo.rcMonitor, sizeof(RECT) );
  515. return DD_OK;
  516. }
  517. }
  518. return DDERR_GENERIC;
  519. }
  520. #endif
  521. // This function updates our GBL with topology information
  522. // relevant to the device in question.
  523. void UpdateRectFromDevice(
  524. LPDDRAWI_DIRECTDRAW_GBL pdrv )
  525. {
  526. DEVMODE dm;
  527. // Sanity Check
  528. DDASSERT( pdrv );
  529. pdrv->cMonitors = GetSystemMetrics( SM_CMONITORS );
  530. if( pdrv->cMonitors > 1 )
  531. {
  532. #ifdef WIN95
  533. /*
  534. * First, get the device rectangle
  535. */
  536. ZeroMemory( &dm, sizeof(dm) );
  537. dm.dmSize = sizeof(dm);
  538. // Get the DevMode for current settings
  539. if( _stricmp( pdrv->cDriverName, DISPLAY_STR ) == 0 )
  540. {
  541. // Don't need g_szPrimaryDisplay here, just use NULL!!!
  542. EnumDisplaySettings( g_szPrimaryDisplay, ENUM_CURRENT_SETTINGS, &dm );
  543. }
  544. else
  545. {
  546. EnumDisplaySettings( pdrv->cDriverName, ENUM_CURRENT_SETTINGS, &dm );
  547. }
  548. //
  549. // the position of the device is in the dmPosition field
  550. // which happens to be unioned with dmOrientation. dmPosition isn't defined
  551. // in our current header
  552. //
  553. // BUG-BUG: After reading the definition of the DEVMODE struct in
  554. // wingdi.h, I'm amazed that the entire dest rectangle should be
  555. // stored at &dm.dmOrientation. But the code below obviously works,
  556. // so I'm reluctant to change it until I know what's going on.
  557. CopyMemory( &pdrv->rectDevice, &dm.dmOrientation, sizeof(RECT) );
  558. #else
  559. if( GetNTDeviceRect( pdrv->cDriverName, &pdrv->rectDevice ) != DD_OK )
  560. {
  561. pdrv->rectDevice.left = 0;
  562. pdrv->rectDevice.top = 0;
  563. pdrv->rectDevice.right = pdrv->vmiData.dwDisplayWidth;
  564. pdrv->rectDevice.bottom = pdrv->vmiData.dwDisplayHeight;
  565. }
  566. #endif
  567. }
  568. if( ( pdrv->cMonitors <= 1 ) || IsRectEmpty( &pdrv->rectDevice ) )
  569. {
  570. pdrv->rectDevice.left = 0;
  571. pdrv->rectDevice.top = 0;
  572. pdrv->rectDevice.right = pdrv->vmiData.dwDisplayWidth;
  573. pdrv->rectDevice.bottom = pdrv->vmiData.dwDisplayHeight;
  574. }
  575. DPF( 1, W, "Device's rect is %d, %d, %d, %d", pdrv->rectDevice.left, pdrv->rectDevice.top, pdrv->rectDevice.right, pdrv->rectDevice.bottom );
  576. /*
  577. * Now get the desktop rect. If we are in virtual desktop mode,
  578. * we will get the whole dektop; otherwise, we will use the device
  579. * rectangle.
  580. */
  581. // BUG-BUG: The VIRTUALDESKTOP and ATTACHEDTODESKTOP flags referred to
  582. // below are never set if we reach this point when we're creating a new
  583. // surface. That means that in a multimon system, pdrv->rectDesktop
  584. // gets set to pdrv->rectDevice instead of to the full desktop.
  585. if( ( pdrv->dwFlags & DDRAWI_VIRTUALDESKTOP ) &&
  586. ( pdrv->dwFlags & DDRAWI_ATTACHEDTODESKTOP ) )
  587. {
  588. int x, y;
  589. x = GetSystemMetrics( SM_XVIRTUALSCREEN ); // left
  590. y = GetSystemMetrics( SM_YVIRTUALSCREEN ); // right
  591. SetRect( &pdrv->rectDesktop,
  592. x, // left
  593. y, // top
  594. x + GetSystemMetrics( SM_CXVIRTUALSCREEN ), // right
  595. y + GetSystemMetrics( SM_CYVIRTUALSCREEN ) // bottom
  596. );
  597. }
  598. else
  599. {
  600. memcpy( &pdrv->rectDesktop, &pdrv->rectDevice, sizeof( RECT ) );
  601. }
  602. DPF( 1, W, "Desktop's rect is %d, %d, %d, %d", pdrv->rectDesktop.left, pdrv->rectDesktop.top, pdrv->rectDesktop.right, pdrv->rectDesktop.bottom );
  603. return;
  604. }
  605. /*
  606. * IsVGADevice()
  607. *
  608. * determine if the passed device name is a VGA
  609. *
  610. */
  611. BOOL IsVGADevice(LPSTR szDevice)
  612. {
  613. //
  614. // assume "DISPLAY" and "DISPLAY1" are VGA devices
  615. //
  616. if (_stricmp(szDevice, DISPLAY_STR) == 0)
  617. return TRUE;
  618. return FALSE;
  619. }
  620. /*
  621. * number of callbacks in a CALLBACK struct
  622. */
  623. #define NUM_CALLBACKS( ptr ) ((ptr->dwSize-2*sizeof( DWORD ))/ sizeof( LPVOID ))
  624. #if defined( WIN95 )
  625. /*
  626. * loadSecondaryDriver
  627. *
  628. * Determine if a secondary DirectDraw driver key is present in the registry.
  629. * If it is extract the DLL name and (optional) entry point to invoke. Load
  630. * the DLL in DDHELP's address space, get the validation entry point and
  631. * invoke it. If it returns TRUE and gives us back a GUID we have certified
  632. * as a secondary driver, call its HAL patching function.
  633. *
  634. * If any of this stuff fails we simply ignore the error. No secondary driver
  635. * - no problem.
  636. *
  637. * Returns TRUE if a secondary is successfully loaded.
  638. */
  639. static BOOL loadSecondaryDriver( LPDDHALINFO lpDDHALInfo )
  640. {
  641. HKEY hKey;
  642. DWORD dwType;
  643. DWORD dwSize;
  644. LPSECONDARY_VALIDATE fpValidate;
  645. LPSECONDARY_PATCHHALINFO fpPatchHALInfo;
  646. char szDriverName[MAX_SECONDARY_DRIVERNAME];
  647. char szEntryPoint[MAX_SECONDARY_ENTRYPOINTNAME];
  648. GUID guid;
  649. BOOL bLoaded = FALSE;
  650. /*
  651. * Any secondary driver information in the registry at all?
  652. */
  653. if( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE,
  654. REGSTR_PATH_SECONDARY,
  655. &hKey ) )
  656. {
  657. /*
  658. * Extract the entry point of the secondary driver. If no entry
  659. * point is specified we will use the default instead.
  660. */
  661. dwSize = sizeof( szEntryPoint ) - 1;
  662. if( ERROR_SUCCESS == RegQueryValueEx( hKey,
  663. REGSTR_VALUE_SECONDARY_ENTRYPOINTNAME,
  664. NULL,
  665. &dwType,
  666. szEntryPoint,
  667. &dwSize ) )
  668. {
  669. if( REG_SZ != dwType )
  670. {
  671. /*
  672. * Key is not a string. Bail.
  673. */
  674. RegCloseKey( hKey );
  675. return FALSE;
  676. }
  677. }
  678. else
  679. {
  680. /*
  681. * No entry point sepecified. Use the default.
  682. */
  683. lstrcpy( szEntryPoint, DEFAULT_SECONDARY_ENTRYPOINTNAME );
  684. }
  685. /*
  686. * Extract the name of the secondary driver's DLL.
  687. */
  688. dwSize = sizeof( szDriverName ) - 1;
  689. if( ERROR_SUCCESS == RegQueryValueEx( hKey,
  690. REGSTR_VALUE_SECONDARY_DRIVERNAME,
  691. NULL,
  692. &dwType,
  693. szDriverName,
  694. &dwSize ) )
  695. {
  696. if( REG_SZ == dwType )
  697. {
  698. /*
  699. * Now ask DDHELP to load this DLL and invoke the entry point specified.
  700. * The value returned by DDHELP will be the address of the secondary
  701. * driver's validation function if all went well.
  702. */
  703. #if defined(WIN95)
  704. LEAVE_WIN16LOCK();
  705. #endif
  706. fpValidate = (LPSECONDARY_VALIDATE)HelperLoadDLL( szDriverName, szEntryPoint, 0UL );
  707. #if defined(WIN95)
  708. ENTER_WIN16LOCK();
  709. #endif
  710. if( NULL != fpValidate )
  711. {
  712. /*
  713. * Now we need to invoke the validate entry point to ensure that
  714. * the secondary driver has been certified by us (and that it actually
  715. * wants to run).
  716. */
  717. fpPatchHALInfo = (fpValidate)( &guid );
  718. if( NULL != fpPatchHALInfo )
  719. {
  720. /*
  721. * Got returned a non-NULL HAL patching function so the secondary
  722. * driver wishes to run. However, we need to verify that the driver
  723. * is one we have certified as being OK to run. Check the guid.
  724. */
  725. if( IsEqualIID( &guid, &guidCertifiedSecondaryDriver ) )
  726. {
  727. LPVOID pFlipRoutine = (LPVOID) lpDDHALInfo->lpDDSurfaceCallbacks->Flip;
  728. /*
  729. * Its a certified secondary driver so invoke its HAL patching
  730. * function with the given HAL info and callback thunks.
  731. * The rule is if this function failes the DDHALINFO must be
  732. * unmodified so we can carry on regardless.
  733. */
  734. (*fpPatchHALInfo)(lpDDHALInfo, &ddHALDD, &ddHALDDSurface, &ddHALDDPalette, &ddHALDDExeBuf);
  735. //
  736. // Only say we loaded it if the HALInfo was changed, specifically if the PVR took
  737. // over the surface flip routine. This is an absolute must for the PVR.
  738. // If the PVR is turned off via the control panel, then this fn pointer will be unchanged,
  739. // and we can know later not to enumerate the PVR via GetDeviceIdentifier.
  740. //
  741. if (pFlipRoutine != (LPVOID) lpDDHALInfo->lpDDSurfaceCallbacks->Flip)
  742. {
  743. bLoaded = TRUE;
  744. }
  745. }
  746. }
  747. }
  748. }
  749. }
  750. RegCloseKey( hKey );
  751. }
  752. return bLoaded;
  753. }
  754. #endif /* WIN95 */
  755. /*
  756. * mergeHELCaps
  757. *
  758. * merge HEL caps with default caps
  759. */
  760. static void mergeHELCaps( LPDDRAWI_DIRECTDRAW_GBL pdrv )
  761. {
  762. int i;
  763. if( pdrv->dwFlags & DDRAWI_EMULATIONINITIALIZED )
  764. {
  765. pdrv->ddBothCaps.dwCaps &= pdrv->ddHELCaps.dwCaps;
  766. pdrv->ddBothCaps.dwCaps2 &= pdrv->ddHELCaps.dwCaps2;
  767. pdrv->ddBothCaps.dwCKeyCaps &= pdrv->ddHELCaps.dwCKeyCaps;
  768. pdrv->ddBothCaps.dwFXCaps &= pdrv->ddHELCaps.dwFXCaps;
  769. pdrv->lpddBothMoreCaps->dwAlphaCaps &= pdrv->lpddHELMoreCaps->dwAlphaCaps;
  770. pdrv->lpddBothMoreCaps->dwFilterCaps &= pdrv->lpddHELMoreCaps->dwFilterCaps;
  771. #ifdef POSTPONED2
  772. pdrv->lpddBothMoreCaps->dwTransformCaps &= pdrv->lpddHELMoreCaps->dwTransformCaps;
  773. #endif //POSTPONED2
  774. pdrv->ddBothCaps.dwSVBCaps &= pdrv->ddHELCaps.dwSVBCaps;
  775. pdrv->ddBothCaps.dwSVBCKeyCaps &= pdrv->ddHELCaps.dwSVBCKeyCaps;
  776. pdrv->ddBothCaps.dwSVBFXCaps &= pdrv->ddHELCaps.dwSVBFXCaps;
  777. pdrv->lpddBothMoreCaps->dwSVBAlphaCaps &= pdrv->lpddHELMoreCaps->dwSVBAlphaCaps;
  778. pdrv->lpddBothMoreCaps->dwSVBFilterCaps &= pdrv->lpddHELMoreCaps->dwSVBFilterCaps;
  779. #ifdef POSTPONED2
  780. pdrv->lpddBothMoreCaps->dwSVBTransformCaps &= pdrv->lpddHELMoreCaps->dwSVBTransformCaps;
  781. #endif //POSTPONED2
  782. pdrv->ddBothCaps.dwVSBCaps &= pdrv->ddHELCaps.dwVSBCaps;
  783. pdrv->ddBothCaps.dwVSBCKeyCaps &= pdrv->ddHELCaps.dwVSBCKeyCaps;
  784. pdrv->ddBothCaps.dwVSBFXCaps &= pdrv->ddHELCaps.dwVSBFXCaps;
  785. pdrv->lpddBothMoreCaps->dwVSBAlphaCaps &= pdrv->lpddHELMoreCaps->dwVSBAlphaCaps;
  786. pdrv->lpddBothMoreCaps->dwVSBFilterCaps &= pdrv->lpddHELMoreCaps->dwVSBFilterCaps;
  787. #ifdef POSTPONED2
  788. pdrv->lpddBothMoreCaps->dwVSBTransformCaps &= pdrv->lpddHELMoreCaps->dwVSBTransformCaps;
  789. #endif //POSTPONED2
  790. pdrv->ddBothCaps.dwSSBCaps &= pdrv->ddHELCaps.dwSSBCaps;
  791. pdrv->ddBothCaps.dwSSBCKeyCaps &= pdrv->ddHELCaps.dwSSBCKeyCaps;
  792. pdrv->ddBothCaps.dwSSBFXCaps &= pdrv->ddHELCaps.dwSSBFXCaps;
  793. pdrv->lpddBothMoreCaps->dwSSBAlphaCaps &= pdrv->lpddHELMoreCaps->dwSSBAlphaCaps;
  794. pdrv->lpddBothMoreCaps->dwSSBFilterCaps &= pdrv->lpddHELMoreCaps->dwSSBFilterCaps;
  795. #ifdef POSTPONED2
  796. pdrv->lpddBothMoreCaps->dwSSBTransformCaps &= pdrv->lpddHELMoreCaps->dwSSBTransformCaps;
  797. #endif //POSTPONED2
  798. for( i=0;i<DD_ROP_SPACE;i++ )
  799. {
  800. pdrv->ddBothCaps.dwRops[i] &= pdrv->ddHELCaps.dwRops[i];
  801. pdrv->ddBothCaps.dwSVBRops[i] &= pdrv->ddHELCaps.dwSVBRops[i];
  802. pdrv->ddBothCaps.dwVSBRops[i] &= pdrv->ddHELCaps.dwVSBRops[i];
  803. pdrv->ddBothCaps.dwSSBRops[i] &= pdrv->ddHELCaps.dwSSBRops[i];
  804. }
  805. pdrv->ddBothCaps.ddsCaps.dwCaps &= pdrv->ddHELCaps.ddsCaps.dwCaps;
  806. if( NULL != pdrv->lpddNLVBothCaps )
  807. {
  808. DDASSERT( NULL != pdrv->lpddNLVHELCaps );
  809. pdrv->lpddNLVBothCaps->dwNLVBCaps &= pdrv->lpddNLVHELCaps->dwNLVBCaps;
  810. pdrv->lpddNLVBothCaps->dwNLVBCaps2 &= pdrv->lpddNLVHELCaps->dwNLVBCaps2;
  811. pdrv->lpddNLVBothCaps->dwNLVBCKeyCaps &= pdrv->lpddNLVHELCaps->dwNLVBCKeyCaps;
  812. pdrv->lpddNLVBothCaps->dwNLVBFXCaps &= pdrv->lpddNLVHELCaps->dwNLVBFXCaps;
  813. for( i = 0; i < DD_ROP_SPACE; i++ )
  814. pdrv->lpddNLVBothCaps->dwNLVBRops[i] &= pdrv->lpddNLVHELCaps->dwNLVBRops[i];
  815. }
  816. if( pdrv->lpddBothMoreCaps != NULL )
  817. {
  818. DDASSERT( pdrv->lpddHELMoreCaps != NULL );
  819. pdrv->lpddBothMoreCaps->dwAlphaCaps &= pdrv->lpddHELMoreCaps->dwAlphaCaps;
  820. pdrv->lpddBothMoreCaps->dwSVBAlphaCaps &= pdrv->lpddHELMoreCaps->dwSVBAlphaCaps;
  821. pdrv->lpddBothMoreCaps->dwVSBAlphaCaps &= pdrv->lpddHELMoreCaps->dwVSBAlphaCaps;
  822. pdrv->lpddBothMoreCaps->dwSSBAlphaCaps &= pdrv->lpddHELMoreCaps->dwSSBAlphaCaps;
  823. pdrv->lpddBothMoreCaps->dwFilterCaps &= pdrv->lpddHELMoreCaps->dwFilterCaps;
  824. pdrv->lpddBothMoreCaps->dwSVBFilterCaps &= pdrv->lpddHELMoreCaps->dwSVBFilterCaps;
  825. pdrv->lpddBothMoreCaps->dwVSBFilterCaps &= pdrv->lpddHELMoreCaps->dwVSBFilterCaps;
  826. pdrv->lpddBothMoreCaps->dwSSBFilterCaps &= pdrv->lpddHELMoreCaps->dwSSBFilterCaps;
  827. #ifdef POSTPONED2
  828. pdrv->lpddBothMoreCaps->dwTransformCaps &= pdrv->lpddHELMoreCaps->dwTransformCaps;
  829. pdrv->lpddBothMoreCaps->dwSVBTransformCaps &= pdrv->lpddHELMoreCaps->dwSVBTransformCaps;
  830. pdrv->lpddBothMoreCaps->dwVSBTransformCaps &= pdrv->lpddHELMoreCaps->dwVSBTransformCaps;
  831. pdrv->lpddBothMoreCaps->dwSSBTransformCaps &= pdrv->lpddHELMoreCaps->dwSSBTransformCaps;
  832. #endif //POSTPONED2
  833. }
  834. }
  835. } /* mergeHELCaps */
  836. // This variable is a shared instance and has been moved to dllmain.c: BOOL bReloadReg;
  837. /*
  838. * capsInit
  839. *
  840. * initialize shared caps
  841. */
  842. static void capsInit( LPDDRAWI_DIRECTDRAW_GBL pdrv )
  843. {
  844. #ifdef DEBUG
  845. if( GetProfileInt("DirectDraw","nohwblt",0) )
  846. {
  847. pdrv->ddCaps.dwCaps &= ~DDCAPS_BLT;
  848. DPF( 2, "Turning off blt <<<<<<<<<<<<<<<<<<<<<<<<<<" );
  849. }
  850. if( GetProfileInt("DirectDraw","nohwtrans",0) )
  851. {
  852. pdrv->ddCaps.dwCKeyCaps &= ~(DDCKEYCAPS_DESTBLT|DDCKEYCAPS_SRCBLT);
  853. DPF( 2, "Turning off hardware transparency <<<<<<<<<<<<<<<<<<<<<<<<<<" );
  854. }
  855. if( GetProfileInt("DirectDraw","nohwfill",0) )
  856. {
  857. pdrv->ddCaps.dwCaps &= ~(DDCAPS_BLTCOLORFILL);
  858. DPF( 2, "Turning off color fill <<<<<<<<<<<<<<<<<<<<<<<<<<" );
  859. }
  860. #endif
  861. // initialize the BothCaps structure
  862. pdrv->ddBothCaps = pdrv->ddCaps;
  863. if( NULL != pdrv->lpddNLVCaps )
  864. {
  865. DDASSERT( NULL != pdrv->lpddNLVBothCaps );
  866. memcpy( pdrv->lpddNLVBothCaps, pdrv->lpddNLVCaps, sizeof( DDNONLOCALVIDMEMCAPS ) );
  867. }
  868. else if ( pdrv->lpddNLVBothCaps != NULL)
  869. {
  870. ZeroMemory( pdrv->lpddNLVBothCaps, sizeof( DDNONLOCALVIDMEMCAPS ) );
  871. pdrv->lpddNLVBothCaps->dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
  872. }
  873. if( pdrv->lpddBothMoreCaps != NULL )
  874. {
  875. DDASSERT( pdrv->lpddMoreCaps != NULL );
  876. memcpy(pdrv->lpddBothMoreCaps, pdrv->lpddMoreCaps, sizeof(DDMORECAPS));
  877. }
  878. } /* capsInit */
  879. #ifdef WINNT
  880. //
  881. // pdd_gbl may be null (if coming from the create code path) or non null (from the reset code path).
  882. // We assert that if pdd_gbl==NULL, then we can't be in an emulated ModeX mode, because the
  883. // only way to get there is to use a ddraw object to set such a mode. So we only have to check
  884. // for fake modex mode if pdd_gbl is non-null.
  885. //
  886. BOOL GetCurrentMode(LPDDRAWI_DIRECTDRAW_GBL pdd_gbl, LPDDHALINFO lpHalInfo, char *szDrvName)
  887. {
  888. LPDDHALMODEINFO pmi;
  889. DEVMODE dm;
  890. HDC hdc;
  891. LPCTSTR pszDevice;
  892. pmi = MemAlloc(sizeof (DDHALMODEINFO));
  893. if (pmi)
  894. {
  895. pszDevice = _stricmp(szDrvName, DISPLAY_STR) ? szDrvName : NULL;
  896. ZeroMemory(&dm, sizeof dm);
  897. dm.dmSize = sizeof dm;
  898. if ( pdd_gbl && pdd_gbl->dwFlags & DDRAWI_MODEX )
  899. {
  900. // If the current mode is modex, then we could only have gotten here if
  901. // it's the current mode.
  902. pmi->dwWidth = pdd_gbl->dmiCurrent.wWidth;
  903. pmi->dwHeight = pdd_gbl->dmiCurrent.wHeight;
  904. pmi->dwBPP = pdd_gbl->dmiCurrent.wBPP;
  905. pmi->wRefreshRate = pdd_gbl->dmiCurrent.wRefreshRate;
  906. pmi->lPitch = pmi->dwWidth;
  907. pmi->dwRBitMask = 0;
  908. pmi->dwGBitMask = 0;
  909. pmi->dwBBitMask = 0;
  910. pmi->dwAlphaBitMask = 0;
  911. }
  912. else if (EnumDisplaySettings(pszDevice, ENUM_CURRENT_SETTINGS, &dm))
  913. {
  914. pmi->dwWidth = dm.dmPelsWidth;
  915. pmi->dwHeight = dm.dmPelsHeight;
  916. pmi->dwBPP = dm.dmBitsPerPel;
  917. pmi->wRefreshRate = (WORD) dm.dmDisplayFrequency;
  918. pmi->lPitch = (pmi->dwWidth * pmi->dwBPP) >> 3;
  919. if (pmi->dwBPP > 8)
  920. {
  921. void FillBitMasks(LPDDPIXELFORMAT pddpf, HDC hdc);
  922. DDPIXELFORMAT ddpf;
  923. hdc = DD_CreateDC(szDrvName);
  924. if (hdc)
  925. {
  926. FillBitMasks(&ddpf, hdc);
  927. DD_DoneDC(hdc);
  928. }
  929. if (pmi->dwBPP == 15)
  930. {
  931. pmi->dwBPP = 16;
  932. pmi->wFlags = DDMODEINFO_555MODE;
  933. }
  934. pmi->dwRBitMask = ddpf.dwRBitMask;
  935. pmi->dwGBitMask = ddpf.dwGBitMask;
  936. pmi->dwBBitMask = ddpf.dwBBitMask;
  937. pmi->dwAlphaBitMask = ddpf.dwRGBAlphaBitMask;
  938. }
  939. else
  940. {
  941. pmi->wFlags = DDMODEINFO_PALETTIZED;
  942. }
  943. lpHalInfo->dwNumModes = 1;
  944. lpHalInfo->dwMonitorFrequency = pmi->wRefreshRate;
  945. }
  946. else
  947. {
  948. MemFree(pmi);
  949. pmi = NULL;
  950. }
  951. }
  952. lpHalInfo->lpModeInfo = pmi;
  953. return pmi != NULL;
  954. }
  955. #endif
  956. static HRESULT
  957. GetDriverInfo(LPDDHAL_GETDRIVERINFO lpGetDriverInfo,
  958. LPDDHAL_GETDRIVERINFODATA lpGDInfo,
  959. LPVOID lpDriverInfo,
  960. DWORD dwSize,
  961. const GUID *lpGUID,
  962. LPDDRAWI_DIRECTDRAW_GBL lpDD,
  963. BOOL bInOut) // Indicates whether the data passed is in/out or just out
  964. {
  965. int i;
  966. // 1K temp buffer to pull driver info into
  967. static DWORD dwDriverInfoBuffer[256];
  968. if (bInOut)
  969. {
  970. DDASSERT((dwSize & 3) == 0);
  971. // Copy over the data from our source
  972. memcpy(dwDriverInfoBuffer, lpDriverInfo, dwSize);
  973. // Only dead-beef the unused part of the buffer
  974. i = dwSize>>2;
  975. }
  976. else
  977. {
  978. i = 0;
  979. }
  980. for (i; i < 256; i += 1)
  981. dwDriverInfoBuffer[i] = 0xdeadbeef;
  982. #ifdef DEBUG
  983. if(dwSize>255*sizeof(DWORD)) { // 0xdeadbeef overwrite test wont work unless dwSize>>2 <= 255
  984. DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Internal DDraw Error: GetDriverInfo() dwSize parameter > 1020");
  985. return DDERR_NODIRECTDRAWSUPPORT;
  986. }
  987. #endif
  988. memset(lpGDInfo, 0, sizeof(*lpGDInfo) );
  989. lpGDInfo->dwSize = sizeof(*lpGDInfo);
  990. lpGDInfo->dwFlags = 0;
  991. memcpy(&lpGDInfo->guidInfo, lpGUID, sizeof(*lpGUID) );
  992. lpGDInfo->dwExpectedSize = dwSize;
  993. lpGDInfo->lpvData = dwDriverInfoBuffer;
  994. lpGDInfo->ddRVal = DDERR_GENERIC;
  995. // Pass a context variable so that the driver
  996. // knows which instance of itself to use
  997. // w.r.t. this function. These are different
  998. // values on Win95 and NT.
  999. #ifdef WIN95
  1000. lpGDInfo->dwContext = lpDD->dwReserved3;
  1001. #else
  1002. lpGDInfo->dwContext = lpDD->hDD;
  1003. #endif
  1004. if ( lpGetDriverInfo(lpGDInfo) == DDHAL_DRIVER_HANDLED && lpGDInfo->ddRVal == DD_OK )
  1005. {
  1006. // Fail if the driver wrote more bytes than the expected size
  1007. if (dwDriverInfoBuffer[dwSize>>2] != 0xdeadbeef)
  1008. {
  1009. return DDERR_NODIRECTDRAWSUPPORT;
  1010. }
  1011. memcpy(lpDriverInfo, dwDriverInfoBuffer, min(dwSize, lpGDInfo->dwActualSize));
  1012. }
  1013. return lpGDInfo->ddRVal;
  1014. }
  1015. static BOOL
  1016. ValidateCallbacks(LPVOID lpCallbacks)
  1017. {
  1018. int N = ((((DWORD FAR *) lpCallbacks)[0] >> 2) - 2) / (sizeof(DWORD_PTR) / sizeof(DWORD));
  1019. if (N > 0)
  1020. {
  1021. DWORD dwFlags = ((DWORD FAR *) lpCallbacks)[1];
  1022. DWORD bit = 1;
  1023. int i;
  1024. LPVOID *pcbrtn = (LPVOID *) &(((DWORD FAR *) lpCallbacks)[2]);
  1025. for (i = 0; i < N; i += 1)
  1026. {
  1027. LPVOID cbrtn;
  1028. cbrtn = *pcbrtn++;
  1029. // If a function is non-NULL and they failed to set the
  1030. // 32-bit flag, fail. We might support 16-bit callbacks
  1031. // in future but not for now.
  1032. if ( (cbrtn != NULL) && ( 0 == (dwFlags & bit) ) )
  1033. return FALSE;
  1034. if (dwFlags & bit)
  1035. {
  1036. #if defined(NT_FIX) || defined(WIN95) // check this some other way // If the bit is set, validate the callback.
  1037. if (! VALIDEX_CODE_PTR(cbrtn) )
  1038. {
  1039. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32-bit callback");
  1040. return FALSE;
  1041. }
  1042. #endif
  1043. }
  1044. bit <<= 1;
  1045. }
  1046. }
  1047. return TRUE;
  1048. }
  1049. /*
  1050. * Validate the core HAL information the driver passed to us.
  1051. */
  1052. BOOL
  1053. ValidateCoreHALInfo( LPDDHALINFO lpDDHALInfo )
  1054. {
  1055. int i;
  1056. LPVIDMEM pvm;
  1057. int numcb;
  1058. LPDDHAL_DDCALLBACKS drvcb;
  1059. LPDDHAL_DDSURFACECALLBACKS surfcb;
  1060. LPDDHAL_DDPALETTECALLBACKS palcb;
  1061. LPDDHAL_DDEXEBUFCALLBACKS exebufcb;
  1062. DWORD bit;
  1063. LPVOID cbrtn;
  1064. TRY
  1065. {
  1066. /*
  1067. * Valid HAL info
  1068. */
  1069. if( !VALIDEX_DDHALINFO_PTR( lpDDHALInfo ) )
  1070. {
  1071. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  1072. DPF(0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid DDHALINFO provided: 0x%p",lpDDHALInfo );
  1073. if( lpDDHALInfo != NULL )
  1074. {
  1075. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: size = was %d, expecting %d or %d", lpDDHALInfo->dwSize, sizeof( DDHALINFO ), sizeof( DDHALINFO_V1) );
  1076. }
  1077. return FALSE;
  1078. }
  1079. if( lpDDHALInfo->dwSize == sizeof( DDHALINFO_V1 ) )
  1080. {
  1081. /*
  1082. * The DDHALINFO structure returned by the driver is in the DDHALINFO_V1
  1083. * format. Convert it to the new DDHALINFO structure.
  1084. */
  1085. convertV1DDHALINFO( lpDDHALInfo );
  1086. }
  1087. /*
  1088. * validate video memory heaps
  1089. */
  1090. for( i=0;i<(int)lpDDHALInfo->vmiData.dwNumHeaps;i++ )
  1091. {
  1092. pvm = &lpDDHALInfo->vmiData.pvmList[i];
  1093. if( pvm->dwFlags & VIDMEM_ISNONLOCAL )
  1094. {
  1095. /*
  1096. * NOTE: It is entirely legal to pass a NULL fpStart for a non-local
  1097. * heap. The start address is meaningless for non-local heaps.
  1098. */
  1099. /*
  1100. * If the heap is non-local then the driver must have specified
  1101. * the DDCAPS2_NONLOCALVIDMEM. If it hasn't we fail the initialization.
  1102. */
  1103. if( !( lpDDHALInfo->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM ) )
  1104. {
  1105. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Non-local video memory heap passed but DDCAPS2_NONLOCALVIDMEM not specified" );
  1106. return FALSE;
  1107. }
  1108. }
  1109. else
  1110. {
  1111. if( (pvm->fpStart == (FLATPTR) NULL) )
  1112. {
  1113. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid video memory fpStart pointer passed" );
  1114. return FALSE;
  1115. }
  1116. /*
  1117. * This is not a local video memory heap and WC is specified. Currently
  1118. * this is not legal.
  1119. */
  1120. #pragma message( REMIND( "Look into enabling WC on local vid mem" ) )
  1121. if( pvm->dwFlags & VIDMEM_ISWC )
  1122. {
  1123. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver can't specify write combining with a local video memory heap" );
  1124. return FALSE;
  1125. }
  1126. }
  1127. }
  1128. /*
  1129. * validate pixel format
  1130. *
  1131. * NOTE: The dwSize check below may seem redundant since the DDPIXELFORMAT
  1132. * struct is embedded in a DDHAL struct whose size has already been validated.
  1133. * But removing this test caused stress failures with drivers that do not
  1134. * support DDraw. The drivers were running "accelerated" but with virtually
  1135. * no caps. So we'll keep this test until the problem is better understood.
  1136. */
  1137. if( lpDDHALInfo->vmiData.ddpfDisplay.dwSize != sizeof( DDPIXELFORMAT ) )
  1138. {
  1139. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid DDPIXELFORMAT in DDHALINFO.vmiData: bad size" );
  1140. return FALSE;
  1141. }
  1142. /*
  1143. * DX4; Validate it some more.
  1144. */
  1145. if ( (lpDDHALInfo->vmiData.ddpfDisplay.dwFlags & DDPF_PALETTEINDEXED8) &&
  1146. (lpDDHALInfo->vmiData.ddpfDisplay.dwRGBBitCount != 8) )
  1147. {
  1148. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid DDPIXELFORMAT in DDHALINFO.vmiData: palettized mode must be 8bpp" );
  1149. return FALSE;
  1150. }
  1151. /*
  1152. * validate driver callback
  1153. */
  1154. drvcb = lpDDHALInfo->lpDDCallbacks;
  1155. if( drvcb != NULL )
  1156. {
  1157. if( !VALID_PTR_PTR( drvcb ) )
  1158. {
  1159. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid driver callback ptr" );
  1160. return FALSE;
  1161. }
  1162. if( !VALIDEX_DDCALLBACKSSIZE( drvcb ) )
  1163. {
  1164. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid size field in lpDriverCallbacks" );
  1165. return FALSE;
  1166. }
  1167. numcb = NUM_CALLBACKS( drvcb );
  1168. bit = 1;
  1169. for( i=0;i<numcb;i++ )
  1170. {
  1171. if( drvcb->dwFlags & bit )
  1172. {
  1173. // 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
  1174. cbrtn = (LPVOID) (&drvcb->DestroyDriver)[i];
  1175. if( cbrtn != NULL )
  1176. {
  1177. #if defined(NT_FIX) || defined(WIN95) // check this some other way
  1178. if( !VALIDEX_CODE_PTR( cbrtn ) )
  1179. {
  1180. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32-bit callback in lpDriverCallbacks" );
  1181. return FALSE;
  1182. }
  1183. #endif
  1184. }
  1185. }
  1186. bit <<= 1;
  1187. }
  1188. }
  1189. /*
  1190. * Turn off optimized surfaces just for now
  1191. */
  1192. if (lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  1193. {
  1194. DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver tried to set DDSCAPS_OPTIMIZED. Not allowed for this release");
  1195. return FALSE;
  1196. }
  1197. /*
  1198. * We used to ensure that no driver ever set dwCaps2. However,
  1199. * we have now run out of bits in ddCaps.dwCaps so we need to
  1200. * allow drivers to set bits in dwCaps2. Hence all we do now
  1201. * is ensure that drivers don't try and impersonate certified
  1202. * drivers by returning DDCAPS2_CERTIFIED. This is something
  1203. * we turn on - they can't set it.
  1204. */
  1205. if( lpDDHALInfo->ddCaps.dwCaps2 & DDCAPS2_CERTIFIED )
  1206. {
  1207. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver tried to set the DDCAPS2_CERTIFIED" );
  1208. return FALSE;
  1209. }
  1210. /*
  1211. * validate surface callbacks
  1212. */
  1213. surfcb = lpDDHALInfo->lpDDSurfaceCallbacks;
  1214. if( surfcb != NULL )
  1215. {
  1216. if( !VALID_PTR_PTR( surfcb ) )
  1217. {
  1218. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid surface callback ptr" );
  1219. return FALSE;
  1220. }
  1221. if( !VALIDEX_DDSURFACECALLBACKSSIZE( surfcb ) )
  1222. {
  1223. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid size field in lpSurfaceCallbacks" );
  1224. return FALSE;
  1225. }
  1226. numcb = NUM_CALLBACKS( surfcb );
  1227. bit = 1;
  1228. for( i=0;i<numcb;i++ )
  1229. {
  1230. if( surfcb->dwFlags & bit )
  1231. {
  1232. // 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
  1233. cbrtn = (LPVOID) (&surfcb->DestroySurface)[i];
  1234. if( cbrtn != NULL )
  1235. {
  1236. #if defined(NT_FIX) || defined(WIN95) //check some other way
  1237. if( !VALIDEX_CODE_PTR( cbrtn ) )
  1238. {
  1239. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32/64-bit callback in lpSurfaceCallbacks" );
  1240. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  1241. DPF( 0, "Callback = 0x%p, i = %d, bit = 0x%08lx", cbrtn, i, bit );
  1242. return FALSE;
  1243. }
  1244. #endif
  1245. }
  1246. }
  1247. bit <<= 1;
  1248. }
  1249. }
  1250. /*
  1251. * validate palette callbacks
  1252. */
  1253. palcb = lpDDHALInfo->lpDDPaletteCallbacks;
  1254. if( palcb != NULL )
  1255. {
  1256. if( !VALID_PTR_PTR( palcb ) )
  1257. {
  1258. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid palette callback ptr" );
  1259. return FALSE;
  1260. }
  1261. if( !VALIDEX_DDPALETTECALLBACKSSIZE( palcb ) )
  1262. {
  1263. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid size field in lpPaletteCallbacks" );
  1264. return FALSE;
  1265. }
  1266. numcb = NUM_CALLBACKS( palcb );
  1267. bit = 1;
  1268. for( i=0;i<numcb;i++ )
  1269. {
  1270. if( palcb->dwFlags & bit )
  1271. {
  1272. // 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
  1273. cbrtn = (LPVOID) (&palcb->DestroyPalette)[i];
  1274. if( cbrtn != NULL )
  1275. {
  1276. #if defined(NT_FIX) || defined(WIN95)
  1277. if( !VALIDEX_CODE_PTR( cbrtn ) )
  1278. {
  1279. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32-bit callback in lpPaletteCallbacks" );
  1280. return FALSE;
  1281. }
  1282. #endif
  1283. }
  1284. }
  1285. bit <<= 1;
  1286. }
  1287. }
  1288. /*
  1289. * validate execute buffer callbacks - but only (and I mean ONLY) if
  1290. * its a V2 driver and it knows about execute buffers.
  1291. */
  1292. if( lpDDHALInfo->dwSize >= DDHALINFOSIZE_V2 )
  1293. {
  1294. exebufcb = lpDDHALInfo->lpDDExeBufCallbacks;
  1295. if( exebufcb != NULL )
  1296. {
  1297. if( !VALID_PTR_PTR( exebufcb ) )
  1298. {
  1299. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid execute buffer callback ptr" );
  1300. return FALSE;
  1301. }
  1302. if( !VALIDEX_DDEXEBUFCALLBACKSSIZE( exebufcb ) )
  1303. {
  1304. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid size field in lpExeBufCallbacks" );
  1305. return FALSE;
  1306. }
  1307. numcb = NUM_CALLBACKS( exebufcb );
  1308. bit = 1;
  1309. for( i=0;i<numcb;i++ )
  1310. {
  1311. if( exebufcb->dwFlags & bit )
  1312. {
  1313. // 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
  1314. cbrtn = (LPVOID) (&exebufcb->CanCreateExecuteBuffer)[i];
  1315. if( cbrtn != NULL )
  1316. {
  1317. #if defined(NT_FIX) || defined(WIN95)
  1318. if( !VALIDEX_CODE_PTR( cbrtn ) )
  1319. {
  1320. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32-bit callback in lpExeBufCallbacks" );
  1321. return FALSE;
  1322. }
  1323. #endif
  1324. }
  1325. }
  1326. bit <<= 1;
  1327. }
  1328. }
  1329. }
  1330. /*
  1331. * Make sure a mode table was specified
  1332. */
  1333. if( ( lpDDHALInfo->dwNumModes > 0 ) &&
  1334. ( lpDDHALInfo->lpModeInfo == NULL ) )
  1335. {
  1336. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver says modes are supported, but DDHALINFO.lpModeInfo = NULL" );
  1337. return FALSE;
  1338. }
  1339. }
  1340. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1341. {
  1342. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Exception encountered validating driver HAL information" );
  1343. DEBUG_BREAK();
  1344. return FALSE;
  1345. }
  1346. return TRUE;
  1347. }
  1348. /*
  1349. * Fetch the new HAL information from a driver (if any) and validate it.
  1350. */
  1351. static BOOL
  1352. GetAndValidateNewHALInfo( LPDDRAWI_DIRECTDRAW_GBL pddd,
  1353. LPDDHALINFO lpDDHALInfo )
  1354. {
  1355. pddd->lpD3DHALCallbacks2 = 0;
  1356. pddd->lpD3DHALCallbacks3 = 0;
  1357. pddd->lpZPixelFormats = NULL;
  1358. pddd->pGetDriverInfo = NULL;
  1359. #ifdef POSTPONED
  1360. pddd->lpDDUmodeDrvInfo = NULL;
  1361. pddd->lpDDOptSurfaceInfo = NULL;
  1362. #endif
  1363. TRY
  1364. {
  1365. memset(&pddd->lpDDCBtmp->HALDDMiscellaneous, 0, sizeof(pddd->lpDDCBtmp->HALDDMiscellaneous) );
  1366. memset(&pddd->lpDDCBtmp->HALDDMiscellaneous2, 0, sizeof(pddd->lpDDCBtmp->HALDDMiscellaneous2) );
  1367. #ifndef WIN95
  1368. memset(&pddd->lpDDCBtmp->HALDDNT, 0, sizeof(pddd->lpDDCBtmp->HALDDNT) );
  1369. #endif
  1370. memset(&pddd->lpDDCBtmp->HALDDVideoPort, 0, sizeof(pddd->lpDDCBtmp->HALDDVideoPort) );
  1371. memset(&pddd->lpDDCBtmp->HALDDColorControl, 0, sizeof(pddd->lpDDCBtmp->HALDDColorControl) );
  1372. memset(&pddd->lpDDCBtmp->HALDDKernel, 0, sizeof(pddd->lpDDCBtmp->HALDDKernel) );
  1373. /*
  1374. * Allocate memory for D3D DDI interfaces queried from GetDriverInfo
  1375. * (the freeing of this memory for failed driver init needs work)
  1376. */
  1377. pddd->lpD3DHALCallbacks2 = MemAlloc( D3DHAL_CALLBACKS2SIZE );
  1378. if (! pddd->lpD3DHALCallbacks2)
  1379. {
  1380. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Out of memory querying D3DCallbacks2" );
  1381. goto failed;
  1382. }
  1383. pddd->lpD3DHALCallbacks3 = MemAlloc( D3DHAL_CALLBACKS3SIZE );
  1384. if (! pddd->lpD3DHALCallbacks3)
  1385. {
  1386. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Out of memory querying D3DCallbacks3" );
  1387. goto failed;
  1388. }
  1389. #ifdef POSTPONED
  1390. pddd->lpDDUmodeDrvInfo =
  1391. (LPDDUMODEDRVINFO) MemAlloc (sizeof (DDUMODEDRVINFO));
  1392. if (! pddd->lpDDUmodeDrvInfo)
  1393. {
  1394. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Out of memory querying UserModeDriverInfo" );
  1395. goto failed;
  1396. }
  1397. #endif
  1398. if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
  1399. {
  1400. HRESULT ret;
  1401. DDHAL_GETDRIVERINFODATA gdidata;
  1402. D3DHAL_CALLBACKS2 D3DCallbacks2;
  1403. D3DHAL_CALLBACKS3 D3DCallbacks3;
  1404. if (! VALIDEX_CODE_PTR (lpDDHALInfo->GetDriverInfo) )
  1405. {
  1406. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: GetDriverInfo callback bit set, but not valid" );
  1407. goto failed;
  1408. }
  1409. // use fact that code pointer was validated before...
  1410. pddd->pGetDriverInfo=lpDDHALInfo->GetDriverInfo;
  1411. /*
  1412. * Probe the driver with a GUID of bogusness. If it claims to
  1413. * understand this one, then fail driver create.
  1414. */
  1415. {
  1416. DWORD dwFakeGUID[4];
  1417. DWORD dwTemp[10];
  1418. memcpy(dwFakeGUID, &CLSID_DirectDraw, sizeof(dwFakeGUID));
  1419. dwFakeGUID[3] += GetCurrentProcessId();
  1420. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1421. dwTemp,
  1422. sizeof(dwTemp),
  1423. (const GUID *) dwFakeGUID, pddd,
  1424. FALSE /* bInOut */);
  1425. if ( ret == DD_OK )
  1426. {
  1427. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver claimed support via GetDriverInfo for bogus GUID!" );
  1428. goto failed;
  1429. }
  1430. }
  1431. /*
  1432. * Notify driver about DXVERSION on NT
  1433. */
  1434. #ifndef WIN95
  1435. if (lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFO2)
  1436. {
  1437. // This buffer is used to pass information down to the driver and get
  1438. // information back from the driver. The GetDriverInfo2 header and
  1439. // any additional information to pass to the driver is copied into this
  1440. // buffer prior to calling GetDriverInfo2. After the call the information
  1441. // returned by the driver is contained in this buffer. All information
  1442. // passed to and from the driver must fit within a buffer of this size.
  1443. // The buffer used by GetDriverInfo2 is constrained to the maximum size
  1444. // specified below by restrictions in the Win2K kernel. It is vital that
  1445. // all data passed to the driver and received from the driver via
  1446. // GetDriverInfo2 fit within a buffer of this number of DWORDS.
  1447. // This size has to be less than 1K to let the kernel do its own buffer
  1448. // overwrite testing.
  1449. #define MAX_GDI2_BUFFER_DWORD_SIZE (249)
  1450. DWORD buffer[MAX_GDI2_BUFFER_DWORD_SIZE];
  1451. DD_DXVERSION* pDXVersion;
  1452. // Set up the DXVersion call
  1453. memset(&buffer, 0, sizeof(buffer));
  1454. pDXVersion = (DD_DXVERSION *)buffer;
  1455. // Before we do anything else, we notify the
  1456. // driver about the DX version information. We ignore
  1457. // errors here.
  1458. pDXVersion->gdi2.dwReserved = sizeof(DD_STEREOMODE);
  1459. pDXVersion->gdi2.dwMagic = D3DGDI2_MAGIC;
  1460. pDXVersion->gdi2.dwType = D3DGDI2_TYPE_DXVERSION;
  1461. pDXVersion->gdi2.dwExpectedSize = sizeof(DD_DXVERSION);
  1462. pDXVersion->dwDXVersion = DD_RUNTIME_VERSION;
  1463. // We assert the sizes are the same because we need to
  1464. // persuade the kernel into accepting this call.
  1465. DDASSERT(sizeof(DD_STEREOMODE) == sizeof(DD_DXVERSION));
  1466. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1467. buffer,
  1468. sizeof(DD_STEREOMODE),
  1469. &GUID_GetDriverInfo2, pddd,
  1470. TRUE /* bInOut */);
  1471. // Errors are ignored here
  1472. ret = 0;
  1473. // Also notify the driver that we have the AGP aliasing
  1474. // work-around in place.
  1475. {
  1476. DD_DEFERRED_AGP_AWARE_DATA aad;
  1477. DWORD dwDrvRet;
  1478. GetDriverInfo2(pddd,
  1479. &dwDrvRet,
  1480. D3DGDI2_TYPE_DEFERRED_AGP_AWARE,
  1481. sizeof(aad), &aad);
  1482. }
  1483. }
  1484. #endif // !WIN95
  1485. memset(&pddd->lpDDCBtmp->HALDDMiscellaneous, 0, sizeof(DDHAL_DDMISCELLANEOUSCALLBACKS) );
  1486. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1487. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1488. &pddd->lpDDCBtmp->HALDDMiscellaneous,
  1489. sizeof(DDHAL_DDMISCELLANEOUSCALLBACKS),
  1490. &GUID_MiscellaneousCallbacks, pddd,
  1491. FALSE /* bInOut */ );
  1492. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1493. // overwrote its buffer.
  1494. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1495. {
  1496. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous): Driver overwrote callbacks buffer" );
  1497. goto failed;
  1498. }
  1499. if ( ret == DD_OK )
  1500. {
  1501. // Fail create if driver already failed validation or
  1502. // claims support but it's not valid.
  1503. if (! VALIDEX_DDMISCELLANEOUSCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDMiscellaneous ) ||
  1504. ( gdidata.dwActualSize < sizeof(DDHAL_DDMISCELLANEOUSCALLBACKS ) ) )
  1505. {
  1506. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous): size not valid" );
  1507. goto failed;
  1508. }
  1509. if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDMiscellaneous) )
  1510. {
  1511. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous): flags set incorrectly" );
  1512. goto failed;
  1513. }
  1514. }
  1515. // Get HALDDMiscellaneous2 interface.
  1516. memset(&pddd->lpDDCBtmp->HALDDMiscellaneous2, 0, sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS) );
  1517. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1518. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1519. &pddd->lpDDCBtmp->HALDDMiscellaneous2,
  1520. sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS),
  1521. &GUID_Miscellaneous2Callbacks, pddd,
  1522. FALSE /* bInOut */);
  1523. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1524. // overwrote its buffer.
  1525. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1526. {
  1527. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous2): Driver overwrote callbacks buffer" );
  1528. goto failed;
  1529. }
  1530. if ( ret == DD_OK )
  1531. {
  1532. // Fail create if driver already failed validation or
  1533. // claims support but it's not valid.
  1534. if (! VALIDEX_DDMISCELLANEOUS2CALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDMiscellaneous2 ) ||
  1535. ( gdidata.dwActualSize < sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS ) ) )
  1536. {
  1537. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous2): size not valid" );
  1538. goto failed;
  1539. }
  1540. if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDMiscellaneous2) )
  1541. {
  1542. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous2): flags set incorrectly" );
  1543. goto failed;
  1544. }
  1545. if (lpDDHALInfo->lpD3DGlobalDriverData &&
  1546. (lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps &
  1547. (D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWTRANSFORMANDLIGHT) )
  1548. )
  1549. {
  1550. // If a driver responds to the Misc2 GUID, then it better return
  1551. // a non-null GetDriverState callback.
  1552. if (0 == pddd->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState)
  1553. {
  1554. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (HALDDMiscellaneous2): no GetDriverState support" );
  1555. goto failed;
  1556. }
  1557. #ifdef WIN95
  1558. // On Win95 the CreateSurfaceEx should be non-NULL
  1559. if (0 == pddd->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx)
  1560. {
  1561. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (HALDDMiscellaneous2): CreateSurfaceEx must be reported with D3DDEVCAPS_DRAWPRIMITIVES2EX" );
  1562. goto failed;
  1563. }
  1564. #else //WIN95
  1565. // DX7 drivers should export GetDriverState always, if they
  1566. // didnt, then most likely they are the transition drivers that
  1567. // are still DX6 and will need to be updated. For now dont
  1568. // validate the presence of this callback. Simply use its
  1569. // presence or absence to spoof the legacy texture callbacks.
  1570. DDASSERT( lpDDHALInfo->lpD3DHALCallbacks->TextureCreate == NULL);
  1571. DDASSERT( lpDDHALInfo->lpD3DHALCallbacks->TextureDestroy == NULL);
  1572. DDASSERT( lpDDHALInfo->lpD3DHALCallbacks->TextureSwap == NULL);
  1573. DDASSERT( lpDDHALInfo->lpD3DHALCallbacks->TextureGetSurf == NULL);
  1574. #endif //WIN95
  1575. }
  1576. }
  1577. #ifdef WIN95
  1578. if (0 != pddd->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx)
  1579. {
  1580. if (lpDDHALInfo->lpD3DGlobalDriverData)
  1581. {
  1582. if (!(lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps &
  1583. D3DDEVCAPS_DRAWPRIMITIVES2EX))
  1584. {
  1585. if(lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps &
  1586. D3DPRASTERCAPS_ZBUFFERLESSHSR)
  1587. //legacy powerVR stackable driver would actually forward new callbacks
  1588. //if the primary driver supports the new callbacks
  1589. {
  1590. pddd->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx=0;
  1591. pddd->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState=0;
  1592. pddd->lpDDCBtmp->HALDDMiscellaneous2.DestroyDDLocal=0;
  1593. }
  1594. else
  1595. {
  1596. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (HALDDMiscellaneous2): CreateSurfaceEx must be reported with D3DDEVCAPS_DRAWPRIMITIVES2EX" );
  1597. goto failed;
  1598. }
  1599. }
  1600. }
  1601. }
  1602. #else //WIN95
  1603. memset(&pddd->lpDDCBtmp->HALDDNT, 0, sizeof(DDHAL_DDNTCALLBACKS) );
  1604. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1605. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1606. &pddd->lpDDCBtmp->HALDDNT,
  1607. sizeof(DDHAL_DDNTCALLBACKS),
  1608. &GUID_NTCallbacks, pddd,
  1609. FALSE /* bInOut */);
  1610. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1611. // overwrote its buffer.
  1612. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1613. {
  1614. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (NT): Driver overwrote callbacks buffer" );
  1615. goto failed;
  1616. }
  1617. if ( ret == DD_OK )
  1618. {
  1619. // Fail create if driver already failed validation or
  1620. // claims support but it's not valid.
  1621. if (! VALIDEX_DDNTCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDNT ) ||
  1622. ( gdidata.dwActualSize < sizeof(DDHAL_DDNTCALLBACKS ) ) )
  1623. {
  1624. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (NT): size not valid" );
  1625. goto failed;
  1626. }
  1627. if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDNT) )
  1628. {
  1629. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (NT): flags set incorrectly" );
  1630. goto failed;
  1631. }
  1632. }
  1633. memset(&pddd->lpDDCBtmp->HALDDVPE2, 0, sizeof(DDHAL_DDVPE2CALLBACKS) );
  1634. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1635. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1636. &pddd->lpDDCBtmp->HALDDVPE2,
  1637. sizeof(DDHAL_DDVPE2CALLBACKS),
  1638. &GUID_VPE2Callbacks, pddd,
  1639. FALSE /* bInOut */);
  1640. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1641. // overwrote its buffer.
  1642. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1643. {
  1644. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VPE2): Driver overwrote callbacks buffer" );
  1645. goto failed;
  1646. }
  1647. if ( ret == DD_OK )
  1648. {
  1649. // Fail create if driver already failed validation or
  1650. // claims support but it's not valid.
  1651. if (! VALIDEX_DDVPE2CALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDVPE2 ) ||
  1652. ( gdidata.dwActualSize < sizeof(DDHAL_DDVPE2CALLBACKS ) ) )
  1653. {
  1654. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VPE2): size not valid" );
  1655. goto failed;
  1656. }
  1657. if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDVPE2) )
  1658. {
  1659. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VPE2): flags set incorrectly" );
  1660. goto failed;
  1661. }
  1662. }
  1663. #endif
  1664. memset(&pddd->lpDDCBtmp->HALDDVideoPort, 0, sizeof(DDHAL_DDVIDEOPORTCALLBACKS) );
  1665. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1666. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1667. &pddd->lpDDCBtmp->HALDDVideoPort,
  1668. sizeof(DDHAL_DDVIDEOPORTCALLBACKS),
  1669. &GUID_VideoPortCallbacks, pddd,
  1670. FALSE /* bInOut */);
  1671. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1672. // overwrote its buffer.
  1673. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1674. {
  1675. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VideoPort): Driver overwrote callbacks buffer" );
  1676. goto failed;
  1677. }
  1678. if ( ret == DD_OK )
  1679. {
  1680. // Fail create if driver already failed validation or
  1681. // claims support but it's not valid.
  1682. if (! VALIDEX_DDVIDEOPORTCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDVideoPort ) ||
  1683. ( gdidata.dwActualSize < sizeof(DDHAL_DDVIDEOPORTCALLBACKS ) ) )
  1684. {
  1685. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VideoPort): size not valid" );
  1686. goto failed;
  1687. }
  1688. if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDVideoPort) )
  1689. {
  1690. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VideoPort): flags set incorrectly" );
  1691. goto failed;
  1692. }
  1693. }
  1694. memset(&pddd->lpDDCBtmp->HALDDMotionComp, 0, sizeof(DDHAL_DDMOTIONCOMPCALLBACKS) );
  1695. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1696. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1697. &pddd->lpDDCBtmp->HALDDMotionComp,
  1698. sizeof(DDHAL_DDMOTIONCOMPCALLBACKS),
  1699. &GUID_MotionCompCallbacks, pddd,
  1700. FALSE /* bInOut */);
  1701. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1702. // overwrote its buffer.
  1703. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1704. {
  1705. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (MotionComp): Driver overwrote callbacks buffer" );
  1706. goto failed;
  1707. }
  1708. if ( ret == DD_OK )
  1709. {
  1710. // Fail create if driver already failed validation or
  1711. // claims support but it's not valid.
  1712. if (! VALIDEX_DDMOTIONCOMPCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDMotionComp ) ||
  1713. ( gdidata.dwActualSize < sizeof(DDHAL_DDMOTIONCOMPCALLBACKS ) ) )
  1714. {
  1715. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (MotionComp): size not valid" );
  1716. goto failed;
  1717. }
  1718. if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDMotionComp) )
  1719. {
  1720. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (MotionComp): flags set incorrectly" );
  1721. goto failed;
  1722. }
  1723. }
  1724. memset(&pddd->lpDDCBtmp->HALDDColorControl, 0, sizeof(DDHAL_DDCOLORCONTROLCALLBACKS) );
  1725. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1726. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1727. &pddd->lpDDCBtmp->HALDDColorControl,
  1728. sizeof(DDHAL_DDCOLORCONTROLCALLBACKS),
  1729. &GUID_ColorControlCallbacks, pddd,
  1730. FALSE /* bInOut */);
  1731. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1732. // overwrote its buffer.
  1733. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1734. {
  1735. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (ColorControl): Driver overwrote callbacks buffer" );
  1736. goto failed;
  1737. }
  1738. if ( ret == DD_OK )
  1739. {
  1740. // Fail create if driver already failed validation or
  1741. // claims support but it's not valid.
  1742. if (! VALIDEX_DDCOLORCONTROLCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDColorControl ) ||
  1743. ( gdidata.dwActualSize < sizeof(DDHAL_DDCOLORCONTROLCALLBACKS ) ) )
  1744. {
  1745. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (ColorControl): size not valid" );
  1746. goto failed;
  1747. }
  1748. if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDColorControl) )
  1749. {
  1750. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (ColorControl): flags set incorrectly" );
  1751. goto failed;
  1752. }
  1753. }
  1754. /*
  1755. * Probe and validate D3DCallbacks2 support
  1756. */
  1757. // memset assures Clear2 will be NULL for DX5 drivers
  1758. memset(&D3DCallbacks2, 0, D3DHAL_CALLBACKS2SIZE );
  1759. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1760. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1761. &D3DCallbacks2, D3DHAL_CALLBACKS2SIZE,
  1762. &GUID_D3DCallbacks2, pddd,
  1763. FALSE /* bInOut */);
  1764. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1765. // overwrote its buffer.
  1766. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1767. {
  1768. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): Driver overwrote callbacks buffer" );
  1769. goto failed;
  1770. }
  1771. if ( ret == DD_OK )
  1772. {
  1773. // Fail create if driver already failed validation or
  1774. // claims support but it's not valid.
  1775. if (! VALIDEX_D3DCALLBACKS2SIZE (&D3DCallbacks2 ))
  1776. {
  1777. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): size not valid" );
  1778. goto failed;
  1779. }
  1780. if (! ValidateCallbacks(&D3DCallbacks2) )
  1781. {
  1782. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): flags set incorrectly" );
  1783. goto failed;
  1784. }
  1785. if ( (D3DCallbacks2.DrawOnePrimitive ||
  1786. D3DCallbacks2.DrawOneIndexedPrimitive ||
  1787. D3DCallbacks2.DrawPrimitives) &&
  1788. (! (D3DCallbacks2.DrawOnePrimitive &&
  1789. D3DCallbacks2.DrawOneIndexedPrimitive &&
  1790. D3DCallbacks2.DrawPrimitives) ) )
  1791. {
  1792. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): must export all or none of DrawPrimitive callbacks" );
  1793. goto failed;
  1794. }
  1795. #if 0
  1796. if ( D3DCallbacks2.DrawOnePrimitive )
  1797. {
  1798. // If they export DrawPrimitive driver entry points but did
  1799. // not set D3DDEVCAPS_DRAWPRIMTLVERTEX, fail driver create.
  1800. if (! (lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX) )
  1801. {
  1802. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): DrawPrimitive entry points exported" );
  1803. DPF_ERR( "from driver but D3DDEVCAPS_DRAWPRIMTLVERTEX not set" );
  1804. goto failed;
  1805. }
  1806. }
  1807. else
  1808. {
  1809. // If they set the caps but don't export the entry points,
  1810. // fail driver create.
  1811. if (lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX )
  1812. {
  1813. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): D3DDEVCAPS_DRAWPRIMTLVERTEX set" );
  1814. DPF_ERR( "but no DrawPrimitive entry points exported" );
  1815. goto failed;
  1816. }
  1817. }
  1818. #endif
  1819. memcpy((LPVOID) pddd->lpD3DHALCallbacks2, &D3DCallbacks2, D3DHAL_CALLBACKS2SIZE);
  1820. }
  1821. else{
  1822. memset((LPVOID) pddd->lpD3DHALCallbacks2, 0, D3DHAL_CALLBACKS2SIZE );
  1823. }
  1824. /*
  1825. * Probe and validate D3DCallbacks3 support
  1826. */
  1827. memset(&D3DCallbacks3, 0, D3DHAL_CALLBACKS3SIZE );
  1828. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1829. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1830. &D3DCallbacks3, D3DHAL_CALLBACKS3SIZE,
  1831. &GUID_D3DCallbacks3, pddd,
  1832. FALSE /* bInOut */);
  1833. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1834. // overwrote its buffer.
  1835. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1836. {
  1837. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): Driver overwrote callbacks buffer" );
  1838. goto failed;
  1839. }
  1840. if ( ret == DD_OK
  1841. #ifdef WIN95 // currently enforced in win95 to only make PowerVR DX5 driver work
  1842. && (lpDDHALInfo->lpD3DGlobalDriverData &&
  1843. (lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2) )
  1844. #endif //WIN95
  1845. )
  1846. {
  1847. // Fail create if driver already failed validation or
  1848. // claims support but it's not valid.
  1849. if (! VALIDEX_D3DCALLBACKS3SIZE (&D3DCallbacks3 ) ||
  1850. ( gdidata.dwActualSize < D3DHAL_CALLBACKS3SIZE ) )
  1851. {
  1852. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): size not valid" );
  1853. goto failed;
  1854. }
  1855. if (! ValidateCallbacks(&D3DCallbacks3) )
  1856. {
  1857. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): flags set incorrectly" );
  1858. goto failed;
  1859. }
  1860. // DrawPrimitives2, ValidateTextureStageState and are the compulsory
  1861. // DDI in Callbacks3 DX6+ drivers support TextureStages, hence it is
  1862. // reasonable to require them to support ValidateTextureStageState
  1863. if (0 == D3DCallbacks3.DrawPrimitives2)
  1864. {
  1865. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): no DrawPrimitives2 support" );
  1866. goto failed;
  1867. }
  1868. if (0 == D3DCallbacks3.ValidateTextureStageState)
  1869. {
  1870. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): no ValidateTextureStageState support" );
  1871. goto failed;
  1872. }
  1873. #ifdef WIN95
  1874. // Now pass the driver the callback pointer to parse unknown
  1875. // execute-buffer commands.
  1876. // If this call fails then fail creating the driver. We need
  1877. // to be this harsh so that the IHVs are forced to
  1878. // implement this callback!
  1879. memset(&gdidata, 0, sizeof(gdidata) );
  1880. gdidata.dwSize = sizeof(gdidata);
  1881. gdidata.dwFlags = 0;
  1882. gdidata.dwContext = pddd->dwReserved3;
  1883. memcpy(&gdidata.guidInfo, &GUID_D3DParseUnknownCommandCallback, sizeof(GUID_D3DParseUnknownCommandCallback) );
  1884. gdidata.dwExpectedSize = 0;
  1885. gdidata.lpvData = &D3DParseUnknownCommand; // We pass the pointer to function
  1886. gdidata.ddRVal = DDERR_GENERIC;
  1887. ret = lpDDHALInfo->GetDriverInfo(&gdidata);
  1888. if (ret != DDHAL_DRIVER_HANDLED || gdidata.ddRVal != DD_OK)
  1889. {
  1890. // Fail driver creation!
  1891. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3) GUID_D3DParseUnknownCommandCallback not recognized, fail driver creation" );
  1892. goto failed;
  1893. }
  1894. #endif
  1895. memcpy((LPVOID) pddd->lpD3DHALCallbacks3, &D3DCallbacks3, D3DHAL_CALLBACKS3SIZE);
  1896. }
  1897. else{
  1898. if (lpDDHALInfo->lpD3DGlobalDriverData)
  1899. lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps &= ~D3DDEVCAPS_DRAWPRIMITIVES2;
  1900. memset((LPVOID) pddd->lpD3DHALCallbacks3, 0, D3DHAL_CALLBACKS3SIZE );
  1901. }
  1902. #if WIN95
  1903. memset(&pddd->lpDDCBtmp->HALDDKernel, 0, sizeof(DDHAL_DDKERNELCALLBACKS) );
  1904. /* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
  1905. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
  1906. &pddd->lpDDCBtmp->HALDDKernel,
  1907. sizeof(DDHAL_DDKERNELCALLBACKS),
  1908. &GUID_KernelCallbacks, pddd,
  1909. FALSE /* bInOut */);
  1910. // GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
  1911. // overwrote its buffer.
  1912. if ( ret == DDERR_NODIRECTDRAWSUPPORT )
  1913. {
  1914. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Kernel): Driver overwrote callbacks buffer" );
  1915. goto failed;
  1916. }
  1917. if ( ret == DD_OK )
  1918. {
  1919. // Fail create if driver already failed validation or
  1920. // claims support but it's not valid.
  1921. if (! VALIDEX_DDKERNELCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDKernel ) ||
  1922. ( gdidata.dwActualSize < sizeof(DDHAL_DDKERNELCALLBACKS ) ) )
  1923. {
  1924. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Kernel): size not valid" );
  1925. goto failed;
  1926. }
  1927. if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDKernel) )
  1928. {
  1929. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Kernel): flags set incorrectly" );
  1930. goto failed;
  1931. }
  1932. }
  1933. #endif
  1934. /*
  1935. * Get Z Pixel Formats, if driver supports this call.
  1936. * Ideally I'd like to handle this the same as TextureFormats, but
  1937. * D3DHAL_GLOBALDRIVERDATA is unexpandable if old drivers are to work,
  1938. * so must create new guid and graft this query onto callback validation
  1939. */
  1940. {
  1941. DWORD tempbuf[249]; // make this <1K bytes or GetDriverInfo() fails cuz it cant do its "expected size overwrite" test within its own 1K tempbuffer
  1942. // variable size field--delay mallocing space until we know how much is needed.
  1943. // have GetDriverInfo stick results in tempbuf
  1944. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo,
  1945. &gdidata,
  1946. tempbuf,
  1947. sizeof(tempbuf), // "expected" bytesize is 249*4, this allows for 31 DDPIXELFORMATs which should be enough
  1948. &GUID_ZPixelFormats, pddd,
  1949. FALSE /* bInOut */);
  1950. if(ret!=DD_OK)
  1951. {
  1952. // A DX6+ driver (until we radically revamp our DDI) is
  1953. // one that responds to Callbacks3 (with DP2 support)
  1954. // This is a non-issue on NT, since the only DX6+ is
  1955. // available on it.
  1956. // DX6+ drivers have to field this GUID, if they
  1957. // report Clear2 (the DDI for stencil clear). No excuses!!
  1958. if (pddd->lpD3DHALCallbacks3->Clear2)
  1959. {
  1960. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: A DX6+ driver should report its ZPixelFormats");
  1961. goto failed;
  1962. }
  1963. else
  1964. {
  1965. DPF(2,"GetDriverInfo: ZPixelFormats not supported by driver"); // driver is pre-dx6
  1966. pddd->dwNumZPixelFormats=0; pddd->lpZPixelFormats=NULL;
  1967. }
  1968. }
  1969. else
  1970. {
  1971. // verify returned buffer is of an expected size
  1972. if((gdidata.dwActualSize-sizeof(DWORD)) % sizeof(DDPIXELFORMAT) != 0) {
  1973. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Error in driver's ZPixelFormats query: driver returned bad-sized buffer");
  1974. goto failed;
  1975. }
  1976. if((tempbuf[0]*sizeof(DDPIXELFORMAT)+sizeof(DWORD))>sizeof(tempbuf)) {
  1977. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Error: driver returned bogus number of Z Formats: %u",pddd->dwNumZPixelFormats );
  1978. goto failed;
  1979. }
  1980. pddd->dwNumZPixelFormats=tempbuf[0];
  1981. pddd->lpZPixelFormats = MemAlloc(pddd->dwNumZPixelFormats*sizeof(DDPIXELFORMAT));
  1982. if (!pddd->lpZPixelFormats) {
  1983. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Out of memory querying Z Pixel Formats" );
  1984. goto failed;
  1985. }
  1986. memcpy(pddd->lpZPixelFormats,&tempbuf[1],pddd->dwNumZPixelFormats*sizeof(DDPIXELFORMAT));
  1987. #ifdef DEBUG
  1988. // simple validation of pixel format fields
  1989. {
  1990. DWORD ii;
  1991. DPF(5,E,"Number of Z Pixel Formats: %u",pddd->dwNumZPixelFormats);
  1992. for(ii=0;ii<pddd->dwNumZPixelFormats;ii++) {
  1993. DPF(5,E,"DDPF_ZBUFFER: %u, DDPF_STENCILBUFFER: %u",0!=(pddd->lpZPixelFormats[ii].dwFlags&DDPF_ZBUFFER),0!=(pddd->lpZPixelFormats[ii].dwFlags&DDPF_STENCILBUFFER));
  1994. DPF(5,E,"zbits %d, stencilbits %d, zbitmask %X, stencilbitmask %X",pddd->lpZPixelFormats[ii].dwZBufferBitDepth,
  1995. pddd->lpZPixelFormats[ii].dwStencilBitDepth,pddd->lpZPixelFormats[ii].dwZBitMask,pddd->lpZPixelFormats[ii].dwStencilBitMask);
  1996. if(!(pddd->lpZPixelFormats[ii].dwFlags&DDPF_ZBUFFER)) {
  1997. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Error in driver's returned ZPixelFormats: ZBUFFER flag not set");
  1998. goto failed;
  1999. }
  2000. }
  2001. }
  2002. #endif //DEBUG
  2003. }
  2004. }
  2005. DPF(4,E, "Done querying driver for callbacks");
  2006. } // if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERCALLBACKSSET )
  2007. }
  2008. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2009. {
  2010. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Exception encountered validating driver HAL information" );
  2011. DEBUG_BREAK();
  2012. goto failed;
  2013. }
  2014. return TRUE;
  2015. failed:
  2016. MemFree((LPVOID) pddd->lpZPixelFormats);
  2017. pddd->lpZPixelFormats = 0;
  2018. MemFree((LPVOID) pddd->lpD3DHALCallbacks2);
  2019. pddd->lpD3DHALCallbacks2 = 0;
  2020. MemFree((LPVOID) pddd->lpD3DHALCallbacks3);
  2021. pddd->lpD3DHALCallbacks3 = 0;
  2022. #ifdef POSTPONED
  2023. MemFree ((LPVOID) pddd->lpDDUmodeDrvInfo);
  2024. pddd->lpDDUmodeDrvInfo = 0;
  2025. MemFree ((LPVOID) pddd->lpDDOptSurfaceInfo);
  2026. pddd->lpDDOptSurfaceInfo = 0;
  2027. #endif
  2028. return FALSE;
  2029. }
  2030. /*
  2031. * GetExtendedHeapAlignment
  2032. * Call the driver to see if it requires alignment for the given heap.
  2033. * Return a pointer to the filled-in alignment data within the block passed in
  2034. * or NULL if failure or no alignment required.
  2035. */
  2036. LPHEAPALIGNMENT GetExtendedHeapAlignment( LPDDRAWI_DIRECTDRAW_GBL pddd, LPDDHAL_GETHEAPALIGNMENTDATA pghad, int iHeap)
  2037. {
  2038. HRESULT rc;
  2039. LPDDHAL_GETHEAPALIGNMENT ghafn =
  2040. pddd->lpDDCBtmp->HALDDMiscellaneous.GetHeapAlignment;
  2041. DDASSERT(pghad);
  2042. ZeroMemory((LPVOID)pghad,sizeof(*pghad));
  2043. if( ghafn != NULL )
  2044. {
  2045. #ifdef WIN95
  2046. pghad->dwInstance = pddd->dwReserved3;
  2047. #else
  2048. pghad->dwInstance = pddd->hDD;
  2049. #endif
  2050. pghad->dwHeap = (DWORD)iHeap;
  2051. pghad->ddRVal = DDERR_GENERIC;
  2052. pghad->Alignment.dwSize = sizeof(HEAPALIGNMENT);
  2053. DOHALCALL_NOWIN16( GetHeapAlignment , ghafn, (*pghad), rc, FALSE );
  2054. if ( (rc == DDHAL_DRIVER_HANDLED) && (pghad->ddRVal == DD_OK) )
  2055. {
  2056. /*
  2057. * Validate alignment
  2058. */
  2059. if ( pghad->Alignment.ddsCaps.dwCaps & ~DDHAL_ALIGNVALIDCAPS )
  2060. {
  2061. DPF(0,"****DirectDraw driver error****:Invalid alignment caps (at most %08x expected, %08x received) in heap %d",DDHAL_ALIGNVALIDCAPS, pghad->Alignment.ddsCaps.dwCaps,iHeap);
  2062. return NULL;
  2063. }
  2064. /*
  2065. * Turning on this flag means that ComputePitch will ignore the
  2066. * legacy alignment fields in VIDMEMINFO for all heaps, not just
  2067. * iHeap.
  2068. */
  2069. DPF(5,V,"Driver reports extended alignment for heap %d",iHeap);
  2070. pddd->dwFlags |= DDRAWI_EXTENDEDALIGNMENT;
  2071. return & pghad->Alignment;
  2072. }
  2073. }
  2074. return NULL;
  2075. }
  2076. /*
  2077. * Get the non-local video memory blitting capabilities.
  2078. */
  2079. BOOL GetNonLocalVidMemCaps( LPDDHALINFO lpDDHALInfo, LPDDRAWI_DIRECTDRAW_GBL pddd )
  2080. {
  2081. DDASSERT( NULL != lpDDHALInfo );
  2082. DDASSERT( NULL != pddd );
  2083. DDASSERT( NULL == pddd->lpddNLVCaps );
  2084. /*
  2085. * We are forced to treat NLVHELCaps and NLVBothCaps differently. Originally, we were destroying
  2086. * them here and letting a subsequent HELInit intiialize the HELCaps, and initcaps/mergeHELCaps
  2087. * rebuild them. Trouble is, there's no HELInit along the reset code path (resetting a driver
  2088. * object after a mode change). This means we were freeing the hel caps and never refilling them
  2089. * after a mode switch. Since the HEL caps are mode-independent, we can get away with not releasing
  2090. * the NLVHELCaps every mode switch. Now we will simply trust that once allocated, they are always valid.
  2091. * After this routine is called, a subsequent initcaps/mergeHELCaps will regenerate the NLVBothCaps
  2092. * from the driver caps (which may have changed- but we rebuilt them anyway) and the unchanging
  2093. * HEL caps.
  2094. *
  2095. * I am leaving this code here commented out as documentation.
  2096. *
  2097. * if( NULL != pddd->lpddNLVHELCaps )
  2098. * {
  2099. * MemFree( pddd->lpddNLVHELCaps );
  2100. * pddd->lpddNLVHELCaps = NULL;
  2101. * }
  2102. * if( NULL != pddd->lpddNLVBothCaps )
  2103. * {
  2104. * MemFree( pddd->lpddNLVBothCaps );
  2105. * pddd->lpddNLVBothCaps = NULL;
  2106. * }
  2107. */
  2108. if( lpDDHALInfo->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM )
  2109. {
  2110. DDNONLOCALVIDMEMCAPS ddNLVCaps;
  2111. ZeroMemory( &ddNLVCaps, sizeof( ddNLVCaps ) );
  2112. if( lpDDHALInfo->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS )
  2113. {
  2114. HRESULT hres;
  2115. /*
  2116. * The driver has different capabilities for non-local video memory
  2117. * to local video memory blitting. If the driver has a GetDriverInfo
  2118. * entry point defined then query it. If the driver doesn't want to
  2119. * handle the query then just assume it has no non-local video memory
  2120. * capabilities.
  2121. */
  2122. hres = DDERR_GENERIC;
  2123. if( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
  2124. {
  2125. DDHAL_GETDRIVERINFODATA gdiData;
  2126. hres = GetDriverInfo( lpDDHALInfo->GetDriverInfo,
  2127. &gdiData,
  2128. &ddNLVCaps,
  2129. sizeof( DDNONLOCALVIDMEMCAPS ),
  2130. &GUID_NonLocalVidMemCaps,
  2131. pddd,
  2132. FALSE /* bInOut */ );
  2133. if( DD_OK == hres )
  2134. {
  2135. /*
  2136. * We should never get back more data than we asked for.
  2137. */
  2138. DDASSERT( gdiData.dwActualSize <= sizeof( DDNONLOCALVIDMEMCAPS ) );
  2139. /*
  2140. * The driver thinks it worked. Check it has done something sensible.
  2141. */
  2142. if( ( ddNLVCaps.dwSize < ( 2UL * sizeof( DWORD ) ) ) ||
  2143. ( gdiData.dwActualSize < ( 2UL * sizeof( DWORD ) ) ) )
  2144. {
  2145. /*
  2146. * Invalid size returned by the driver. Fail initialization.
  2147. */
  2148. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not initialization. Invalid non-local vidmem caps returned by driver" );
  2149. return FALSE;
  2150. }
  2151. /*
  2152. * We zeroed the structure before passing it to the driver so
  2153. * everything is cool if we got less data than we asked for.
  2154. * Just bump the size up to the expected size.
  2155. */
  2156. ddNLVCaps.dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
  2157. }
  2158. else if ( DDERR_GENERIC != hres )
  2159. {
  2160. /*
  2161. * If we failed for any other reason than generic (which means
  2162. * driver not handled in this scenario) then fail initialization.
  2163. * Things have gone badly wrong.
  2164. */
  2165. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Fatal error when querying for non-local video memory caps" );
  2166. return FALSE;
  2167. }
  2168. }
  2169. if( DDERR_GENERIC == hres )
  2170. {
  2171. /*
  2172. * Driver doesn't have a GetDriverInfo entry point or it does but doesn't
  2173. * want to handle GUID_GetNonLocalVidMemCaps. Assume this means no caps
  2174. * at all. The structure is already zeroed so just set the size.
  2175. */
  2176. ddNLVCaps.dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
  2177. }
  2178. }
  2179. else
  2180. {
  2181. int i;
  2182. /*
  2183. * The driver does not have non-local video memory capabilities which
  2184. * are different from the video ones so just make the non-local case
  2185. * identical to the video memory ones.
  2186. */
  2187. ddNLVCaps.dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
  2188. ddNLVCaps.dwNLVBCaps = lpDDHALInfo->ddCaps.dwCaps;
  2189. ddNLVCaps.dwNLVBCaps2 = lpDDHALInfo->ddCaps.dwCaps2;
  2190. ddNLVCaps.dwNLVBCKeyCaps = lpDDHALInfo->ddCaps.dwCKeyCaps;
  2191. ddNLVCaps.dwNLVBFXCaps = lpDDHALInfo->ddCaps.dwFXCaps;
  2192. for( i = 0; i < DD_ROP_SPACE; i++ )
  2193. ddNLVCaps.dwNLVBRops[i] = lpDDHALInfo->ddCaps.dwRops[i];
  2194. }
  2195. #ifndef WINNT
  2196. /*
  2197. * Memphis: Max AGP is sysmem-12megs, same as VGARTD,
  2198. */
  2199. if ( (dwRegFlags & DDRAW_REGFLAGS_AGPPOLICYMAXBYTES) == 0)
  2200. {
  2201. /*
  2202. * If there's nothing in the registry, figure our own out
  2203. */
  2204. MEMORYSTATUS s = {sizeof(s)};
  2205. GlobalMemoryStatus(&s);
  2206. if (s.dwTotalPhys > 0xc00000)
  2207. dwAGPPolicyMaxBytes = (DWORD)(s.dwTotalPhys - 0xc00000);
  2208. else
  2209. dwAGPPolicyMaxBytes = 0;
  2210. DPF(1,"Max AGP size set to %08x (total phys is %08x)",dwAGPPolicyMaxBytes,s.dwTotalPhys);
  2211. }
  2212. else
  2213. {
  2214. DPF(1,"Max AGP size set to registry value of %08x",dwAGPPolicyMaxBytes);
  2215. }
  2216. #endif
  2217. /*
  2218. * If we got this far we have some valid non-local video memory capabilities so
  2219. * allocate the storage in the driver object to hold them.
  2220. */
  2221. pddd->lpddNLVCaps = (LPDDNONLOCALVIDMEMCAPS)MemAlloc( sizeof( DDNONLOCALVIDMEMCAPS ) );
  2222. if( NULL == pddd->lpddNLVCaps)
  2223. {
  2224. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate non-local video memory capabilities" );
  2225. return FALSE;
  2226. }
  2227. /*
  2228. * If the NLVHELcaps pointer is null, we'll allocate it here.
  2229. */
  2230. if( NULL == pddd->lpddNLVHELCaps)
  2231. pddd->lpddNLVHELCaps = (LPDDNONLOCALVIDMEMCAPS)MemAlloc( sizeof( DDNONLOCALVIDMEMCAPS ) );
  2232. if( NULL == pddd->lpddNLVHELCaps)
  2233. {
  2234. MemFree( pddd->lpddNLVCaps );
  2235. pddd->lpddNLVCaps = NULL;
  2236. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate non-local video memory capabilities" );
  2237. return FALSE;
  2238. }
  2239. /*
  2240. * If the NLVBothCaps pointer is null, we'll allocate it here.
  2241. */
  2242. if( NULL == pddd->lpddNLVBothCaps)
  2243. pddd->lpddNLVBothCaps = (LPDDNONLOCALVIDMEMCAPS)MemAlloc( sizeof( DDNONLOCALVIDMEMCAPS ) );
  2244. if( NULL == pddd->lpddNLVBothCaps)
  2245. {
  2246. MemFree( pddd->lpddNLVCaps );
  2247. pddd->lpddNLVCaps = NULL;
  2248. MemFree( pddd->lpddNLVHELCaps );
  2249. pddd->lpddNLVHELCaps = NULL;
  2250. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate non-local video memory capabilities" );
  2251. return FALSE;
  2252. }
  2253. /*
  2254. * This code is structure so by this point the size of the temporary buffer should
  2255. * be sizeof( DDNONLOCALVIDMEMCAPS )
  2256. */
  2257. DDASSERT( sizeof( DDNONLOCALVIDMEMCAPS ) == ddNLVCaps.dwSize );
  2258. CopyMemory(pddd->lpddNLVCaps, &ddNLVCaps, sizeof( DDNONLOCALVIDMEMCAPS ) );
  2259. /*
  2260. * The HEL caps and the merged caps are zero to start with (they are initialized later).
  2261. * (actually they may not be zero in the reset case: we don't destroy the hel caps
  2262. * on mode changes anymore.)
  2263. */
  2264. pddd->lpddNLVHELCaps->dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
  2265. pddd->lpddNLVBothCaps->dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
  2266. }
  2267. return TRUE;
  2268. } /* GetNonLocalVidMemCaps */
  2269. /*
  2270. * This function is currently only used in NT
  2271. */
  2272. #ifdef WINNT
  2273. BOOL GetDDStereoMode( LPDDRAWI_DIRECTDRAW_GBL pdrv,
  2274. DWORD dwWidth,
  2275. DWORD dwHeight,
  2276. DWORD dwBpp,
  2277. DWORD dwRefreshRate)
  2278. {
  2279. DDHAL_GETDRIVERINFODATA gdidata;
  2280. HRESULT hres;
  2281. DDSTEREOMODE ddStereoMode;
  2282. DDASSERT( pdrv != NULL );
  2283. /*
  2284. * If driver does not support GetDriverInfo callback, it also
  2285. * has no extended capabilities to report, so we're done.
  2286. */
  2287. if( !VALIDEX_CODE_PTR (pdrv->pGetDriverInfo) )
  2288. {
  2289. return FALSE;
  2290. }
  2291. /*
  2292. * The mode can't be stereo if the driver doesn't support it...
  2293. */
  2294. if (0 == (pdrv->ddCaps.dwCaps2 & DDCAPS2_STEREO))
  2295. {
  2296. return FALSE;
  2297. }
  2298. ZeroMemory( &ddStereoMode, sizeof(DDSTEREOMODE));
  2299. ddStereoMode.dwSize=sizeof(DDSTEREOMODE);
  2300. ddStereoMode.dwWidth=dwWidth;
  2301. ddStereoMode.dwHeight=dwHeight;
  2302. ddStereoMode.dwBpp=dwBpp;
  2303. ddStereoMode.dwRefreshRate=dwRefreshRate;
  2304. ddStereoMode.bSupported = TRUE;
  2305. /*
  2306. * Get the actual driver data
  2307. */
  2308. memset(&gdidata, 0, sizeof(gdidata) );
  2309. gdidata.dwSize = sizeof(gdidata);
  2310. gdidata.dwFlags = 0;
  2311. gdidata.guidInfo = GUID_DDStereoMode;
  2312. gdidata.dwExpectedSize = sizeof(DDSTEREOMODE);
  2313. gdidata.lpvData = &ddStereoMode;
  2314. gdidata.ddRVal = DDERR_GENERIC;
  2315. // Pass a context variable so that the driver
  2316. // knows which instance of itself to use
  2317. // w.r.t. this function. These are different
  2318. // values on Win95 and NT.
  2319. #ifdef WIN95
  2320. gdidata.dwContext = pdrv->dwReserved3;
  2321. #else
  2322. gdidata.dwContext = pdrv->hDD;
  2323. #endif
  2324. if ( pdrv->pGetDriverInfo(&gdidata) == DDHAL_DRIVER_HANDLED)
  2325. {
  2326. // GUID_DDStereoMode is a way to turn OFF stereo per-mode, since
  2327. // it is expected that a driver that can do stereo can do stereo in
  2328. // any mode.
  2329. if( gdidata.ddRVal == DD_OK )
  2330. {
  2331. return ddStereoMode.bSupported;
  2332. }
  2333. }
  2334. return TRUE;
  2335. } /* GetDDStereoMode */
  2336. #endif //WINNT
  2337. BOOL GetDDMoreSurfaceCaps( LPDDHALINFO lpDDHALInfo, LPDDRAWI_DIRECTDRAW_GBL pdrv )
  2338. {
  2339. DDHAL_GETDRIVERINFODATA gdiData;
  2340. HRESULT hres;
  2341. DWORD dwSize;
  2342. LPDDMORESURFACECAPS lpddMoreSurfaceCaps=NULL;
  2343. BOOL retval=TRUE;
  2344. DWORD heap;
  2345. DDASSERT( lpDDHALInfo != NULL );
  2346. DDASSERT( pdrv != NULL );
  2347. /*
  2348. * If driver does not support GetDriverInfo callback, it also
  2349. * has no extended capabilities to report, so we're done.
  2350. */
  2351. if( !(lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET) )
  2352. {
  2353. goto Succeeded;
  2354. }
  2355. /*
  2356. * The size of DDMORESURFACECAPS is variable.
  2357. * We have to do this calculation signed, since dwNumHeaps might be zero, in which case we need
  2358. * to subtract some from sizeof DDMORESURFACECAPS.
  2359. */
  2360. dwSize = (DWORD) (sizeof(DDMORESURFACECAPS) + (((signed int)pdrv->vmiData.dwNumHeaps)-1) * sizeof(DDSCAPSEX)*2 );
  2361. /*
  2362. * Allocate some temporary space.
  2363. * The caps bits will go into the pdrv, and the extended heap restrictions will go into
  2364. * the VMEMHEAP structs off of pdrv->vmiData->pvmList->lpHeap
  2365. */
  2366. lpddMoreSurfaceCaps = (LPDDMORESURFACECAPS)MemAlloc( dwSize );
  2367. if (lpddMoreSurfaceCaps == NULL)
  2368. {
  2369. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate extended surface capabilities" );
  2370. goto Failed;
  2371. }
  2372. ZeroMemory( lpddMoreSurfaceCaps , dwSize);
  2373. /*
  2374. * Get the actual driver data
  2375. */
  2376. hres = GetDriverInfo( lpDDHALInfo->GetDriverInfo,
  2377. &gdiData,
  2378. lpddMoreSurfaceCaps,
  2379. dwSize,
  2380. &GUID_DDMoreSurfaceCaps,
  2381. pdrv,
  2382. FALSE /* bInOut */ );
  2383. if( hres != DD_OK )
  2384. {
  2385. goto Succeeded;
  2386. }
  2387. /*
  2388. * We should never get back more data than we asked for. If we
  2389. * do, that probably means the driver version is newer than the
  2390. * DirectDraw runtime version. In that case, we just fail.
  2391. */
  2392. if( gdiData.dwActualSize > dwSize )
  2393. {
  2394. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Driver gives too big a size for DDMORESURFACECAPS. Check the dwSize calculation." );
  2395. goto Failed;
  2396. }
  2397. /*
  2398. * The surface caps go into the pdrv:
  2399. */
  2400. pdrv->ddsCapsMore = lpddMoreSurfaceCaps->ddsCapsMore;
  2401. if (pdrv->vmiData.dwNumHeaps == 0)
  2402. {
  2403. /*
  2404. * No heaps means we are done
  2405. */
  2406. goto Succeeded;
  2407. }
  2408. DDASSERT(NULL != pdrv->vmiData.pvmList);
  2409. for (heap = 0; heap < pdrv->vmiData.dwNumHeaps; heap ++ )
  2410. {
  2411. LPVMEMHEAP lpHeap = pdrv->vmiData.pvmList[heap].lpHeap;
  2412. /*
  2413. * A quick sanity check. If we have nonzero dwNumHeaps, then we better have
  2414. * a heap descriptor pointer. This also saves us if someone rearranges the caller of this
  2415. * routine so that the vidmeminit calls have not yet been made.
  2416. */
  2417. if (!lpHeap)
  2418. {
  2419. DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Rearrange this call to GetDDMoreSurfaceCaps so it comes after vidmeminit");
  2420. goto Failed;
  2421. }
  2422. lpHeap->ddsCapsEx = lpddMoreSurfaceCaps->ddsExtendedHeapRestrictions[heap].ddsCapsEx;
  2423. lpHeap->ddsCapsExAlt = lpddMoreSurfaceCaps->ddsExtendedHeapRestrictions[heap].ddsCapsExAlt;
  2424. }
  2425. Succeeded:
  2426. retval = TRUE;
  2427. goto Exit;
  2428. Failed:
  2429. retval = FALSE;
  2430. Exit:
  2431. MemFree(lpddMoreSurfaceCaps);
  2432. return retval;
  2433. } /* GetDDMoreSurfaceCaps */
  2434. /*
  2435. * Interrogate the driver to get more driver capabilities, as specified in
  2436. * the DDMORECAPS structure. These caps augment those specified by the
  2437. * driver in the DDHALINFO structure. Return TRUE if the call succeeds,
  2438. * or FALSE if an error condition is detected. If the call succeeds, the
  2439. * function ensures that storage is allocated for all of the DirectDraw
  2440. * object's additional caps.
  2441. */
  2442. BOOL GetDDMoreCaps( LPDDHALINFO lpDDHALInfo, LPDDRAWI_DIRECTDRAW_GBL pdrv )
  2443. {
  2444. DDMORECAPS ddMoreCaps;
  2445. DDHAL_GETDRIVERINFODATA gdiData;
  2446. HRESULT hres;
  2447. DDASSERT( lpDDHALInfo != NULL );
  2448. DDASSERT( pdrv != NULL );
  2449. /*
  2450. * Make sure memory is allocated and initialized for the driver's
  2451. * lpddMoreCaps, lpddHELMoreCaps, and lpddBothMoreCaps pointers.
  2452. */
  2453. if (pdrv->lpddMoreCaps == NULL) // hardware caps
  2454. {
  2455. pdrv->lpddMoreCaps = (LPDDMORECAPS)MemAlloc( sizeof( DDMORECAPS ) );
  2456. if (pdrv->lpddMoreCaps == NULL)
  2457. {
  2458. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate extended capabilities" );
  2459. return FALSE;
  2460. }
  2461. }
  2462. ZeroMemory( pdrv->lpddMoreCaps, sizeof(DDMORECAPS) );
  2463. pdrv->lpddMoreCaps->dwSize = sizeof( DDMORECAPS );
  2464. if (pdrv->lpddHELMoreCaps == NULL) // HEL caps
  2465. {
  2466. pdrv->lpddHELMoreCaps = (LPDDMORECAPS)MemAlloc( sizeof( DDMORECAPS ) );
  2467. if (pdrv->lpddHELMoreCaps == NULL)
  2468. {
  2469. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate extended capabilities" );
  2470. return FALSE;
  2471. }
  2472. ZeroMemory( pdrv->lpddHELMoreCaps, sizeof(DDMORECAPS) );
  2473. pdrv->lpddHELMoreCaps->dwSize = sizeof( DDMORECAPS );
  2474. }
  2475. if (pdrv->lpddBothMoreCaps == NULL) // bitwise AND of hardware and HEL caps
  2476. {
  2477. pdrv->lpddBothMoreCaps = (LPDDMORECAPS)MemAlloc( sizeof( DDMORECAPS ) );
  2478. if (pdrv->lpddBothMoreCaps == NULL)
  2479. {
  2480. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate extended capabilities" );
  2481. return FALSE;
  2482. }
  2483. }
  2484. ZeroMemory( pdrv->lpddBothMoreCaps, sizeof(DDMORECAPS) );
  2485. pdrv->lpddBothMoreCaps->dwSize = sizeof( DDMORECAPS );
  2486. /*
  2487. * If driver does not support GetDriverInfo callback, it also
  2488. * has no extended capabilities to report, so we're done.
  2489. */
  2490. if( !(lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET) )
  2491. {
  2492. return TRUE; // no extended capabilities to report
  2493. }
  2494. #if 0
  2495. /*
  2496. * Get the extended capabilities from the driver.
  2497. */
  2498. ZeroMemory( &ddMoreCaps, sizeof( DDMORECAPS ) );
  2499. hres = GetDriverInfo( lpDDHALInfo->GetDriverInfo,
  2500. &gdiData,
  2501. &ddMoreCaps,
  2502. sizeof( DDMORECAPS ),
  2503. &GUID_DDMoreCaps,
  2504. pdrv );
  2505. if( hres != DD_OK )
  2506. {
  2507. return TRUE; // no extended capabilities to report
  2508. }
  2509. /*
  2510. * We should never get back more data than we asked for. If we
  2511. * do, that probably means the driver version is newer than the
  2512. * DirectDraw runtime version. In that case, we just fail.
  2513. */
  2514. if( gdiData.dwActualSize > sizeof( DDMORECAPS ) )
  2515. {
  2516. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Driver gives too big a size for DDMORECAPS" );
  2517. return FALSE; // error
  2518. }
  2519. /*
  2520. * We zeroed the structure before passing it to the driver so
  2521. * everything is cool if we got less data than we asked for.
  2522. * Just bump the size up to the expected size.
  2523. */
  2524. ddMoreCaps.dwSize = sizeof( DDMORECAPS );
  2525. /*
  2526. * Store the hardware driver's extended caps in the global DirectDraw object.
  2527. */
  2528. CopyMemory(pdrv->lpddMoreCaps, &ddMoreCaps, sizeof( DDMORECAPS ) );
  2529. #endif
  2530. return TRUE;
  2531. } /* GetDDMoreCaps */
  2532. /*
  2533. * DirectDrawObjectCreate
  2534. *
  2535. * Create a DIRECTDRAW object.
  2536. */
  2537. LPDDRAWI_DIRECTDRAW_GBL DirectDrawObjectCreate(
  2538. LPDDHALINFO lpDDHALInfo,
  2539. BOOL reset,
  2540. LPDDRAWI_DIRECTDRAW_GBL oldpdd,
  2541. HANDLE hDDVxd,
  2542. char *szDrvName,
  2543. DWORD dwDriverContext,
  2544. DWORD dwLocalFlags )
  2545. {
  2546. LPDDRAWI_DIRECTDRAW_GBL pddd=NULL;
  2547. int drv_size;
  2548. int drv_callbacks_size;
  2549. int size;
  2550. LPVIDMEM pvm;
  2551. int i;
  2552. int j;
  2553. int devheapno;
  2554. int numcb;
  2555. LPDDHAL_DDCALLBACKS drvcb;
  2556. LPDDHAL_DDSURFACECALLBACKS surfcb;
  2557. LPDDHAL_DDPALETTECALLBACKS palcb;
  2558. LPDDHAL_DDEXEBUFCALLBACKS exebufcb;
  2559. DWORD bit;
  2560. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  2561. DWORD freevm;
  2562. BOOL isagpaware;
  2563. #ifdef WIN95
  2564. DWORD ptr16;
  2565. #endif
  2566. #ifdef WINNT
  2567. /*
  2568. * Need somewhere to put the callback fn ptrs given to us by the NT driver...
  2569. */
  2570. DDHAL_DDCALLBACKS ddNTHALDD;
  2571. DDHAL_DDSURFACECALLBACKS ddNTHALDDSurface;
  2572. DDHAL_DDPALETTECALLBACKS ddNTHALDDPalette;
  2573. D3DHAL_CALLBACKS d3dNTHALCallbacks;
  2574. D3DHAL_CALLBACKS *pd3dNTHALCallbacks=0;
  2575. D3DHAL_GLOBALDRIVERDATA d3dNTHALDriverData;
  2576. D3DHAL_GLOBALDRIVERDATA *pd3dNTHALDriverData;
  2577. LPDDSURFACEDESC pddsdD3dTextureFormats;
  2578. DDHAL_DDEXEBUFCALLBACKS ddNTHALBufferCallbacks;
  2579. LPDDHAL_DDEXEBUFCALLBACKS pddNTHALBufferCallbacks;
  2580. BOOL ismemalloced=FALSE;
  2581. #endif
  2582. ENTER_DDRAW();
  2583. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  2584. DPF( 4, "DirectDrawObjectCreate: oldpdd == 0x%p, reset = %d", oldpdd, reset );
  2585. DDASSERT( (oldpdd == NULL) == (reset==FALSE) );
  2586. /*
  2587. * make sure the driver isn't trying to lie to us about the old object
  2588. * This check should always be made at the top of this routine, since it's
  2589. * possible in stress scenarios for ddhelp's modeset thread to wake up
  2590. * just before it's killed at the end of DD_Release (since the code to kill
  2591. * the mode set thread is executed AFTER the last LEAVE_DDRAW in DD_Release).
  2592. */
  2593. DPF( 5, "DIRECTDRAW object passed in = 0x%p", oldpdd );
  2594. if( oldpdd != NULL )
  2595. {
  2596. pdrv_lcl = lpDriverLocalList;
  2597. while( pdrv_lcl != NULL )
  2598. {
  2599. if( pdrv_lcl->lpGbl == oldpdd )
  2600. {
  2601. break;
  2602. }
  2603. pdrv_lcl = pdrv_lcl->lpLink;
  2604. }
  2605. if( pdrv_lcl == NULL )
  2606. {
  2607. DPF_ERR( "REUSED DRIVER OBJECT SPECIFIED, BUT NOT IN LIST" );
  2608. DDASSERT(FALSE);
  2609. goto ErrorExit;
  2610. }
  2611. }
  2612. // If a null driver name is passed in then use the one
  2613. // in the oldpdd passed in. We need one or the other!
  2614. if( szDrvName == NULL )
  2615. {
  2616. if( oldpdd == NULL )
  2617. {
  2618. DPF_ERR( "DDrawObjectCreate: oldpdd == NULL && szDrvName == NULL" );
  2619. DDASSERT( 0 );
  2620. goto ErrorExit;
  2621. }
  2622. szDrvName = oldpdd->cDriverName;
  2623. }
  2624. #ifdef USE_ALIAS
  2625. if( NULL != oldpdd )
  2626. {
  2627. /*
  2628. * The absolutely first thing we want to do is to check to see if there are
  2629. * any outstanding video memory locks and if there are we need to remap
  2630. * the aliased to dummy memory to ensure we don't write over memory we don't
  2631. * own or to memory that does not exist.
  2632. */
  2633. if( ( NULL != oldpdd->phaiHeapAliases ) && ( oldpdd->phaiHeapAliases->dwRefCnt > 1UL ) )
  2634. {
  2635. DDASSERT( INVALID_HANDLE_VALUE != hDDVxd );
  2636. if( FAILED( MapHeapAliasesToDummyMem( hDDVxd, oldpdd->phaiHeapAliases ) ) )
  2637. {
  2638. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not map existing video memory aliases to dummy memory" );
  2639. goto ErrorExit;
  2640. }
  2641. }
  2642. }
  2643. #endif /* USE_ALIAS */
  2644. /*
  2645. * Is this OS AGP aware?
  2646. *
  2647. * NOTE: VXD handle is only necessary on Win95. On NT, hDDVxd will simply
  2648. * be NULL and be unused by this function.
  2649. */
  2650. #ifdef WINNT
  2651. isagpaware = TRUE;
  2652. #else
  2653. isagpaware = OSIsAGPAware( hDDVxd );
  2654. if( !isagpaware )
  2655. {
  2656. if( dwRegFlags & DDRAW_REGFLAGS_FORCEAGPSUPPORT )
  2657. {
  2658. /*
  2659. * Pretend the OS is AGP aware for debugging purposes.
  2660. */
  2661. DPF( 1, "Force enabling AGP support for debugging purposes" );
  2662. isagpaware = TRUE;
  2663. }
  2664. }
  2665. #endif //not WINNT
  2666. if( dwRegFlags & DDRAW_REGFLAGS_DISABLEAGPSUPPORT )
  2667. {
  2668. /*
  2669. * Pretend the OS is not AGP aware.
  2670. */
  2671. DPF( 1, "Disabling APG support for debugging purposes" );
  2672. isagpaware = FALSE;
  2673. }
  2674. /*
  2675. * Under NT, we're forced to create a direct draw global object before we can
  2676. * query the driver for its ddhalinfo.
  2677. * Consequently, we validate the incoming ddhalinfo pointer first in its very
  2678. * own try-except block, then allocate the global structure, then (on NT only)
  2679. * call the driver to register the global object and get its halinfo.
  2680. * (Under win95, the halinfo will have been filled in by the caller) jeffno 960116
  2681. */
  2682. /*
  2683. * initialize a new driver object if we don't have one already
  2684. */
  2685. if( (oldpdd == NULL) || reset )
  2686. {
  2687. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  2688. DPF( 4, "oldpdd == 0x%p, reset = %d", oldpdd, reset );
  2689. /*
  2690. * Allocate memory for the global object.
  2691. * We also allocate a DDHAL_CALLBACKS structure with the global
  2692. * object. This structure is used to hold the single copy of
  2693. * the HAL function table under Win95 and it is used as
  2694. * temporary storage of the function table under NT
  2695. */
  2696. drv_size = sizeof( DDRAWI_DIRECTDRAW_GBL );
  2697. drv_callbacks_size = drv_size + sizeof( DDHAL_CALLBACKS );
  2698. #ifdef WIN95
  2699. pddd = (LPDDRAWI_DIRECTDRAW_GBL) MemAlloc16( drv_callbacks_size, &ptr16 );
  2700. #else
  2701. pddd = (LPDDRAWI_DIRECTDRAW_GBL) MemAlloc( drv_callbacks_size );
  2702. #endif
  2703. DPF( 5,"Driver Object: %ld base bytes", drv_callbacks_size );
  2704. if( pddd == NULL )
  2705. {
  2706. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not allocate space for driver object" );
  2707. goto ErrorExit;
  2708. }
  2709. #ifdef WIN95
  2710. // Store the value returned by the 32-bit driver
  2711. // into the pdrv; this allows the 32-bit driver to remember
  2712. // any state it needs to for all future calls to it. This
  2713. // was added for multi-monitor support. <kd>
  2714. if( oldpdd )
  2715. pddd->dwReserved3= oldpdd->dwReserved3;
  2716. else
  2717. pddd->dwReserved3 = dwDriverContext;
  2718. DPF( 5, "dwReserved3 of DDrawGbl is set to 0x%x", pddd->dwReserved3 );
  2719. // Initialize value of global DDRAW.VXD handle to INVALID_HANDLE_VALUE.
  2720. // This should always normally be INVALID_HANDLE_VALUE, unless if we
  2721. // are in the middle of a createSurface() call.
  2722. pddd->hDDVxd = (DWORD) INVALID_HANDLE_VALUE;
  2723. DPF( 6, "hDDVxd of DDrawGbl is set to INVALID_HANDLE_VALUE - 0x%p", pddd->hDDVxd );
  2724. #else
  2725. /*
  2726. * In the reset code path, this per-process hDD will have been stuffed into
  2727. * the oldpdd by FetchDirectDrawData.
  2728. */
  2729. if (reset)
  2730. {
  2731. DDASSERT(oldpdd);
  2732. pddd->hDD = oldpdd->hDD;
  2733. }
  2734. #endif WIN95
  2735. pddd->lpDDCBtmp = (LPDDHAL_CALLBACKS)(((LPSTR) pddd) + drv_size );
  2736. #ifdef WINNT
  2737. pddd->SurfaceHandleList.dwList=NULL;
  2738. pddd->SurfaceHandleList.dwFreeList=0;
  2739. if (lpDDHALInfo && !(lpDDHALInfo->ddCaps.dwCaps & DDCAPS_NOHARDWARE))
  2740. {
  2741. HDC hDC;
  2742. BOOL bNewMode;
  2743. BOOL bRetVal;
  2744. /*
  2745. * Now that we have a ddraw GBL structure available, we can tell
  2746. * the driver about it...
  2747. */
  2748. DPF(5,K,"WinNT driver conversation started");
  2749. if (!reset)
  2750. {
  2751. hDC = DD_CreateDC( szDrvName ); // create temporary DC
  2752. if (!hDC)
  2753. {
  2754. DPF(0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Unable to create temporary DC for driver");
  2755. goto ErrorExit;
  2756. }
  2757. bRetVal = DdCreateDirectDrawObject(pddd, hDC);
  2758. DD_DoneDC(hDC); // delete temporary DC
  2759. if (!bRetVal)
  2760. {
  2761. /*
  2762. * this means we're in emulation
  2763. */
  2764. DPF(0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:NT Kernel mode would not create driver object... Failing over to emulation");
  2765. goto ErrorExit;
  2766. }
  2767. }
  2768. /*
  2769. * Now we can get the driver info...
  2770. * The first call to this routine lets us know how much space to
  2771. * reserve for the fourcc and vidmem lists
  2772. */
  2773. if (!DdReenableDirectDrawObject(pddd,&bNewMode) ||
  2774. !DdQueryDirectDrawObject(pddd,
  2775. lpDDHALInfo,
  2776. &ddNTHALDD,
  2777. &ddNTHALDDSurface,
  2778. &ddNTHALDDPalette,
  2779. &d3dNTHALCallbacks,
  2780. &d3dNTHALDriverData,
  2781. &ddNTHALBufferCallbacks,
  2782. NULL,
  2783. NULL,
  2784. NULL))
  2785. {
  2786. DPF(1, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:First call to DdQueryDirectDrawObject failed!");
  2787. goto ErrorExit;
  2788. }
  2789. /*
  2790. * The second call allows the driver to fill in the fourcc and
  2791. * vidmem lists. First we make space for them.
  2792. */
  2793. lpDDHALInfo->vmiData.pvmList = MemAlloc(lpDDHALInfo->vmiData.dwNumHeaps * sizeof(VIDMEM));
  2794. if (NULL == lpDDHALInfo->vmiData.pvmList)
  2795. {
  2796. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No RAM for pvmList");
  2797. goto ErrorExit;
  2798. }
  2799. lpDDHALInfo->lpdwFourCC = MemAlloc(lpDDHALInfo->ddCaps.dwNumFourCCCodes * sizeof(DWORD));
  2800. if (NULL == lpDDHALInfo->lpdwFourCC)
  2801. {
  2802. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No RAM for FourCC List");
  2803. goto ErrorExit;
  2804. }
  2805. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  2806. DPF(5, K, "numheaps = %d, numfourcc = %d", lpDDHALInfo->vmiData.dwNumHeaps, lpDDHALInfo->ddCaps.dwNumFourCCCodes);
  2807. DPF(5, K, "ptrs: 0x%p, 0x%p", lpDDHALInfo->lpdwFourCC, lpDDHALInfo->vmiData.pvmList);
  2808. // If Direct3D information was returned, allocate space for
  2809. // the real information to be stored in and for the
  2810. // appropriate number of texture formats
  2811. if (d3dNTHALCallbacks.dwSize > 0 &&
  2812. d3dNTHALDriverData.dwSize > 0)
  2813. {
  2814. // We need to allocate space for the d3dhalcallbacks etc. only once,
  2815. // since d3d caches them across mode changes.
  2816. // We are allowed to reallocate the texture format list, since d3d only
  2817. // caches a pointer to D3DHAL_GLOBALDRIVERDATA, which is where the pointer
  2818. // to the texture formats is kept.
  2819. if ( NULL == oldpdd || NULL == oldpdd->lpD3DHALCallbacks )
  2820. {
  2821. pddd->lpD3DHALCallbacks = pd3dNTHALCallbacks =
  2822. (LPD3DHAL_CALLBACKS) MemAlloc(sizeof(D3DHAL_CALLBACKS)+
  2823. sizeof(D3DHAL_GLOBALDRIVERDATA)+
  2824. sizeof(DDHAL_DDEXEBUFCALLBACKS));
  2825. // Mark memory allocated in this path (not get from old one)
  2826. // so that we can free this memory if error occur later.
  2827. ismemalloced = TRUE;
  2828. }
  2829. else
  2830. pddd->lpD3DHALCallbacks = pd3dNTHALCallbacks = oldpdd->lpD3DHALCallbacks;
  2831. if (pd3dNTHALCallbacks == NULL)
  2832. {
  2833. DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****:D3D memory allocation failed!");
  2834. goto ErrorExit;
  2835. }
  2836. pd3dNTHALDriverData = (LPD3DHAL_GLOBALDRIVERDATA)
  2837. (pd3dNTHALCallbacks+1);
  2838. pddNTHALBufferCallbacks = (LPDDHAL_DDEXEBUFCALLBACKS)
  2839. (pd3dNTHALDriverData+1);
  2840. // free old texture list and allocate a new one.
  2841. MemFree(pd3dNTHALDriverData->lpTextureFormats);
  2842. pddsdD3dTextureFormats = pd3dNTHALDriverData->lpTextureFormats =
  2843. MemAlloc(sizeof(DDSURFACEDESC) * d3dNTHALDriverData.dwNumTextureFormats);
  2844. // WOW64: include the number of textures in the driver data so that WOW64 can
  2845. // thunk the texture formats
  2846. pd3dNTHALDriverData->dwNumTextureFormats = d3dNTHALDriverData.dwNumTextureFormats;
  2847. }
  2848. else
  2849. {
  2850. pd3dNTHALCallbacks = NULL;
  2851. pd3dNTHALDriverData = NULL;
  2852. pddNTHALBufferCallbacks = NULL;
  2853. pddsdD3dTextureFormats = NULL;
  2854. }
  2855. if (!DdQueryDirectDrawObject(pddd,
  2856. lpDDHALInfo,
  2857. &ddNTHALDD,
  2858. &ddNTHALDDSurface,
  2859. &ddNTHALDDPalette,
  2860. pd3dNTHALCallbacks,
  2861. pd3dNTHALDriverData,
  2862. pddNTHALBufferCallbacks,
  2863. pddsdD3dTextureFormats,
  2864. lpDDHALInfo->lpdwFourCC,
  2865. lpDDHALInfo->vmiData.pvmList))
  2866. {
  2867. DPF(1, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Third call to DdQueryDirectDrawObject failed!");
  2868. goto ErrorExit;
  2869. }
  2870. #ifdef DEBUG
  2871. {
  2872. int i;
  2873. DPF(5,K,"NT driver video ram data as reported by driver:");
  2874. DPF(5,K," VIDMEMINFO.fpPrimary =%08x",lpDDHALInfo->vmiData.fpPrimary);
  2875. DPF(5,K," VIDMEMINFO.dwFlags =%08x",lpDDHALInfo->vmiData.dwFlags);
  2876. DPF(5,K," VIDMEMINFO.dwDisplayWidth =%08x",lpDDHALInfo->vmiData.dwDisplayWidth);
  2877. DPF(5,K," VIDMEMINFO.dwDisplayHeight =%08x",lpDDHALInfo->vmiData.dwDisplayHeight);
  2878. DPF(5,K," VIDMEMINFO.lDisplayPitch =%08x",lpDDHALInfo->vmiData.lDisplayPitch);
  2879. DPF(5,K," VIDMEMINFO.dwOffscreenAlign =%08x",lpDDHALInfo->vmiData.dwOffscreenAlign);
  2880. DPF(5,K," VIDMEMINFO.dwOverlayAlign =%08x",lpDDHALInfo->vmiData.dwOverlayAlign);
  2881. DPF(5,K," VIDMEMINFO.dwTextureAlign =%08x",lpDDHALInfo->vmiData.dwTextureAlign);
  2882. DPF(5,K," VIDMEMINFO.dwZBufferAlign =%08x",lpDDHALInfo->vmiData.dwZBufferAlign);
  2883. DPF(5,K," VIDMEMINFO.dwAlphaAlign =%08x",lpDDHALInfo->vmiData.dwAlphaAlign);
  2884. DPF(5,K," VIDMEMINFO.dwNumHeaps =%08x",lpDDHALInfo->vmiData.dwNumHeaps);
  2885. DPF(5,K," VIDMEMINFO.ddpfDisplay.dwSize =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwSize);
  2886. DPF(5,K," VIDMEMINFO.ddpfDisplay.dwFlags =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwFlags);
  2887. DPF(5,K," VIDMEMINFO.ddpfDisplay.dwFourCC =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwFourCC);
  2888. DPF(5,K," VIDMEMINFO.ddpfDisplay.dwRGBBitCount =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwRGBBitCount);
  2889. DPF(5,K," VIDMEMINFO.ddpfDisplay.dwRBitMask =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwRBitMask);
  2890. DPF(5,K," VIDMEMINFO.ddpfDisplay.dwGBitMask =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwGBitMask);
  2891. DPF(5,K," VIDMEMINFO.ddpfDisplay.dwBBitMask =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwBBitMask);
  2892. DPF(5,K," VIDMEMINFO.ddpfDisplay.dwRGBAlphaBitMask =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwRGBAlphaBitMask);
  2893. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  2894. DPF(5, K, " Vidmem list ptr is 0x%p", lpDDHALInfo->vmiData.pvmList);
  2895. for (i=0;i<(int) lpDDHALInfo->vmiData.dwNumHeaps;i++)
  2896. {
  2897. DPF(5, K, " heap flags: %03x", lpDDHALInfo->vmiData.pvmList[i].dwFlags);
  2898. DPF(5, K, " Start of chunk: 0x%p", lpDDHALInfo->vmiData.pvmList[i].fpStart);
  2899. DPF(5, K, " End of chunk: 0x%p", lpDDHALInfo->vmiData.pvmList[i].fpEnd);
  2900. }
  2901. }
  2902. #endif
  2903. lpDDHALInfo->lpDDCallbacks = &ddNTHALDD;
  2904. lpDDHALInfo->lpDDSurfaceCallbacks = &ddNTHALDDSurface;
  2905. lpDDHALInfo->lpDDPaletteCallbacks = &ddNTHALDDPalette;
  2906. ddNTHALBufferCallbacks.dwSize =sizeof ddNTHALBufferCallbacks; //since kernel is busted
  2907. ddNTHALBufferCallbacks.dwFlags =
  2908. DDHAL_EXEBUFCB32_CANCREATEEXEBUF|
  2909. DDHAL_EXEBUFCB32_CREATEEXEBUF |
  2910. DDHAL_EXEBUFCB32_DESTROYEXEBUF |
  2911. DDHAL_EXEBUFCB32_LOCKEXEBUF |
  2912. DDHAL_EXEBUFCB32_UNLOCKEXEBUF ;
  2913. lpDDHALInfo->lpDDExeBufCallbacks = &ddNTHALBufferCallbacks;
  2914. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  2915. DPF(5, K, "Surface callback as reported by Kernel is 0x%p", lpDDHALInfo->lpDDCallbacks->CreateSurface);
  2916. }
  2917. else
  2918. {
  2919. /*
  2920. * Normally, we specify a null DC handle to register our fake
  2921. * DDraw driver, but with secondary monitors we need to specify
  2922. * a device DC or else things fall apart.
  2923. */
  2924. HDC hdcTemp = NULL;
  2925. if( ( _stricmp( szDrvName, DISPLAY_STR ) != 0 ) &&
  2926. ( _stricmp( szDrvName, g_szPrimaryDisplay ) != 0 ) &&
  2927. IsMultiMonitor() &&
  2928. ( ( szDrvName[0] == '\\' ) &&
  2929. ( szDrvName[1] == '\\' ) &&
  2930. ( szDrvName[2] == '.') ) )
  2931. {
  2932. hdcTemp = DD_CreateDC( szDrvName ); // create temporary DC
  2933. }
  2934. if (!DdCreateDirectDrawObject(pddd, hdcTemp))
  2935. {
  2936. DPF(1, "NT Kernel mode would not create fake DD driver object");
  2937. goto ErrorExit;
  2938. }
  2939. if( hdcTemp != NULL )
  2940. {
  2941. DD_DoneDC(hdcTemp); // delete temporary DC
  2942. }
  2943. }
  2944. if (!GetCurrentMode(oldpdd, lpDDHALInfo, szDrvName))
  2945. {
  2946. DPF(0, "Could not get current mode information");
  2947. goto ErrorExit;
  2948. }
  2949. if (oldpdd && oldpdd->lpModeInfo)
  2950. {
  2951. DDASSERT(oldpdd->lpModeInfo == &oldpdd->ModeInfo);
  2952. memcpy(&oldpdd->ModeInfo, lpDDHALInfo->lpModeInfo, sizeof (DDHALMODEINFO));
  2953. }
  2954. #endif //WINNT
  2955. } //end if oldpdd==NULL || reset
  2956. if( !ValidateCoreHALInfo( lpDDHALInfo ) )
  2957. {
  2958. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Exception encountered validating driver parameters" );
  2959. goto ErrorExit;
  2960. }
  2961. // We only want to get new HALInfo if we haven't already
  2962. // done this. The oldpdd == NULL check implies that we are
  2963. // building a driver from scratch.
  2964. if( (oldpdd == NULL) && pddd && !GetAndValidateNewHALInfo( pddd, lpDDHALInfo ) )
  2965. {
  2966. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Exception encountered querying for optional driver parameters" );
  2967. goto ErrorExit;
  2968. }
  2969. /*
  2970. * reset specified without a driver object existing is just a create
  2971. */
  2972. if( reset && (oldpdd == NULL) )
  2973. {
  2974. reset = FALSE;
  2975. }
  2976. /*
  2977. * initialize a new driver object if we don't have one already
  2978. */
  2979. if( (oldpdd == NULL) || reset )
  2980. {
  2981. DPF(4,"oldpdd == NULL || reset");
  2982. /*
  2983. * validate blt stuff
  2984. */
  2985. if( lpDDHALInfo->ddCaps.dwCaps & DDCAPS_BLT )
  2986. {
  2987. if( lpDDHALInfo->lpDDSurfaceCallbacks->Blt == NULL )
  2988. {
  2989. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No Blt Fn, but BLT specified" );
  2990. goto ErrorExit;
  2991. }
  2992. if( !(lpDDHALInfo->ddCaps.dwRops[ (SRCCOPY>>16)/32 ] &
  2993. (1<<((SRCCOPY>>16) % 32)) ) )
  2994. {
  2995. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:BLT specified, but SRCCOPY not supported!" );
  2996. goto ErrorExit;
  2997. }
  2998. }
  2999. else
  3000. {
  3001. DPF( 2, "Driver can't blt" );
  3002. }
  3003. /*
  3004. * validate align fields
  3005. */
  3006. if( lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN )
  3007. {
  3008. if( !VALID_ALIGNMENT( lpDDHALInfo->vmiData.dwOffscreenAlign ) )
  3009. {
  3010. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Invalid dwOffscreenAlign (%d) with DDSCAPS_OFFSCREENPLAIN specified",
  3011. lpDDHALInfo->vmiData.dwOffscreenAlign );
  3012. goto ErrorExit;
  3013. }
  3014. }
  3015. if( lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  3016. {
  3017. if( !VALID_ALIGNMENT( lpDDHALInfo->vmiData.dwOverlayAlign ) )
  3018. {
  3019. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Invalid dwOverlayAlign (%d) with DDSCAPS_OVERLAY specified",
  3020. lpDDHALInfo->vmiData.dwOverlayAlign );
  3021. goto ErrorExit;
  3022. }
  3023. }
  3024. if( lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER )
  3025. {
  3026. if( !VALID_ALIGNMENT( lpDDHALInfo->vmiData.dwZBufferAlign ) )
  3027. {
  3028. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Invalid dwZBufferAlign (%d) with DDSCAPS_ZBUFFER specified",
  3029. lpDDHALInfo->vmiData.dwZBufferAlign );
  3030. goto ErrorExit;
  3031. }
  3032. }
  3033. if( lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_TEXTURE )
  3034. {
  3035. if( !VALID_ALIGNMENT( lpDDHALInfo->vmiData.dwTextureAlign ) )
  3036. {
  3037. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Invalid dwTextureAlign (%d) with DDSCAPS_TEXTURE specified",
  3038. lpDDHALInfo->vmiData.dwTextureAlign );
  3039. goto ErrorExit;
  3040. }
  3041. }
  3042. #ifndef WINNT
  3043. /*
  3044. * NT only reports one display mode if we are in the Ctrl-Alt-Del screen
  3045. * so don't fail if NT changes the number of display modes.
  3046. */
  3047. /*
  3048. * make sure display driver doesn't try to change the number of
  3049. * modes supported after a mode change
  3050. */
  3051. if( reset )
  3052. {
  3053. if( lpDDHALInfo->dwNumModes != 0 )
  3054. {
  3055. if( lpDDHALInfo->dwNumModes != oldpdd->dwSaveNumModes )
  3056. {
  3057. DPF(0, "*******************************************************");
  3058. DPF(0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Reset attempted to change number of modes from %d to %d",oldpdd->dwSaveNumModes,lpDDHALInfo->dwNumModes );
  3059. DPF(0, "*******************************************************");
  3060. goto ErrorExit;
  3061. }
  3062. }
  3063. }
  3064. #endif
  3065. /* memory for pddd was allocated at the top of this routine */
  3066. /*
  3067. * If this is the first time through, initialize a bunch of stuff.
  3068. * There are a number of fields that we only need to fill in when
  3069. * the driver object is created.
  3070. */
  3071. if( !reset )
  3072. {
  3073. #ifdef WIN95
  3074. /*
  3075. * set up a 16-bit pointer for use by the driver
  3076. */
  3077. pddd->lp16DD = (LPVOID) ptr16;
  3078. DPF( 5, "pddd->lp16DD = %08lx", pddd->lp16DD );
  3079. #endif
  3080. /*
  3081. * fill in misc. values
  3082. */
  3083. pddd->lpDriverHandle = pddd;
  3084. pddd->hInstance = lpDDHALInfo->hInstance;
  3085. // init doubly-linked overlay zorder list
  3086. pddd->dbnOverlayRoot.next = &(pddd->dbnOverlayRoot);
  3087. pddd->dbnOverlayRoot.prev = pddd->dbnOverlayRoot.next;
  3088. pddd->dbnOverlayRoot.object = NULL;
  3089. pddd->dbnOverlayRoot.object_int = NULL;
  3090. /*
  3091. * modes...
  3092. */
  3093. pddd->dwNumModes = lpDDHALInfo->dwNumModes;
  3094. pddd->dwSaveNumModes = lpDDHALInfo->dwNumModes;
  3095. if( pddd->dwNumModes > 0 )
  3096. {
  3097. size = pddd->dwNumModes * sizeof( DDHALMODEINFO );
  3098. #ifdef WIN95
  3099. pddd->lpModeInfo = MemAlloc( size );
  3100. if( pddd->lpModeInfo == NULL )
  3101. {
  3102. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate mode info!" );
  3103. goto ErrorExit;
  3104. }
  3105. #else
  3106. pddd->lpModeInfo = &pddd->ModeInfo;
  3107. DDASSERT( 1 == pddd->dwNumModes );
  3108. #endif
  3109. memcpy( pddd->lpModeInfo, lpDDHALInfo->lpModeInfo, size );
  3110. #ifdef WIN95
  3111. /*
  3112. * Check if we can add Mode X
  3113. */
  3114. do
  3115. {
  3116. if (lpDDHALInfo->dwFlags & DDHALINFO_MODEXILLEGAL)
  3117. {
  3118. break;
  3119. }
  3120. /*
  3121. * ModeX not allowed for PC98
  3122. * Check OS's locale.
  3123. */
  3124. if ( GetSystemDefaultLCID() == 0x0411 )
  3125. {
  3126. /*
  3127. * System is Windows 95 J
  3128. * Now retrieve keyboard ID to check PC98
  3129. */
  3130. DWORD dwSubType = GetKeyboardType(1);
  3131. if (HIBYTE(dwSubType) == 0x0D)
  3132. {
  3133. /* NEC PC98 series */
  3134. break;
  3135. }
  3136. }
  3137. /* NOT NEC PC98 series */
  3138. if (IsVGADevice( szDrvName ))
  3139. {
  3140. AddModeXModes( pddd );
  3141. /*
  3142. * OR in modex and/or standard VGA caps, so the app knows if
  3143. * it can pass the standard vga flag to enum modes.
  3144. */
  3145. lpDDHALInfo->ddCaps.ddsCaps.dwCaps |= (DDSCAPS_STANDARDVGAMODE|DDSCAPS_MODEX);
  3146. /*
  3147. * Do the HEL caps just for rationality
  3148. */
  3149. pddd->ddHELCaps.ddsCaps.dwCaps |= (DDSCAPS_STANDARDVGAMODE|DDSCAPS_MODEX);
  3150. }
  3151. break;
  3152. } while(0);
  3153. ExpandModeTable( pddd );
  3154. MassageModeTable( pddd );
  3155. #endif
  3156. }
  3157. else
  3158. {
  3159. pddd->lpModeInfo = NULL;
  3160. }
  3161. /*
  3162. * driver naming.. This is a special case for when we are
  3163. * invoked by the display driver directly, and not through
  3164. * the DirectDrawCreate path. Basically, everything except
  3165. * special 'secondary devices' like the 3DFx are DISPLAYDRV.
  3166. *
  3167. * If the driver says it's primary; ok. Else if it is "DISPLAY"
  3168. * or if the name is like "\\.\display4" then it is a Memphis/NT5
  3169. * multi-mon display device.
  3170. */
  3171. if( (lpDDHALInfo->dwFlags & DDHALINFO_ISPRIMARYDISPLAY) ||
  3172. _stricmp( szDrvName, DISPLAY_STR ) == 0 ||
  3173. (szDrvName[0] == '\\' && szDrvName[1] == '\\' && szDrvName[2] == '.') )
  3174. {
  3175. pddd->dwFlags |= DDRAWI_DISPLAYDRV;
  3176. pddd->dwFlags |= DDRAWI_GDIDRV;
  3177. lstrcpy( pddd->cDriverName, szDrvName );
  3178. }
  3179. /*
  3180. * modex modes are illegal on some hardware. specifically
  3181. * NEC machines in japan. this allows the driver to specify
  3182. * that its hardware does not support modex. modex modes are
  3183. * then turned off everywhere as a result.
  3184. */
  3185. if( lpDDHALInfo->dwFlags & DDHALINFO_MODEXILLEGAL )
  3186. {
  3187. pddd->dwFlags |= DDRAWI_MODEXILLEGAL;
  3188. }
  3189. }
  3190. /*
  3191. * resetting
  3192. */
  3193. else
  3194. {
  3195. /*
  3196. * copy old struct onto new one (before we start updating)
  3197. * preserve the lpDDCB pointer
  3198. */
  3199. {
  3200. LPDDHAL_CALLBACKS save_ptr=pddd->lpDDCBtmp;
  3201. memcpy( pddd, oldpdd, drv_callbacks_size );
  3202. pddd->lpDDCBtmp = save_ptr;
  3203. }
  3204. /*
  3205. * mark all existing surfaces as gone. Note, we don't rebuild
  3206. * the aliases at this point as they are going to be rebuilt
  3207. * below anyway.
  3208. */
  3209. InvalidateAllSurfaces( oldpdd, hDDVxd, FALSE );
  3210. #ifdef USE_ALIAS
  3211. /*
  3212. * The video memory heaps are about to go so release the
  3213. * aliases to those heaps that the local objects maintain.
  3214. *
  3215. * NOTE: If any surfaces are currently locked and using
  3216. * those aliases then the aliases will not actually be
  3217. * discarded until the last lock is released. In which
  3218. * case these aliases will be mapped to the dummy page
  3219. * by this point.
  3220. */
  3221. if( NULL != oldpdd->phaiHeapAliases )
  3222. {
  3223. DDASSERT( INVALID_HANDLE_VALUE != hDDVxd );
  3224. ReleaseHeapAliases( hDDVxd, oldpdd->phaiHeapAliases );
  3225. /*
  3226. * NOTE: Need to NULL out the heap alias pointer in the
  3227. * new driver object also as we just copied them above.
  3228. */
  3229. oldpdd->phaiHeapAliases = NULL;
  3230. pddd->phaiHeapAliases = NULL;
  3231. }
  3232. #endif /* USE_ALIAS */
  3233. #ifndef WINNT
  3234. /*
  3235. * discard old vidmem heaps
  3236. */
  3237. for( i=0;i<(int)oldpdd->vmiData.dwNumHeaps;i++ )
  3238. {
  3239. pvm = &(oldpdd->vmiData.pvmList[i]);
  3240. if( pvm->lpHeap != NULL )
  3241. {
  3242. HeapVidMemFini( pvm, hDDVxd );
  3243. }
  3244. }
  3245. #endif //not WINNT
  3246. }
  3247. /*
  3248. * fill in misc data
  3249. */
  3250. pddd->ddCaps = lpDDHALInfo->ddCaps;
  3251. pddd->vmiData.fpPrimary = lpDDHALInfo->vmiData.fpPrimary;
  3252. pddd->vmiData.dwFlags = lpDDHALInfo->vmiData.dwFlags;
  3253. pddd->vmiData.dwDisplayWidth = lpDDHALInfo->vmiData.dwDisplayWidth;
  3254. pddd->vmiData.dwDisplayHeight = lpDDHALInfo->vmiData.dwDisplayHeight;
  3255. pddd->vmiData.lDisplayPitch = lpDDHALInfo->vmiData.lDisplayPitch;
  3256. pddd->vmiData.ddpfDisplay = lpDDHALInfo->vmiData.ddpfDisplay;
  3257. pddd->vmiData.dwOffscreenAlign = lpDDHALInfo->vmiData.dwOffscreenAlign;
  3258. pddd->vmiData.dwOverlayAlign = lpDDHALInfo->vmiData.dwOverlayAlign;
  3259. pddd->vmiData.dwTextureAlign = lpDDHALInfo->vmiData.dwTextureAlign;
  3260. pddd->vmiData.dwZBufferAlign = lpDDHALInfo->vmiData.dwZBufferAlign;
  3261. pddd->vmiData.dwAlphaAlign = lpDDHALInfo->vmiData.dwAlphaAlign;
  3262. #ifdef WIN95
  3263. /*
  3264. * We need to compute the number of heaps that are actually usable.
  3265. * The number of usable heaps may be different from the number of
  3266. * heap descriptors passed to us by the driver due to AGP. If the
  3267. * driver attempts to pass AGP heaps to use and the OS we are running
  3268. * under doesn't have AGP support we can't use those heaps so we
  3269. * ignore them.
  3270. */
  3271. pddd->vmiData.dwNumHeaps = lpDDHALInfo->vmiData.dwNumHeaps;
  3272. for( i=0;i<(int)lpDDHALInfo->vmiData.dwNumHeaps;i++ )
  3273. {
  3274. if( ( lpDDHALInfo->vmiData.pvmList[i].dwFlags & VIDMEM_ISNONLOCAL ) && !isagpaware )
  3275. {
  3276. DPF(3, "Discarding AGP heap %d", i);
  3277. pddd->vmiData.dwNumHeaps--;
  3278. }
  3279. }
  3280. /*
  3281. * NOTE: Its not illegal to end up with no video memory heaps at this point.
  3282. * Under the current AGP implementation the primary is always in local
  3283. * video memory so we always end up with a valid primary if nothing else.
  3284. * Therefore, we stay in non-emulated mode.
  3285. */
  3286. #ifdef WIN95
  3287. #ifdef DEBUG
  3288. if( 0UL == pddd->vmiData.dwNumHeaps )
  3289. {
  3290. DPF( 2, "All video memory heaps have been disabled." );
  3291. }
  3292. #endif /* DEBUG */
  3293. #endif //WIN95
  3294. #endif
  3295. /*
  3296. * fpPrimaryOrig has no user-mode meaning under NT... primary's surface may have different address
  3297. * across processes.
  3298. * There is a new flag (DDRAWISURFGBL_ISGDISURFACE) which identifies a surface gbl object
  3299. * as representing the surface which GDI believes is the front buffer. jeffno 960122
  3300. */
  3301. pddd->fpPrimaryOrig = lpDDHALInfo->vmiData.fpPrimary;
  3302. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3303. DPF(5,"Primary video ram pointer is 0x%p", lpDDHALInfo->vmiData.fpPrimary);
  3304. #ifdef WIN95
  3305. pddd->dwMonitorFrequency = lpDDHALInfo->dwMonitorFrequency;
  3306. if( ( pddd->dwMonitorFrequency == 0 ) &&
  3307. ( lpDDHALInfo->dwModeIndex != (DWORD) -1 ) &&
  3308. ( lpDDHALInfo->lpModeInfo != NULL ) &&
  3309. ( lpDDHALInfo->lpModeInfo[lpDDHALInfo->dwModeIndex].wRefreshRate != 0 ) &&
  3310. !( lpDDHALInfo->lpModeInfo[lpDDHALInfo->dwModeIndex].wFlags & DDMODEINFO_MAXREFRESH ))
  3311. {
  3312. pddd->dwMonitorFrequency = lpDDHALInfo->lpModeInfo[lpDDHALInfo->dwModeIndex].wRefreshRate;
  3313. }
  3314. pddd->dwModeIndexOrig = lpDDHALInfo->dwModeIndex;
  3315. pddd->dwModeIndex = lpDDHALInfo->dwModeIndex;
  3316. DPF( 5, "Current and Original Mode = %d", pddd->dwModeIndex );
  3317. DPF( 5, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ MODE INDEX = %ld", pddd->dwModeIndex );
  3318. #else
  3319. pddd->dmiCurrent.wWidth = (WORD) lpDDHALInfo->lpModeInfo->dwWidth;
  3320. pddd->dmiCurrent.wHeight = (WORD) lpDDHALInfo->lpModeInfo->dwHeight;
  3321. if (lpDDHALInfo->lpModeInfo->dwBPP == 16)
  3322. {
  3323. pddd->dmiCurrent.wBPP = (lpDDHALInfo->lpModeInfo->wFlags & DDMODEINFO_555MODE) ? 15 : 16;
  3324. }
  3325. else
  3326. {
  3327. pddd->dmiCurrent.wBPP = (BYTE) lpDDHALInfo->lpModeInfo->dwBPP;
  3328. }
  3329. pddd->dmiCurrent.wRefreshRate = lpDDHALInfo->lpModeInfo->wRefreshRate;
  3330. pddd->dwMonitorFrequency = lpDDHALInfo->lpModeInfo->wRefreshRate;
  3331. pddd->dmiCurrent.wMonitorsAttachedToDesktop = (BYTE) GetNumberOfMonitorAttachedToDesktop();
  3332. #endif
  3333. /*
  3334. * pdevice info
  3335. */
  3336. #ifdef WIN95
  3337. if( lpDDHALInfo->lpPDevice != NULL )
  3338. {
  3339. LPDIBENGINE pde;
  3340. pde = MapSLFix( (DWORD) lpDDHALInfo->lpPDevice );
  3341. if( (pde->deType != 0x5250) || !(pde->deFlags & MINIDRIVER))
  3342. {
  3343. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Not a DIBEngine mini driver" );
  3344. goto ErrorExit;
  3345. }
  3346. pddd->dwPDevice = (DWORD)lpDDHALInfo->lpPDevice;
  3347. pddd->lpwPDeviceFlags = &pde->deFlags;
  3348. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3349. DPF( 5, "lpPDevice = 0x%p", pde );
  3350. if(pde->deBitsPixel == 16)
  3351. {
  3352. if(pde->deFlags & FIVE6FIVE)
  3353. {
  3354. pddd->vmiData.ddpfDisplay.dwRBitMask = 0xf800;
  3355. pddd->vmiData.ddpfDisplay.dwGBitMask = 0x07e0;
  3356. pddd->vmiData.ddpfDisplay.dwBBitMask = 0x001f;
  3357. }
  3358. else
  3359. {
  3360. pddd->vmiData.ddpfDisplay.dwRBitMask = 0x7c00;
  3361. pddd->vmiData.ddpfDisplay.dwGBitMask = 0x03e0;
  3362. pddd->vmiData.ddpfDisplay.dwBBitMask = 0x001f;
  3363. }
  3364. // Update the current mode to reflect the correct bitmasks
  3365. // NOTE: The driver can return a dwModeIndex of -1 if in
  3366. // a currently unsupported mode. Therefore, we must not
  3367. // initialize these masks if such an index has been
  3368. // returned.
  3369. if( 0xFFFFFFFFUL != pddd->dwModeIndex )
  3370. {
  3371. pddd->lpModeInfo[ pddd->dwModeIndex ].dwRBitMask = pddd->vmiData.ddpfDisplay.dwRBitMask;
  3372. pddd->lpModeInfo[ pddd->dwModeIndex ].dwGBitMask = pddd->vmiData.ddpfDisplay.dwGBitMask;
  3373. pddd->lpModeInfo[ pddd->dwModeIndex ].dwBBitMask = pddd->vmiData.ddpfDisplay.dwBBitMask;
  3374. }
  3375. DPF(5, "Setting the bitmasks for the driver (R:%04lx G:%04lx B:%04lx)",
  3376. pddd->vmiData.ddpfDisplay.dwRBitMask,
  3377. pddd->vmiData.ddpfDisplay.dwGBitMask,
  3378. pddd->vmiData.ddpfDisplay.dwBBitMask);
  3379. }
  3380. }
  3381. else
  3382. #else
  3383. /*
  3384. * Grab masks from NT driver
  3385. */
  3386. pddd->vmiData.ddpfDisplay.dwRBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwRBitMask;
  3387. pddd->vmiData.ddpfDisplay.dwGBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwGBitMask;
  3388. pddd->vmiData.ddpfDisplay.dwBBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwBBitMask;
  3389. if( 0xFFFFFFFFUL != pddd->dwModeIndex )
  3390. {
  3391. pddd->lpModeInfo[ pddd->dwModeIndex ].dwRBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwRBitMask;
  3392. pddd->lpModeInfo[ pddd->dwModeIndex ].dwGBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwGBitMask;
  3393. pddd->lpModeInfo[ pddd->dwModeIndex ].dwBBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwBBitMask;
  3394. }
  3395. DPF(5, "Setting the bitmasks for the driver (R:%04lx G:%04lx B:%04lx)",
  3396. pddd->vmiData.ddpfDisplay.dwRBitMask,
  3397. pddd->vmiData.ddpfDisplay.dwGBitMask,
  3398. pddd->vmiData.ddpfDisplay.dwBBitMask);
  3399. #endif
  3400. {
  3401. if( !reset )
  3402. {
  3403. pddd->dwPDevice = 0;
  3404. pddd->lpwPDeviceFlags = (WORD *)&dwFakeFlags;
  3405. }
  3406. }
  3407. /*
  3408. * fourcc codes...
  3409. */
  3410. MemFree( pddd->lpdwFourCC );
  3411. pddd->lpdwFourCC = NULL;
  3412. if (oldpdd != NULL)
  3413. {
  3414. oldpdd->lpdwFourCC = NULL;
  3415. }
  3416. pddd->ddCaps.dwNumFourCCCodes = lpDDHALInfo->ddCaps.dwNumFourCCCodes;
  3417. pddd->dwNumFourCC = pddd->ddCaps.dwNumFourCCCodes;
  3418. if( pddd->ddCaps.dwNumFourCCCodes > 0 )
  3419. {
  3420. size = pddd->ddCaps.dwNumFourCCCodes * sizeof( DWORD );
  3421. pddd->lpdwFourCC = MemAlloc( size );
  3422. if( pddd->lpdwFourCC == NULL )
  3423. {
  3424. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate FOURCC data!" );
  3425. goto ErrorExit;
  3426. }
  3427. memcpy( pddd->lpdwFourCC, lpDDHALInfo->lpdwFourCC, size );
  3428. }
  3429. /*
  3430. * Extended 3D caps structure
  3431. *
  3432. */
  3433. if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
  3434. {
  3435. HRESULT ret;
  3436. DDHAL_GETDRIVERINFODATA gdidata;
  3437. if (oldpdd != NULL)
  3438. {
  3439. oldpdd->lpD3DExtendedCaps = 0;
  3440. }
  3441. if (! pddd->lpD3DExtendedCaps)
  3442. {
  3443. pddd->lpD3DExtendedCaps = MemAlloc( D3DHAL_D3DEXTENDEDCAPSSIZE );
  3444. }
  3445. if (! pddd->lpD3DExtendedCaps)
  3446. {
  3447. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not allocate D3D extended caps structure" );
  3448. }
  3449. else
  3450. {
  3451. memset( (LPVOID) pddd->lpD3DExtendedCaps, 0, D3DHAL_D3DEXTENDEDCAPSSIZE );
  3452. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo,
  3453. &gdidata,
  3454. (LPVOID) pddd->lpD3DExtendedCaps,
  3455. D3DHAL_D3DEXTENDEDCAPSSIZE,
  3456. &GUID_D3DExtendedCaps,
  3457. pddd,
  3458. FALSE /* bInOut */);
  3459. if (ret != DD_OK)
  3460. {
  3461. DPF ( 2,"D3D Extended Caps query failed" );
  3462. MemFree( (LPVOID) pddd->lpD3DExtendedCaps );
  3463. pddd->lpD3DExtendedCaps = 0;
  3464. }
  3465. }
  3466. // Extended caps was not compulsory for pre-DX6 drivers.
  3467. // Extended caps is compulsory for DX6+ drivers since it contains
  3468. // information about the driver's multitexture capabilities, FVF
  3469. // support and stencil support.
  3470. if (pddd->lpD3DHALCallbacks3->DrawPrimitives2)
  3471. {
  3472. if (pddd->lpD3DExtendedCaps == NULL)
  3473. {
  3474. DPF_ERR ( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:DX6+ drivers should report D3D Extended Caps, failing driver creation" );
  3475. goto ErrorExit;
  3476. }
  3477. else if (gdidata.dwActualSize != pddd->lpD3DExtendedCaps->dwSize)
  3478. {
  3479. DPF_ERR ( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Actual size reported is not equal to dwSize field in the Extended caps structure" );
  3480. goto ErrorExit;
  3481. }
  3482. else if (pddd->lpD3DExtendedCaps->dwSize < D3DHAL_D3DDX6EXTENDEDCAPSSIZE)
  3483. {
  3484. DPF_ERR ( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Driver reported insufficient D3D Extended Caps, failing driver creation" );
  3485. goto ErrorExit;
  3486. }
  3487. // If stencil capabilities are reported the driver should have
  3488. // exported Clear2
  3489. if (pddd->lpD3DExtendedCaps->dwStencilCaps != 0)
  3490. {
  3491. if ((pddd->lpD3DHALCallbacks3->Clear2 == NULL) &&
  3492. (0 == pddd->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState)
  3493. )
  3494. {
  3495. DPF_ERR ( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Pre DX7 Driver should report clear2 if any stencilcaps are set, failing driver creation" );
  3496. goto ErrorExit;
  3497. }
  3498. }
  3499. }
  3500. }
  3501. else // Driver doesn't have DDHALINFO_GETDRIVERINFOSET
  3502. {
  3503. if (pddd->lpD3DExtendedCaps)
  3504. {
  3505. memset( (LPVOID) pddd->lpD3DExtendedCaps, 0, D3DHAL_D3DEXTENDEDCAPSSIZE );
  3506. if (oldpdd)
  3507. {
  3508. oldpdd->lpD3DExtendedCaps = NULL;
  3509. }
  3510. }
  3511. }
  3512. if (lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFO2)
  3513. {
  3514. pddd->dwFlags |= DDRAWI_DRIVERINFO2;
  3515. }
  3516. /*
  3517. * video port descriptions
  3518. */
  3519. if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
  3520. {
  3521. MemFree( pddd->lpDDVideoPortCaps );
  3522. pddd->lpDDVideoPortCaps = NULL;
  3523. if (oldpdd != NULL)
  3524. {
  3525. oldpdd->lpDDVideoPortCaps = NULL;
  3526. }
  3527. pddd->ddCaps.dwMaxVideoPorts = lpDDHALInfo->ddCaps.dwMaxVideoPorts;
  3528. if( pddd->ddCaps.dwMaxVideoPorts > 0 )
  3529. {
  3530. HRESULT ret;
  3531. DDHAL_GETDRIVERINFODATA gdidata;
  3532. size = pddd->ddCaps.dwMaxVideoPorts * sizeof( DDVIDEOPORTCAPS );
  3533. pddd->lpDDVideoPortCaps = MemAlloc( size );
  3534. if( pddd->lpDDVideoPortCaps == NULL )
  3535. {
  3536. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate video port caps!" );
  3537. goto ErrorExit;
  3538. }
  3539. memset( pddd->lpDDVideoPortCaps, 0, size );
  3540. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo,
  3541. &gdidata,
  3542. pddd->lpDDVideoPortCaps,
  3543. size,
  3544. &GUID_VideoPortCaps, pddd,
  3545. FALSE /* bInOut */);
  3546. if (ret != DD_OK)
  3547. {
  3548. DPF ( 2,"VideoPortCaps query failed" );
  3549. MemFree(pddd->lpDDVideoPortCaps);
  3550. pddd->lpDDVideoPortCaps = NULL;
  3551. }
  3552. }
  3553. }
  3554. /*
  3555. * Kernel mode capabilities
  3556. *
  3557. * We only get these once we munge them when creating the driver
  3558. * object and we don't want to munge them everytime. We do need
  3559. * to munge the video port caps, however, to reflect the autoflip
  3560. * capabilities.
  3561. */
  3562. if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
  3563. {
  3564. if (pddd->lpDDKernelCaps == NULL)
  3565. {
  3566. HRESULT ret;
  3567. DDHAL_GETDRIVERINFODATA gdidata;
  3568. size = sizeof( DDKERNELCAPS );
  3569. pddd->lpDDKernelCaps = MemAlloc( size );
  3570. if( pddd->lpDDKernelCaps == NULL )
  3571. {
  3572. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate kernel caps!" );
  3573. goto ErrorExit;
  3574. }
  3575. memset( pddd->lpDDKernelCaps, 0, size );
  3576. ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo,
  3577. &gdidata,
  3578. pddd->lpDDKernelCaps,
  3579. size,
  3580. &GUID_KernelCaps, pddd,
  3581. FALSE /* bInOut */);
  3582. #ifdef WIN95
  3583. if( !IsWindows98() )
  3584. {
  3585. ret = DDERR_GENERIC;
  3586. }
  3587. #endif
  3588. if (ret != DD_OK)
  3589. {
  3590. DPF ( 2, "KernelCaps query failed" );
  3591. MemFree(pddd->lpDDKernelCaps);
  3592. pddd->lpDDKernelCaps = NULL;
  3593. }
  3594. }
  3595. #ifdef WIN95
  3596. else
  3597. {
  3598. MungeAutoflipCaps(pddd);
  3599. }
  3600. #endif
  3601. }
  3602. /*
  3603. * fill in rops
  3604. */
  3605. if( lpDDHALInfo->ddCaps.dwCaps & DDCAPS_BLT )
  3606. {
  3607. for( i=0;i<DD_ROP_SPACE;i++ )
  3608. {
  3609. pddd->ddCaps.dwRops[i] = lpDDHALInfo->ddCaps.dwRops[i];
  3610. }
  3611. }
  3612. /*
  3613. * get (or generate) the non-local video memory caps.
  3614. */
  3615. MemFree( pddd->lpddNLVCaps );
  3616. pddd->lpddNLVCaps = NULL;
  3617. if (oldpdd != NULL)
  3618. {
  3619. oldpdd->lpddNLVCaps = NULL;
  3620. }
  3621. if( !GetNonLocalVidMemCaps( lpDDHALInfo, pddd ) )
  3622. {
  3623. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not initialize non-local video memory caps" );
  3624. goto ErrorExit;
  3625. }
  3626. /*
  3627. * Get the driver's extended capabilities.
  3628. */
  3629. if( !GetDDMoreCaps( lpDDHALInfo, pddd ) )
  3630. {
  3631. // An error occurred during GetDDMoreCaps() call above.
  3632. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not initialize extended caps" );
  3633. goto ErrorExit;
  3634. }
  3635. /*
  3636. * Direct3D data structures
  3637. */
  3638. //#ifdef WINNT
  3639. // MemFree((void *)pddd->lpD3DHALCallbacks);
  3640. //#endif
  3641. if( lpDDHALInfo->dwSize >= DDHALINFOSIZE_V2 )
  3642. {
  3643. // Direct3D data is present
  3644. pddd->lpD3DGlobalDriverData = lpDDHALInfo->lpD3DGlobalDriverData;
  3645. pddd->lpD3DHALCallbacks = lpDDHALInfo->lpD3DHALCallbacks;
  3646. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3647. DPF( 5, "DDHALInfo contains D3D pointers: 0x%p 0x%p", pddd->lpD3DGlobalDriverData, pddd->lpD3DHALCallbacks);
  3648. }
  3649. else
  3650. {
  3651. // No Direct3D data present in DDHALInfo
  3652. pddd->lpD3DGlobalDriverData = 0;
  3653. pddd->lpD3DHALCallbacks = 0;
  3654. DPF( 1, "No Direct3D Support in driver");
  3655. }
  3656. freevm = 0;
  3657. #ifndef WINNT
  3658. /*
  3659. * NT kernel does the memory management now
  3660. */
  3661. MemFree( pddd->vmiData.pvmList );
  3662. pddd->vmiData.pvmList = NULL;
  3663. if (oldpdd != NULL)
  3664. {
  3665. oldpdd->vmiData.pvmList = NULL;
  3666. }
  3667. if( pddd->vmiData.dwNumHeaps > 0 )
  3668. {
  3669. size = sizeof( VIDMEM ) * pddd->vmiData.dwNumHeaps;
  3670. pddd->vmiData.pvmList = MemAlloc( size );
  3671. if( pddd->vmiData.pvmList == NULL )
  3672. {
  3673. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate heap info!" );
  3674. goto ErrorExit;
  3675. }
  3676. }
  3677. devheapno = 0;
  3678. for( i=0;i<(int)lpDDHALInfo->vmiData.dwNumHeaps;i++ )
  3679. {
  3680. /*
  3681. * Ask driver for any additional heap alignment requirements
  3682. */
  3683. DDHAL_GETHEAPALIGNMENTDATA ghad;
  3684. LPHEAPALIGNMENT pghad=0;
  3685. /*
  3686. * pghad will be null if no alignment
  3687. */
  3688. pghad = GetExtendedHeapAlignment(pddd, &ghad, i );
  3689. if( !( lpDDHALInfo->vmiData.pvmList[i].dwFlags & VIDMEM_ISNONLOCAL ) || isagpaware )
  3690. {
  3691. DWORD dwHeapFlags;
  3692. pvm = &(pddd->vmiData.pvmList[devheapno]);
  3693. *pvm = lpDDHALInfo->vmiData.pvmList[i];
  3694. dwHeapFlags = 0UL;
  3695. /*
  3696. * if a heap is specified, then we don't need to allocate
  3697. * one ourselves (for shared media devices)
  3698. */
  3699. if( !(pvm->dwFlags & VIDMEM_ISHEAP) )
  3700. {
  3701. #ifdef DEBUG
  3702. if( pvm->dwFlags & VIDMEM_ISLINEAR )
  3703. {
  3704. int vram = GetProfileInt("DirectDraw", "vram", -1);
  3705. if (vram > 0 && (pvm->fpStart + vram*1024L-1) < pvm->fpEnd)
  3706. {
  3707. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3708. DPF( 1, "pretending display card has only %dk VRAM", vram);
  3709. DPF( 1, "pvm->fpStart = 0x%p, pvm->fpEnd = 0x%p", pvm->fpStart, pvm->fpEnd );
  3710. pvm->fpEnd = pvm->fpStart + vram*1024L-1;
  3711. }
  3712. }
  3713. #endif
  3714. DPF(5,V,"Heap #%d is 0x%08x x 0x%08x",devheapno,pvm->dwWidth,pvm->dwHeight);
  3715. if ( ! HeapVidMemInit( pvm, pddd->vmiData.lDisplayPitch, hDDVxd , pghad ) )
  3716. {
  3717. pvm->lpHeap = NULL;
  3718. /*
  3719. * If this is an AGP heap, we probably failed because we couldn't reserve
  3720. * any AGP memory. This this case, we simply want to remove the heap
  3721. * rather than fail to emulation. We do not want to remove the AGP
  3722. * caps, however, since some drivers (e.g. nVidia) can allocate it
  3723. * without using our heap.
  3724. */
  3725. if( pvm->dwFlags & VIDMEM_ISNONLOCAL )
  3726. {
  3727. /*
  3728. * At this time, dwNumHeaps should always be greater than 0,
  3729. * but I added the check anyway in case something changes later.
  3730. */
  3731. if( pddd->vmiData.dwNumHeaps > 0 )
  3732. {
  3733. if( --pddd->vmiData.dwNumHeaps == 0 )
  3734. {
  3735. MemFree( pddd->vmiData.pvmList );
  3736. pddd->vmiData.pvmList = NULL;
  3737. }
  3738. }
  3739. continue;
  3740. }
  3741. }
  3742. }
  3743. if( pvm->lpHeap == NULL )
  3744. {
  3745. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not create video memory heap!" );
  3746. for( j=0;j<devheapno;j++ )
  3747. {
  3748. pvm = &(pddd->vmiData.pvmList[j]);
  3749. HeapVidMemFini( pvm, hDDVxd );
  3750. }
  3751. goto ErrorExit;
  3752. }
  3753. freevm += VidMemAmountFree( pvm->lpHeap );
  3754. devheapno++;
  3755. }
  3756. else
  3757. {
  3758. /*
  3759. * This is an AGP memory heap but the operating system
  3760. * does not have the necessary AGP extensions. Discard
  3761. * this heap descriptor.
  3762. */
  3763. DPF( 1, "Discarding AGP heap %d. OS does not have AGP support", i );
  3764. }
  3765. }
  3766. #endif //not WINNT
  3767. pddd->ddCaps.dwVidMemTotal = freevm;
  3768. /*
  3769. * Grab any extended surface caps and heap restrictions from the driver
  3770. */
  3771. if( !GetDDMoreSurfaceCaps( lpDDHALInfo, pddd ) )
  3772. {
  3773. // An error occurred during GetDDMoreCaps() call above.
  3774. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not initialize extended surface caps" );
  3775. goto ErrorExit;
  3776. }
  3777. /*
  3778. * Differences between win95 and NT HAL setup.
  3779. * On Win95, the 32bit entry points (DDHALCALLBACKS.DDHAL...) are reset to point to the
  3780. * helper functions inside w95hal.c, and only overwritten (with what comes in in the
  3781. * DDHALINFO structure from the driver) if the corresponding bit is set in the DDHALINFO's
  3782. * lpDD*...dwFlags coming in from the driver.
  3783. * On NT, there's no thunking, so the only use for the pointers stored in the
  3784. * DDHALCALLBACKS.cb... entries is deciding if there's a HAL function pointer before
  3785. * doing a HALCALL. Since the 32 bit callbacks are not initialized to point
  3786. * to the w95hal.c stubs, we zero them out before copying the individual driver callbacks
  3787. * one by one.
  3788. */
  3789. /*
  3790. * set up driver HAL
  3791. */
  3792. #ifdef WIN95
  3793. //Initialise HAL to 32-bit stubs in w95hal.c:
  3794. pddd->lpDDCBtmp->HALDD = ddHALDD;
  3795. #else
  3796. memset(&pddd->lpDDCBtmp->HALDD,0,sizeof(pddd->lpDDCBtmp->HALDD));
  3797. #endif
  3798. drvcb = lpDDHALInfo->lpDDCallbacks;
  3799. if( drvcb != NULL )
  3800. {
  3801. numcb = NUM_CALLBACKS( drvcb );
  3802. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  3803. DPF(5,"DDHal callback flags:%08x",drvcb->dwFlags);
  3804. for (i=0;i<numcb;i++) DPF(5," 0x%p",(&drvcb->DestroyDriver)[i]);
  3805. bit = 1;
  3806. for( i=0;i<numcb;i++ )
  3807. {
  3808. if( drvcb->dwFlags & bit )
  3809. {
  3810. // 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
  3811. (&pddd->lpDDCBtmp->HALDD.DestroyDriver)[i] = (&drvcb->DestroyDriver)[i];
  3812. }
  3813. bit <<= 1;
  3814. }
  3815. }
  3816. /*
  3817. * set up surface HAL
  3818. */
  3819. #ifdef WIN95
  3820. pddd->lpDDCBtmp->HALDDSurface = ddHALDDSurface;
  3821. #else
  3822. memset(&pddd->lpDDCBtmp->HALDDSurface,0,sizeof(pddd->lpDDCBtmp->HALDDSurface));
  3823. #endif
  3824. surfcb = lpDDHALInfo->lpDDSurfaceCallbacks;
  3825. if( surfcb != NULL )
  3826. {
  3827. numcb = NUM_CALLBACKS( surfcb );
  3828. bit = 1;
  3829. for( i=0;i<numcb;i++ )
  3830. {
  3831. if( surfcb->dwFlags & bit )
  3832. {
  3833. // 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
  3834. (&pddd->lpDDCBtmp->HALDDSurface.DestroySurface)[i] = (&surfcb->DestroySurface)[i];
  3835. }
  3836. bit <<= 1;
  3837. }
  3838. }
  3839. /*
  3840. * set up palette callbacks
  3841. */
  3842. #ifdef WIN95
  3843. pddd->lpDDCBtmp->HALDDPalette = ddHALDDPalette;
  3844. #else
  3845. memset (&pddd->lpDDCBtmp->HALDDPalette,0,sizeof(pddd->lpDDCBtmp->HALDDPalette));
  3846. #endif
  3847. palcb = lpDDHALInfo->lpDDPaletteCallbacks;
  3848. if( palcb != NULL )
  3849. {
  3850. numcb = NUM_CALLBACKS( palcb );
  3851. bit = 1;
  3852. for( i=0;i<numcb;i++ )
  3853. {
  3854. if( palcb->dwFlags & bit )
  3855. {
  3856. // 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
  3857. (&pddd->lpDDCBtmp->HALDDPalette.DestroyPalette)[i] = (&palcb->DestroyPalette)[i];
  3858. }
  3859. bit <<= 1;
  3860. }
  3861. }
  3862. /*
  3863. * set up execute buffer callbacks
  3864. * NOTE: Need explicit check for V2 driver as V1 driver knows nothing
  3865. * about these. For an old driver the default HAL callback table will
  3866. * be used unmodified.
  3867. */
  3868. #ifdef WIN95
  3869. pddd->lpDDCBtmp->HALDDExeBuf = ddHALDDExeBuf;
  3870. #endif
  3871. if( lpDDHALInfo->dwSize >= DDHALINFOSIZE_V2 )
  3872. {
  3873. exebufcb = lpDDHALInfo->lpDDExeBufCallbacks;
  3874. if( exebufcb != NULL )
  3875. {
  3876. numcb = NUM_CALLBACKS( exebufcb );
  3877. bit = 1;
  3878. for( i=0;i<numcb;i++ )
  3879. {
  3880. if( exebufcb->dwFlags & bit )
  3881. {
  3882. // 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
  3883. (&pddd->lpDDCBtmp->HALDDExeBuf.CanCreateExecuteBuffer)[i] = (&exebufcb->CanCreateExecuteBuffer)[i];
  3884. }
  3885. bit <<= 1;
  3886. }
  3887. }
  3888. }
  3889. /*
  3890. * make sure we wipe out old callbacks!
  3891. */
  3892. memset( &pddd->lpDDCBtmp->cbDDCallbacks, 0, sizeof( pddd->lpDDCBtmp->cbDDCallbacks ) );
  3893. memset( &pddd->lpDDCBtmp->cbDDSurfaceCallbacks, 0, sizeof( pddd->lpDDCBtmp->cbDDSurfaceCallbacks ) );
  3894. memset( &pddd->lpDDCBtmp->cbDDPaletteCallbacks, 0, sizeof( pddd->lpDDCBtmp->cbDDPaletteCallbacks ) );
  3895. memset( &pddd->lpDDCBtmp->cbDDExeBufCallbacks, 0, sizeof( pddd->lpDDCBtmp->cbDDExeBufCallbacks ) );
  3896. /*
  3897. * copy callback routines
  3898. */
  3899. if( lpDDHALInfo->lpDDCallbacks != NULL )
  3900. {
  3901. memcpy( &pddd->lpDDCBtmp->cbDDCallbacks, lpDDHALInfo->lpDDCallbacks,
  3902. (UINT) lpDDHALInfo->lpDDCallbacks->dwSize );
  3903. }
  3904. if( lpDDHALInfo->lpDDSurfaceCallbacks != NULL )
  3905. {
  3906. memcpy( &pddd->lpDDCBtmp->cbDDSurfaceCallbacks, lpDDHALInfo->lpDDSurfaceCallbacks,
  3907. (UINT) lpDDHALInfo->lpDDSurfaceCallbacks->dwSize );
  3908. }
  3909. if( lpDDHALInfo->lpDDPaletteCallbacks != NULL )
  3910. {
  3911. memcpy( &pddd->lpDDCBtmp->cbDDPaletteCallbacks, lpDDHALInfo->lpDDPaletteCallbacks,
  3912. (UINT) lpDDHALInfo->lpDDPaletteCallbacks->dwSize );
  3913. }
  3914. if( ( lpDDHALInfo->dwSize >= DDHALINFOSIZE_V2 ) &&
  3915. ( lpDDHALInfo->lpDDExeBufCallbacks != NULL ) )
  3916. {
  3917. memcpy( &pddd->lpDDCBtmp->cbDDExeBufCallbacks, lpDDHALInfo->lpDDExeBufCallbacks,
  3918. (UINT) lpDDHALInfo->lpDDExeBufCallbacks->dwSize );
  3919. }
  3920. #ifndef WIN95
  3921. if (pddd->lpDDCBtmp->HALDDNT.SetExclusiveMode)
  3922. {
  3923. pddd->lpDDCBtmp->HALDD.SetExclusiveMode =
  3924. pddd->lpDDCBtmp->cbDDCallbacks.SetExclusiveMode =
  3925. pddd->lpDDCBtmp->HALDDNT.SetExclusiveMode;
  3926. }
  3927. if (pddd->lpDDCBtmp->HALDDNT.FlipToGDISurface)
  3928. {
  3929. pddd->lpDDCBtmp->HALDD.FlipToGDISurface =
  3930. pddd->lpDDCBtmp->cbDDCallbacks.FlipToGDISurface =
  3931. pddd->lpDDCBtmp->HALDDNT.FlipToGDISurface;
  3932. }
  3933. #endif
  3934. /*
  3935. * init shared caps
  3936. */
  3937. capsInit( pddd );
  3938. mergeHELCaps( pddd );
  3939. /*
  3940. * if we were asked to reset, keep the new data
  3941. */
  3942. if( reset )
  3943. {
  3944. /*
  3945. * copy new structure onto original one
  3946. * being careful to preserve lpDDCB
  3947. */
  3948. {
  3949. LPDDHAL_CALLBACKS save_ptr = oldpdd->lpDDCBtmp;
  3950. memcpy( oldpdd, pddd, drv_callbacks_size );
  3951. oldpdd->lpDDCBtmp = save_ptr;
  3952. }
  3953. MemFree( pddd );
  3954. pddd = oldpdd;
  3955. }
  3956. }
  3957. else
  3958. {
  3959. DPF( 4, "Driver object already exists" );
  3960. #ifdef DEBUG
  3961. /*
  3962. * pddd is now allocated at the top of the routine, before the if that goes
  3963. * with the preceding else... jeffno 960115
  3964. */
  3965. if (pddd)
  3966. {
  3967. DPF(4,"Allocated space for a driver object when it wasn't necessary!");
  3968. }
  3969. #endif
  3970. MemFree(pddd); //should be NULL, just in case...
  3971. pddd = oldpdd;
  3972. }
  3973. /*
  3974. * set bank switched
  3975. */
  3976. if( pddd->dwFlags & DDRAWI_DISPLAYDRV )
  3977. {
  3978. HDC hdc;
  3979. hdc = DD_CreateDC( szDrvName );
  3980. if( DCIIsBanked( hdc ) ) //NT_FIX??
  3981. {
  3982. pddd->ddCaps.dwCaps |= DDCAPS_BANKSWITCHED;
  3983. DPF( 2, "Setting DDCAPS_BANKSWITCHED" );
  3984. }
  3985. else
  3986. {
  3987. pddd->ddCaps.dwCaps &= ~DDCAPS_BANKSWITCHED;
  3988. DPF( 2, "NOT Setting DDCAPS_BANKSWITCHED" );
  3989. }
  3990. DD_DoneDC( hdc );
  3991. /*
  3992. * Display drivers can all render windowed
  3993. */
  3994. //BEGIN VOODOO2 HACK
  3995. if ( (0 == (dwRegFlags & DDRAW_REGFLAGS_ENUMERATEATTACHEDSECONDARIES)) ||
  3996. (IsVGADevice( szDrvName )) )
  3997. //END VOODOO2 HACK
  3998. {
  3999. pddd->ddCaps.dwCaps2 |= DDCAPS2_CANRENDERWINDOWED;
  4000. }
  4001. }
  4002. InitGamma( pddd, szDrvName );
  4003. /*
  4004. * Disable non-local video memory if the operating system
  4005. * is not AGP aware.
  4006. */
  4007. if( ( pddd->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM ) && !isagpaware )
  4008. {
  4009. DPF( 2, "OS is not AGP aware. Disabling DDCAPS2_NONLOCALVIDMEM" );
  4010. pddd->ddCaps.dwCaps2 &= ~DDCAPS2_NONLOCALVIDMEM;
  4011. }
  4012. if( !( pddd->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM ))
  4013. {
  4014. if (lpDDHALInfo->lpD3DGlobalDriverData && (lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM))
  4015. { //some drivers(Riva128 on PCI) incorrectly sets D3DDEVCAPS_TEXTURENONLOCALVIDMEM
  4016. DPF( 1, "driver set D3DDEVCAPS_TEXTURENONLOCALVIDMEM w/o DDCAPS2_NONLOCALVIDMEM:turning off D3DDEVCAPS_TEXTURENONLOCALVIDMEM" );
  4017. lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps &= ~D3DDEVCAPS_TEXTURENONLOCALVIDMEM;
  4018. }
  4019. }
  4020. #ifdef USE_ALIAS
  4021. /*
  4022. * Can we use VRAM aliasing and PDEVICE modification to avoid taking
  4023. * the Win16 lock when locking a VRAM surface? Can't if the device is
  4024. * bankswitched or if the DIB Engine is not a version we recognize.
  4025. */
  4026. if (!(lpDDHALInfo->ddCaps.dwCaps & DDCAPS_NOHARDWARE))
  4027. {
  4028. if( ( pddd->dwFlags & DDRAWI_DISPLAYDRV ) &&
  4029. ( ( pddd->ddCaps.dwCaps & DDCAPS_BANKSWITCHED ) || ( !DD16_FixupDIBEngine() ) ) )
  4030. {
  4031. pddd->dwFlags |= DDRAWI_NEEDSWIN16FORVRAMLOCK;
  4032. DPF( 2, "Win16 lock must be taken for VRAM locks" );
  4033. }
  4034. else
  4035. {
  4036. pddd->dwFlags &= ~DDRAWI_NEEDSWIN16FORVRAMLOCK;
  4037. DPF( 2, "Taking the Win16 lock may not be necessary for VRAM locks" );
  4038. }
  4039. /*
  4040. * Create the virtual memory heap aliases for this global object
  4041. */
  4042. if( ( pddd->dwFlags & DDRAWI_DISPLAYDRV ) &&
  4043. !( pddd->dwFlags & DDRAWI_NEEDSWIN16FORVRAMLOCK ) )
  4044. {
  4045. DDASSERT( INVALID_HANDLE_VALUE != hDDVxd );
  4046. if( FAILED( CreateHeapAliases( hDDVxd, pddd ) ) )
  4047. {
  4048. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4049. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not create the heap aliases for driver object 0x%p", pddd );
  4050. goto ErrorExit;
  4051. }
  4052. }
  4053. }
  4054. #endif /* USE_ALIAS */
  4055. #ifdef WIN95
  4056. /*
  4057. * If we have a driver which has AGP support and which has provided us with a
  4058. * notification callback so that we can tell it the GART linear and physical
  4059. * addresses of the heaps it provided to us then invoke that callback now
  4060. * for the non-local heaps we initialized.
  4061. */
  4062. if( (NULL != pddd) && (pddd->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM) )
  4063. {
  4064. LPDDHAL_UPDATENONLOCALHEAP unlhfn;
  4065. DDHAL_UPDATENONLOCALHEAPDATA unlhd;
  4066. LPVIDMEM lpHeap;
  4067. DWORD rc;
  4068. unlhfn = pddd->lpDDCBtmp->HALDDMiscellaneous.UpdateNonLocalHeap;
  4069. if( NULL != unlhfn )
  4070. {
  4071. unlhd.lpDD = pddd;
  4072. unlhd.ulPolicyMaxBytes = dwAGPPolicyMaxBytes;
  4073. unlhd.ddRVal = DDERR_GENERIC; /* Force the driver to return something sensible */
  4074. unlhd.UpdateNonLocalHeap = NULL;
  4075. for( i = 0; i < (int)pddd->vmiData.dwNumHeaps; i++ )
  4076. {
  4077. lpHeap = &pddd->vmiData.pvmList[i];
  4078. if( lpHeap->dwFlags & VIDMEM_ISNONLOCAL )
  4079. {
  4080. DPF( 4, "Notifying driver of update to non-local heap %d", i );
  4081. unlhd.dwHeap = i;
  4082. unlhd.fpGARTLin = lpHeap->lpHeap->fpGARTLin;
  4083. unlhd.fpGARTDev = lpHeap->lpHeap->fpGARTDev;
  4084. DOHALCALL( UpdateNonLocalHeap, unlhfn, unlhd, rc, FALSE );
  4085. /*
  4086. * Currently this callback is pure notification. The driver
  4087. * cannot fail it.
  4088. */
  4089. DDASSERT( DDHAL_DRIVER_HANDLED == rc );
  4090. DDASSERT( DD_OK == unlhd.ddRVal );
  4091. }
  4092. }
  4093. }
  4094. }
  4095. #endif
  4096. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4097. DPF( 5, "DirectDrawObjectCreate: Returning global object 0x%p", pddd );
  4098. #ifdef WINNT
  4099. MemFree(lpDDHALInfo->lpdwFourCC);
  4100. MemFree(lpDDHALInfo->vmiData.pvmList);
  4101. #endif
  4102. LEAVE_DDRAW();
  4103. return pddd;
  4104. ErrorExit:
  4105. // We must not free memory in the reset path, since the oldpdd will survive this
  4106. // call to DirectDrawObjectCreate, and be freed by IDD::Release sometime later.
  4107. // We will not NULL out all these ptrs either, since that would invite a bazillion
  4108. // stress failures elsewhere in the code. We will leave the ptrs valid, but set
  4109. // DDUNSUPPORTEDMODE in the mode index, both to throttle further usage of this ddraw
  4110. // global (which now is full of caps etc. from the wrong mode) and as an indicator
  4111. // that this is what happened in future stress investigations.
  4112. // We are also going to wimp out and change only the NT path.
  4113. if (pddd
  4114. #ifdef WINNT
  4115. && !reset
  4116. #endif
  4117. )
  4118. {
  4119. MemFree( pddd->lpDDVideoPortCaps );
  4120. MemFree( pddd->lpddNLVCaps );
  4121. MemFree( pddd->lpddNLVHELCaps );
  4122. MemFree( pddd->lpddNLVBothCaps );
  4123. MemFree( pddd->lpD3DHALCallbacks2 );
  4124. MemFree( pddd->lpD3DHALCallbacks3 );
  4125. MemFree( pddd->lpZPixelFormats );
  4126. MemFree( pddd->lpddMoreCaps );
  4127. MemFree( pddd->lpddHELMoreCaps );
  4128. MemFree( pddd->lpddBothMoreCaps );
  4129. #ifdef POSTPONED
  4130. MemFree( pddd->lpDDOptSurfaceInfo );
  4131. MemFree( pddd->lpDDUmodeDrvInfo );
  4132. #endif //POSTPONED
  4133. #ifdef WINNT
  4134. if (pddd->hDD != 0)
  4135. {
  4136. // Delete the object if not resetting. If we were just resetting
  4137. // we should not delete it as it may work later; the call to
  4138. // enable or query the DirectDraw object may have failed because
  4139. // the system is displaying the logon desktop, or is in 4 bpp or
  4140. // another unsupported mode.
  4141. if (!reset)
  4142. {
  4143. DdDeleteDirectDrawObject(pddd);
  4144. }
  4145. }
  4146. #endif //WINNT
  4147. MemFree( pddd );
  4148. }
  4149. #ifdef WINNT
  4150. if (reset && pddd)
  4151. {
  4152. pddd->dwModeIndex = DDUNSUPPORTEDMODE;
  4153. }
  4154. MemFree(lpDDHALInfo->lpdwFourCC);
  4155. MemFree(lpDDHALInfo->vmiData.pvmList);
  4156. if (ismemalloced && !reset)
  4157. {
  4158. MemFree(pd3dNTHALCallbacks);
  4159. }
  4160. #endif
  4161. LEAVE_DDRAW();
  4162. return NULL;
  4163. } /* DirectDrawObjectCreate */
  4164. #pragma message( REMIND( "I'm drowning in a sea of ancient unfixed pragma reminders" ) )
  4165. /*
  4166. * CleanUpD3DHAL
  4167. *
  4168. * Notify the Direct3D driver using the ContextDestroyAll callbacks
  4169. * that the given process has died so that it may cleanup any context
  4170. * associated with that process.
  4171. *
  4172. * NOTE: This function is only invoked if we have Direct3D
  4173. * support in the DirectDraw driver and if the process
  4174. * terminates without cleaning up normally.
  4175. *
  4176. * I would call the ContextDestroyAll callback directly from here
  4177. * instead of through this convoluted exported fn, but d3dhal.h
  4178. * can't be included here because of the dependencies.
  4179. */
  4180. void CleanUpD3DHAL(LPD3DHAL_CALLBACKS lpD3DHALCallbacks, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl)
  4181. {
  4182. D3DHALCleanUpProc lpD3DHALCleanUpProc;
  4183. HINSTANCE hD3DInstance;
  4184. if (DDRAWILCL_DIRECTDRAW7 & pdrv_lcl->dwLocalFlags)
  4185. {
  4186. hD3DInstance = LoadLibrary( D3DDX7_DLLNAME );
  4187. DPF(4,"Calling %s in %s",D3DHALCLEANUP_PROCNAME,D3DDX7_DLLNAME);
  4188. }
  4189. else
  4190. {
  4191. hD3DInstance = LoadLibrary( D3D_DLLNAME );
  4192. DPF(4,"Calling %s in %s",D3DHALCLEANUP_PROCNAME,D3D_DLLNAME);
  4193. }
  4194. // Attempt to locate the cleanup entry point.
  4195. if (0 != hD3DInstance)
  4196. {
  4197. lpD3DHALCleanUpProc = (D3DHALCleanUpProc)GetProcAddress( hD3DInstance,
  4198. D3DHALCLEANUP_PROCNAME );
  4199. if( NULL == lpD3DHALCleanUpProc )
  4200. {
  4201. // this is really either an internal error, or d3dim.dll is suddenly missing
  4202. DPF(0,"Error: can't find cleanup entry point %s in %s, driver's 3D resources won't be freed",D3DHALCLEANUP_PROCNAME,D3D_DLLNAME);
  4203. }
  4204. else
  4205. {
  4206. (*lpD3DHALCleanUpProc)( lpD3DHALCallbacks, pid );
  4207. }
  4208. FreeLibrary(hD3DInstance);
  4209. }
  4210. }
  4211. #ifdef WIN95
  4212. /*
  4213. * CurrentProcessCleanup
  4214. *
  4215. * make sure terminating process cleans up after itself...
  4216. */
  4217. BOOL CurrentProcessCleanup( BOOL was_term )
  4218. {
  4219. DWORD pid;
  4220. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  4221. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  4222. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  4223. LPDDRAWI_DIRECTDRAW_INT pdrv_link_int;
  4224. BOOL rc;
  4225. BOOL fD3DCleanedUp;
  4226. ENTER_DDRAW();
  4227. pid = GETCURRPID();
  4228. pdrv_int = lpDriverObjectList;
  4229. rc = FALSE;
  4230. fD3DCleanedUp = FALSE;
  4231. /*
  4232. * run through each driver, looking for the current process handle
  4233. * Delete all local objects created by this process.
  4234. */
  4235. while( pdrv_int != NULL )
  4236. {
  4237. pdrv_link_int = pdrv_int->lpLink;
  4238. /*
  4239. * if we find the process, release it and remove it from list
  4240. */
  4241. pdrv_lcl = pdrv_int->lpLcl;
  4242. if( pdrv_lcl->dwProcessId == pid )
  4243. {
  4244. DWORD refcnt;
  4245. pdrv = pdrv_lcl->lpGbl;
  4246. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4247. DPF( 4, "Process %08lx still attached to driver 0x%p", pid, pdrv_int );
  4248. DPF( 5, " Refcnt = %ld", pdrv_int->dwIntRefCnt );
  4249. if( pdrv != NULL )
  4250. {
  4251. DPF( 5, " DRV Refcnt = %ld", pdrv->dwRefCnt );
  4252. }
  4253. // Clean up DX8
  4254. #ifdef WIN95
  4255. CleanupD3D8( pdrv, TRUE, pid);
  4256. #endif
  4257. rc = TRUE;
  4258. /*
  4259. * D3D uses a bogus DDraw interface to create surfaces, which
  4260. * means that we AddRef the LCL and GBL, but since the INT is
  4261. * not in the lpDriverObjectList, we never release them. The
  4262. * result is that LCL/GBLs are never released and this causes
  4263. * lots of problems (for example, we don't call DonExclusiveMode
  4264. * to turn off the 3DFX pass through). If the process cleans up
  4265. * correctly, so does D3D, but if we cleanup on DDHELPs thread,
  4266. * D3D has already been unloaded. The work-around is to
  4267. * determine if this is the last INT referncing the LCL and if
  4268. * the ref counts don't match, make the INT re count match the LCL.
  4269. */
  4270. if( dwHelperPid == GetCurrentProcessId() )
  4271. {
  4272. LPDDRAWI_DIRECTDRAW_INT pTemp_int;
  4273. pTemp_int = lpDriverObjectList;
  4274. while( pTemp_int != NULL )
  4275. {
  4276. if( ( pTemp_int != pdrv_int ) &&
  4277. ( pTemp_int->lpLcl == pdrv_lcl ) )
  4278. {
  4279. break;
  4280. }
  4281. pTemp_int = pTemp_int->lpLink;
  4282. }
  4283. if( pTemp_int == NULL )
  4284. {
  4285. pdrv_int->dwIntRefCnt = pdrv_lcl->dwLocalRefCnt;
  4286. }
  4287. }
  4288. /*
  4289. * punt process from any surfaces and palettes
  4290. */
  4291. if( pdrv != NULL )
  4292. {
  4293. #ifdef POSTPONED2
  4294. ProcessSpriteCleanup( pdrv, pid ); // master sprite list
  4295. #endif //POSTPONED2
  4296. ProcessSurfaceCleanup( pdrv, pid, NULL );
  4297. ProcessPaletteCleanup( pdrv, pid, NULL );
  4298. ProcessClipperCleanup( pdrv, pid, NULL );
  4299. ProcessVideoPortCleanup( pdrv, pid, NULL );
  4300. }
  4301. /*
  4302. * Has the process terminated and a Direct3D driver
  4303. * object been queried off this driver object?
  4304. */
  4305. if( was_term && ( pdrv_lcl->pD3DIUnknown != NULL ) )
  4306. {
  4307. /*
  4308. * Yes... so we need to do two things:
  4309. *
  4310. * 1) Simply discard the IUnknown interface pointer
  4311. * for the Direct3D object as that object is now
  4312. * gone (it was allocated by a local DLL in a
  4313. * local heap of a process that is now gone).
  4314. *
  4315. * 2) If we have hardware 3D support and we have not
  4316. * yet notified the driver of the death of this
  4317. * process tell it now.
  4318. */
  4319. DPF( 4, "Discarding Direct3D interface - process terminated" );
  4320. pdrv_lcl->pD3DIUnknown = NULL;
  4321. if( ( pdrv->lpD3DHALCallbacks != NULL ) && !fD3DCleanedUp )
  4322. {
  4323. DPF( 4, "Notifying Direct3D driver of process termination" );
  4324. CleanUpD3DHAL( pdrv->lpD3DHALCallbacks, pid, pdrv_lcl);
  4325. fD3DCleanedUp = TRUE;
  4326. }
  4327. }
  4328. /*
  4329. * now release the driver object
  4330. * If exclusive mode was held by this process, it will
  4331. * be relinquished when the local object is deleted.
  4332. */
  4333. refcnt = pdrv_int->dwIntRefCnt;
  4334. while( refcnt > 0 )
  4335. {
  4336. DD_Release( (LPDIRECTDRAW) pdrv_int );
  4337. refcnt--;
  4338. }
  4339. }
  4340. /*
  4341. * go to the next driver
  4342. */
  4343. pdrv_int = pdrv_link_int;
  4344. }
  4345. /*
  4346. * Release driver independent clippers owned by this process.
  4347. */
  4348. ProcessClipperCleanup( NULL, pid, NULL );
  4349. /*
  4350. * Remove any process entries from the window list. They could be left
  4351. * around if the window was subclassed.
  4352. */
  4353. CleanupWindowList( pid );
  4354. LEAVE_DDRAW();
  4355. DPF( 4, "Done with CurrentProcessCleanup, rc = %d", rc);
  4356. return rc;
  4357. } /* CurrentProcessCleanup */
  4358. #endif //WIN95
  4359. /*
  4360. * RemoveDriverFromList
  4361. *
  4362. * remove driver object from linked list of driver objects.
  4363. * assumes DirectDraw lock is taken.
  4364. */
  4365. void RemoveDriverFromList( LPDDRAWI_DIRECTDRAW_INT lpDD_int, BOOL final )
  4366. {
  4367. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  4368. LPDDRAWI_DIRECTDRAW_INT pdlast_int;
  4369. ENTER_DRIVERLISTCSECT();
  4370. pdrv_int = lpDriverObjectList;
  4371. pdlast_int = NULL;
  4372. while( pdrv_int != NULL )
  4373. {
  4374. if( pdrv_int == lpDD_int )
  4375. {
  4376. if( pdlast_int == NULL )
  4377. {
  4378. lpDriverObjectList = pdrv_int->lpLink;
  4379. }
  4380. else
  4381. {
  4382. pdlast_int->lpLink = pdrv_int->lpLink;
  4383. }
  4384. break;
  4385. }
  4386. pdlast_int = pdrv_int;
  4387. pdrv_int = pdrv_int->lpLink;
  4388. }
  4389. #ifdef DEBUG
  4390. if( pdrv_int == NULL )
  4391. {
  4392. DPF( 3, "ERROR!! Could not find driver in global object list" );
  4393. }
  4394. #endif
  4395. LEAVE_DRIVERLISTCSECT();
  4396. } /* RemoveDriverFromList */
  4397. /*
  4398. * RemoveLocalFromList
  4399. *
  4400. * remove local object from linked list of local objects.
  4401. * assumes DirectDraw lock is taken.
  4402. */
  4403. void RemoveLocalFromList( LPDDRAWI_DIRECTDRAW_LCL this_lcl )
  4404. {
  4405. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  4406. LPDDRAWI_DIRECTDRAW_LCL pdlast_lcl;
  4407. ENTER_DRIVERLISTCSECT();
  4408. pdrv_lcl = lpDriverLocalList;
  4409. pdlast_lcl = NULL;
  4410. while( pdrv_lcl != NULL )
  4411. {
  4412. if( pdrv_lcl == this_lcl )
  4413. {
  4414. if( pdlast_lcl == NULL )
  4415. {
  4416. lpDriverLocalList = pdrv_lcl->lpLink;
  4417. }
  4418. else
  4419. {
  4420. pdlast_lcl->lpLink = pdrv_lcl->lpLink;
  4421. }
  4422. break;
  4423. }
  4424. pdlast_lcl = pdrv_lcl;
  4425. pdrv_lcl = pdrv_lcl->lpLink;
  4426. }
  4427. #ifdef DEBUG
  4428. if( pdrv_lcl == NULL )
  4429. {
  4430. DPF( 3, "ERROR!! Could not find driver local in global list" );
  4431. }
  4432. #endif
  4433. LEAVE_DRIVERLISTCSECT();
  4434. } /* RemoveLocalFromList */
  4435. /*
  4436. * doneDC
  4437. */
  4438. void DD_DoneDC( HDC hdc_dd )
  4439. {
  4440. if( hdc_dd != NULL )
  4441. {
  4442. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4443. DPF( 5, "DeleteDC 0x%p", hdc_dd );
  4444. DeleteDC( hdc_dd );
  4445. hdc_dd = NULL;
  4446. }
  4447. } /* doneDC */
  4448. #undef DPF_MODNAME
  4449. #define DPF_MODNAME "DirectDrawCreate"
  4450. // prototype for helinit
  4451. BOOL HELInit( LPDDRAWI_DIRECTDRAW_GBL pdrv, BOOL helonly );
  4452. /*
  4453. * helInit
  4454. */
  4455. BOOL helInit( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD dwFlags, BOOL hel_only )
  4456. {
  4457. if( (dwFlags & DDCREATE_HARDWAREONLY) )
  4458. {
  4459. return TRUE;
  4460. }
  4461. /*
  4462. * get the HEL to fill in details:
  4463. *
  4464. * - dwHELDriverCaps
  4465. * - dwHELStretchDriverCaps
  4466. * - dwHELRopsSupported
  4467. * - ddsHELCaps
  4468. * - HELDD
  4469. * - HELDDSurface
  4470. * - HELDDPalette
  4471. * - HELDDExeBuf
  4472. */
  4473. if( HELInit( pdrv, hel_only ) )
  4474. {
  4475. /*
  4476. * find the intersection of the driver and the HEL caps...
  4477. */
  4478. pdrv->dwFlags |= DDRAWI_EMULATIONINITIALIZED;
  4479. mergeHELCaps( pdrv );
  4480. }
  4481. else
  4482. {
  4483. DPF( 3, "HELInit failed" );
  4484. pdrv->dwFlags |= DDRAWI_NOEMULATION;
  4485. }
  4486. return TRUE;
  4487. } /* helInit */
  4488. /*
  4489. * createDC
  4490. *
  4491. * create a new DC given a device name.
  4492. * doneDC() should be called to free DC
  4493. *
  4494. * the following are valid for device names:
  4495. *
  4496. * DISPLAY - the main display device via CreateDC("DISPLAY", ...)
  4497. * this is the normal case.
  4498. *
  4499. * foobar - the foobar.drv via CreateDC("foobar", ...)
  4500. * used for secondary displays listed in the registry
  4501. *
  4502. * \\.\DisplayX - display device X via CreateDC(NULL,"\\.\DisplayX",...)
  4503. * used on Memphis and NT5 for secondary displays
  4504. *
  4505. */
  4506. HDC DD_CreateDC( LPSTR pdrvname )
  4507. {
  4508. HDC hdc;
  4509. UINT u;
  4510. DDASSERT( pdrvname != NULL );
  4511. #ifdef DEBUG
  4512. if (pdrvname[0] == 0)
  4513. {
  4514. DPF( 3, "createDC() empty string!!!" );
  4515. DebugBreak();
  4516. return NULL;
  4517. }
  4518. #endif
  4519. #if defined(NT_FIX) || defined(WIN95)
  4520. u = SetErrorMode( SEM_NOOPENFILEERRORBOX );
  4521. #endif
  4522. #ifdef WINNT
  4523. /*
  4524. * Note that DirectDraw refers to the driver for the primary monitor
  4525. * in a multimon system as "display", but NT uses "display" to refer
  4526. * to the desktop as a whole. To handle this mismatch, we store
  4527. * NT's name for the primary monitor's driver in g_szPrimaryDisplay
  4528. * and substitute this name in place of "display" in our calls to NT.
  4529. */
  4530. if ( GetSystemMetrics( SM_CMONITORS ) > 1 )
  4531. {
  4532. if ( (_stricmp(pdrvname, DISPLAY_STR) == 0) )
  4533. {
  4534. if (g_szPrimaryDisplay[0] == '\0')
  4535. {
  4536. getPrimaryDisplayName();
  4537. }
  4538. pdrvname = g_szPrimaryDisplay;
  4539. }
  4540. }
  4541. #endif //WINNT
  4542. DPF( 5, "createDC(%s)", pdrvname );
  4543. if (pdrvname[0] == '\\' && pdrvname[1] == '\\' && pdrvname[2] == '.')
  4544. hdc = CreateDC( NULL, pdrvname, NULL, NULL);
  4545. else
  4546. hdc = CreateDC( pdrvname, NULL, NULL, NULL);
  4547. #if defined(NT_FIX) || defined(WIN95) //fix this error mode stuff
  4548. SetErrorMode( u );
  4549. #endif
  4550. if (hdc == NULL)
  4551. {
  4552. DPF( 3, "createDC(%s) FAILED!", pdrvname );
  4553. }
  4554. return hdc;
  4555. } /* createDC */
  4556. /*
  4557. * CreateFirstDC
  4558. *
  4559. * same as DD_CreateDC, except DDHELP is notified of the new driver.
  4560. * used only durring
  4561. */
  4562. static HDC DD_CreateFirstDC( LPSTR pdrvname )
  4563. {
  4564. #ifdef WIN95
  4565. if (pdrvname != NULL)
  4566. {
  4567. #ifndef WIN16_SEPARATE
  4568. LEAVE_DDRAW();
  4569. #endif
  4570. SignalNewDriver( pdrvname, TRUE );
  4571. #ifndef WIN16_SEPARATE
  4572. ENTER_DDRAW();
  4573. #endif
  4574. }
  4575. #endif
  4576. return DD_CreateDC(pdrvname);
  4577. } /* createDC */
  4578. /*
  4579. * strToGUID
  4580. *
  4581. * converts a string in the form xxxxxxxx-xxxx-xxxx-xx-xx-xx-xx-xx-xx-xx-xx
  4582. * into a guid
  4583. */
  4584. static BOOL strToGUID( LPSTR str, GUID * pguid )
  4585. {
  4586. int idx;
  4587. LPSTR ptr;
  4588. LPSTR next;
  4589. DWORD data;
  4590. DWORD mul;
  4591. BYTE ch;
  4592. BOOL done;
  4593. idx = 0;
  4594. done = FALSE;
  4595. while( !done )
  4596. {
  4597. /*
  4598. * find the end of the current run of digits
  4599. */
  4600. ptr = str;
  4601. while( (*str) != '-' && (*str) != 0 )
  4602. {
  4603. str++;
  4604. }
  4605. if( *str == 0 )
  4606. {
  4607. done = TRUE;
  4608. }
  4609. else
  4610. {
  4611. next = str+1;
  4612. }
  4613. /*
  4614. * scan backwards from the end of the string to the beginning,
  4615. * converting characters from hex chars to numbers as we go
  4616. */
  4617. str--;
  4618. mul = 1;
  4619. data = 0;
  4620. while( str >= ptr )
  4621. {
  4622. ch = *str;
  4623. if( ch >= 'A' && ch <= 'F' )
  4624. {
  4625. data += mul * (DWORD) (ch-'A'+10);
  4626. }
  4627. else if( ch >= 'a' && ch <= 'f' )
  4628. {
  4629. data += mul * (DWORD) (ch-'a'+10);
  4630. }
  4631. else if( ch >= '0' && ch <= '9' )
  4632. {
  4633. data += mul * (DWORD) (ch-'0');
  4634. }
  4635. else
  4636. {
  4637. return FALSE;
  4638. }
  4639. mul *= 16;
  4640. str--;
  4641. }
  4642. /*
  4643. * stuff the current number into the guid
  4644. */
  4645. switch( idx )
  4646. {
  4647. case 0:
  4648. pguid->Data1 = data;
  4649. break;
  4650. case 1:
  4651. pguid->Data2 = (WORD) data;
  4652. break;
  4653. case 2:
  4654. pguid->Data3 = (WORD) data;
  4655. break;
  4656. default:
  4657. pguid->Data4[ idx-3 ] = (BYTE) data;
  4658. break;
  4659. }
  4660. /*
  4661. * did we find all 11 numbers?
  4662. */
  4663. idx++;
  4664. if( idx == 11 )
  4665. {
  4666. if( done )
  4667. {
  4668. return TRUE;
  4669. }
  4670. else
  4671. {
  4672. return FALSE;
  4673. }
  4674. }
  4675. str = next;
  4676. }
  4677. return FALSE;
  4678. } /* strToGUID */
  4679. /*
  4680. * getDriverNameFromGUID
  4681. *
  4682. * look up the name of a driver based on the interface id
  4683. */
  4684. BOOL getDriverNameFromGUID( GUID *pguid, LPSTR pdrvname, BOOL *pisdisp, BOOL *pisprimary )
  4685. {
  4686. DWORD keyidx;
  4687. HKEY hkey;
  4688. HKEY hsubkey;
  4689. char keyname[256];
  4690. DWORD cb;
  4691. DWORD type;
  4692. GUID guid;
  4693. *pisdisp = FALSE;
  4694. *pdrvname = 0;
  4695. /*
  4696. * first check for a driver guid returned via EnumDisplayDevices.
  4697. */
  4698. if (pguid->Data1 >= DisplayGUID.Data1 &&
  4699. pguid->Data1 <= DisplayGUID.Data1 + 32 &&
  4700. memcmp(&pguid->Data2,&DisplayGUID.Data2,sizeof(GUID)-sizeof(DWORD))==0)
  4701. {
  4702. DISPLAY_DEVICEA dd;
  4703. ZeroMemory(&dd, sizeof(dd));
  4704. dd.cb = sizeof(dd);
  4705. if (xxxEnumDisplayDevicesA(NULL, pguid->Data1 - DisplayGUID.Data1, &dd, 0)
  4706. #ifdef WINNT
  4707. && (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
  4708. #endif
  4709. )
  4710. {
  4711. lstrcpy(pdrvname, dd.DeviceName);
  4712. if( dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE )
  4713. {
  4714. *pisprimary = TRUE;
  4715. }
  4716. *pisdisp = TRUE;
  4717. return TRUE;
  4718. }
  4719. return FALSE;
  4720. }
  4721. if( RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDHW, &hkey ) )
  4722. {
  4723. DPF( 3, "No registry information for any drivers" );
  4724. return FALSE;
  4725. }
  4726. keyidx = 0;
  4727. /*
  4728. * enumerate all subkeys under HKEY_LOCALMACHINE\Hardware\DirectDrawDrivers
  4729. */
  4730. while( !RegEnumKey( hkey, keyidx, keyname, sizeof( keyname ) ) )
  4731. {
  4732. if( strToGUID( keyname, &guid ) )
  4733. {
  4734. if( !RegOpenKey( hkey, keyname, &hsubkey ) )
  4735. {
  4736. if( IsEqualGUID( pguid, &guid ) )
  4737. {
  4738. cb = MAX_PATH-1;
  4739. if( !RegQueryValueEx( hsubkey, REGSTR_KEY_DDHW_DRIVERNAME, NULL, &type,
  4740. (CONST LPBYTE)pdrvname, &cb ) )
  4741. {
  4742. if( type == REG_SZ )
  4743. {
  4744. DPF( 5, "Found driver \"%s\"\n", pdrvname );
  4745. RegCloseKey( hsubkey );
  4746. RegCloseKey( hkey );
  4747. return TRUE;
  4748. }
  4749. }
  4750. DPF_ERR( "Could not get driver name!" );
  4751. RegCloseKey( hsubkey );
  4752. RegCloseKey( hkey );
  4753. return FALSE;
  4754. }
  4755. RegCloseKey( hsubkey );
  4756. }
  4757. }
  4758. keyidx++;
  4759. }
  4760. RegCloseKey( hkey );
  4761. return FALSE;
  4762. } /* getDriverNameFromGUID */
  4763. /*
  4764. * NewDriverInterface
  4765. *
  4766. * contruct a new interface to an existing driver object
  4767. */
  4768. LPVOID NewDriverInterface( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPVOID lpvtbl )
  4769. {
  4770. LPDDRAWI_DIRECTDRAW_INT pnew_int;
  4771. LPDDRAWI_DIRECTDRAW_LCL pnew_lcl;
  4772. DWORD size;
  4773. if( (lpvtbl == &ddCallbacks) ||
  4774. (lpvtbl == &ddUninitCallbacks) ||
  4775. (lpvtbl == &dd2UninitCallbacks) ||
  4776. (lpvtbl == &dd2Callbacks) ||
  4777. (lpvtbl == &dd4UninitCallbacks) ||
  4778. // (lpvtbl == &ddUninitNonDelegatingUnknownCallbacks) ||
  4779. (lpvtbl == &dd4Callbacks) ||
  4780. (lpvtbl == &dd7UninitCallbacks) ||
  4781. (lpvtbl == &dd7Callbacks) )
  4782. {
  4783. size = sizeof( DDRAWI_DIRECTDRAW_LCL );
  4784. }
  4785. else
  4786. {
  4787. return NULL;
  4788. }
  4789. pnew_lcl = MemAlloc( size );
  4790. if( NULL == pnew_lcl )
  4791. {
  4792. return NULL;
  4793. }
  4794. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4795. DPF( 5, "***New local allocated 0x%p for global pdrv 0x%p", pnew_lcl, pdrv );
  4796. pnew_int = MemAlloc( sizeof( DDRAWI_DIRECTDRAW_INT ) );
  4797. if( NULL == pnew_int )
  4798. {
  4799. MemFree( pnew_lcl );
  4800. return NULL;
  4801. }
  4802. /*
  4803. * set up data
  4804. */
  4805. ENTER_DRIVERLISTCSECT();
  4806. pnew_int->lpVtbl = lpvtbl;
  4807. pnew_int->lpLcl = pnew_lcl;
  4808. pnew_int->dwIntRefCnt = 1;
  4809. pnew_int->lpLink = lpDriverObjectList;
  4810. lpDriverObjectList = pnew_int;
  4811. pnew_lcl->lpGbl = pdrv;
  4812. pnew_lcl->dwLocalRefCnt = 1;
  4813. pnew_lcl->dwProcessId = GetCurrentProcessId();
  4814. pnew_lcl->hGammaCalibrator = (ULONG_PTR) INVALID_HANDLE_VALUE;
  4815. pnew_lcl->lpGammaCalibrator = NULL;
  4816. #ifdef WIN95
  4817. pnew_lcl->SurfaceHandleList.dwList=NULL;
  4818. pnew_lcl->SurfaceHandleList.dwFreeList=0;
  4819. #endif //WIN95
  4820. pnew_lcl->lpLink = lpDriverLocalList;
  4821. lpDriverLocalList = pnew_lcl;
  4822. if( pdrv != NULL )
  4823. {
  4824. pnew_lcl->lpDDCB = pdrv->lpDDCBtmp;
  4825. pnew_lcl->lpGbl->dwRefCnt++;
  4826. #ifdef WIN95
  4827. pnew_lcl->dwPreferredMode = pdrv->dwModeIndex;
  4828. #else
  4829. pnew_lcl->dmiPreferred = pdrv->dmiCurrent;
  4830. #endif
  4831. }
  4832. #ifdef WIN95
  4833. /*
  4834. * NOTE: We no longer get the DirectSound VXD handle at this point.
  4835. * We not get initialize it in InternalDirectDrawCreate(). This works
  4836. * well as the only two places this code currently gets invoked are
  4837. * the class factory stuff and DirectDrawCreate(). In the case of the
  4838. * class factory stuff this means there will be no VXD handle until
  4839. * initialize is called. This is not a problem, however, as there
  4840. * is nothing you can do with the VXD handle until Initialize() is
  4841. * called.
  4842. */
  4843. pnew_lcl->hDDVxd = (DWORD) INVALID_HANDLE_VALUE;
  4844. #endif /* WIN95 */
  4845. /*
  4846. * We lazily evaluate the Direct3D interface. Also note that
  4847. * the Direct3D IUnknown goes into the local DirectDraw object
  4848. * rather than the global one as the Direct3D DLL is not shared.
  4849. * Everyone gets their own copy.
  4850. */
  4851. pnew_lcl->hD3DInstance = NULL;
  4852. pnew_lcl->pD3DIUnknown = NULL;
  4853. LEAVE_DRIVERLISTCSECT();
  4854. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  4855. DPF( 5, "New driver object created, interface ptr = 0x%p", pnew_int );
  4856. return pnew_int;
  4857. } /* NewDriverInterface */
  4858. /*
  4859. * FetchDirectDrawData
  4860. *
  4861. * Go get new HAL info...
  4862. */
  4863. LPDDRAWI_DIRECTDRAW_GBL FetchDirectDrawData(
  4864. LPDDRAWI_DIRECTDRAW_GBL pdrv,
  4865. BOOL reset,
  4866. DWORD hInstance,
  4867. HANDLE hDDVxd,
  4868. char * szDrvName,
  4869. DWORD dwDriverContext,
  4870. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  4871. {
  4872. DWORD dw16BitVidmemInfo;
  4873. DWORD dw32BitVidmemInfo;
  4874. DDHALINFO ddhi;
  4875. LPDDRAWI_DIRECTDRAW_GBL newpdrv;
  4876. BOOL bLoadedSecondary=FALSE;
  4877. if( szDrvName == NULL )
  4878. {
  4879. if ( pdrv == NULL )
  4880. {
  4881. // This shouldn't happen
  4882. DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:FetchDirectDrawData: Driver and Driver Name is NULL");
  4883. DDASSERT( 0 );
  4884. return 0;
  4885. }
  4886. szDrvName = pdrv->cDriverName;
  4887. }
  4888. if( pdrv != NULL && (pdrv->dwFlags & DDRAWI_NOHARDWARE) )
  4889. {
  4890. HDC hdc;
  4891. // ATTENTION: why do this? Can't we just say pdrv->hdc instead of creating a dc??
  4892. hdc = DD_CreateDC( pdrv->cDriverName );
  4893. newpdrv = FakeDDCreateDriverObject( hdc, pdrv->cDriverName, pdrv, TRUE, hDDVxd );
  4894. if (newpdrv)
  4895. {
  4896. newpdrv->ddCaps.dwCaps2 |= DDCAPS2_CERTIFIED;
  4897. UpdateRectFromDevice( newpdrv );
  4898. }
  4899. DD_DoneDC( hdc );
  4900. return newpdrv;
  4901. }
  4902. else
  4903. {
  4904. ZeroMemory(&ddhi, sizeof(ddhi));
  4905. if( pdrv != NULL )
  4906. {
  4907. ddhi.hInstance = pdrv->hInstance;
  4908. }
  4909. else
  4910. {
  4911. ddhi.hInstance = hInstance;
  4912. }
  4913. #if defined(WIN95)
  4914. ENTER_WIN16LOCK();
  4915. DD16_GetHALInfo( &ddhi );
  4916. if( ddhi.lpDDCallbacks != NULL )
  4917. {
  4918. ddhi.lpDDCallbacks = MapSLFix( (DWORD) ddhi.lpDDCallbacks );
  4919. }
  4920. if( ddhi.lpDDSurfaceCallbacks != NULL )
  4921. {
  4922. ddhi.lpDDSurfaceCallbacks = MapSLFix( (DWORD) ddhi.lpDDSurfaceCallbacks );
  4923. }
  4924. if( ddhi.lpDDPaletteCallbacks != NULL )
  4925. {
  4926. ddhi.lpDDPaletteCallbacks = MapSLFix( (DWORD) ddhi.lpDDPaletteCallbacks );
  4927. }
  4928. if( ( ddhi.dwSize >= DDHALINFOSIZE_V2 ) && ( ddhi.lpDDExeBufCallbacks != NULL ) )
  4929. {
  4930. ddhi.lpDDExeBufCallbacks = MapSLFix( (DWORD) ddhi.lpDDExeBufCallbacks );
  4931. }
  4932. if( ddhi.lpdwFourCC != NULL )
  4933. {
  4934. ddhi.lpdwFourCC = MapSLFix( (DWORD) ddhi.lpdwFourCC );
  4935. }
  4936. if( ddhi.lpModeInfo != NULL )
  4937. {
  4938. ddhi.lpModeInfo = MapSLFix( (DWORD) ddhi.lpModeInfo );
  4939. }
  4940. if( ddhi.vmiData.pvmList != NULL )
  4941. {
  4942. dw16BitVidmemInfo = (DWORD) ddhi.vmiData.pvmList;
  4943. ddhi.vmiData.pvmList = MapSLFix( (DWORD)dw16BitVidmemInfo );
  4944. dw32BitVidmemInfo = (DWORD) ddhi.vmiData.pvmList;
  4945. }
  4946. if ( ddhi.lpD3DGlobalDriverData &&
  4947. (ddhi.dwFlags & DDHALINFO_GETDRIVERINFOSET) && !reset)
  4948. {
  4949. // this is a hack to Enforce D3DDEVCAPS_DRAWPRIMITIVES2 only on satackable drivers
  4950. // but not on Primary drivers as we are reluctant to force DDI revised
  4951. ddhi.lpD3DGlobalDriverData->hwCaps.dwDevCaps |= D3DDEVCAPS_DRAWPRIMITIVES2;
  4952. }
  4953. /*
  4954. * Give a secondary driver (if any) a chance.
  4955. */
  4956. if (IsVGADevice(szDrvName))
  4957. {
  4958. /*
  4959. * Only allow secondaries to hijack primary device
  4960. */
  4961. bLoadedSecondary = loadSecondaryDriver( &ddhi );
  4962. }
  4963. #endif
  4964. #ifdef WINNT
  4965. /*
  4966. * This is necessary to make GetDriverInfo function on NT. The handle in pdrv-hDD is per-process,
  4967. * so we need to fetch it from the local object. If this is a create call, then pdrv and pdrv_lcl
  4968. * will be null, and DirectDrawObjectCreate will create the hDD for this driver/process pair.
  4969. * If this is not a create call then it's a reset call, and we can stuff the already created hDD
  4970. * into the global so that it can be passed into GetDriverInfo. (Yes, a hack).
  4971. */
  4972. if (pdrv_lcl && pdrv)
  4973. {
  4974. DDASSERT(reset == TRUE);
  4975. pdrv->hDD = pdrv_lcl->hDD;
  4976. }
  4977. #endif
  4978. newpdrv = DirectDrawObjectCreate( &ddhi, reset, pdrv, hDDVxd, szDrvName, dwDriverContext,
  4979. pdrv_lcl ? pdrv_lcl->dwLocalFlags : 0);
  4980. if( newpdrv )
  4981. {
  4982. // Is this a
  4983. // Figure out the RECT for the device
  4984. UpdateRectFromDevice( newpdrv );
  4985. //Record if a secondary (PowerVR) was loaded
  4986. if ( bLoadedSecondary )
  4987. {
  4988. newpdrv->dwFlags |= DDRAWI_SECONDARYDRIVERLOADED;
  4989. }
  4990. }
  4991. #ifdef WINNT
  4992. /*
  4993. * On NT, they can switch to and from 4bpp modes where DDraw
  4994. * can't be used. If DirectDrawObjectCreate fails,
  4995. * set the mode index and clear out the caps and set
  4996. * dwModeIndex to unsupported so that it can't create or
  4997. * restore surfaces.
  4998. */
  4999. if( pdrv != NULL)
  5000. {
  5001. if( newpdrv )
  5002. {
  5003. pdrv->dwModeIndex = 0;
  5004. }
  5005. else
  5006. {
  5007. pdrv->dwModeIndex = DDUNSUPPORTEDMODE;
  5008. memset( &( pdrv->ddCaps ), 0, sizeof( DDCORECAPS ) );
  5009. pdrv->ddCaps.dwSize = sizeof( DDCORECAPS );
  5010. pdrv->ddCaps.dwCaps = DDCAPS_NOHARDWARE;
  5011. }
  5012. }
  5013. #endif
  5014. /*
  5015. * Tell the HEL a mode has changed (possibly externally)
  5016. */
  5017. ResetBITMAPINFO(newpdrv);
  5018. #ifdef WINNT
  5019. //GetCurrentMode will have allocated mem for this. If it's null, it hasn't.
  5020. MemFree( ddhi.lpModeInfo );
  5021. #endif
  5022. #if defined(WIN95)
  5023. LEAVE_WIN16LOCK();
  5024. #endif
  5025. }
  5026. return newpdrv;
  5027. } /* FetchDirectDrawData */
  5028. /*
  5029. * DirectDrawSupported
  5030. */
  5031. BOOL DirectDrawSupported( BOOL bDisplayMessage )
  5032. {
  5033. HDC hdc;
  5034. unsigned u;
  5035. hdc = GetDC( NULL );
  5036. u = GetDeviceCaps( hdc, BITSPIXEL ) * GetDeviceCaps( hdc, PLANES );
  5037. ReleaseDC( NULL, hdc );
  5038. if(( u < 8 ) && bDisplayMessage)
  5039. {
  5040. DPF( 0, "DirectDraw does not work in less than 8bpp modes" );
  5041. #ifdef WIN95
  5042. DirectDrawMsg(MAKEINTRESOURCE(IDS_DONTWORK_BPP));
  5043. #endif
  5044. return FALSE;
  5045. }
  5046. return TRUE;
  5047. } /* DirectDrawSupported */
  5048. /*
  5049. * DirectDrawCreate
  5050. *
  5051. * One of the two end-user API exported from DDRAW.DLL.
  5052. * Creates the DIRECTDRAW object.
  5053. */
  5054. #undef DPF_MODNAME
  5055. #define DPF_MODNAME "DirectDrawCreate"
  5056. HRESULT WINAPI DirectDrawCreate(
  5057. GUID FAR * lpGUID,
  5058. LPDIRECTDRAW FAR *lplpDD,
  5059. IUnknown FAR *pUnkOuter )
  5060. {
  5061. HRESULT hr;
  5062. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  5063. DPF(2,A,"ENTERAPI: DirectDrawCreate");
  5064. DPF(3,A," GUID *: 0x%p, LPLPDD: 0x%p, pUnkOuter: 0x%p", lpGUID, lplpDD, pUnkOuter);
  5065. if (pUnkOuter )
  5066. {
  5067. return CLASS_E_NOAGGREGATION;
  5068. }
  5069. bReloadReg = FALSE;
  5070. if( GetProfileInt("DirectDraw","reloadreg",0) )
  5071. {
  5072. bReloadReg = TRUE;
  5073. DPF( 3, "Reload registry each time" );
  5074. }
  5075. hr = InternalDirectDrawCreate( lpGUID, lplpDD, NULL, 0UL, NULL );
  5076. #ifdef POSTPONED
  5077. /*
  5078. * Fix up the owning unknown for this object
  5079. */
  5080. if (hr == DD_OK && *lplpDD)
  5081. {
  5082. LPDDRAWI_DIRECTDRAW_INT this_int = (LPDDRAWI_DIRECTDRAW_INT)*lplpDD;
  5083. if (pUnkOuter)
  5084. {
  5085. this_int->lpLcl->pUnkOuter = pUnkOuter;
  5086. }
  5087. else
  5088. {
  5089. this_int->lpLcl->pUnkOuter = (IUnknown*) &NonDelegatingIUnknownInterface;
  5090. }
  5091. }
  5092. #endif
  5093. #ifdef DEBUG
  5094. if (hr == DD_OK)
  5095. /*
  5096. * DD_OK implies lplpDD must be a valid pointer, so can't AV.
  5097. */
  5098. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  5099. DPF(3,A," DirectDrawCreate succeeds, and returns ddraw pointer 0x%p", *lplpDD);
  5100. else
  5101. DPF_APIRETURNS(hr);
  5102. #endif //debug
  5103. return hr;
  5104. } /* DirectDrawCreate */
  5105. /*
  5106. * DirectDrawCreateEx
  5107. *
  5108. * One of the two end-user API exported from DDRAW.DLL.
  5109. * Creates the DIRECTDRAW object.
  5110. */
  5111. #undef DPF_MODNAME
  5112. #define DPF_MODNAME "DirectDrawCreateEx"
  5113. HRESULT WINAPI DirectDrawCreateEx(
  5114. LPGUID rGuid,
  5115. LPVOID *lplpDD,
  5116. REFIID iid,
  5117. IUnknown FAR *pUnkOuter )
  5118. {
  5119. HRESULT hr;
  5120. LPDIRECTDRAW lpDD1;
  5121. DPF(2,A,"ENTERAPI: DirectDrawCreateEx");
  5122. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  5123. DPF(3,A,"rGuid: 0x%p, LPLPDD: 0x%p, pUnkOuter: 0x%p", rGuid, lplpDD, pUnkOuter);
  5124. if (pUnkOuter )
  5125. {
  5126. return CLASS_E_NOAGGREGATION;
  5127. }
  5128. if ( rGuid != NULL )
  5129. {
  5130. if ( !VALID_IID_PTR( rGuid ) )
  5131. {
  5132. DPF_ERR( "GUID reference is invalid" );
  5133. return DDERR_INVALIDPARAMS;
  5134. }
  5135. }
  5136. if (!IsEqualIID(iid, &IID_IDirectDraw7 ) )
  5137. {
  5138. DPF_ERR( "only IID_IDirectDraw7 is supported" );
  5139. return DDERR_INVALIDPARAMS;
  5140. }
  5141. bReloadReg = FALSE;
  5142. if( GetProfileInt("DirectDraw","reloadreg",0) )
  5143. {
  5144. bReloadReg = TRUE;
  5145. DPF( 3, "Reload registry each time" );
  5146. }
  5147. hr = InternalDirectDrawCreate((GUID FAR *)rGuid,&lpDD1, NULL, DDRAWILCL_DIRECTDRAW7, NULL );
  5148. #ifdef POSTPONED
  5149. /*
  5150. * Fix up the owning unknown for this object
  5151. */
  5152. if (hr == DD_OK && lpDD1)
  5153. {
  5154. LPDDRAWI_DIRECTDRAW_INT this_int = (LPDDRAWI_DIRECTDRAW_INT)lpDD1;
  5155. if (pUnkOuter)
  5156. {
  5157. this_int->lpLcl->pUnkOuter = pUnkOuter;
  5158. }
  5159. else
  5160. {
  5161. this_int->lpLcl->pUnkOuter = (IUnknown*) &NonDelegatingIUnknownInterface;
  5162. }
  5163. }
  5164. #endif
  5165. if (DD_OK != hr)
  5166. {
  5167. *lplpDD=NULL;
  5168. }
  5169. if (hr == DD_OK)
  5170. {
  5171. /*
  5172. * DD_OK implies lpDD1 must be a valid pointer, so can't AV.
  5173. */
  5174. // Now QI for the IDirectDraw7 interface
  5175. hr=lpDD1->lpVtbl->QueryInterface(lpDD1,&IID_IDirectDraw7,lplpDD);
  5176. lpDD1->lpVtbl->Release(lpDD1);
  5177. #ifdef DEBUG
  5178. if (lpDD1)
  5179. {
  5180. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  5181. DPF(3,A," DirectDrawCreateEx succeeds, and returns ddraw pointer 0x%p", *lplpDD);
  5182. }
  5183. #endif //debug
  5184. }
  5185. else
  5186. {
  5187. DPF_APIRETURNS(hr);
  5188. }
  5189. return hr;
  5190. } /* DirectDrawCreateEx */
  5191. /*
  5192. * getDriverInterface
  5193. */
  5194. static LPDDRAWI_DIRECTDRAW_INT getDriverInterface(
  5195. LPDDRAWI_DIRECTDRAW_INT pnew_int,
  5196. LPDDRAWI_DIRECTDRAW_GBL pdrv )
  5197. {
  5198. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  5199. if( pnew_int != NULL )
  5200. {
  5201. /*
  5202. * an interface was already created, so just assign the
  5203. * global data pointer and initialize a few things
  5204. */
  5205. DPF( 4, "Interface pointer already exists!" );
  5206. pdrv_lcl = pnew_int->lpLcl;
  5207. pdrv_lcl->lpGbl = pdrv;
  5208. pdrv_lcl->lpDDCB = pdrv->lpDDCBtmp;
  5209. #ifdef WIN95
  5210. pdrv_lcl->dwPreferredMode = pdrv->dwModeIndex;
  5211. #else
  5212. pdrv_lcl->dmiPreferred = pdrv->dmiCurrent;
  5213. #endif
  5214. pdrv->dwRefCnt += pdrv_lcl->dwLocalRefCnt;
  5215. }
  5216. else
  5217. {
  5218. pnew_int = NewDriverInterface( pdrv, &ddCallbacks );
  5219. }
  5220. return pnew_int;
  5221. } /* getDriverInterface */
  5222. // Utility function that tells us if there is more than
  5223. // one display device in the system. (We count all devices,
  5224. // regardless of whether they are attached to the desktop.)
  5225. BOOL IsMultiMonitor(void)
  5226. {
  5227. int i, n;
  5228. // Each loop below enumerates one display device.
  5229. for (i = 0, n = 0; ; i++)
  5230. {
  5231. DISPLAY_DEVICEA dd;
  5232. // Zero the memory of the DISPLAY_DEVICE struct between calls to
  5233. // EnumDisplayDevices
  5234. ZeroMemory(&dd, sizeof(dd));
  5235. dd.cb = sizeof(dd);
  5236. if (!xxxEnumDisplayDevicesA(NULL, i, &dd, 0))
  5237. {
  5238. break; // no more devices to enumerate
  5239. }
  5240. if (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
  5241. {
  5242. continue; // not a real hardware display driver
  5243. }
  5244. // We're just trying to count the number of display devices in the
  5245. // system and see if there is more than one.
  5246. if (++n > 1)
  5247. {
  5248. return TRUE; // multiple display devices
  5249. }
  5250. }
  5251. return FALSE; // single display device
  5252. }
  5253. extern DWORD HackMeBaby( void );
  5254. BOOL fDoesGDI(HDC hdc)
  5255. {
  5256. //
  5257. // the 3Dfx driver always return 1 to every thing
  5258. // verify GetNearest() color works.
  5259. //
  5260. BOOL b = GetNearestColor(hdc, 0x000000) == 0x000000 &&
  5261. GetNearestColor(hdc, 0xFFFFFF) == 0xFFFFFF;
  5262. if(b)
  5263. {
  5264. DPF(3,"Driver is a GDI driver");
  5265. }
  5266. return b;
  5267. }
  5268. /*
  5269. * IsAttachedToDesktop
  5270. *
  5271. * DCI is hardwired to the primary display which means it can't
  5272. * be used on a multi-mon system. Usually GDI disables it for
  5273. * us, but it does not when there are two monitors and only one
  5274. * of them uses the desktop. We'd still like to use DCI for
  5275. * the desktop in this case, but we can't use it if the monitor
  5276. * is not attached to the desktop. That is why this function exists.
  5277. */
  5278. BOOL IsAttachedToDesktop( LPGUID lpGuid )
  5279. {
  5280. DWORD n;
  5281. GUID guid;
  5282. DISPLAY_DEVICEA dd;
  5283. if( !IsMultiMonitor() )
  5284. {
  5285. return TRUE;
  5286. }
  5287. /*
  5288. * Assume that the primary is always attached
  5289. */
  5290. if( (lpGuid == (GUID *) DDCREATE_EMULATIONONLY) ||
  5291. (lpGuid == (GUID *) DDCREATE_HARDWAREONLY) ||
  5292. (lpGuid == NULL) ||
  5293. (IsEqualGUID( lpGuid, &GUID_NULL) ) )
  5294. {
  5295. return TRUE;
  5296. }
  5297. ZeroMemory(&dd, sizeof(dd));
  5298. dd.cb = sizeof(dd);
  5299. for( n=0; xxxEnumDisplayDevicesA( NULL, n, &dd, 0 ); n++ )
  5300. {
  5301. guid = DisplayGUID;
  5302. guid.Data1 += n;
  5303. if( IsEqualIID( lpGuid, &guid) )
  5304. {
  5305. if( dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP )
  5306. {
  5307. return TRUE;
  5308. }
  5309. else
  5310. {
  5311. return FALSE;
  5312. }
  5313. }
  5314. ZeroMemory( &dd, sizeof(dd) );
  5315. dd.cb = sizeof(dd);
  5316. }
  5317. return TRUE;
  5318. } /* IsAttachedToDesktop */
  5319. /*
  5320. * Functions to dynamically link against exports we need in user32 on
  5321. * older OSes
  5322. */
  5323. //These statics will be per-process, cuz it's outside the shared section
  5324. typedef BOOL (WINAPI * LPENUMMONITORS) (HDC, LPRECT, MONITORENUMPROC, LPARAM);
  5325. typedef BOOL (WINAPI * LPGETMONINFO) (HMONITOR, MONITORINFO *);
  5326. typedef BOOL (WINAPI * LPISDEBUG) (void);
  5327. static LPISDEBUG pIsDebuggerPresent = 0;
  5328. static LPENUMMONITORS pEnumMonitors = 0;
  5329. static LPGETMONINFO pGetMonitorInfo = 0;
  5330. static BOOL bTriedToGetProcAlready = FALSE;
  5331. BOOL DynamicLinkToOS(void)
  5332. {
  5333. if (1) //!pEnumMonitors)
  5334. {
  5335. HMODULE hUser32;
  5336. HMODULE hKernel32;
  5337. if (0) //bTriedToGetProcAlready)
  5338. return FALSE;
  5339. bTriedToGetProcAlready = TRUE;
  5340. hUser32 = GetModuleHandle(TEXT("USER32"));
  5341. pEnumMonitors = (LPENUMMONITORS) GetProcAddress(hUser32,"EnumDisplayMonitors");
  5342. pGetMonitorInfo = (LPGETMONINFO) GetProcAddress(hUser32,"GetMonitorInfoA");
  5343. hKernel32 = GetModuleHandle(TEXT("KERNEL32"));
  5344. pIsDebuggerPresent = (LPISDEBUG) GetProcAddress(hKernel32,"IsDebuggerPresent");
  5345. if (!pEnumMonitors || !pGetMonitorInfo || !pIsDebuggerPresent)
  5346. {
  5347. DPF(3,"Failed to get proc addresses");
  5348. return FALSE;
  5349. }
  5350. }
  5351. DDASSERT(pEnumMonitors);
  5352. DDASSERT(pGetMonitorInfo);
  5353. DDASSERT(pEnumMonitors);
  5354. return TRUE;
  5355. }
  5356. BOOL InternalGetMonitorInfo(HMONITOR hMon, MONITORINFO *lpInfo)
  5357. {
  5358. DynamicLinkToOS();
  5359. if (!pGetMonitorInfo)
  5360. return FALSE;
  5361. return pGetMonitorInfo(hMon, lpInfo);
  5362. }
  5363. typedef struct
  5364. {
  5365. LPSTR pName;
  5366. HMONITOR hMon;
  5367. } CALLBACKSTRUCT, * LPCALLBACKSTRUCT;
  5368. BOOL InternalEnumMonitors(MONITORENUMPROC proc, LPCALLBACKSTRUCT lp)
  5369. {
  5370. DynamicLinkToOS();
  5371. if (!pEnumMonitors)
  5372. return FALSE;
  5373. pEnumMonitors(NULL,NULL,proc,(LPARAM)lp);
  5374. return TRUE;
  5375. }
  5376. /*
  5377. * InternalIsDebuggerPresent
  5378. * A little helper so that this runtime runs against older OSes
  5379. */
  5380. BOOL InternalIsDebuggerPresent(void)
  5381. {
  5382. DynamicLinkToOS();
  5383. if (!pIsDebuggerPresent)
  5384. return FALSE;
  5385. return pIsDebuggerPresent();
  5386. }
  5387. //
  5388. // getPrimaryDisplayName
  5389. //
  5390. void getPrimaryDisplayName(void)
  5391. {
  5392. DISPLAY_DEVICE dd;
  5393. int i;
  5394. ZeroMemory(&dd, sizeof dd);
  5395. dd.cb = sizeof dd;
  5396. for (i = 0; xxxEnumDisplayDevicesA(NULL, i, &dd, 0); ++i)
  5397. {
  5398. if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
  5399. {
  5400. lstrcpyn(g_szPrimaryDisplay, dd.DeviceName, sizeof g_szPrimaryDisplay);
  5401. return;
  5402. }
  5403. }
  5404. lstrcpy(g_szPrimaryDisplay, DISPLAY_STR);
  5405. }
  5406. /*
  5407. * InternalDirectDrawCreate
  5408. */
  5409. HRESULT InternalDirectDrawCreate(
  5410. GUID * lpGUID,
  5411. LPDIRECTDRAW *lplpDD,
  5412. LPDDRAWI_DIRECTDRAW_INT pnew_int,
  5413. DWORD dwCallFlags,
  5414. char * pDeviceName)
  5415. {
  5416. DCICMD cmd;
  5417. UINT u;
  5418. int rc;
  5419. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  5420. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  5421. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  5422. LPSTR pdrvname;
  5423. HDC hdc_dd;
  5424. BOOL isdispdrv;
  5425. BOOL hel_only;
  5426. DWORD dwFlags;
  5427. char drvname[MAX_PATH];
  5428. DWORD pid;
  5429. HKEY hkey;
  5430. DWORD hackflags;
  5431. #ifdef WIN95
  5432. int halver;
  5433. #endif
  5434. HANDLE hDDVxd;
  5435. BOOL bIsPrimary;
  5436. BOOL bExplicitMonitor = FALSE;
  5437. ULONG_PTR hDD;
  5438. #ifndef DX_FINAL_RELEASE
  5439. #pragma message( REMIND( "Remove time bomb for final!" ))
  5440. {
  5441. SYSTEMTIME st;
  5442. TCHAR tstrText[MAX_PATH];
  5443. TCHAR tstrTitle[MAX_PATH];
  5444. GetSystemTime( &st );
  5445. if( ( st.wYear > DX_EXPIRE_YEAR ) ||
  5446. ( ( st.wYear == DX_EXPIRE_YEAR ) &&
  5447. ( ( st.wMonth > DX_EXPIRE_MONTH ) || ( ( st.wMonth == DX_EXPIRE_MONTH ) && ( st.wDay >= DX_EXPIRE_DAY ) ) ) ) )
  5448. {
  5449. LoadString( hModule, IDS_TIME_BOMB, tstrText, MAX_PATH);
  5450. LoadString( hModule, IDS_TIME_BOMB_TITLE, tstrTitle, MAX_PATH);
  5451. if( 0 == MessageBox( NULL, tstrText, tstrTitle, MB_OK) )
  5452. {
  5453. DPF( 0, "DirectDraw Beta Expired. Please Update" );
  5454. *lplpDD = (LPDIRECTDRAW) NULL;
  5455. return DDERR_GENERIC;
  5456. }
  5457. }
  5458. }
  5459. #endif //DX_FINAL_RELEASE
  5460. /*
  5461. * validate parameters
  5462. */
  5463. if( !VALIDEX_PTR_PTR( lplpDD ) )
  5464. {
  5465. DPF_ERR( "Invalid lplpDD" );
  5466. return DDERR_INVALIDPARAMS;
  5467. }
  5468. *lplpDD = (LPDIRECTDRAW) NULL;
  5469. /*
  5470. * check for < 8 bpp and disallow.
  5471. */
  5472. if( !DirectDrawSupported(!(dwCallFlags & DDRAWILCL_DIRECTDRAW8)) )
  5473. {
  5474. return DDERR_NODIRECTDRAWSUPPORT;
  5475. }
  5476. ENTER_CSDDC();
  5477. ENTER_DDRAW();
  5478. hackflags = HackMeBaby();
  5479. DPF( 5, "DirectDrawCreate: pid = %08lx", GETCURRPID() );
  5480. /*
  5481. * pull in registry values
  5482. */
  5483. DPF( 4, "Reading Registry" );
  5484. if( !RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDRAW, &hkey ) )
  5485. {
  5486. DWORD type;
  5487. DWORD value;
  5488. DWORD cb;
  5489. cb = sizeof( value );
  5490. dwRegFlags &= ~(DDRAW_REGFLAGS_MODEXONLY |
  5491. DDRAW_REGFLAGS_EMULATIONONLY |
  5492. DDRAW_REGFLAGS_SHOWFRAMERATE |
  5493. DDRAW_REGFLAGS_ENABLEPRINTSCRN |
  5494. DDRAW_REGFLAGS_DISABLEWIDESURF |
  5495. DDRAW_REGFLAGS_NODDSCAPSINDDSD |
  5496. DDRAW_REGFLAGS_DISABLEMMX |
  5497. DDRAW_REGFLAGS_FORCEREFRESHRATE |
  5498. DDRAW_REGFLAGS_DISABLEAGPSUPPORT);
  5499. dwRegFlags &= ~DDRAW_REGFLAGS_AGPPOLICYMAXBYTES;
  5500. #ifndef WINNT
  5501. #ifdef DEBUG
  5502. dwAGPPolicyCommitDelta = DEFAULT_AGP_COMMIT_DELTA;
  5503. #endif /* DEBUG */
  5504. #endif
  5505. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_MODEXONLY, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5506. {
  5507. DPF( 2, " ModeXOnly: %d", value );
  5508. if( value )
  5509. {
  5510. dwRegFlags |= DDRAW_REGFLAGS_MODEXONLY;
  5511. }
  5512. }
  5513. cb = sizeof( value );
  5514. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_EMULATIONONLY, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5515. {
  5516. DPF( 2, " EmulationOnly: %d", value );
  5517. if( value )
  5518. {
  5519. dwRegFlags |= DDRAW_REGFLAGS_EMULATIONONLY;
  5520. }
  5521. }
  5522. cb = sizeof( value );
  5523. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_SHOWFRAMERATE, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5524. {
  5525. DPF( 2, " ShowFrameRate: %d", value );
  5526. if( value )
  5527. {
  5528. dwRegFlags |= DDRAW_REGFLAGS_SHOWFRAMERATE;
  5529. }
  5530. }
  5531. cb = sizeof( value );
  5532. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_ENABLEPRINTSCRN, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5533. {
  5534. DPF( 2, " EnablePrintScreen: %d", value );
  5535. if( value )
  5536. {
  5537. dwRegFlags |= DDRAW_REGFLAGS_ENABLEPRINTSCRN;
  5538. }
  5539. }
  5540. cb = sizeof( value );
  5541. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_FORCEAGPSUPPORT, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5542. {
  5543. DPF( 2, " ForceAGPSupport: %d", value );
  5544. if( value )
  5545. {
  5546. dwRegFlags |= DDRAW_REGFLAGS_FORCEAGPSUPPORT;
  5547. }
  5548. }
  5549. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEAGPSUPPORT, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5550. {
  5551. DPF( 2, " DisableAGPSupport: %d", value );
  5552. if( value )
  5553. {
  5554. dwRegFlags |= DDRAW_REGFLAGS_DISABLEAGPSUPPORT;
  5555. }
  5556. }
  5557. cb = sizeof( value );
  5558. #ifdef WIN95
  5559. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_AGPPOLICYMAXPAGES, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5560. {
  5561. DPF( 2, " AGPPolicyMaxPages: %d", value );
  5562. dwRegFlags |= DDRAW_REGFLAGS_AGPPOLICYMAXBYTES;
  5563. dwAGPPolicyMaxBytes = value * 4096;
  5564. }
  5565. #ifdef DEBUG
  5566. cb = sizeof( value );
  5567. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_AGPPOLICYCOMMITDELTA, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5568. {
  5569. DPF( 2, " AGPPolicyCommitDelta: %d", value );
  5570. dwAGPPolicyCommitDelta = value;
  5571. }
  5572. #endif /* DEBUG */
  5573. #endif
  5574. cb = sizeof( value );
  5575. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEMMX, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5576. {
  5577. DPF( 2, " DisableMMX: %d", value );
  5578. if( value )
  5579. {
  5580. dwRegFlags |= DDRAW_REGFLAGS_DISABLEMMX;
  5581. }
  5582. }
  5583. cb = sizeof( value );
  5584. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_NODDSCAPSINDDSD, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5585. {
  5586. DPF( 2, " Disable ddscaps in DDSURFACEDESC: %d", value );
  5587. if( value )
  5588. {
  5589. dwRegFlags |= DDRAW_REGFLAGS_NODDSCAPSINDDSD;
  5590. }
  5591. }
  5592. cb = sizeof( value );
  5593. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEWIDERSURFACES, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5594. {
  5595. DPF( 2, " DisableWiderSurfaces:%d", value );
  5596. if( value )
  5597. {
  5598. dwRegFlags |= DDRAW_REGFLAGS_DISABLEWIDESURF;
  5599. }
  5600. }
  5601. cb = sizeof( value );
  5602. if( !RegQueryValueEx( hkey, REGSTR_VAL_D3D_USENONLOCALVIDMEM, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5603. {
  5604. DPF( 2, " UseNonLocalVidmem:%d", value );
  5605. if( value )
  5606. {
  5607. dwRegFlags |= DDRAW_REGFLAGS_USENONLOCALVIDMEM;
  5608. }
  5609. }
  5610. cb = sizeof( value );
  5611. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_FORCEREFRESHRATE, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5612. {
  5613. DPF( 2, " ForceRefreshRate:%d", value );
  5614. if( value )
  5615. {
  5616. dwRegFlags |= DDRAW_REGFLAGS_FORCEREFRESHRATE;
  5617. dwForceRefreshRate = value;
  5618. }
  5619. }
  5620. #ifdef DEBUG
  5621. /*
  5622. * NOSYSLOCK (No Win16 locking) control flags. DEBUG only.
  5623. */
  5624. dwRegFlags &= ~(DDRAW_REGFLAGS_DISABLENOSYSLOCK | DDRAW_REGFLAGS_FORCENOSYSLOCK | DDRAW_REGFLAGS_DISABLEINACTIVATE);
  5625. cb = sizeof( value );
  5626. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLENOSYSLOCK, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5627. {
  5628. DPF( 2, " DisableNoSysLock:%d", value );
  5629. if( value )
  5630. {
  5631. dwRegFlags |= DDRAW_REGFLAGS_DISABLENOSYSLOCK;
  5632. }
  5633. }
  5634. cb = sizeof( value );
  5635. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_FORCENOSYSLOCK, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5636. {
  5637. DPF( 2, " ForceNoSysLock:%d", value );
  5638. if( value )
  5639. {
  5640. dwRegFlags |= DDRAW_REGFLAGS_FORCENOSYSLOCK;
  5641. }
  5642. }
  5643. if( ( dwRegFlags & DDRAW_REGFLAGS_DISABLENOSYSLOCK ) &&
  5644. ( dwRegFlags & DDRAW_REGFLAGS_FORCENOSYSLOCK ) )
  5645. {
  5646. DPF( 0, "Attempt to both disable and force NOSYSLOCK on locks. Ignoring both" );
  5647. dwRegFlags &= ~(DDRAW_REGFLAGS_DISABLENOSYSLOCK | DDRAW_REGFLAGS_FORCENOSYSLOCK);
  5648. }
  5649. /*
  5650. * Hack to allow multi-mon debugging w/o minimizing the exclusive
  5651. * mode app when it gets a WM_ACTIVATEAPP msg. We only do this
  5652. * in the debug version.
  5653. */
  5654. cb = sizeof( value );
  5655. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEINACTIVATE, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5656. {
  5657. DPF( 2, " DisableInactivate:%d", value );
  5658. if( value && InternalIsDebuggerPresent() )
  5659. {
  5660. dwRegFlags |= DDRAW_REGFLAGS_DISABLEINACTIVATE;
  5661. }
  5662. }
  5663. #endif /* DEBUG */
  5664. RegCloseKey(hkey);
  5665. }
  5666. if( !RegOpenKey( HKEY_LOCAL_MACHINE, RESPATH_D3D, &hkey ) )
  5667. {
  5668. DWORD type;
  5669. DWORD value;
  5670. DWORD cb;
  5671. cb = sizeof( value );
  5672. dwRegFlags &= ~DDRAW_REGFLAGS_FLIPNONVSYNC;
  5673. if( !RegQueryValueEx( hkey, REGSTR_VAL_D3D_FLIPNOVSYNC, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  5674. {
  5675. DPF( 2, REGSTR_VAL_D3D_FLIPNOVSYNC" :%d", value );
  5676. if( value )
  5677. {
  5678. dwRegFlags |= DDRAW_REGFLAGS_FLIPNONVSYNC;
  5679. }
  5680. }
  5681. RegCloseKey(hkey);
  5682. }
  5683. hdc_dd = NULL;
  5684. hDD = 0;
  5685. dwFlags = 0;
  5686. //
  5687. // Get the primary display name, which will usually be something like
  5688. // \\.\Display1 and in some cases may be \\.\Display1\Unit0. We only
  5689. // do this one time, and store it globally. On Win98, the global name
  5690. // will be shared between all processes, and on NT5, each process will
  5691. // have its own copy. Also, note that the primary device name may change
  5692. // on NT5; we need to look into this.
  5693. //
  5694. if (g_szPrimaryDisplay[0] == '\0')
  5695. {
  5696. getPrimaryDisplayName();
  5697. }
  5698. /*
  5699. * any special cases?
  5700. */
  5701. bIsPrimary = FALSE;
  5702. isdispdrv = FALSE;
  5703. if( dwRegFlags & DDRAW_REGFLAGS_EMULATIONONLY )
  5704. {
  5705. DWORD cMonitors = GetSystemMetrics( SM_CMONITORS );
  5706. dwFlags |= DDCREATE_EMULATIONONLY;
  5707. if( cMonitors <= 1 )
  5708. {
  5709. // For compatibility with pre-multimon versions of DDraw
  5710. bIsPrimary = TRUE;
  5711. }
  5712. }
  5713. if( pDeviceName == NULL)
  5714. {
  5715. if( lpGUID == (GUID *) DDCREATE_EMULATIONONLY )
  5716. {
  5717. dwFlags |= DDCREATE_EMULATIONONLY;
  5718. bIsPrimary = TRUE;
  5719. }
  5720. else if( lpGUID == NULL )
  5721. {
  5722. bIsPrimary = TRUE;
  5723. }
  5724. else if( lpGUID == (GUID *) DDCREATE_HARDWAREONLY )
  5725. {
  5726. dwFlags |= DDCREATE_HARDWAREONLY;
  5727. bIsPrimary = TRUE;
  5728. }
  5729. if (bIsPrimary)
  5730. {
  5731. lpGUID = (GUID *) &GUID_NULL; // primary monitor
  5732. }
  5733. else if( !VALIDEX_GUID_PTR( lpGUID ) )
  5734. {
  5735. DPF_ERR( "Invalid GUID passed in" );
  5736. LEAVE_DDRAW();
  5737. LEAVE_CSDDC();
  5738. return DDERR_INVALIDPARAMS;
  5739. }
  5740. if( IsEqualGUID( lpGUID, &GUID_NULL ) )
  5741. {
  5742. pdrvname = DISPLAY_STR; // "display"
  5743. isdispdrv = TRUE;
  5744. bIsPrimary = TRUE;
  5745. }
  5746. else
  5747. {
  5748. if( !getDriverNameFromGUID( lpGUID, drvname, &isdispdrv, &bIsPrimary ) )
  5749. {
  5750. DPF_ERR( "Invalid GUID for driver" );
  5751. LEAVE_DDRAW();
  5752. LEAVE_CSDDC();
  5753. return DDERR_INVALIDDIRECTDRAWGUID;
  5754. }
  5755. pdrvname = drvname;
  5756. }
  5757. }
  5758. else
  5759. {
  5760. pdrvname = pDeviceName;
  5761. }
  5762. if ((ULONG_PTR)pdrvname != (ULONG_PTR)DISPLAY_STR)
  5763. {
  5764. bExplicitMonitor = TRUE;
  5765. if (_stricmp(pdrvname, g_szPrimaryDisplay) == 0)
  5766. {
  5767. pdrvname = DISPLAY_STR;
  5768. }
  5769. }
  5770. pid = GETCURRPID();
  5771. #ifdef WIN95
  5772. /*
  5773. * We need to ensure that DDHELP has a handle to the DirectX VXD
  5774. * that it can use when creating, freeing or mapping virtual memory
  5775. * aliases or AGP heaps on mode switches or cleanups.
  5776. */
  5777. if( INVALID_HANDLE_VALUE == hHelperDDVxd )
  5778. {
  5779. hHelperDDVxd = HelperGetDDVxd();
  5780. if( INVALID_HANDLE_VALUE == hHelperDDVxd )
  5781. {
  5782. DPF_ERR( "DDHELP could not load the DirectX VXD" );
  5783. LEAVE_DDRAW();
  5784. LEAVE_CSDDC();
  5785. return DDERR_GENERIC;
  5786. }
  5787. }
  5788. /*
  5789. * Create a handle for VXD communication. We will use this for
  5790. * alias construction in this function and we will later store
  5791. * this in the local object for later alias manipulation and
  5792. * page locking purposes.
  5793. */
  5794. hDDVxd = GetDXVxdHandle();
  5795. if( INVALID_HANDLE_VALUE == hDDVxd )
  5796. {
  5797. DPF_ERR( "Unable to open the DirectX VXD" );
  5798. LEAVE_DDRAW();
  5799. LEAVE_CSDDC();
  5800. return DDERR_GENERIC;
  5801. }
  5802. #else /* WIN95 */
  5803. hDDVxd = INVALID_HANDLE_VALUE;
  5804. #endif /* WIN95 */
  5805. /*
  5806. * run the driver list, looking for one that already exists. We used to run
  5807. * the interface list, but thanks to D3D it is possible for all locals to exist
  5808. * w/o anything in the interface list.
  5809. */
  5810. pdrv_lcl = lpDriverLocalList;
  5811. while( pdrv_lcl != NULL )
  5812. {
  5813. pdrv = pdrv_lcl->lpGbl;
  5814. if( pdrv != NULL )
  5815. {
  5816. if( !_stricmp( pdrv->cDriverName, pdrvname ) )
  5817. {
  5818. // If they asked for hardware; then don't accept the
  5819. // emulated driver
  5820. if( !(dwFlags & DDCREATE_EMULATIONONLY) &&
  5821. !(pdrv->dwFlags & DDRAWI_NOHARDWARE) )
  5822. {
  5823. DPF( 2, "Driver \"%s\" found for hardware", pdrvname );
  5824. break;
  5825. }
  5826. // If they asked for emulation; then don't accept the
  5827. // hardware driver
  5828. if( (dwFlags & DDCREATE_EMULATIONONLY) &&
  5829. (pdrv->dwFlags & DDRAWI_NOHARDWARE) )
  5830. {
  5831. DPF( 2, "Driver \"%s\" found for emulation", pdrvname );
  5832. break;
  5833. }
  5834. // Compatibility: on single monitor systems take whatever
  5835. // we got. (This is what we did in DX3)
  5836. if( pdrv->cMonitors <= 1 )
  5837. {
  5838. DPF( 2, "Driver \"%s\" found", pdrvname );
  5839. break;
  5840. }
  5841. }
  5842. }
  5843. pdrv_lcl = pdrv_lcl->lpLink;
  5844. }
  5845. /*
  5846. * if driver object already exists, get emulation layer if needed,
  5847. * create a new interface to it and return
  5848. */
  5849. if( pdrv_lcl != NULL )
  5850. {
  5851. LPDDRAWI_DIRECTDRAW_LCL tmp_lcl;
  5852. // This is the hdc we need to release if something
  5853. // goes wrong; since we are sometimes
  5854. // sharing an HDC with an existing LCL, we must
  5855. // be careful not to release it while it is still
  5856. // in use.
  5857. HDC hdcCleanup = NULL;
  5858. /*
  5859. * see if the current process has attached to this driver before...
  5860. */
  5861. tmp_lcl = lpDriverLocalList;
  5862. while( tmp_lcl != NULL )
  5863. {
  5864. if( tmp_lcl->dwProcessId == pid &&
  5865. tmp_lcl->lpGbl == pdrv)
  5866. {
  5867. break;
  5868. }
  5869. tmp_lcl = tmp_lcl->lpLink;
  5870. }
  5871. if( tmp_lcl == NULL )
  5872. {
  5873. hdc_dd = NULL;
  5874. }
  5875. else
  5876. {
  5877. // We found the process/driver pair we were looking for.
  5878. hdc_dd = (HDC) tmp_lcl->hDC;
  5879. DDASSERT(hdc_dd != 0);
  5880. hDD = tmp_lcl->hDD;
  5881. }
  5882. /*
  5883. * we need a new DC if this is a new process/driver pair...
  5884. */
  5885. if( hdc_dd == NULL )
  5886. {
  5887. DWORD flags;
  5888. flags = pdrv->dwFlags;
  5889. hdc_dd = DD_CreateFirstDC( pdrvname );
  5890. if( hdc_dd == NULL )
  5891. {
  5892. DPF_ERR( "Could not get a DC for the driver" );
  5893. CLOSEVXD( hDDVxd );
  5894. LEAVE_DDRAW();
  5895. LEAVE_CSDDC();
  5896. /* GEE: decided this error was rare enough to be left generic */
  5897. return DDERR_GENERIC;
  5898. }
  5899. if (!(pdrv->dwFlags & DDRAWI_DISPLAYDRV))
  5900. {
  5901. if (fDoesGDI(hdc_dd))
  5902. {
  5903. pdrv->dwFlags |= DDRAWI_GDIDRV;
  5904. }
  5905. else
  5906. {
  5907. pdrv->dwFlags &= ~DDRAWI_GDIDRV;
  5908. }
  5909. }
  5910. // We need to free it if something goes wrong
  5911. hdcCleanup = hdc_dd;
  5912. }
  5913. /*
  5914. * Set up emulation for display and non-display drivers
  5915. */
  5916. if( dwFlags & DDCREATE_EMULATIONONLY )
  5917. {
  5918. if( !(pdrv->dwFlags & DDRAWI_NOHARDWARE) )
  5919. {
  5920. DD_DoneDC(hdcCleanup);
  5921. DPF_ERR( "EMULATIONONLY requested, but driver exists and has hardware" );
  5922. CLOSEVXD( hDDVxd );
  5923. LEAVE_DDRAW();
  5924. LEAVE_CSDDC();
  5925. /* GEE: Why do we fail emulation only calls just because we have a driver? */
  5926. return DDERR_GENERIC;
  5927. }
  5928. }
  5929. /*
  5930. * we will need to load the emulation layer...
  5931. */
  5932. if( !(pdrv->dwFlags & DDRAWI_NOEMULATION) &&
  5933. !(pdrv->dwFlags & DDRAWI_EMULATIONINITIALIZED ) )
  5934. {
  5935. capsInit( pdrv );
  5936. hel_only = ((dwFlags & DDCREATE_EMULATIONONLY) != 0);
  5937. if( !helInit( pdrv, dwFlags, hel_only ) )
  5938. {
  5939. DD_DoneDC(hdcCleanup);
  5940. DPF_ERR( "HEL initialization failed" );
  5941. CLOSEVXD( hDDVxd );
  5942. LEAVE_DDRAW();
  5943. LEAVE_CSDDC();
  5944. /* GEE: HEL can only fail in v1 for lack of memory */
  5945. return DDERR_GENERIC;
  5946. }
  5947. }
  5948. pdrv_int = getDriverInterface( pnew_int, pdrv );
  5949. if( pdrv_int == NULL )
  5950. {
  5951. DD_DoneDC(hdcCleanup);
  5952. DPF_ERR( "No memory for driver callbacks." );
  5953. CLOSEVXD( hDDVxd );
  5954. LEAVE_DDRAW();
  5955. LEAVE_CSDDC();
  5956. return DDERR_OUTOFMEMORY;
  5957. }
  5958. pdrv_lcl = pdrv_int->lpLcl;
  5959. pdrv_lcl->dwAppHackFlags = hackflags;
  5960. #ifdef DEBUG
  5961. if( dwRegFlags & DDRAW_REGFLAGS_DISABLEINACTIVATE )
  5962. {
  5963. pdrv_lcl->dwLocalFlags |= DDRAWILCL_DISABLEINACTIVATE;
  5964. }
  5965. #endif
  5966. if( IsAttachedToDesktop( lpGUID ) )
  5967. {
  5968. pdrv->dwFlags |= DDRAWI_ATTACHEDTODESKTOP;
  5969. }
  5970. if (bExplicitMonitor)
  5971. {
  5972. pdrv_lcl->dwLocalFlags |= DDRAWILCL_EXPLICITMONITOR;
  5973. }
  5974. pdrv_lcl->dwLocalFlags |= dwCallFlags;
  5975. pdrv_lcl->hDDVxd = (ULONG_PTR) hDDVxd;
  5976. #ifdef WIN95
  5977. if( hdcCleanup )
  5978. {
  5979. // If we had to create a DC from
  5980. // scratch then we need to mark it
  5981. // private so that it will be never
  5982. // be deleted out from under us
  5983. DDASSERT( hdcCleanup == hdc_dd );
  5984. DD16_MakeObjectPrivate( hdc_dd, TRUE );
  5985. }
  5986. #endif
  5987. #ifdef WINNT
  5988. if( hdcCleanup )
  5989. {
  5990. BOOL bRetVal;
  5991. // We had to create a DC from scratch for this process/driver pair.
  5992. DDASSERT(hdcCleanup == hdc_dd);
  5993. // GDI creates a DirectDraw handle for each unique process/driver pair.
  5994. if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
  5995. {
  5996. // A fake DDraw driver that lets the HEL do everything.
  5997. bRetVal = DdCreateDirectDrawObject(pdrv, (HDC)0);
  5998. }
  5999. else
  6000. {
  6001. // A real DDraw driver with hardware acceleration.
  6002. bRetVal = DdCreateDirectDrawObject(pdrv, hdc_dd);
  6003. }
  6004. if (!bRetVal)
  6005. {
  6006. DPF_ERR( "Call to DdCreateDirectDrawObject failed!");
  6007. DD_DoneDC(hdc_dd);
  6008. LEAVE_DDRAW();
  6009. LEAVE_CSDDC();
  6010. return DDERR_NODIRECTDRAWHW;
  6011. }
  6012. // The DdCreateDirectDrawObject() call above loaded a DD handle into a
  6013. // into a temp location in the driver GBL object, but we must now save
  6014. // the handle in the driver LCL object so it won't be overwritten if
  6015. // another process calls DdCreateDirectDrawObject() on the same driver.
  6016. hDD = pdrv->hDD;
  6017. }
  6018. pdrv_lcl->hDD = hDD;
  6019. #endif //WINNT
  6020. (HDC) pdrv_lcl->hDC = hdc_dd;
  6021. *lplpDD = (LPDIRECTDRAW) pdrv_int;
  6022. LEAVE_DDRAW();
  6023. LEAVE_CSDDC();
  6024. return DD_OK;
  6025. }
  6026. /*
  6027. * if no match among the existing drivers, then we have to go off
  6028. * and create one
  6029. */
  6030. hdc_dd = DD_CreateFirstDC( pdrvname );
  6031. if( hdc_dd == NULL )
  6032. {
  6033. DPF_ERR( "Could not create driver, CreateDC failed!" );
  6034. CLOSEVXD( hDDVxd );
  6035. LEAVE_DDRAW();
  6036. LEAVE_CSDDC();
  6037. return DDERR_CANTCREATEDC;
  6038. }
  6039. #ifdef WIN95
  6040. /*
  6041. * HACK-O-RAMA TIME! We need to do something smart if the VGA is
  6042. * powered down or if we're in a DOS box. We don't have the pDevice
  6043. * yet, so we'll hack around w/ the DC we just created.
  6044. */
  6045. if( DD16_IsDeviceBusy( hdc_dd ) )
  6046. {
  6047. /*
  6048. * Something is happenning, but we don't know what. If it's
  6049. * a DOS box, creating a simple POPUP should make it go away.
  6050. */
  6051. WNDCLASS cls;
  6052. HWND hWnd;
  6053. cls.lpszClassName = "DDrawHackWindow";
  6054. cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  6055. cls.hInstance = hModule;
  6056. cls.hIcon = NULL;
  6057. cls.hCursor = NULL;
  6058. cls.lpszMenuName = NULL;
  6059. cls.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  6060. cls.lpfnWndProc = DefWindowProc;
  6061. cls.cbWndExtra = 0;
  6062. cls.cbClsExtra = 0;
  6063. RegisterClass(&cls);
  6064. hWnd = CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,
  6065. "DDrawHackWindow", "DDrawHackWindow",
  6066. WS_OVERLAPPED|WS_POPUP|WS_VISIBLE, 0, 0, 2, 2,
  6067. NULL, NULL, hModule, NULL);
  6068. if( hWnd != NULL )
  6069. {
  6070. DestroyWindow( hWnd );
  6071. UnregisterClass( "DDrawHackWindow", hModule );
  6072. }
  6073. /*
  6074. * Check again, and if we're still busy, that probably means
  6075. * that the device is powered down. In that case, forcing
  6076. * emulaiton is probably the right thing to do.
  6077. */
  6078. if( DD16_IsDeviceBusy( hdc_dd ) )
  6079. {
  6080. dwFlags |= DDCREATE_EMULATIONONLY;
  6081. }
  6082. }
  6083. #endif
  6084. if( dwFlags & DDCREATE_EMULATIONONLY )
  6085. {
  6086. hel_only = TRUE;
  6087. }
  6088. else
  6089. {
  6090. hel_only = FALSE;
  6091. /*
  6092. * "That's the chicago way..."
  6093. * Win95 drivers are talked to through the ExtEscape DCI extensions.
  6094. * Under NT we get at our drivers through the gdi32p dll.
  6095. * Consequently all this dci stuff goes away for NT. You'll find the
  6096. * equivalent stuff done at the top of DirectDrawObjectCreate
  6097. */
  6098. #ifdef WIN95
  6099. /*
  6100. * see if the DCICOMMAND escape is supported
  6101. */
  6102. u = DCICOMMAND;
  6103. halver = ExtEscape( hdc_dd, QUERYESCSUPPORT, sizeof(u),
  6104. (LPCSTR)&u, 0, NULL );
  6105. if( (halver != DD_HAL_VERSION) && (halver != DD_HAL_VERSION_EXTERNAL) )
  6106. {
  6107. if( halver <= 0 )
  6108. {
  6109. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No DIRECTDRAW escape support" );
  6110. }
  6111. else
  6112. {
  6113. if (halver == 0x5250)
  6114. {
  6115. DPF(0,"****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Acceleration slider is set to NONE");
  6116. }
  6117. else
  6118. {
  6119. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:DIRECTDRAW driver is wrong version, got 0x%04lx, expected 0x%04lx",
  6120. halver, DD_HAL_VERSION_EXTERNAL );
  6121. }
  6122. }
  6123. // We don't release the DC anymore becuase it always becomes part
  6124. // of the DDRAW_GBL object in all DisplayDrv cases.
  6125. hel_only = TRUE;
  6126. }
  6127. #endif //win95
  6128. }
  6129. if( hel_only && (dwFlags & DDCREATE_HARDWAREONLY))
  6130. {
  6131. DPF_ERR( "Only emulation available, but HARDWAREONLY requested" );
  6132. CLOSEVXD( hDDVxd );
  6133. LEAVE_DDRAW();
  6134. LEAVE_CSDDC();
  6135. DD_DoneDC(hdc_dd);
  6136. return DDERR_NODIRECTDRAWHW;
  6137. }
  6138. #ifdef WIN95
  6139. // On non-multi-mon systems, we do this because
  6140. // we did it in DX3. We set TRUE for multi-mon systems
  6141. // because that will prevent us from using Death/Resurrection
  6142. // which is Dangerous if some future DDraw object ever is
  6143. // created for the secondary device. We can't wait until
  6144. // the second device is created; because it's possible that
  6145. // primary device is already in the middle of a death/resurrection
  6146. // sequence and it is bad bad karma to change the flag between
  6147. // the beginning of modex and the end of modex. (Specifically,
  6148. // we'll see either a resurrection not being called when it should
  6149. // have been or a resurrection called when it shouldn't have been.)
  6150. if( IsMultiMonitor() )
  6151. DD16_SetCertified( TRUE );
  6152. else
  6153. DD16_SetCertified( FALSE );
  6154. #endif
  6155. /*
  6156. * go try to create the driver object
  6157. */
  6158. if( !hel_only )
  6159. {
  6160. DWORD hInstance = 0;
  6161. DWORD dwDriverData32 = 0;
  6162. DWORD p16;
  6163. DDHALDDRAWFNS ddhddfns;
  6164. BOOL bFailedWhackoVersion = FALSE;
  6165. BOOL bPassDriverInit = TRUE;
  6166. /*
  6167. * "That's the chicago way..."
  6168. * Win95 drivers are talked to through the ExtEscape DCI extensions.
  6169. * Under NT we get at our drivers through the gdi32p dll.
  6170. * Consequently all this dci stuff goes away for NT. You'll find the
  6171. * equivalent stuff done at the top of DirectDrawObjectCreate
  6172. */
  6173. #ifdef WIN95
  6174. DD32BITDRIVERDATA data;
  6175. DDVERSIONDATA verdata;
  6176. /*
  6177. * Notify the driver of the DirectDraw version.
  6178. *
  6179. * Why this is neccesary: After DX3 it became a requirement for
  6180. * newer DDraws to work w/ older HALs and visa versa. DD_VERSION
  6181. * was set at 0x200 in DX3 and all of the drivers hardcoded it.
  6182. * Therefore, setting dwVersion to anything other than 0x200 would
  6183. * cause DX3 HALs to fail. The other option was to put the real
  6184. * version in dwParam1 of the DDGET32BITDRIVERNAME call, but this
  6185. * option seems a little cleaner. Since the information could be
  6186. * useful in the future, we also ask the HAL to tell us what
  6187. * version of DirectDraw they were designed for.
  6188. */
  6189. DPF( 4, "DDVERSIONINFO" );
  6190. /*
  6191. * On debug builds, probe the driver with a totally whacko ddraw version
  6192. * This ensures we can increment this version in the future i.e. that
  6193. * any existing drivers which catch this escape don't hard code for
  6194. * whatever version of the DDK they use
  6195. * We fail the driver if they give out on some large random ddraw version but
  6196. * pass on 0x500
  6197. */
  6198. cmd.dwCommand = (DWORD) DDVERSIONINFO;
  6199. cmd.dwParam1 = (GetCurrentProcessId() & 0xfff) + 0x501; //always > 0x500
  6200. cmd.dwParam2 = 0;
  6201. cmd.dwReserved = 0;
  6202. cmd.dwVersion = DD_VERSION; // So older HALs won't fail
  6203. verdata.dwHALVersion = 0;
  6204. verdata.dwReserved1 = 0;
  6205. verdata.dwReserved2 = 0;
  6206. rc = ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
  6207. (LPCSTR)&cmd, sizeof( verdata ), (LPSTR) &verdata );
  6208. if (rc <= 0)
  6209. {
  6210. //Removed this DPF: It's misleading
  6211. //DPF(1,"Driver failed random future DDraw version");
  6212. bFailedWhackoVersion = TRUE;
  6213. }
  6214. cmd.dwCommand = (DWORD) DDVERSIONINFO;
  6215. cmd.dwParam1 = DD_RUNTIME_VERSION;
  6216. cmd.dwParam2 = 0;
  6217. cmd.dwReserved = 0;
  6218. cmd.dwVersion = DD_VERSION; // So older HALs won't fail
  6219. verdata.dwHALVersion = 0;
  6220. verdata.dwReserved1 = 0;
  6221. verdata.dwReserved2 = 0;
  6222. rc = ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
  6223. (LPCSTR)&cmd, sizeof( verdata ), (LPSTR) &verdata );
  6224. DPF( 5, "HAL version: %X", verdata.dwHALVersion );
  6225. /*
  6226. * If the driver failed the whacko version, but passed for 0x500 (DX5),
  6227. * then fail the driver.
  6228. */
  6229. if( rc > 0 && verdata.dwHALVersion >= 0x500 && bFailedWhackoVersion )
  6230. {
  6231. DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****Driver Failed a DDVERSIONINFO for a random future ddraw version but passed for DX5.");
  6232. bPassDriverInit = FALSE;
  6233. isdispdrv = FALSE;
  6234. pdrv = NULL;
  6235. hel_only = TRUE;
  6236. }
  6237. /*
  6238. * load up the 32-bit display driver DLL
  6239. */
  6240. DPF( 4, "DDGET32BITDRIVERNAME" );
  6241. cmd.dwCommand = (DWORD) DDGET32BITDRIVERNAME;
  6242. cmd.dwParam1 = 0;
  6243. cmd.dwVersion = DD_VERSION;
  6244. rc = ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
  6245. (LPCSTR)&cmd, sizeof( data ), (LPSTR) &data );
  6246. if( rc > 0 )
  6247. {
  6248. #ifndef WIN16_SEPARATE
  6249. LEAVE_DDRAW();
  6250. #endif
  6251. dwDriverData32 = HelperLoadDLL( data.szName, data.szEntryPoint, data.dwContext );
  6252. DPF( 5, "DriverInit returned 0x%x", dwDriverData32 );
  6253. #ifndef WIN16_SEPARATE
  6254. ENTER_DDRAW();
  6255. #endif
  6256. }
  6257. /*
  6258. * get the 16-bit callbacks
  6259. */
  6260. DD16_GetDriverFns( &ddhddfns );
  6261. DPF( 4, "DDNEWCALLBACKFNS" );
  6262. cmd.dwCommand = (DWORD) DDNEWCALLBACKFNS;
  6263. #ifdef WIN95
  6264. p16 = MapLS( &ddhddfns );
  6265. cmd.dwParam1 = p16;
  6266. cmd.dwParam2 = 0;
  6267. #else
  6268. cmd.dwParam1 = (UINT) &ddhddfns;
  6269. cmd.dwParam2 = 0;
  6270. #endif
  6271. cmd.dwVersion = DD_VERSION;
  6272. cmd.dwReserved = 0;
  6273. ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
  6274. (LPCSTR)&cmd, 0, NULL );
  6275. UnMapLS( p16 );
  6276. /*
  6277. * try to create the driver object now
  6278. */
  6279. DPF( 4, "DDCREATEDRIVEROBJECT" );
  6280. cmd.dwCommand = (DWORD) DDCREATEDRIVEROBJECT;
  6281. cmd.dwParam1 = dwDriverData32;
  6282. cmd.dwParam2 = 0;
  6283. cmd.dwVersion = DD_VERSION;
  6284. cmd.dwReserved = 0;
  6285. rc = ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
  6286. (LPCSTR)&cmd, sizeof( DWORD ), (LPVOID) &hInstance );
  6287. DPF( 5, "hInstance = %08lx", hInstance );
  6288. if( rc <= 0 )
  6289. {
  6290. DPF( 0, "ExtEscape rc=%ld, GetLastError=%ld", rc, GetLastError() );
  6291. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No DDCREATEDRIVEROBJECT support in driver" );
  6292. isdispdrv = FALSE;
  6293. pdrv = NULL;
  6294. hel_only = TRUE;
  6295. }
  6296. DPF(5,"bPassDriverInit:%d, rc:%d",bPassDriverInit,rc);
  6297. if ( (bPassDriverInit) && (rc > 0) )
  6298. #endif //WIN95
  6299. {
  6300. /*
  6301. * create our driver object
  6302. */
  6303. #ifdef WINNT
  6304. uDisplaySettingsUnique=DdQueryDisplaySettingsUniqueness();
  6305. #endif
  6306. pdrv = FetchDirectDrawData( NULL, FALSE, hInstance, hDDVxd, pdrvname, dwDriverData32 , NULL);
  6307. if( pdrv )
  6308. {
  6309. #ifdef WIN95
  6310. pdrv->dwInternal1 = verdata.dwHALVersion;
  6311. //Record 32-bit driver data so we can get its version info later
  6312. pdrv->dd32BitDriverData = data;
  6313. #else
  6314. /*
  6315. * NT gets the same driver version as ddraw. Kernel
  6316. * has to filter ddraw.dll's ravings for the driver
  6317. */
  6318. pdrv->dwInternal1 = DD_RUNTIME_VERSION;
  6319. #endif
  6320. strcpy( pdrv->cDriverName, pdrvname );
  6321. #ifdef WIN95
  6322. //
  6323. // If we have to run in emulation only, then we better make sure we are
  6324. // on a minidriver. If not, then emulation is unreliable so we'll bail
  6325. // This is done to work around some messed up "remote control" programs
  6326. // that turn off C1_DIBENGINE and make us fail (IsWin95MiniDriver used
  6327. // to be called from IsDirectDrawSupported). The thinking is that if there's ddraw
  6328. // support, then it is pretty much guaranteed to be a minidriver. If there's
  6329. // no support, then we can trust the absence of C1_DIBENGINE and thus fail ddraw init
  6330. //
  6331. if( (pdrv->ddCaps.dwCaps & DDCAPS_NOHARDWARE) && !DD16_IsWin95MiniDriver() )
  6332. {
  6333. DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:DirectDraw requires a Windows95 display driver" );
  6334. DirectDrawMsg(MAKEINTRESOURCE(IDS_DONTWORK_DRV));
  6335. CLOSEVXD( hDDVxd );
  6336. LEAVE_DDRAW();
  6337. LEAVE_CSDDC();
  6338. DD_DoneDC(hdc_dd);
  6339. return DDERR_GENERIC;
  6340. }
  6341. #endif
  6342. }
  6343. // 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
  6344. DPF( 5, "pdrv = 0x%p", pdrv );
  6345. if( pdrv == NULL )
  6346. {
  6347. DPF( 3, "Got returned NULL pdrv!" );
  6348. isdispdrv = FALSE;
  6349. hel_only = TRUE;
  6350. }
  6351. #ifdef WIN95
  6352. else
  6353. {
  6354. /*
  6355. * The only certified drivers are ones that we produced.
  6356. * DD_HAL_VERSION is different for internal vs external.
  6357. * We use this difference pick out ours.
  6358. */
  6359. if( halver == DD_HAL_VERSION )
  6360. {
  6361. pdrv->ddCaps.dwCaps2 |= DDCAPS2_CERTIFIED;
  6362. DD16_SetCertified( TRUE );
  6363. }
  6364. }
  6365. #endif
  6366. }
  6367. }
  6368. /*
  6369. * no driver object found, so fake one up for the HEL (only do this
  6370. * for generic display drivers)
  6371. */
  6372. if( pdrv == NULL || hel_only )
  6373. {
  6374. hel_only = TRUE;
  6375. pdrv = FakeDDCreateDriverObject( hdc_dd, pdrvname, NULL, FALSE, hDDVxd );
  6376. if( pdrv == NULL )
  6377. {
  6378. DPF_ERR( "Could not create HEL object" );
  6379. CLOSEVXD( hDDVxd );
  6380. LEAVE_DDRAW();
  6381. LEAVE_CSDDC();
  6382. DD_DoneDC(hdc_dd);
  6383. return DDERR_GENERIC;
  6384. }
  6385. /*
  6386. * the HEL is certified
  6387. */
  6388. pdrv->ddCaps.dwCaps2 |= DDCAPS2_CERTIFIED;
  6389. strcpy( pdrv->cDriverName, pdrvname );
  6390. // Initialize Rect information for this pdrv
  6391. UpdateRectFromDevice( pdrv );
  6392. }
  6393. /*
  6394. * Even if it's not a display driver, it may still be a GDI driver
  6395. */
  6396. if( hdc_dd != NULL )
  6397. {
  6398. if( !(pdrv->dwFlags & DDRAWI_DISPLAYDRV))
  6399. {
  6400. if (fDoesGDI(hdc_dd))
  6401. {
  6402. pdrv->dwFlags |= DDRAWI_GDIDRV;
  6403. }
  6404. else
  6405. {
  6406. pdrv->dwFlags &= ~DDRAWI_GDIDRV;
  6407. }
  6408. }
  6409. }
  6410. /*
  6411. * initialize for HEL usage
  6412. */
  6413. capsInit( pdrv );
  6414. if( !helInit( pdrv, dwFlags, hel_only ) )
  6415. {
  6416. DPF_ERR( "helInit FAILED" );
  6417. CLOSEVXD( hDDVxd );
  6418. LEAVE_DDRAW();
  6419. LEAVE_CSDDC();
  6420. /* GEE: HEL can only fail in v1 for lack of memory */
  6421. DD_DoneDC(hdc_dd);
  6422. return DDERR_GENERIC;
  6423. }
  6424. /*
  6425. * create a new interface, and update the driver object with
  6426. * random bits o' data.
  6427. */
  6428. pdrv_int = getDriverInterface( pnew_int, pdrv );
  6429. if( pdrv_int == NULL )
  6430. {
  6431. DPF_ERR( "No memory for driver callbacks." );
  6432. CLOSEVXD( hDDVxd );
  6433. LEAVE_DDRAW();
  6434. LEAVE_CSDDC();
  6435. DD_DoneDC(hdc_dd);
  6436. return DDERR_OUTOFMEMORY;
  6437. }
  6438. pdrv_lcl = pdrv_int->lpLcl;
  6439. pdrv_lcl->dwAppHackFlags = hackflags;
  6440. #ifdef DEBUG
  6441. if( dwRegFlags & DDRAW_REGFLAGS_DISABLEINACTIVATE )
  6442. {
  6443. pdrv_lcl->dwLocalFlags |= DDRAWILCL_DISABLEINACTIVATE;
  6444. }
  6445. #endif
  6446. if( IsAttachedToDesktop( lpGUID ) )
  6447. {
  6448. pdrv->dwFlags |= DDRAWI_ATTACHEDTODESKTOP;
  6449. }
  6450. if (bExplicitMonitor)
  6451. {
  6452. pdrv_lcl->dwLocalFlags |= DDRAWILCL_EXPLICITMONITOR;
  6453. }
  6454. pdrv_lcl->dwLocalFlags |= dwCallFlags;
  6455. /*
  6456. * Will be initialized to NULL on NT.
  6457. */
  6458. pdrv_lcl->hDDVxd = (ULONG_PTR) hDDVxd;
  6459. if( hdc_dd != NULL )
  6460. {
  6461. #ifdef WIN95
  6462. // Make sure it doesn't get released by mistake
  6463. DD16_MakeObjectPrivate(hdc_dd, TRUE);
  6464. #endif
  6465. (HDC) pdrv_lcl->hDC = hdc_dd;
  6466. }
  6467. strcpy( pdrv->cDriverName, pdrvname );
  6468. #ifdef WINNT
  6469. /*
  6470. * The FetchDirectDrawData() call above loaded a DD handle into a
  6471. * into a temp location in the driver GBL object; we must now save
  6472. * the handle in the driver LCL object so it won't be overwritten.
  6473. */
  6474. pdrv_lcl->hDD = pdrv->hDD;
  6475. #endif //WINNT
  6476. // Initialize cObsolete just in case some driver references the
  6477. // field. It will always be initialized to "DISPLAY".
  6478. lstrcpy(pdrv->cObsolete, DISPLAY_STR);
  6479. /*
  6480. * Initialize the kernel interface
  6481. */
  6482. if( isdispdrv && !hel_only )
  6483. {
  6484. InitKernelInterface( pdrv_lcl );
  6485. }
  6486. LEAVE_DDRAW();
  6487. #ifdef WIN95
  6488. if( !hel_only )
  6489. {
  6490. extern DWORD WINAPI OpenVxDHandle( HANDLE hWin32Obj );
  6491. DWORD event16;
  6492. HANDLE h;
  6493. HelperCreateModeSetThread( DDNotifyModeSet, &h, pdrv_lcl->lpGbl,
  6494. pdrv->hInstance );
  6495. if( h != NULL )
  6496. {
  6497. event16 = OpenVxDHandle( h );
  6498. DPF( 4, "16-bit event handle=%08lx", event16 );
  6499. DD16_SetEventHandle( pdrv->hInstance, event16 );
  6500. pdrv->dwEvent16 = event16;
  6501. CloseHandle( h );
  6502. }
  6503. }
  6504. /*
  6505. * Create thread that will notify us when we are returning from
  6506. * a DOS box so we can invalidate the surfaces.
  6507. */
  6508. if( !hel_only && bIsPrimary && IsWindows98() )
  6509. {
  6510. DWORD event16;
  6511. HANDLE h;
  6512. HelperCreateDOSBoxThread( DDNotifyDOSBox, &h, pdrv_lcl->lpGbl,
  6513. pdrv->hInstance );
  6514. if( h != NULL )
  6515. {
  6516. event16 = OpenVxDHandle( h );
  6517. DPF( 4, "DOS Box event handle=%08lx", event16 );
  6518. pdrv->dwDOSBoxEvent = event16;
  6519. SetKernelDOSBoxEvent( pdrv_lcl );
  6520. CloseHandle( h );
  6521. }
  6522. }
  6523. #endif
  6524. LEAVE_CSDDC();
  6525. *lplpDD = (LPDIRECTDRAW) pdrv_int;
  6526. return DD_OK;
  6527. } /* InternalDirectDrawCreate */
  6528. BOOL CALLBACK MonitorEnumProc(HMONITOR hMon, HDC hdc, LPRECT lpr, LPARAM lParam)
  6529. {
  6530. MONITORINFOEX mix;
  6531. MONITORINFO mi;
  6532. LPCALLBACKSTRUCT lpcb = (LPCALLBACKSTRUCT) lParam;
  6533. mi.cbSize = sizeof(mi);
  6534. if (!InternalGetMonitorInfo(hMon,&mi))
  6535. return FALSE;
  6536. mix.cbSize = sizeof(mix);
  6537. if (!InternalGetMonitorInfo(hMon,(MONITORINFO*) &mix))
  6538. return FALSE;
  6539. if (!strcmp(lpcb->pName,(LPSTR)mix.szDevice))
  6540. {
  6541. //Found it!!
  6542. lpcb->hMon = hMon;
  6543. return FALSE;
  6544. }
  6545. return TRUE;
  6546. }
  6547. /*
  6548. * GetMonitorFromDeviceName
  6549. */
  6550. HMONITOR GetMonitorFromDeviceName(LPSTR szName)
  6551. {
  6552. CALLBACKSTRUCT cbs;
  6553. cbs.pName = szName;
  6554. cbs.hMon = NULL;
  6555. if (!InternalEnumMonitors(MonitorEnumProc, &cbs))
  6556. return NULL;
  6557. return cbs.hMon;
  6558. }
  6559. /*
  6560. * These callbacks are used to munge DirectDrawEnumerateEx's callback into the old
  6561. * style callback.
  6562. */
  6563. typedef struct
  6564. {
  6565. LPDDENUMCALLBACKA lpCallback;
  6566. LPVOID lpContext;
  6567. } ENUMCALLBACKTRANSLATORA, * LPENUMCALLBACKTRANSLATORA;
  6568. BOOL FAR PASCAL TranslateCallbackA(GUID FAR *lpGUID, LPSTR pName , LPSTR pDesc , LPVOID pContext, HMONITOR hm)
  6569. {
  6570. LPENUMCALLBACKTRANSLATORA pTrans = (LPENUMCALLBACKTRANSLATORA) pContext;
  6571. return (pTrans->lpCallback) (lpGUID,pName,pDesc,pTrans->lpContext);
  6572. }
  6573. typedef struct
  6574. {
  6575. LPDDENUMCALLBACKW lpCallback;
  6576. LPVOID lpContext;
  6577. } ENUMCALLBACKTRANSLATORW, * LPENUMCALLBACKTRANSLATORW;
  6578. BOOL FAR PASCAL TranslateCallbackW(GUID FAR *lpGUID, LPWSTR pName , LPWSTR pDesc , LPVOID pContext, HMONITOR hm)
  6579. {
  6580. LPENUMCALLBACKTRANSLATORW pTrans = (LPENUMCALLBACKTRANSLATORW) pContext;
  6581. return (pTrans->lpCallback) (lpGUID,pName,pDesc,pTrans->lpContext);
  6582. }
  6583. #undef DPF_MODNAME
  6584. #define DPF_MODNAME "DirectDrawEnumerateA"
  6585. /*
  6586. * DirectDrawEnumerateA
  6587. */
  6588. HRESULT WINAPI DirectDrawEnumerateA(
  6589. LPDDENUMCALLBACKA lpCallback,
  6590. LPVOID lpContext )
  6591. {
  6592. ENUMCALLBACKTRANSLATORA Translate;
  6593. Translate.lpCallback = lpCallback;
  6594. Translate.lpContext = lpContext;
  6595. DPF(2,A,"ENTERAPI: DirectDrawEnumerateA");
  6596. if( !VALIDEX_CODE_PTR( lpCallback ) )
  6597. {
  6598. DPF( 0, "Invalid callback routine" );
  6599. return DDERR_INVALIDPARAMS;
  6600. }
  6601. #ifdef DEBUG
  6602. if (IsMultiMonitor())
  6603. {
  6604. DPF(0,"***********************************************");
  6605. DPF(0,"* Use DirectDrawEnumerateEx to enumerate *");
  6606. DPF(0,"* multiple monitors *");
  6607. DPF(0,"***********************************************");
  6608. }
  6609. #endif
  6610. return DirectDrawEnumerateExA(TranslateCallbackA, (LPVOID) & Translate, DDENUM_NONDISPLAYDEVICES);
  6611. } /* DirectDrawEnumerateA */
  6612. #undef DPF_MODNAME
  6613. #define DPF_MODNAME "DirectDrawEnumerateW"
  6614. /*
  6615. * DirectDrawEnumerateW
  6616. */
  6617. HRESULT WINAPI DirectDrawEnumerateW(
  6618. LPDDENUMCALLBACKW lpCallback,
  6619. LPVOID lpContext )
  6620. {
  6621. ENUMCALLBACKTRANSLATORW Translate;
  6622. Translate.lpCallback = lpCallback;
  6623. Translate.lpContext = lpContext;
  6624. DPF(2,A,"ENTERAPI: DirectDrawEnumerateW");
  6625. if( !VALIDEX_CODE_PTR( lpCallback ) )
  6626. {
  6627. DPF( 0, "Invalid callback routine" );
  6628. return DDERR_INVALIDPARAMS;
  6629. }
  6630. #ifdef DEBUG
  6631. if (IsMultiMonitor())
  6632. {
  6633. DPF(0,"***********************************************");
  6634. DPF(0,"* Use DirectDrawEnumerateEx to enumerate *");
  6635. DPF(0,"* multiple monitors *");
  6636. DPF(0,"***********************************************");
  6637. }
  6638. #endif
  6639. return DirectDrawEnumerateExW(TranslateCallbackW, (LPVOID) & Translate, DDENUM_NONDISPLAYDEVICES);
  6640. } /* DirectDrawEnumerateW */
  6641. #undef DPF_MODNAME
  6642. #define DPF_MODNAME "DirectDrawEnumerateA"
  6643. /*
  6644. * DirectDrawEnumerateA
  6645. */
  6646. HRESULT WINAPI DirectDrawEnumerateExA(
  6647. LPDDENUMCALLBACKEXA lpCallback,
  6648. LPVOID lpContext,
  6649. DWORD dwFlags )
  6650. {
  6651. DWORD rc;
  6652. DWORD keyidx;
  6653. HKEY hkey;
  6654. HKEY hsubkey;
  6655. char keyname[256];
  6656. char desc[256];
  6657. char drvname[MAX_PATH];
  6658. DWORD cb;
  6659. DWORD n;
  6660. DWORD type;
  6661. GUID guid;
  6662. HDC hdc;
  6663. DISPLAY_DEVICEA dd;
  6664. BOOL bEnumerateSecondariesLike3dfx=FALSE;
  6665. DPF(2,A,"ENTERAPI: DirectDrawEnumerateExA");
  6666. //BEGIN VOODOO2 HACK
  6667. {
  6668. HKEY hkey;
  6669. dwRegFlags &= ~DDRAW_REGFLAGS_ENUMERATEATTACHEDSECONDARIES;
  6670. if( !RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDRAW, &hkey ) )
  6671. {
  6672. DWORD cb;
  6673. DWORD value;
  6674. cb = sizeof( value );
  6675. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_ENUMSECONDARY, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  6676. {
  6677. DPF( 2, " EnumerateAttachedSecondaries: %d", value );
  6678. if( value )
  6679. {
  6680. bEnumerateSecondariesLike3dfx = TRUE;
  6681. dwRegFlags |= DDRAW_REGFLAGS_ENUMERATEATTACHEDSECONDARIES;
  6682. }
  6683. }
  6684. RegCloseKey(hkey);
  6685. }
  6686. }
  6687. //END VOODOO2 HACK
  6688. #ifdef WIN95
  6689. /*
  6690. * Did DDHELP fail to initialize properly?
  6691. */
  6692. if( dwHelperPid == 0 )
  6693. {
  6694. return DDERR_NODIRECTDRAWSUPPORT;
  6695. }
  6696. #endif
  6697. if( !VALIDEX_CODE_PTR( lpCallback ) )
  6698. {
  6699. DPF( 0, "Invalid callback routine" );
  6700. return DDERR_INVALIDPARAMS;
  6701. }
  6702. if( dwFlags & ~DDENUM_VALID)
  6703. {
  6704. DPF_ERR("Invalid flags for DirectDrawEnumerateEx");
  6705. return DDERR_INVALIDPARAMS;
  6706. }
  6707. #ifdef WINNT
  6708. // We do not support detached devices on NT so silently ignore the flag:
  6709. dwFlags &= ~DDENUM_DETACHEDSECONDARYDEVICES;
  6710. #endif
  6711. LoadString( hModule, IDS_PRIMARYDISPLAY, desc, sizeof(desc) );
  6712. TRY
  6713. {
  6714. rc = lpCallback( NULL, desc, DISPLAY_STR, lpContext, NULL );
  6715. }
  6716. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  6717. {
  6718. DPF_ERR( "Exception occurred during DirectDrawEnumerateEx callback" );
  6719. return DDERR_INVALIDPARAMS;
  6720. }
  6721. if( !rc )
  6722. {
  6723. return DD_OK;
  6724. }
  6725. if (dwFlags & DDENUM_NONDISPLAYDEVICES)
  6726. {
  6727. if( RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDHW, &hkey ) == 0 )
  6728. {
  6729. /*
  6730. * enumerate all subkeys under HKEY_LOCALMACHINE\Hardware\DirectDrawDrivers
  6731. */
  6732. keyidx = 0;
  6733. while( !RegEnumKey( hkey, keyidx, keyname, sizeof( keyname ) ) )
  6734. {
  6735. if( strToGUID( keyname, &guid ) )
  6736. {
  6737. if( !RegOpenKey( hkey, keyname, &hsubkey ) )
  6738. {
  6739. cb = sizeof( desc ) - 1;
  6740. if( !RegQueryValueEx( hsubkey, REGSTR_KEY_DDHW_DESCRIPTION, NULL, &type,
  6741. (CONST LPBYTE)desc, &cb ) )
  6742. {
  6743. if( type == REG_SZ )
  6744. {
  6745. desc[cb] = 0;
  6746. cb = sizeof( drvname ) - 1;
  6747. if( !RegQueryValueEx( hsubkey, REGSTR_KEY_DDHW_DRIVERNAME, NULL, &type,
  6748. (CONST LPBYTE)drvname, &cb ) )
  6749. {
  6750. /*
  6751. * It is possible that the registry is out
  6752. * of date, so we will try to create a DC.
  6753. * The problem is that the Voodoo 1 driver
  6754. * will suceed on a Voodoo 2, Banshee, or
  6755. * Voodoo 3 (and hang later), so we need to
  6756. * hack around it.
  6757. */
  6758. drvname[cb] = 0;
  6759. if( Voodoo1GoodToGo( &guid ) )
  6760. {
  6761. hdc = DD_CreateDC( drvname );
  6762. }
  6763. else
  6764. {
  6765. hdc = NULL;
  6766. }
  6767. if( ( type == REG_SZ ) &&
  6768. ( hdc != NULL ) )
  6769. {
  6770. drvname[cb] = 0;
  6771. DPF( 5, "Enumerating GUID "
  6772. "%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
  6773. guid.Data1,
  6774. guid.Data2,
  6775. guid.Data3,
  6776. guid.Data4[ 0 ],
  6777. guid.Data4[ 1 ],
  6778. guid.Data4[ 2 ],
  6779. guid.Data4[ 3 ],
  6780. guid.Data4[ 4 ],
  6781. guid.Data4[ 5 ],
  6782. guid.Data4[ 6 ],
  6783. guid.Data4[ 7 ] );
  6784. DPF( 5, " Driver Name = %s", drvname );
  6785. DPF( 5, " Description = %s", desc );
  6786. rc = lpCallback( &guid, desc, drvname, lpContext , NULL);
  6787. if( !rc )
  6788. {
  6789. DD_DoneDC( hdc );
  6790. RegCloseKey( hsubkey );
  6791. RegCloseKey( hkey );
  6792. return DD_OK;
  6793. }
  6794. }
  6795. if( hdc != NULL )
  6796. {
  6797. DD_DoneDC( hdc );
  6798. }
  6799. }
  6800. }
  6801. }
  6802. RegCloseKey( hsubkey );
  6803. }
  6804. }
  6805. keyidx++;
  6806. }
  6807. RegCloseKey( hkey );
  6808. }
  6809. }
  6810. else
  6811. {
  6812. DPF( 3, "No registry information for any drivers" );
  6813. }
  6814. /*
  6815. * now enumerate all devices returned by EnumDisplayDevices
  6816. * We do this after the secondary drivers to hopefully not confuse people
  6817. * who are looking for 3DFx and have written bad code. Putting these
  6818. * after the 3DFx seems the safest thing to do..
  6819. */
  6820. /* If there is only one device in the system then we don't
  6821. * enumerate it because it already is implicitly the primary
  6822. * This will improve behavior for badly written (i.e. our samples)
  6823. * D3D apps that are searching for a 3DFx device.
  6824. */
  6825. if( !IsMultiMonitor() )
  6826. {
  6827. // If there is only one device; then just stop here.
  6828. DPF( 3, "Only one Display device in the current system." );
  6829. return DD_OK;
  6830. }
  6831. DPF( 3, "More than one display device in the current system." );
  6832. // Zero the memory of the DisplayDevice struct between calls to
  6833. // EnumDisplayDevices
  6834. ZeroMemory(&dd, sizeof(dd));
  6835. dd.cb = sizeof(dd);
  6836. for( n=0; xxxEnumDisplayDevicesA( NULL, n, &dd, 0 ); n++ )
  6837. {
  6838. GUID guid;
  6839. //
  6840. // skip drivers that are not hardware devices
  6841. //
  6842. if( dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER )
  6843. continue;
  6844. guid = DisplayGUID;
  6845. guid.Data1 += n;
  6846. if ( (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) ?
  6847. ((dwFlags & DDENUM_ATTACHEDSECONDARYDEVICES) ||
  6848. //BEGIN VOODOO2 HACK
  6849. (bEnumerateSecondariesLike3dfx && !(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) ):
  6850. //END VOODOO2 HACK
  6851. (dwFlags & DDENUM_DETACHEDSECONDARYDEVICES) )
  6852. {
  6853. HMONITOR hMonitor;
  6854. DPF( 5, "Enumerating GUID "
  6855. "%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
  6856. guid.Data1,
  6857. guid.Data2,
  6858. guid.Data3,
  6859. guid.Data4[ 0 ],
  6860. guid.Data4[ 1 ],
  6861. guid.Data4[ 2 ],
  6862. guid.Data4[ 3 ],
  6863. guid.Data4[ 4 ],
  6864. guid.Data4[ 5 ],
  6865. guid.Data4[ 6 ],
  6866. guid.Data4[ 7 ] );
  6867. DPF( 5, " Driver Name = %s", dd.DeviceName );
  6868. DPF( 5, " Description = %s", dd.DeviceString );
  6869. hMonitor = GetMonitorFromDeviceName(dd.DeviceName);
  6870. rc = lpCallback( &guid, dd.DeviceString, dd.DeviceName, lpContext, hMonitor);
  6871. if( !rc )
  6872. {
  6873. return DD_OK;
  6874. }
  6875. }
  6876. // Zero the memory of the DisplayDevice struct between calls to
  6877. // EnumDisplayDevices
  6878. ZeroMemory( &dd, sizeof(dd) );
  6879. dd.cb = sizeof(dd);
  6880. }
  6881. return DD_OK;
  6882. } /* DirectDrawEnumerateExA */
  6883. #undef DPF_MODNAME
  6884. #define DPF_MODNAME "DirectDrawEnumerateExW"
  6885. /*
  6886. * DirectDrawEnumerateExW
  6887. */
  6888. HRESULT WINAPI DirectDrawEnumerateExW(
  6889. LPDDENUMCALLBACKEXW lpCallback,
  6890. LPVOID lpContext,
  6891. DWORD dwFlags)
  6892. {
  6893. DPF(2,A,"ENTERAPI: DirectDrawEnumerateExW");
  6894. DPF_ERR( "DirectDrawEnumerateEx for unicode is not created" );
  6895. return DDERR_UNSUPPORTED;
  6896. } /* DirectDrawEnumerateExW */
  6897. /*
  6898. * these are exported... temp. hack for non-Win95
  6899. */
  6900. #ifndef WIN95
  6901. void DDAPI thk3216_ThunkData32( void )
  6902. {
  6903. }
  6904. void DDAPI thk1632_ThunkData32( void )
  6905. {
  6906. }
  6907. DWORD DDAPI DDGetPID( void )
  6908. {
  6909. return 0;
  6910. }
  6911. int DDAPI DDGetRequest( void )
  6912. {
  6913. return 0;
  6914. }
  6915. BOOL DDAPI DDGetDCInfo( LPSTR fname )
  6916. {
  6917. return 0;
  6918. }
  6919. void DDAPI DDHAL32_VidMemFree(
  6920. LPVOID this,
  6921. int heap,
  6922. FLATPTR ptr )
  6923. {
  6924. }
  6925. FLATPTR DDAPI DDHAL32_VidMemAlloc(
  6926. LPVOID this,
  6927. int heap,
  6928. DWORD dwWidth,
  6929. DWORD dwHeight )
  6930. {
  6931. return 0;
  6932. }
  6933. #ifdef POSTPONED
  6934. BOOL DDAPI DD32_HandleExternalModeChange(LPDEVMODE pModeInfo)
  6935. {
  6936. return FALSE;
  6937. }
  6938. #endif
  6939. #endif
  6940. /*
  6941. * _DirectDrawMsg
  6942. */
  6943. DWORD WINAPI _DirectDrawMsg(LPVOID msg)
  6944. {
  6945. char title[80];
  6946. char ach[512];
  6947. MSGBOXPARAMS mb;
  6948. LoadString( hModule, IDS_TITLE, title, sizeof(title) );
  6949. if( HIWORD((ULONG_PTR)msg) )
  6950. {
  6951. lstrcpy( ach, (LPSTR)msg );
  6952. }
  6953. else
  6954. {
  6955. LoadString( hModule, (int)((ULONG_PTR)msg), ach, sizeof(ach) );
  6956. }
  6957. mb.cbSize = sizeof(mb);
  6958. mb.hwndOwner = NULL;
  6959. mb.hInstance = hModule;
  6960. mb.lpszText = ach;
  6961. mb.lpszCaption = title;
  6962. mb.dwStyle = MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_ICONSTOP;
  6963. mb.lpszIcon = 0;
  6964. mb.dwContextHelpId = 0;
  6965. mb.lpfnMsgBoxCallback = NULL;
  6966. mb.dwLanguageId = 0;
  6967. return MessageBoxIndirect(&mb);
  6968. } /* _DirectDrawMsg */
  6969. /*
  6970. * DirectDrawMsg
  6971. *
  6972. * display an error message to the user, bring the message box up
  6973. * in another thread so the caller does not get reentered.
  6974. */
  6975. DWORD DirectDrawMsg( LPSTR msg )
  6976. {
  6977. HANDLE h;
  6978. DWORD dw;
  6979. HKEY hkey;
  6980. //
  6981. // get the current error mode, dont show a message box if the app
  6982. // does not want us too.
  6983. //
  6984. dw = SetErrorMode(0);
  6985. SetErrorMode(dw);
  6986. if( dw & SEM_FAILCRITICALERRORS )
  6987. {
  6988. return 0;
  6989. }
  6990. /*
  6991. * If the registry says no dialogs, then no dialogs.
  6992. */
  6993. if( !RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDRAW, &hkey ) )
  6994. {
  6995. DWORD type;
  6996. DWORD value;
  6997. DWORD cb;
  6998. cb = sizeof( value );
  6999. if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEDIALOGS, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  7000. {
  7001. if (value)
  7002. {
  7003. RegCloseKey( hkey );
  7004. return 0;
  7005. }
  7006. }
  7007. RegCloseKey( hkey );
  7008. }
  7009. if( h = CreateThread(NULL, 0, _DirectDrawMsg, (LPVOID)msg, 0, &dw) )
  7010. {
  7011. WaitForSingleObject( h, INFINITE );
  7012. GetExitCodeThread( h, &dw );
  7013. CloseHandle( h );
  7014. }
  7015. else
  7016. {
  7017. dw = 0;
  7018. }
  7019. return dw;
  7020. } /* DirectDrawMsg */
  7021. /*
  7022. * convertV1DDHALINFO
  7023. *
  7024. * Convert an obsolete DDHALINFO structure to the latest and greatest structure.
  7025. * This function takes a pointer to an LPDDHALINFO structure which has the same size as
  7026. * the new structure but has been filled in as if it is the V1 structure. Information is moved
  7027. * around in the structure and the new fields are cleared.
  7028. */
  7029. void convertV1DDHALINFO( LPDDHALINFO lpDDHALInfo )
  7030. {
  7031. DDHALINFO ddNew;
  7032. LPDDHALINFO_V1 lpddOld = (LPVOID)lpDDHALInfo;
  7033. int i;
  7034. ddNew.dwSize = sizeof( DDHALINFO );
  7035. ddNew.lpDDCallbacks = lpddOld->lpDDCallbacks;
  7036. ddNew.lpDDSurfaceCallbacks = lpddOld->lpDDSurfaceCallbacks;
  7037. ddNew.lpDDPaletteCallbacks = lpddOld->lpDDPaletteCallbacks;
  7038. ddNew.vmiData = lpddOld->vmiData;
  7039. // ddCaps
  7040. ddNew.ddCaps.dwSize = lpddOld->ddCaps.dwSize;
  7041. ddNew.ddCaps.dwCaps = lpddOld->ddCaps.dwCaps;
  7042. ddNew.ddCaps.dwCaps2 = lpddOld->ddCaps.dwCaps2;
  7043. ddNew.ddCaps.dwCKeyCaps = lpddOld->ddCaps.dwCKeyCaps;
  7044. ddNew.ddCaps.dwFXCaps = lpddOld->ddCaps.dwFXCaps;
  7045. ddNew.ddCaps.dwFXAlphaCaps = lpddOld->ddCaps.dwFXAlphaCaps;
  7046. ddNew.ddCaps.dwPalCaps = lpddOld->ddCaps.dwPalCaps;
  7047. ddNew.ddCaps.dwSVCaps = lpddOld->ddCaps.dwSVCaps;
  7048. ddNew.ddCaps.dwAlphaBltConstBitDepths = lpddOld->ddCaps.dwAlphaBltConstBitDepths;
  7049. ddNew.ddCaps.dwAlphaBltPixelBitDepths = lpddOld->ddCaps.dwAlphaBltPixelBitDepths;
  7050. ddNew.ddCaps.dwAlphaBltSurfaceBitDepths = lpddOld->ddCaps.dwAlphaBltSurfaceBitDepths;
  7051. ddNew.ddCaps.dwAlphaOverlayConstBitDepths = lpddOld->ddCaps.dwAlphaOverlayConstBitDepths;
  7052. ddNew.ddCaps.dwAlphaOverlayPixelBitDepths = lpddOld->ddCaps.dwAlphaOverlayPixelBitDepths;
  7053. ddNew.ddCaps.dwAlphaOverlaySurfaceBitDepths = lpddOld->ddCaps.dwAlphaOverlaySurfaceBitDepths;
  7054. ddNew.ddCaps.dwZBufferBitDepths = lpddOld->ddCaps.dwZBufferBitDepths;
  7055. ddNew.ddCaps.dwVidMemTotal = lpddOld->ddCaps.dwVidMemTotal;
  7056. ddNew.ddCaps.dwVidMemFree = lpddOld->ddCaps.dwVidMemFree;
  7057. ddNew.ddCaps.dwMaxVisibleOverlays = lpddOld->ddCaps.dwMaxVisibleOverlays;
  7058. ddNew.ddCaps.dwCurrVisibleOverlays = lpddOld->ddCaps.dwCurrVisibleOverlays;
  7059. ddNew.ddCaps.dwNumFourCCCodes = lpddOld->ddCaps.dwNumFourCCCodes;
  7060. ddNew.ddCaps.dwAlignBoundarySrc = lpddOld->ddCaps.dwAlignBoundarySrc;
  7061. ddNew.ddCaps.dwAlignSizeSrc = lpddOld->ddCaps.dwAlignSizeSrc;
  7062. ddNew.ddCaps.dwAlignBoundaryDest = lpddOld->ddCaps.dwAlignBoundaryDest;
  7063. ddNew.ddCaps.dwAlignSizeDest = lpddOld->ddCaps.dwAlignSizeDest;
  7064. ddNew.ddCaps.dwAlignStrideAlign = lpddOld->ddCaps.dwAlignStrideAlign;
  7065. ddNew.ddCaps.ddsCaps = lpddOld->ddCaps.ddsCaps;
  7066. ddNew.ddCaps.dwMinOverlayStretch = lpddOld->ddCaps.dwMinOverlayStretch;
  7067. ddNew.ddCaps.dwMaxOverlayStretch = lpddOld->ddCaps.dwMaxOverlayStretch;
  7068. ddNew.ddCaps.dwMinLiveVideoStretch = lpddOld->ddCaps.dwMinLiveVideoStretch;
  7069. ddNew.ddCaps.dwMaxLiveVideoStretch = lpddOld->ddCaps.dwMaxLiveVideoStretch;
  7070. ddNew.ddCaps.dwMinHwCodecStretch = lpddOld->ddCaps.dwMinHwCodecStretch;
  7071. ddNew.ddCaps.dwMaxHwCodecStretch = lpddOld->ddCaps.dwMaxHwCodecStretch;
  7072. ddNew.ddCaps.dwSVBCaps = 0;
  7073. ddNew.ddCaps.dwSVBCKeyCaps = 0;
  7074. ddNew.ddCaps.dwSVBFXCaps = 0;
  7075. ddNew.ddCaps.dwVSBCaps = 0;
  7076. ddNew.ddCaps.dwVSBCKeyCaps = 0;
  7077. ddNew.ddCaps.dwVSBFXCaps = 0;
  7078. ddNew.ddCaps.dwSSBCaps = 0;
  7079. ddNew.ddCaps.dwSSBCKeyCaps = 0;
  7080. ddNew.ddCaps.dwSSBFXCaps = 0;
  7081. ddNew.ddCaps.dwMaxVideoPorts = 0;
  7082. ddNew.ddCaps.dwCurrVideoPorts = 0;
  7083. ddNew.ddCaps.dwReserved1 = lpddOld->ddCaps.dwReserved1;
  7084. ddNew.ddCaps.dwReserved2 = lpddOld->ddCaps.dwReserved2;
  7085. ddNew.ddCaps.dwReserved3 = lpddOld->ddCaps.dwReserved3;
  7086. ddNew.ddCaps.dwSVBCaps2 = 0;
  7087. for(i=0; i<DD_ROP_SPACE; i++)
  7088. {
  7089. ddNew.ddCaps.dwRops[i] = lpddOld->ddCaps.dwRops[i];
  7090. ddNew.ddCaps.dwSVBRops[i] = 0;
  7091. ddNew.ddCaps.dwVSBRops[i] = 0;
  7092. ddNew.ddCaps.dwSSBRops[i] = 0;
  7093. }
  7094. ddNew.dwMonitorFrequency = lpddOld->dwMonitorFrequency;
  7095. ddNew.GetDriverInfo = NULL; // was unused hWndListBox in v1
  7096. ddNew.dwModeIndex = lpddOld->dwModeIndex;
  7097. ddNew.lpdwFourCC = lpddOld->lpdwFourCC;
  7098. ddNew.dwNumModes = lpddOld->dwNumModes;
  7099. ddNew.lpModeInfo = lpddOld->lpModeInfo;
  7100. ddNew.dwFlags = lpddOld->dwFlags;
  7101. ddNew.lpPDevice = lpddOld->lpPDevice;
  7102. ddNew.hInstance = lpddOld->hInstance;
  7103. ddNew.lpD3DGlobalDriverData = 0;
  7104. ddNew.lpD3DHALCallbacks = 0;
  7105. ddNew.lpDDExeBufCallbacks = NULL;
  7106. *lpDDHALInfo = ddNew;
  7107. }
  7108. // The callback used by Win9x drivers and the software rasterizers to help them
  7109. // parse execute buffers.
  7110. HRESULT CALLBACK D3DParseUnknownCommand (LPVOID lpvCommands,
  7111. LPVOID *lplpvReturnedCommand)
  7112. {
  7113. LPD3DINSTRUCTION lpInstr = (LPD3DINSTRUCTION) lpvCommands;
  7114. // Initialize the return address to the command's address
  7115. *lplpvReturnedCommand = lpvCommands;
  7116. switch (lpInstr->bOpcode)
  7117. {
  7118. case D3DOP_PROCESSVERTICES:
  7119. // cannot do D3DOP_PROCESSVERTICES here even for in-place copy because we
  7120. // generally don't pass the execute buffer's vertex buffer as the DP2 vertex buffer
  7121. return D3DERR_COMMAND_UNPARSED;
  7122. case D3DOP_SPAN:
  7123. *lplpvReturnedCommand = (LPVOID) ((LPBYTE)lpInstr +
  7124. sizeof (D3DINSTRUCTION) +
  7125. lpInstr->wCount *
  7126. lpInstr->bSize);
  7127. return DD_OK;
  7128. case D3DDP2OP_VIEWPORTINFO:
  7129. *lplpvReturnedCommand = (LPVOID) ((LPBYTE)lpInstr +
  7130. sizeof(D3DHAL_DP2COMMAND) +
  7131. lpInstr->wCount *
  7132. sizeof(D3DHAL_DP2VIEWPORTINFO));
  7133. return DD_OK;
  7134. case D3DDP2OP_WINFO:
  7135. *lplpvReturnedCommand = (LPVOID) ((LPBYTE)lpInstr +
  7136. sizeof(D3DHAL_DP2COMMAND) +
  7137. lpInstr->wCount *
  7138. sizeof(D3DHAL_DP2WINFO));
  7139. return DD_OK;
  7140. case D3DOP_MATRIXLOAD:
  7141. case D3DOP_MATRIXMULTIPLY:
  7142. case D3DOP_STATETRANSFORM:
  7143. case D3DOP_STATELIGHT:
  7144. case D3DOP_TEXTURELOAD:
  7145. case D3DOP_BRANCHFORWARD:
  7146. case D3DOP_SETSTATUS:
  7147. case D3DOP_EXIT:
  7148. return D3DERR_COMMAND_UNPARSED;
  7149. default:
  7150. return DDERR_GENERIC;
  7151. }
  7152. }
  7153. /*
  7154. * fetchModeXData
  7155. */
  7156. LPDDRAWI_DIRECTDRAW_GBL fetchModeXData(
  7157. LPDDRAWI_DIRECTDRAW_GBL pdrv,
  7158. LPDDHALMODEINFO pmi,
  7159. HANDLE hDDVxd )
  7160. {
  7161. DDHALINFO ddhi;
  7162. LPDDRAWI_DIRECTDRAW_GBL new_pdrv;
  7163. DDPIXELFORMAT dpf;
  7164. #ifdef WINNT
  7165. DDHALMODEINFO dmi;
  7166. #endif
  7167. /*
  7168. * initialize the DDHALINFO struct
  7169. */
  7170. memset( &ddhi, 0, sizeof( ddhi ) );
  7171. ddhi.dwSize = sizeof( ddhi );
  7172. /*
  7173. * capabilities supported (none)
  7174. */
  7175. ddhi.ddCaps.dwCaps = 0;
  7176. ddhi.ddCaps.dwFXCaps = 0;
  7177. ddhi.ddCaps.dwCKeyCaps = 0;
  7178. ddhi.ddCaps.ddsCaps.dwCaps = 0;
  7179. /*
  7180. * pointer to primary surface.
  7181. */
  7182. if ( pmi->wFlags & DDMODEINFO_STANDARDVGA )
  7183. {
  7184. ddhi.vmiData.fpPrimary = 0xa0000;
  7185. }
  7186. else
  7187. {
  7188. //This needs to be SCREEN_PTR or the HEL won't realize it's a bad address
  7189. //(since when restoring display modes, restoreSurface for the primary will
  7190. //call into AllocSurfaceMem which will triviallt allocate the primary surface
  7191. //by setting fpVidMem == fpPrimaryOrig which will have been set to whatever
  7192. //we set here.
  7193. ddhi.vmiData.fpPrimary = 0xffbadbad;
  7194. }
  7195. /*
  7196. * build mode and pixel format info
  7197. */
  7198. ddhi.vmiData.dwDisplayHeight = pmi->dwHeight;
  7199. ddhi.vmiData.dwDisplayWidth = pmi->dwWidth;
  7200. ddhi.vmiData.lDisplayPitch = pmi->lPitch;
  7201. BuildPixelFormat( NULL, pmi, &dpf );
  7202. ddhi.vmiData.ddpfDisplay = dpf;
  7203. /*
  7204. * fourcc code information
  7205. */
  7206. ddhi.ddCaps.dwNumFourCCCodes = 0;
  7207. ddhi.lpdwFourCC = NULL;
  7208. /*
  7209. * Fill in heap info
  7210. */
  7211. ddhi.vmiData.dwNumHeaps = 0;
  7212. ddhi.vmiData.pvmList = NULL;
  7213. /*
  7214. * required alignments of the scanlines of each kind of memory
  7215. * (DWORD is the MINIMUM)
  7216. */
  7217. ddhi.vmiData.dwOffscreenAlign = sizeof( DWORD );
  7218. ddhi.vmiData.dwTextureAlign = sizeof( DWORD );
  7219. ddhi.vmiData.dwZBufferAlign = sizeof( DWORD );
  7220. /*
  7221. * callback functions
  7222. */
  7223. ddhi.lpDDCallbacks = NULL;
  7224. ddhi.lpDDSurfaceCallbacks = NULL;
  7225. ddhi.lpDDPaletteCallbacks = NULL;
  7226. /*
  7227. * create the driver object
  7228. */
  7229. #ifdef WINNT
  7230. //We can only get into modex if the ddraw object has already been created:
  7231. DDASSERT(pdrv);
  7232. //Don't fetch the driver's caps
  7233. ddhi.ddCaps.dwCaps = DDCAPS_NOHARDWARE;
  7234. //Force the modex data into the pdd. This causes GetCurrentMode to be a noop.
  7235. //pdrv->dwFlags |= DDRAWI_NOHARDWARE;
  7236. pdrv->dmiCurrent.wWidth =(WORD)pmi->dwWidth;
  7237. pdrv->dmiCurrent.wHeight =(WORD)pmi->dwHeight;
  7238. pdrv->dmiCurrent.wBPP =(BYTE)pmi->dwBPP;
  7239. pdrv->dmiCurrent.wRefreshRate =pmi->wRefreshRate;
  7240. pdrv->dmiCurrent.wMonitorsAttachedToDesktop=(BYTE)GetNumberOfMonitorAttachedToDesktop();
  7241. #endif
  7242. new_pdrv = DirectDrawObjectCreate( &ddhi, TRUE, pdrv, hDDVxd, NULL, 0 , 0 /* ATTENTION: No local flags for modex driver */ );
  7243. DPF(5,"MODEX driver object's display is %dx%d, pitch is %d", ddhi.vmiData.dwDisplayHeight,ddhi.vmiData.dwDisplayWidth,ddhi.vmiData.lDisplayPitch);
  7244. if( new_pdrv != NULL )
  7245. {
  7246. new_pdrv->dwFlags |= DDRAWI_MODEX;
  7247. if ( pmi->wFlags & DDMODEINFO_STANDARDVGA )
  7248. {
  7249. new_pdrv->dwFlags |= DDRAWI_STANDARDVGA;
  7250. }
  7251. #ifdef WIN95
  7252. if( new_pdrv->dwPDevice != 0 )
  7253. {
  7254. new_pdrv->dwPDevice = 0;
  7255. new_pdrv->lpwPDeviceFlags = (WORD *)&dwFakeFlags;
  7256. }
  7257. #endif //WIN95
  7258. }
  7259. DPF( 5, "ModeX DirectDraw object created (Standard VGA flag:%d)", (new_pdrv->dwFlags & DDRAWI_STANDARDVGA) ? 1 : 0 );
  7260. DPF( 5, " width=%ld, height=%ld, %ld bpp",
  7261. new_pdrv->vmiData.dwDisplayWidth,
  7262. new_pdrv->vmiData.dwDisplayHeight,
  7263. new_pdrv->vmiData.ddpfDisplay.dwRGBBitCount );
  7264. DPF( 5, " lDisplayPitch = %ld", new_pdrv->vmiData.lDisplayPitch );
  7265. return new_pdrv;
  7266. } /* fetchModeXData */
  7267. #ifdef WINNT
  7268. /*
  7269. * GetDriverInfo2
  7270. */
  7271. DWORD APIENTRY GetDriverInfo2(LPDDRAWI_DIRECTDRAW_GBL lpGbl,
  7272. DWORD* pdwDrvRet,
  7273. DWORD dwType,
  7274. DWORD dwSize,
  7275. void* pBuffer)
  7276. {
  7277. DD_GETDRIVERINFO2DATA* pGDI2Data;
  7278. DWORD ret;
  7279. DDHAL_GETDRIVERINFODATA gdidata;
  7280. // We cannot do anything if the driver doesn't support GetDriverInfo2
  7281. if ((lpGbl == NULL) || (!(lpGbl->dwFlags & DDRAWI_DRIVERINFO2)))
  7282. {
  7283. return 0;
  7284. }
  7285. // Setup GetDriverInfo2 call
  7286. pGDI2Data = (DD_GETDRIVERINFO2DATA*) pBuffer;
  7287. memset(pGDI2Data, 0, sizeof(*pGDI2Data));
  7288. pGDI2Data->dwReserved = sizeof(DD_STEREOMODE);
  7289. pGDI2Data->dwMagic = D3DGDI2_MAGIC;
  7290. pGDI2Data->dwType = dwType;
  7291. pGDI2Data->dwExpectedSize = dwSize;
  7292. ret = GetDriverInfo(lpGbl->pGetDriverInfo,
  7293. &gdidata,
  7294. pBuffer,
  7295. sizeof(DD_STEREOMODE),
  7296. &GUID_GetDriverInfo2,
  7297. lpGbl,
  7298. TRUE /* bInOut */);
  7299. *pdwDrvRet = gdidata.ddRVal;
  7300. return ret;
  7301. }
  7302. /*
  7303. * NotifyDriverOfFreeAliasedLocks
  7304. *
  7305. * This notifies the driver that we have unlocked all outstanding aliased
  7306. * locks on the device. It is possible to have multiple GBLs using the same
  7307. * physical device, so we need to handle that.
  7308. */
  7309. void NotifyDriverOfFreeAliasedLocks()
  7310. {
  7311. DD_FREE_DEFERRED_AGP_DATA fad;
  7312. DWORD dwDrvRet;
  7313. LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
  7314. LPDDRAWI_DIRECTDRAW_LCL pdd_temp;
  7315. BOOL bSkipThisOne;
  7316. if (dwNumLockedWhenModeSwitched == 0)
  7317. {
  7318. // Notify each device that all outstanding syslocks are gone
  7319. fad.dwProcessId = GetCurrentProcessId();
  7320. pdd_lcl = lpDriverLocalList;
  7321. while (pdd_lcl != NULL)
  7322. {
  7323. bSkipThisOne = FALSE;
  7324. pdd_temp = lpDriverLocalList;
  7325. while ((pdd_temp != NULL) &&
  7326. (pdd_temp != pdd_lcl))
  7327. {
  7328. if (pdd_temp->lpGbl == pdd_lcl->lpGbl)
  7329. {
  7330. bSkipThisOne = TRUE;
  7331. break;
  7332. }
  7333. pdd_temp = pdd_temp->lpLink;
  7334. }
  7335. if (!bSkipThisOne)
  7336. {
  7337. GetDriverInfo2(pdd_lcl->lpGbl, &dwDrvRet,
  7338. D3DGDI2_TYPE_FREE_DEFERRED_AGP,
  7339. sizeof(fad), &fad);
  7340. }
  7341. pdd_lcl = pdd_lcl->lpLink;
  7342. }
  7343. }
  7344. }
  7345. /*
  7346. * NotifyDriverToDeferFrees
  7347. *
  7348. * This notifies the driver that we are doing a mode change and they
  7349. * should start defering AGP free if they need to.
  7350. */
  7351. void NotifyDriverToDeferFrees()
  7352. {
  7353. DD_FREE_DEFERRED_AGP_DATA fad;
  7354. DWORD dwDrvRet;
  7355. LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
  7356. LPDDRAWI_DIRECTDRAW_LCL pdd_temp;
  7357. BOOL bSkipThisOne;
  7358. // Notify each device that all outstanding syslocks are gone
  7359. fad.dwProcessId = GetCurrentProcessId();
  7360. pdd_lcl = lpDriverLocalList;
  7361. while (pdd_lcl != NULL)
  7362. {
  7363. bSkipThisOne = FALSE;
  7364. pdd_temp = lpDriverLocalList;
  7365. while ((pdd_temp != NULL) &&
  7366. (pdd_temp != pdd_lcl))
  7367. {
  7368. if (pdd_temp->lpGbl == pdd_lcl->lpGbl)
  7369. {
  7370. bSkipThisOne = TRUE;
  7371. break;
  7372. }
  7373. pdd_temp = pdd_temp->lpLink;
  7374. }
  7375. if (!bSkipThisOne)
  7376. {
  7377. GetDriverInfo2(pdd_lcl->lpGbl, &dwDrvRet,
  7378. D3DGDI2_TYPE_DEFER_AGP_FREES,
  7379. sizeof(fad), &fad);
  7380. }
  7381. pdd_lcl = pdd_lcl->lpLink;
  7382. }
  7383. }
  7384. /*
  7385. * CheckAliasedLocksOnModeChange
  7386. *
  7387. * On NT we have to tell the driver when we are done using all surfaces that were
  7388. * locked with NOSYSLOCK so they can properly handle the case when they manage
  7389. * their own AGP heaps.
  7390. */
  7391. void CheckAliasedLocksOnModeChange()
  7392. {
  7393. DWORD dwGDI2Ret;
  7394. LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
  7395. LPDDRAWI_DIRECTDRAW_LCL pdd_temp;
  7396. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  7397. BOOL bSkipThisOne;
  7398. // For each device, figure out how many surfs are holding aliased locks and
  7399. // mark the surfaces.
  7400. dwNumLockedWhenModeSwitched = 0;
  7401. pdd_lcl = lpDriverLocalList;
  7402. while (pdd_lcl != NULL)
  7403. {
  7404. // if we have already processed this GBL, don't do it again!
  7405. bSkipThisOne = FALSE;
  7406. pdd_temp = lpDriverLocalList;
  7407. while ((pdd_temp != NULL) &&
  7408. (pdd_temp != pdd_lcl))
  7409. {
  7410. if (pdd_temp->lpGbl == pdd_lcl->lpGbl)
  7411. {
  7412. bSkipThisOne = TRUE;
  7413. break;
  7414. }
  7415. pdd_temp = pdd_temp->lpLink;
  7416. }
  7417. if (!bSkipThisOne &&
  7418. (pdd_lcl->lpGbl != NULL))
  7419. {
  7420. // We need to start fresh with each device, so clear all flags we
  7421. // have outstanding as to whether the surface has an outstanding
  7422. // NOSYSLOCK lock.
  7423. psurf_int = pdd_lcl->lpGbl->dsList;
  7424. while (psurf_int != NULL)
  7425. {
  7426. if (psurf_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_NOTIFYWHENUNLOCKED)
  7427. {
  7428. psurf_int->lpLcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
  7429. }
  7430. psurf_int = psurf_int->lpLink;
  7431. }
  7432. // Now we go back through them and re-mark them.
  7433. psurf_int = pdd_lcl->lpGbl->dsList;
  7434. while (psurf_int != NULL)
  7435. {
  7436. if ((psurf_int->lpLcl->lpGbl->dwUsageCount > 0) &&
  7437. !(psurf_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_NOTIFYWHENUNLOCKED))
  7438. {
  7439. // The code below relies on the fact that the NT kernel
  7440. // cannot handle multiple locks to the same surface if any
  7441. // one of them is a NOSYSLOCK. If this ever changes, this
  7442. // code needs to be changed.
  7443. if (psurf_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_LOCKNOTHOLDINGWIN16LOCK)
  7444. {
  7445. psurf_int->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
  7446. dwNumLockedWhenModeSwitched++;
  7447. }
  7448. else if ((psurf_int->lpLcl->lpGbl->lpRectList != NULL) &&
  7449. (psurf_int->lpLcl->lpGbl->lpRectList->dwFlags & ACCESSRECT_NOTHOLDINGWIN16LOCK))
  7450. {
  7451. psurf_int->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
  7452. dwNumLockedWhenModeSwitched++;
  7453. }
  7454. }
  7455. psurf_int = psurf_int->lpLink;
  7456. }
  7457. }
  7458. pdd_lcl = pdd_lcl->lpLink;
  7459. }
  7460. // Now see if we can notify the drivers to free the surfaces or not.
  7461. if ((dwNumLockedWhenModeSwitched == 0) &&
  7462. (lpDriverLocalList != NULL))
  7463. {
  7464. // For DX9, add logic here to handle bad PDEVs
  7465. NotifyDriverOfFreeAliasedLocks();
  7466. }
  7467. }
  7468. #endif