DRVMGR.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:84k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2. **-----------------------------------------------------------------------------
  3. **  Name:       DrvMgr.cpp
  4. **  Purpose:    Implements DD/D3D Driver/Device enumeration
  5. **
  6. **  Copyright (c) 1995 - 1997 by Microsoft, all rights reserved.
  7. **-----------------------------------------------------------------------------
  8. */
  9. /*
  10. **-----------------------------------------------------------------------------
  11. **  Includes
  12. **-----------------------------------------------------------------------------
  13. */
  14. #include "DrvMgr.h"
  15. #include "Debug.h"
  16. /*
  17. **-----------------------------------------------------------------------------
  18. **  Typedefs
  19. **-----------------------------------------------------------------------------
  20. */
  21. // Used with Enumeration Callbacks
  22. typedef struct tagDD_CB_INFO 
  23. {
  24.     BOOL   fResult;     // Success/Failure
  25.     DWORD   cCount;       // Current count
  26.     void *    lpExtra; // Current Driver/Device/Etc.
  27. } DD_CB_INFO;
  28. typedef DD_CB_INFO * LPDD_CB_INFO;
  29. /*
  30. **-----------------------------------------------------------------------------
  31. **  Global Variables
  32. **-----------------------------------------------------------------------------
  33. */
  34. // Global DDDrvMgr data
  35. DWORD       DDDrvMgr::g_fFlags = 0L;
  36. DWORD DDDrvMgr::g_cDrivers = 0L;
  37. LPDDDrvInfo DDDrvMgr::g_lpDriverRoot = NULL;
  38. LPDDDrvInfo DDDrvMgr::g_lpDriverTail = NULL;
  39. /*
  40. **-----------------------------------------------------------------------------
  41. **  Local Prototypes
  42. **-----------------------------------------------------------------------------
  43. */
  44. BOOL WINAPI DriverEnumCallback (LPGUID lpGuid, LPTSTR lpDesc, 
  45.                                 LPTSTR lpName, LPVOID lpExtra);
  46. HRESULT WINAPI ModeEnumCallback (LPDDSURFACEDESC lpDDSurfDesc,
  47.                                  LPVOID lpExtra);
  48. HRESULT WINAPI TextureFormatEnumCallback (LPDDSURFACEDESC lpTexFormatDesc,
  49.   LPVOID lpExtra);
  50. HRESULT WINAPI DeviceEnumCallback (LPGUID lpGuid, 
  51.    LPTSTR lpName,  
  52.    LPTSTR lpDesc,
  53.                                    LPD3DDEVICEDESC lpHalDevice,
  54.                                    LPD3DDEVICEDESC lpHelDevice, 
  55.                                    LPVOID lpExtra);
  56.     
  57. /*
  58. **-----------------------------------------------------------------------------
  59. **  Functions
  60. **-----------------------------------------------------------------------------
  61. */
  62. /*
  63. **-----------------------------------------------------------------------------
  64. ** Name:    ValidateDriver
  65. ** Purpose: Find DD driver matching user choice
  66. ** or returns the primary driver on failure
  67. **-----------------------------------------------------------------------------
  68. */
  69. LPDDDrvInfo ValidateDriver (LPGUID lpDDGuid)
  70. {
  71. LPDDDrvInfo lpDrvNew, lpDrvNext;
  72.     // Find Driver matching specified GUID
  73.     lpDrvNew = DDDrvMgr::FindDriver (lpDDGuid, &lpDrvNext);
  74.     if (lpDrvNew)
  75. {
  76. // Exact match
  77. return lpDrvNew;
  78. }
  79. // Return next best match (or failure)
  80. return lpDrvNext;
  81. } // End ValidateDriver
  82.   
  83. /*
  84. **-----------------------------------------------------------------------------
  85. ** Name:    ValidateMode
  86. ** Purpose: Find DD mode matching user choice (w,h,bpp)
  87. ** Notes: filters modes against device, if specified.
  88. **-----------------------------------------------------------------------------
  89. */
  90. LPDDModeInfo ValidateMode (
  91. LPDDDrvInfo  lpDriver,  /* In:  DD Driver */
  92. DWORD  w, /* In:  width, height, bpp */
  93. DWORD  h,
  94. DWORD  bpp,
  95. DWORD  refresh,
  96. LPD3DDevInfo lpFilter) /* In: Device used as filter */
  97. {
  98. LPDDModeInfo lpModeNew, lpModeNext;
  99. // Check Parameters
  100. if (! lpDriver)
  101. return FALSE;
  102. if (! lpFilter)
  103. lpModeNew = lpDriver->FindMode (w, h, bpp, refresh, &lpModeNext);
  104. else
  105. {
  106. // Filter mode against D3D device compatiblity
  107. lpModeNew = lpDriver->FindModeSupportsDevice (w, h, bpp, refresh,
  108.   lpFilter,
  109.   &lpModeNext);
  110. }
  111.     if (lpModeNew)
  112. {
  113. // Exact match
  114. return lpModeNew;
  115. }
  116. // Return next best match (or failure)
  117. return lpModeNext;
  118. } // End ValidateMode
  119.   
  120.   
  121. /*
  122. **-----------------------------------------------------------------------------
  123. ** Name:    ValidateDevice
  124. ** Purpose: Find D3D device matching user choice
  125. ** Notes: Filters devices against mode, if specified.
  126. **-----------------------------------------------------------------------------
  127. */
  128. LPD3DDevInfo ValidateDevice(
  129. LPDDDrvInfo  lpDriver,
  130. LPGUID  lpD3DGuid,
  131. LPDDModeInfo lpFilter)
  132. {
  133. LPD3DDevInfo lpDevNew, lpDevNext;
  134. // Check Parameters
  135. if (! lpDriver)
  136. return FALSE;
  137. if (! lpFilter)
  138. {
  139. lpDevNew = lpDriver->FindDevice (lpD3DGuid, &lpDevNext);
  140. }
  141. else
  142. {
  143. // Filter device against mode
  144. lpDevNew = lpDriver->FindDeviceSupportsMode (lpD3DGuid, 
  145.         lpFilter,
  146.  &lpDevNext);
  147. }
  148.     if (lpDevNew)
  149. {
  150. // Exact match
  151. return lpDevNew;
  152. }
  153. // Return next best match (or failure)
  154. return lpDevNext;
  155. } // End ValidateDevice
  156.   
  157.   
  158. /*
  159. **-----------------------------------------------------------------------------
  160. ** Name:    ValidateFormat
  161. ** Purpose: Find texture format matching user choice (ddpfPixelformat)
  162. ** Notes: filters modes against device, if specified.
  163. **-----------------------------------------------------------------------------
  164. */
  165. LPDDModeInfo ValidateFormat (
  166. LPD3DDevInfo lpDevice,  /* In:  D3D Device */
  167. DWORD  bpp)
  168. {
  169. LPDDModeInfo lpFormatNew, lpFormatNext;
  170. // Check Parameters
  171. if (! lpDevice)
  172. return FALSE;
  173. lpFormatNew = lpDevice->FindFormat (bpp, &lpFormatNext);
  174.     if (lpFormatNew)
  175. {
  176. // Exact match
  177. return lpFormatNew;
  178. }
  179. // Return next best match (or failure)
  180. return lpFormatNext;
  181. } // End ValidateFormat
  182.   
  183. /*
  184. **-----------------------------------------------------------------------------
  185. ** Name:    ValidateFormat
  186. ** Purpose: Find texture format matching user choice (ddpfPixelformat)
  187. ** Notes: filters modes against device, if specified.
  188. **-----------------------------------------------------------------------------
  189. */
  190. LPDDModeInfo ValidateFormat (
  191. LPD3DDevInfo lpDevice,  /* In:  D3D Device */
  192. LPDDPIXELFORMAT lpddpf)
  193. {
  194. LPDDModeInfo lpFormatNew, lpFormatNext;
  195. // Check Parameters
  196. if (! lpDevice)
  197. return FALSE;
  198. lpFormatNew = lpDevice->FindFormat (lpddpf, &lpFormatNext);
  199.     if (lpFormatNew)
  200. {
  201. // Exact match
  202. return lpFormatNew;
  203. }
  204. // Return next best match (or failure)
  205. return lpFormatNext;
  206. } // End ValidateFormat
  207.   
  208. /*
  209. **-----------------------------------------------------------------------------
  210. ** Name:    GetDesktopMode
  211. ** Purpose: Find DD mode corresponding to desktop 
  212. ** and a compatible D3D device.
  213. ** Notes:
  214. **
  215. ** 1.  We have no choice, we are stuck with the current desktop mode.
  216. **  2.  Since we can't change the mode, we must choose a D3D device
  217. ** that is compatible with the current mode.
  218. **
  219. **-----------------------------------------------------------------------------
  220. */
  221. BOOL GetDesktopMode (
  222. LPDDDrvInfo  lpDriver, /* In:   Driver */
  223. LPGUID  lpD3DGuid, /* In:   Requested D3D device guid */
  224. LPDDModeInfo * lpMode, /* Out:  Desktop Mode */
  225. LPD3DDevInfo * lpDev) /* Out:  D3D device compatible with mode */
  226. {
  227. HWND  hDesktop;
  228. HDC  hdc;
  229. DWORD  w, h, bpp;
  230. LPDDModeInfo lpModeNew;
  231. LPD3DDevInfo lpDevNew, lpDevNext;
  232. // Check Parameters
  233. if ((! lpDriver) || (! lpMode) || (! lpDev))
  234. return FALSE;
  235. // Get Desktop Mode info
  236. hDesktop = GetDesktopWindow ();
  237. hdc = GetDC (hDesktop);
  238. w = GetDeviceCaps (hdc, HORZRES);
  239. h = GetDeviceCaps (hdc, VERTRES);
  240. bpp = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps (hdc, BITSPIXEL);
  241. ReleaseDC (hDesktop, hdc);
  242. // Get Mode
  243. lpModeNew = lpDriver->FindMode (w, h, bpp, 0, NULL);
  244. if (! lpModeNew)
  245. return FALSE;
  246. // Get Compatible Device
  247. lpDevNew = lpDriver->FindDeviceSupportsMode (lpD3DGuid,
  248.            lpModeNew,
  249.  &lpDevNext);
  250. if (! lpDevNew)
  251. {
  252. if (! lpDevNext)
  253. return FALSE;
  254. lpDevNew = lpDevNext;
  255. }
  256. // Save results
  257. *lpMode = lpModeNew;
  258. *lpDev  = lpDevNew;
  259. // Success
  260. return TRUE;
  261. } // End GetDesktopMode
  262.   
  263. /*
  264. **-----------------------------------------------------------------------------
  265. ** Name:    GetFullscreenMode
  266. ** Purpose: Find D3D Device and a compatible mode
  267. ** Notes:
  268. **
  269. **  1. Pick the D3D device first
  270. **  2. Pick a DD mode that is compatible with our D3D device choice.
  271. **-----------------------------------------------------------------------------
  272. */
  273. BOOL GetFullscreenMode (
  274. LPDDDrvInfo  lpDriver, /* In:   Driver */
  275. LPGUID  lpD3DGuid, /* In:   requested D3D device guid */
  276. DWORD  w, /* In:  requested mode */
  277. DWORD  h,
  278. DWORD  bpp,
  279. DWORD        refresh,
  280. LPDDModeInfo * lpMode, /* Out:  Valid Desktop Mode compatible with device */
  281. LPD3DDevInfo * lpDev) /* Out:  Valid D3D device */
  282. {
  283. LPDDModeInfo lpModeNew, lpModeNext;
  284. LPD3DDevInfo lpDevNew, lpDevNext;
  285. // Check Parameters
  286. if ((! lpDriver) || (! lpMode) || (! lpDev))
  287. return FALSE;
  288. // Get D3D Device
  289. lpDevNew = lpDriver->FindDevice (lpD3DGuid, &lpDevNext);
  290. if (! lpDevNew)
  291. {
  292. if (! lpDevNext)
  293. return FALSE;
  294. lpDevNew = lpDevNext;
  295. }
  296. // Double check requested mode parameters
  297. if ((w == 0) || (h == 0) || (bpp == 0))
  298. {
  299. // Pick a reasonable full screen default
  300. // Most Hardware devices support 16 bpp,
  301. // many don't support 8 bpp, so pick 16
  302. w   = 640;
  303. h = 480;
  304. bpp = 16;
  305. }
  306. // Get Compatible Mode
  307. lpModeNew = lpDriver->FindModeSupportsDevice (w, h, bpp, refresh,
  308.       lpDevNew,
  309.   &lpModeNext);
  310. if (! lpModeNew)
  311. {
  312. if (! lpModeNext)
  313. return FALSE;
  314. lpModeNew = lpModeNext;
  315. }
  316. // Save results
  317. *lpMode = lpModeNew;
  318. *lpDev  = lpDevNew;
  319. // Success
  320. return TRUE;
  321. } // End GetFullscreenMode
  322.   
  323. /*
  324. **-----------------------------------------------------------------------------
  325. ** Name:    ChooseDriverDefaults
  326. ** Purpose: Chooses default driver, mode, and device
  327. ** Notes:
  328. **
  329. ** Windowed: The mode comes from the desktop and can't be changed
  330. ** so derive the device from the mode.
  331. **  FullScreen: Any mode is fine.  Hardware is more interesting than
  332. ** software, so derive the mode from the device
  333. ** 
  334. **-----------------------------------------------------------------------------
  335. */
  336. HRESULT ChooseDriverDefaults (
  337.     LPGUID lpGuidDD, // In: Requested DD Guid
  338.     DWORD  dwW, // In: Requested Mode (w,h,bpp,refresh)
  339. DWORD  dwH,
  340. DWORD  dwBPP, 
  341. DWORD  dwRefresh,
  342.     LPGUID lpGuidD3D, // In: Requested D3D Guid
  343. BOOL   fFullScreen, // In:  Fullscreen or Windowed mode
  344. LPDDDrvInfo * lpDriver, // Out: Valid Driver
  345. LPDDModeInfo * lpMode, // Out: Valid Mode
  346. LPD3DDevInfo * lpDevice) // Out: Valid Device
  347. {
  348. HRESULT hResult;
  349.     LPDDDrvInfo lpDrvNew;
  350. LPDDModeInfo lpModeNew;
  351. LPD3DDevInfo lpDevNew;
  352. // Check Parameters
  353. if ((! lpDriver) || (! lpMode) || (! lpDevice))
  354. {
  355. hResult = APPERR_INVALIDPARAMS;
  356. REPORTERR (hResult);
  357. return hResult;
  358. }
  359. // Initialize Driver Manager, if necessary
  360. if (! DDDrvMgr::isInitialized ())
  361. {
  362. hResult = DDDrvMgr::Init ();
  363. if (FAILED (hResult))
  364. return hResult;
  365. }
  366.     
  367.     // Find Driver matching specified GUID
  368.     lpDrvNew = ValidateDriver (lpGuidDD);
  369. if (! lpDrvNew)
  370.     {
  371.         // Error, invalid DD Guid
  372. hResult = APPERR_INVALIDPARAMS;
  373. REPORTERR (hResult);
  374.         return hResult;
  375.     }
  376. if (fFullScreen)
  377. {
  378. // Get D3D device and compatible mode
  379.     if (! GetFullscreenMode (lpDrvNew, lpGuidD3D, 
  380.  dwW, dwH, dwBPP, dwRefresh,
  381.  &lpModeNew, &lpDevNew))
  382. {
  383. hResult = APPERR_GENERIC;
  384. REPORTERR (hResult);
  385. return hResult;
  386. }
  387. }
  388. else
  389. {
  390. // Get Desktop mode and compatible D3D device
  391. if (! GetDesktopMode (lpDrvNew, lpGuidD3D, &lpModeNew, &lpDevNew))
  392. {
  393. hResult = APPERR_GENERIC;
  394. REPORTERR (hResult);
  395. return hResult;
  396. }
  397. }
  398. // Return results
  399. *lpDriver = lpDrvNew;
  400. *lpMode   = lpModeNew;
  401. *lpDevice = lpDevNew;
  402.     // Success
  403.     return DD_OK;
  404. } // End ChooseDriverDefaults
  405.   
  406. /*
  407. **-----------------------------------------------------------------------------
  408. **  Name:       FlagsToBitDepth
  409. **  Purpose:    Gets Bit Depth from DDPF Flags
  410. **-----------------------------------------------------------------------------
  411. */
  412. DWORD FlagsToBitDepth (DWORD dwFlags)
  413. {
  414.     if (dwFlags & DDBD_1)
  415.         return 1L;
  416.     else if (dwFlags & DDBD_2)
  417.         return 2L;
  418.     else if (dwFlags & DDBD_4)
  419.         return 4L;
  420.     else if (dwFlags & DDBD_8)
  421.         return 8L;
  422.     else if (dwFlags & DDBD_16)
  423.         return 16L;
  424.     else if (dwFlags & DDBD_24)
  425.         return 24L;
  426.     else if (dwFlags & DDBD_32)
  427.         return 32L;
  428.     else
  429.         return 0L; 
  430. } // End FlagsToBitDepth
  431. /*
  432. **-----------------------------------------------------------------------------
  433. **  Name:       BitDepthToFlags
  434. **  Purpose:    Converts BPP to corresponding DDPF flag
  435. **-----------------------------------------------------------------------------
  436. */
  437. DWORD BitDepthToFlags (DWORD dwBPP)
  438. {
  439.     switch (dwBPP) 
  440. {
  441. case 1:
  442.     return DDBD_1;
  443. case 2:
  444.     return DDBD_2;
  445. case 4:
  446.     return DDBD_4;
  447. case 8:
  448.     return DDBD_8;
  449. case 16:
  450.     return DDBD_16;
  451. case 24:
  452.     return DDBD_24;
  453. case 32:
  454.     return DDBD_32;
  455. default:
  456. // Error
  457.     return (DWORD)0L;
  458.     }
  459. } // End BitDepthToFlags
  460.   
  461. /*
  462. **-----------------------------------------------------------------------------
  463. ** Name:    isPalettized
  464. **-----------------------------------------------------------------------------
  465. */
  466. BOOL isPalettized (LPDDPIXELFORMAT lpddpf)
  467. {
  468.     if (! lpddpf)
  469.     {
  470.         // Error, 
  471.         return FALSE;
  472.     }
  473.     if (lpddpf->dwFlags & DDPF_PALETTEINDEXED1)
  474.         return TRUE;
  475.     if (lpddpf->dwFlags & DDPF_PALETTEINDEXED2)
  476.         return TRUE;
  477.     if (lpddpf->dwFlags & DDPF_PALETTEINDEXED4)
  478.         return TRUE;
  479.     if (lpddpf->dwFlags & DDPF_PALETTEINDEXED8)
  480.         return TRUE;
  481.     // Not palettized
  482.     return FALSE;
  483. } // End IsPalettized
  484. /*
  485. **-----------------------------------------------------------------------------
  486. **  Local Functions
  487. **-----------------------------------------------------------------------------
  488. */
  489.   
  490. /*
  491. **-----------------------------------------------------------------------------
  492. **  Name:       DriverEnumCallback
  493. **  Purpose:    Add this DD driver to global driver list
  494. **-----------------------------------------------------------------------------
  495. */
  496. BOOL WINAPI DriverEnumCallback(
  497.     GUID FAR *  lpGuid,
  498.     LPTSTR      lpDesc, 
  499.     LPTSTR      lpName,
  500.     LPVOID      lpExtra)
  501. {
  502.     HRESULT         hResult;
  503.     LPDD_CB_INFO lpInfo;
  504.     LPDDDrvInfo     lpDriver;
  505.     DWORD           dwIndex;
  506.     if (! lpExtra)
  507.     {
  508.         // Programming error, invalid pointer
  509.         return DDENUMRET_OK;
  510.     }
  511.     lpInfo = (LPDD_CB_INFO)lpExtra;
  512.     dwIndex = lpInfo->cCount;
  513.     // Get Pointer to driver info
  514.     lpDriver = new DDDrvInfo;
  515.     if (! lpDriver)
  516.     {
  517.         // Error, Not enough memory to create driver
  518.         return DDENUMRET_OK;
  519.     }
  520.     // Initialize driver 
  521. // Enumerate modes, D3D devices
  522.     hResult = lpDriver->Create (lpGuid, lpName, lpDesc);
  523.     if (FAILED (hResult))
  524.     {
  525.         // Error, Driver Create failed
  526.         return DDENUMRET_OK;
  527.     }
  528. // Add To Global Driver List
  529. hResult = DDDrvMgr::AddDriver (lpDriver);
  530. if (FAILED (hResult))
  531. {
  532. // Error, Driver Create Failed
  533. return DDENUMRET_OK;
  534. }
  535.     // Increment driver count
  536.     lpInfo->cCount++;
  537.     // Success
  538.     return DDENUMRET_OK;
  539. } // End DriverEnumCallback
  540. /*
  541. **-----------------------------------------------------------------------------
  542. **  Name:       ModeEnumCallback
  543. **  Purpose:    Add this mode to the driver
  544. **-----------------------------------------------------------------------------
  545. */
  546. HRESULT WINAPI ModeEnumCallback (
  547.     LPDDSURFACEDESC lpDDSurfDesc,
  548.     LPVOID          lpExtra)
  549. {
  550. HRESULT hResult;
  551. LPDDModeInfo lpMode;
  552.     LPDD_CB_INFO lpInfo;
  553.     LPDDDrvInfo lpDriver;
  554.     DWORD           dwIndex;
  555.     if (! lpExtra)
  556.     {
  557.         // Programming error, invalid pointer
  558.         return DDENUMRET_OK;
  559.     }
  560.     lpInfo   = (LPDD_CB_INFO)lpExtra;
  561.     lpDriver = (LPDDDrvInfo) lpInfo->lpExtra;
  562.     dwIndex  = lpInfo->cCount;
  563.     if (! lpDriver)
  564.     {
  565.         // Programming Error, invalid pointer
  566.         return DDENUMRET_OK;
  567.     }
  568.     if (! lpDDSurfDesc)
  569.     {
  570.         // Error, invalid pointer
  571.         return DDENUMRET_CANCEL;
  572.     }
  573.     // Double check structure size
  574.     if (lpDDSurfDesc->dwSize != sizeof(DDSURFACEDESC))
  575.     {
  576.         // Error, structure is wrong size
  577.         return DDENUMRET_CANCEL;
  578.     }
  579. // Create Mode node
  580. lpMode = new DDModeInfo;
  581. if (! lpMode)
  582. {
  583.         // Error, not enough memory to store mode info
  584.         return DDENUMRET_OK;
  585. }
  586.     // Copy surface description
  587.     lpMode->ddSurfDesc = *lpDDSurfDesc;
  588. // Add Mode to Driver Mode List
  589. hResult = lpDriver->AddMode (lpMode);
  590. if (FAILED (hResult))
  591. {
  592.         // Error, not enough memory to store mode info
  593.         return DDENUMRET_OK;
  594. }
  595.     // Update mode count
  596.     lpInfo->cCount++;
  597.         
  598.     return DDENUMRET_OK;
  599. } // End ModeEnumCallback
  600. /*
  601. **-----------------------------------------------------------------------------
  602. **  Name:       TextureFormatEnumCallback
  603. **  Purpose:    Add this mode to the driver
  604. **-----------------------------------------------------------------------------
  605. */
  606. HRESULT WINAPI TextureFormatEnumCallback (
  607.     LPDDSURFACEDESC lpTextureFormat,
  608.     LPVOID          lpExtra)
  609. {
  610. HRESULT hResult;
  611. LPDDModeInfo lpFormat;
  612.     LPDD_CB_INFO lpInfo;
  613.     LPD3DDevInfo lpDevice;
  614.     DWORD           dwIndex;
  615.     if (! lpExtra)
  616.     {
  617.         // Programming error, invalid pointer
  618.         return DDENUMRET_OK;
  619.     }
  620.     lpInfo   = (LPDD_CB_INFO)lpExtra;
  621.     lpDevice = (LPD3DDevInfo)lpInfo->lpExtra;
  622.     dwIndex  = lpInfo->cCount;
  623.     if (! lpDevice)
  624.     {
  625.         // Programming error, invalid pointer
  626.         return DDENUMRET_OK;
  627.     }
  628.     if (! lpTextureFormat)
  629.     {
  630.         // Error, invalid pointer
  631.         return DDENUMRET_CANCEL;
  632.     }
  633.     // Double check structure size
  634.     if (lpTextureFormat->dwSize != sizeof(DDSURFACEDESC))
  635.     {
  636.         // Error, structure is wrong size
  637.         return DDENUMRET_CANCEL;
  638.     }
  639. // Create format node
  640. lpFormat = new DDModeInfo;
  641. if (! lpFormat)
  642. {
  643.         // Error, not enough memory to store format info
  644.         return DDENUMRET_OK;
  645. }
  646.     // Copy texture format description
  647.     lpFormat->ddSurfDesc = *lpTextureFormat;
  648. // Add format to D3D device format list
  649. hResult = lpDevice->AddFormat (lpFormat);
  650. if (FAILED (hResult))
  651. {
  652.         // Error, not enough memory to store mode info
  653.         return DDENUMRET_OK;
  654. }
  655.     // Update format count
  656.     lpInfo->cCount++;
  657.         
  658.     return DDENUMRET_OK;
  659. } // End TextureFormatEnumCallback
  660.   
  661.   
  662. /*
  663. **-----------------------------------------------------------------------------
  664. **  Name:       DeviceEnumCallback
  665. **  Purpose:    Add this D3D Device Driver info to the driver
  666. **-----------------------------------------------------------------------------
  667. */
  668. HRESULT WINAPI DeviceEnumCallback (
  669.     LPGUID          lpGuid,
  670.     LPTSTR          lpName,
  671.     LPTSTR          lpDesc,
  672.     LPD3DDEVICEDESC lpHalDevice,
  673.     LPD3DDEVICEDESC lpHelDevice,
  674.     LPVOID          lpExtra)
  675. {
  676.     HRESULT         hResult;
  677.     LPDD_CB_INFO lpInfo;
  678.     LPDDDrvInfo     lpDriver;
  679. LPD3DDevInfo lpDevice;
  680.     DWORD           dwIndex;
  681.     if (! lpExtra)
  682.     {
  683.         // Programming error, invalid pointer
  684.         return DDENUMRET_OK;
  685.     }
  686.     lpInfo   = (LPDD_CB_INFO) lpExtra;
  687.     lpDriver = (LPDDDrvInfo) lpInfo->lpExtra;
  688.     dwIndex  = lpInfo->cCount;
  689.     if (! lpDriver)
  690.     {
  691.         // Programming Error, invalid pointer
  692.         return DDENUMRET_OK;
  693.     }
  694. // Create D3D Device node
  695. lpDevice = new D3DDevInfo;
  696. if (! lpDevice)
  697. {
  698.         // Not Enough memory to create D3D device node
  699.         return DDENUMRET_OK;
  700. }
  701.     // Initialize D3D Device info
  702.     hResult = lpDevice->Create (lpGuid, lpName, lpDesc,
  703.                                 lpHalDevice, lpHelDevice);
  704.     if (FAILED (hResult))
  705.     {
  706.         // Error
  707.         return DDENUMRET_OK;
  708.     }
  709. // Add to Driver D3D Device list
  710. hResult = lpDriver->AddDevice (lpDevice);
  711. if (FAILED (hResult))
  712. {
  713.         // Error
  714.         return DDENUMRET_OK;
  715. }
  716.     // Update D3D device Driver count
  717.     lpInfo->cCount++;
  718.         
  719.     return DDENUMRET_OK;
  720. } // End DeviceEnumCallback
  721.   
  722. /*
  723. **-----------------------------------------------------------------------------
  724. **  DDModeInfo Methods
  725. **-----------------------------------------------------------------------------
  726. */
  727. /*
  728. **-----------------------------------------------------------------------------
  729. **  Name:       DDModeInfo::GetWidth
  730. **  Purpose:    Gets the Width for this mode
  731. **-----------------------------------------------------------------------------
  732. */
  733. DWORD DDModeInfo::GetWidth (void)
  734. {
  735.     // Check parameters
  736.     if (ddSurfDesc.dwSize != sizeof (DDSURFACEDESC))
  737.         return 0L;
  738. // Check that Pixel format is valid
  739. if (! (ddSurfDesc.dwFlags & DDSD_WIDTH))
  740. return 0L;
  741. // Get Bits Per Pixel
  742. return ddSurfDesc.dwWidth;
  743. } // DDModeInfo::GetWidth
  744.   
  745. /*
  746. **-----------------------------------------------------------------------------
  747. **  Name:       DDModeInfo::GetHeight
  748. **  Purpose:    Gets the Height for this mode
  749. **-----------------------------------------------------------------------------
  750. */
  751. DWORD DDModeInfo::GetHeight (void)
  752. {
  753.     // Check parameters
  754.     if (ddSurfDesc.dwSize != sizeof (DDSURFACEDESC))
  755.         return 0L;
  756. // Check that Pixel format is valid
  757. if (! (ddSurfDesc.dwFlags & DDSD_HEIGHT))
  758. return 0L;
  759. // Get Bits Per Pixel
  760. return ddSurfDesc.dwHeight;
  761. } // DDModeInfo::GetHeight
  762. /*
  763. **-----------------------------------------------------------------------------
  764. **  Name:       DDModeInfo::GetBPP
  765. **  Purpose:    Gets the Bits per pixel for this mode
  766. **-----------------------------------------------------------------------------
  767. */
  768. DWORD DDModeInfo::GetBPP (void)
  769. {
  770.     // Check parameters
  771.     if (ddSurfDesc.dwSize != sizeof (DDSURFACEDESC))
  772.         return 0L;
  773. // Check that Pixel format is valid
  774. if (! (ddSurfDesc.dwFlags & DDSD_PIXELFORMAT))
  775. return 0L;
  776. if (ddSurfDesc.ddpfPixelFormat.dwSize != sizeof(DDPIXELFORMAT))
  777. return 0L;
  778. // Assume it is RGB
  779. return ddSurfDesc.ddpfPixelFormat.dwRGBBitCount;
  780. } // DDModeInfo::GetBPP
  781. /*
  782. **-----------------------------------------------------------------------------
  783. **  Name:       DDModeInfo::GetMode
  784. **  Purpose:    Gets the Mode info (w,h,bpp) for this mode
  785. **-----------------------------------------------------------------------------
  786. */
  787. HRESULT DDModeInfo::GetMode (
  788. DWORD & dwW, 
  789. DWORD & dwH, 
  790. DWORD & dwBPP,
  791. DWORD & dwRefresh)
  792. {
  793.     // Check parameters
  794.     if (ddSurfDesc.dwSize != sizeof (DDSURFACEDESC))
  795.         return DDERR_GENERIC;
  796. // Check that width is valid
  797. if (! (ddSurfDesc.dwFlags & DDSD_WIDTH))
  798. return DDERR_GENERIC;
  799. // Check that height is valid
  800. if (! (ddSurfDesc.dwFlags & DDSD_HEIGHT))
  801. return DDERR_GENERIC;
  802. // Check that Pixel format is valid
  803. if (! (ddSurfDesc.dwFlags & DDSD_PIXELFORMAT))
  804. return DDERR_GENERIC;
  805. if (ddSurfDesc.ddpfPixelFormat.dwSize != sizeof(DDPIXELFORMAT))
  806. return DDERR_GENERIC;
  807. // Get Width, height, BPP
  808. dwW = ddSurfDesc.dwWidth;
  809. dwH = ddSurfDesc.dwHeight;
  810. dwBPP = ddSurfDesc.ddpfPixelFormat.dwRGBBitCount;
  811. dwRefresh = 0L;
  812. // Success
  813. return DD_OK;
  814. } // DDModeInfo::GetMode
  815. /*
  816. **-----------------------------------------------------------------------------
  817. **  Name:       DDModeInfo::ModeSupportedByDevice
  818. **  Purpose:    
  819. **-----------------------------------------------------------------------------
  820. */
  821. BOOL DDModeInfo::ModeSupported (LPD3DDevInfo lpDevice)
  822. {
  823. // Check Parameters
  824. if (! lpDevice)
  825. return FALSE;
  826. // Make sure D3D device supports this mode
  827. DWORD dwBPP    = GetBPP ();
  828. DWORD dwFlag   = BitDepthToFlags (dwBPP);
  829. DWORD dwDepths = 0L;
  830. // Get Supported Bit Depths for this D3D device
  831. if (lpDevice->isHardware ())
  832. dwDepths = lpDevice->d3dHalDesc.dwDeviceRenderBitDepth;
  833. else
  834. dwDepths = lpDevice->d3dHelDesc.dwDeviceRenderBitDepth;
  835. if (dwDepths & dwFlag)
  836. {
  837. // Supported !!!
  838. return TRUE;
  839. }
  840. // Not Supported !!!
  841. return FALSE;
  842. } // End DDModeInfo::ModeSupported
  843.   
  844.   
  845.   
  846. /*
  847. **-----------------------------------------------------------------------------
  848. **  Name:       DDModeInfo::Match
  849. **  Purpose:    Checks if this mode matches (w,h,bpp)
  850. **-----------------------------------------------------------------------------
  851. */
  852. BOOL DDModeInfo::Match (DWORD dwW, DWORD dwH, DWORD dwBPP)
  853. {
  854.     // Check parameters
  855.     if (ddSurfDesc.dwSize != sizeof (DDSURFACEDESC))
  856.         return FALSE;
  857. // Check for Match
  858.     if ((ddSurfDesc.dwWidth  == dwW) &&
  859.         (ddSurfDesc.dwHeight == dwH))
  860. {
  861. if (ddSurfDesc.ddpfPixelFormat.dwRGBBitCount == dwBPP)
  862. return TRUE;
  863.     }
  864.     return FALSE;
  865. } // DDModeInfo::Match
  866.   
  867. /*
  868. **-----------------------------------------------------------------------------
  869. **  Name:       DDDrvInfo::Match
  870. **  Purpose:    Checks if this mode matches with this surface desc
  871. **-----------------------------------------------------------------------------
  872. */
  873. BOOL DDModeInfo::Match (const DDSURFACEDESC & ddsd)
  874. {
  875.     // Check parameters
  876.     if (ddsd.dwSize != sizeof (DDSURFACEDESC))
  877.         return FALSE;
  878.     // Check Height
  879.     if (ddsd.dwFlags & DDSD_HEIGHT)
  880.     {
  881.         if (ddsd.dwHeight != ddSurfDesc.dwHeight)
  882.             return FALSE;
  883.     }
  884.     // Check Width
  885.     if (ddsd.dwFlags & DDSD_WIDTH)
  886.     {
  887.         if (ddsd.dwWidth != ddSurfDesc.dwWidth)
  888.             return FALSE;
  889.     }
  890.     // Check Pitch
  891.     if (ddsd.dwFlags & DDSD_PITCH)
  892.     {
  893.         if (ddsd.lPitch != ddSurfDesc.lPitch)
  894.             return FALSE;
  895.     }
  896.     // Check Back Buffer count
  897.     if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT)
  898.     {
  899.         if (ddsd.dwBackBufferCount != ddSurfDesc.dwBackBufferCount)
  900.             return FALSE;
  901.     }
  902.     // Check MipMap count
  903.     if (ddsd.dwFlags & DDSD_MIPMAPCOUNT)
  904.     {
  905.         if (ddsd.dwMipMapCount != ddSurfDesc.dwMipMapCount)
  906.             return FALSE;
  907.     }
  908.     // Check ZBufferBitDepth
  909.     if (ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH)
  910.     {
  911.         if (ddsd.dwZBufferBitDepth != ddSurfDesc.dwZBufferBitDepth)
  912.             return FALSE;
  913.     }
  914.     // Check Refresh Rate
  915.     if (ddsd.dwFlags & DDSD_REFRESHRATE)
  916.     {
  917.         if (ddsd.dwRefreshRate != ddSurfDesc.dwRefreshRate)
  918.             return FALSE;
  919.     }
  920.     // Check Alpha Bit Depth
  921.     if (ddsd.dwFlags & DDSD_ALPHABITDEPTH)
  922.     {
  923.         if (ddsd.dwAlphaBitDepth != ddSurfDesc.dwAlphaBitDepth)
  924.             return FALSE;
  925.     }
  926.     // Check ColorKey Dest Blt
  927.     if (ddsd.dwFlags & DDSD_CKDESTBLT)
  928.     {
  929.         if (ddsd.ddckCKDestBlt.dwColorSpaceLowValue != 
  930.             ddSurfDesc.ddckCKDestBlt.dwColorSpaceLowValue)
  931.             return FALSE;
  932.         if (ddsd.ddckCKDestBlt.dwColorSpaceHighValue != 
  933.             ddSurfDesc.ddckCKDestBlt.dwColorSpaceHighValue)
  934.             return FALSE;
  935.     }
  936.     // Check ColorKey Dest Overlay
  937.     if (ddsd.dwFlags & DDSD_CKDESTBLT)
  938.     {
  939.         if (ddsd.ddckCKDestOverlay.dwColorSpaceLowValue != 
  940.             ddSurfDesc.ddckCKDestOverlay.dwColorSpaceLowValue)
  941.             return FALSE;
  942.         if (ddsd.ddckCKDestOverlay.dwColorSpaceHighValue != 
  943.             ddSurfDesc.ddckCKDestOverlay.dwColorSpaceHighValue)
  944.             return FALSE;
  945.     }
  946.     
  947.     // Check ColorKey Src Blt
  948.     if (ddsd.dwFlags & DDSD_CKSRCBLT)
  949.     {
  950.         if (ddsd.ddckCKSrcBlt.dwColorSpaceLowValue != 
  951.             ddSurfDesc.ddckCKSrcBlt.dwColorSpaceLowValue)
  952.             return FALSE;
  953.         if (ddsd.ddckCKSrcBlt.dwColorSpaceHighValue != 
  954.             ddSurfDesc.ddckCKSrcBlt.dwColorSpaceHighValue)
  955.             return FALSE;
  956.     }
  957.     // Check ColorKey Src Overlay
  958.     if (ddsd.dwFlags & DDSD_CKSRCOVERLAY)
  959.     {
  960.         if (ddsd.ddckCKSrcOverlay.dwColorSpaceLowValue != 
  961.             ddSurfDesc.ddckCKSrcOverlay.dwColorSpaceLowValue)
  962.             return FALSE;
  963.         if (ddsd.ddckCKSrcOverlay.dwColorSpaceHighValue != 
  964.             ddSurfDesc.ddckCKSrcOverlay.dwColorSpaceHighValue)
  965.             return FALSE;
  966.     }
  967.     // Check Pixel Format
  968.     if (ddsd.dwFlags & DDSD_PIXELFORMAT)
  969.     {
  970. if (! Match (ddsd.ddpfPixelFormat))
  971. return FALSE;
  972.     }
  973.     // Check Caps
  974.     if (ddsd.dwFlags & DDSD_CAPS)
  975.     {
  976.         // Superset is OK
  977.         if ((ddsd.ddsCaps.dwCaps & ddSurfDesc.ddsCaps.dwCaps) !=
  978.             ddsd.ddsCaps.dwCaps)
  979.             return FALSE;
  980.     }
  981.     // Success, we have a match
  982.     return TRUE;
  983. } // DDModeInfo::Match
  984.   
  985. /*
  986. **-----------------------------------------------------------------------------
  987. **  Name:       DDModeInfo::Match
  988. **  Purpose:    Checks if this mode matches (bpp)
  989. **-----------------------------------------------------------------------------
  990. */
  991. BOOL DDModeInfo::Match (DWORD dwBPP)
  992. {
  993.     // Check parameters
  994.     if (ddSurfDesc.dwSize != sizeof (DDSURFACEDESC))
  995.         return FALSE;
  996. // Check for Match
  997. if (ddSurfDesc.ddpfPixelFormat.dwRGBBitCount == dwBPP)
  998. return TRUE;
  999.     return FALSE;
  1000. } // DDModeInfo::Match
  1001.   
  1002. /*
  1003. **-----------------------------------------------------------------------------
  1004. **  Name:       DDDrvInfo::Match
  1005. **  Purpose:    Checks if this mode matches the requested pixel format
  1006. **-----------------------------------------------------------------------------
  1007. */
  1008. BOOL DDModeInfo::Match (const DDPIXELFORMAT & ddpf)
  1009. {
  1010. DWORD dwCheck;
  1011.     // Check parameters
  1012. if (ddpf.dwSize != sizeof (DDPIXELFORMAT))
  1013. return FALSE;
  1014. // Check Alpha-Only flag
  1015.     if (ddpf.dwFlags & DDPF_ALPHA)
  1016.     {
  1017. // Is this mode alpha only too ?!?
  1018.         if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_ALPHA))
  1019.             return FALSE;
  1020. // Do Alpha bit depths match ?!?
  1021. if (ddpf.dwAlphaBitDepth != ddSurfDesc.ddpfPixelFormat.dwAlphaBitDepth)
  1022. return FALSE;
  1023.     }
  1024. // Check ZBuffer-Only flag
  1025.     if (ddpf.dwFlags & DDPF_ZBUFFER)
  1026.     {
  1027. // Is this mode Z-buffer only too ?!?
  1028.         if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_ZBUFFER))
  1029.             return FALSE;
  1030. // Do Z-depths match ?!?
  1031. if (ddpf.dwZBufferBitDepth != ddSurfDesc.ddpfPixelFormat.dwZBufferBitDepth)
  1032. return FALSE;
  1033.     }
  1034. // Check Compressed flag
  1035. if (ddpf.dwFlags & DDPF_COMPRESSED)
  1036. {
  1037. // Is this mode compressed too ?!?
  1038.         if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_COMPRESSED))
  1039.             return FALSE;
  1040. }
  1041. // Check FourCC flag
  1042. if (ddpf.dwFlags & DDPF_FOURCC)
  1043. {
  1044. // Is this mode a fourCC code too ?!?
  1045. if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_FOURCC))
  1046. return FALSE;
  1047. // Do fourCC codes match ?!?
  1048. if (ddSurfDesc.ddpfPixelFormat.dwFourCC != ddpf.dwFourCC)
  1049. return FALSE;
  1050. }
  1051.     // Check Palette flags
  1052. dwCheck = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
  1053.       DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 |
  1054.   DDPF_PALETTEINDEXEDTO8;
  1055. if (ddpf.dwFlags & dwCheck)
  1056. {
  1057. DWORD dwOne = ddpf.dwFlags & dwCheck;
  1058. DWORD dwTwo = ddSurfDesc.ddpfPixelFormat.dwFlags & dwCheck;
  1059. // Do palette formats match ?!?
  1060. if (dwOne != dwTwo)
  1061. return FALSE;
  1062. }
  1063. // Check RGB flags
  1064. if (ddpf.dwFlags & DDPF_RGB)
  1065. {
  1066. // Does this mode support RGB too ???
  1067. if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_RGB))
  1068. return FALSE;
  1069. // Check RGBTOYUV flag
  1070. if (ddpf.dwFlags & DDPF_RGBTOYUV)
  1071. {
  1072. // Does this mode support RGBTOYUV too???
  1073. if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_RGBTOYUV))
  1074. return FALSE;
  1075. }
  1076. // Do BPP's match?
  1077. if (ddpf.dwRGBBitCount != ddSurfDesc.ddpfPixelFormat.dwRGBBitCount)
  1078. return FALSE;
  1079. // Do Masks match
  1080. if (ddpf.dwRBitMask != ddSurfDesc.ddpfPixelFormat.dwRBitMask)
  1081. return FALSE;
  1082. if (ddpf.dwGBitMask != ddSurfDesc.ddpfPixelFormat.dwGBitMask)
  1083. return FALSE;
  1084. if (ddpf.dwBBitMask != ddSurfDesc.ddpfPixelFormat.dwBBitMask)
  1085. return FALSE;
  1086. // Check Alpha Channel
  1087. if (ddpf.dwFlags & DDPF_ALPHAPIXELS)
  1088. {
  1089. // Does this mode support Alphachannel as well ?!?
  1090. if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS))
  1091. return FALSE;
  1092. // Do Alpha channel masks match
  1093. if (ddpf.dwRGBAlphaBitMask != ddSurfDesc.ddpfPixelFormat.dwRGBAlphaBitMask)
  1094. return FALSE;
  1095. }
  1096. // Check Z channel
  1097. if (ddpf.dwFlags & DDPF_ZPIXELS)
  1098. {
  1099. // Does this mode support Z channel as well ?!?
  1100. if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_ZPIXELS))
  1101. return FALSE;
  1102. // Do Z channel masks match
  1103. if (ddpf.dwRGBZBitMask != ddSurfDesc.ddpfPixelFormat.dwRGBZBitMask)
  1104. return FALSE;
  1105. }
  1106. }
  1107. // Check YUV flags
  1108. if (ddpf.dwFlags & DDPF_YUV)
  1109. {
  1110. // Does this mode support YUV too ???
  1111. if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_YUV))
  1112. return FALSE;
  1113. // Do BPP's match?
  1114. if (ddpf.dwYUVBitCount != ddSurfDesc.ddpfPixelFormat.dwYUVBitCount)
  1115. return FALSE;
  1116. // Do Masks match
  1117. if (ddpf.dwYBitMask != ddSurfDesc.ddpfPixelFormat.dwYBitMask)
  1118. return FALSE;
  1119. if (ddpf.dwUBitMask != ddSurfDesc.ddpfPixelFormat.dwUBitMask)
  1120. return FALSE;
  1121. if (ddpf.dwVBitMask != ddSurfDesc.ddpfPixelFormat.dwVBitMask)
  1122. return FALSE;
  1123. // Check Alpha channel
  1124. if (ddpf.dwFlags & DDPF_ALPHAPIXELS)
  1125. {
  1126. // Does this mode support Alphachannel as well ?!?
  1127. if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS))
  1128. return FALSE;
  1129. // Do Alpha channel masks match
  1130. if (ddpf.dwYUVAlphaBitMask != ddSurfDesc.ddpfPixelFormat.dwYUVAlphaBitMask)
  1131. return FALSE;
  1132. }
  1133. // Check Z channel
  1134. if (ddpf.dwFlags & DDPF_ZPIXELS)
  1135. {
  1136. // Does this mode support Z channel as well ?!?
  1137. if (! (ddSurfDesc.ddpfPixelFormat.dwFlags & DDPF_ZPIXELS))
  1138. return FALSE;
  1139. // Do Z channel masks match
  1140. if (ddpf.dwRGBZBitMask != ddSurfDesc.ddpfPixelFormat.dwRGBZBitMask)
  1141. return FALSE;
  1142. }
  1143. }
  1144.     // Success, we have a match
  1145.     return TRUE;
  1146. } // DDModeInfo::Match
  1147.   
  1148.   
  1149. /*
  1150. **-----------------------------------------------------------------------------
  1151. **  D3DDevInfo Methods
  1152. **-----------------------------------------------------------------------------
  1153. */
  1154. /*
  1155. **-----------------------------------------------------------------------------
  1156. **  Name:       D3DDevInfo::isHardware
  1157. **  Purpose:    Checks if this D3D Device is a hardware driver
  1158. **-----------------------------------------------------------------------------
  1159. */
  1160. BOOL D3DDevInfo::isHardware (void)
  1161. {
  1162.     // No correct way of doing this,
  1163.     // but if the hardware caps don't specify a shading
  1164.     // model then it probably isn't hardware accelerated
  1165.     DWORD dwColorModel = d3dHalDesc.dcmColorModel;
  1166.     if (dwColorModel)
  1167.         return TRUE;
  1168.     return FALSE;
  1169. } // End D3DDevInfo::isHardware
  1170. /*
  1171. **-----------------------------------------------------------------------------
  1172. **  Name:       DDDrvInfo::Match
  1173. **  Purpose:    Checks if this D3D Device matches this guid
  1174. **-----------------------------------------------------------------------------
  1175. */
  1176. BOOL D3DDevInfo::Match (LPGUID lpGuid)
  1177. {
  1178.     if (lpGuid == NULL)
  1179.         return FALSE;
  1180.     if (! isValid ())
  1181.         return FALSE;
  1182.     
  1183.     if (guid != *lpGuid)
  1184.         return FALSE;
  1185.     // Success
  1186.     return TRUE;
  1187. } // End D3DDevInfo::Match
  1188. /*
  1189. **-----------------------------------------------------------------------------
  1190. **  Name:       D3DDevInfo::Match
  1191. **  Purpose:    Checks if this D3D Device matches the specified
  1192. **              hardware and/or software description
  1193. **-----------------------------------------------------------------------------
  1194. */
  1195. BOOL D3DDevInfo::Match (LPD3DDEVICEDESC lpHal, LPD3DDEVICEDESC lpHel)
  1196. {
  1197.     if (! isValid ())
  1198.         return FALSE;
  1199.     // Check Parameters
  1200.     if ((! lpHal) && (! lpHel))
  1201.         return FALSE;
  1202.     //
  1203.     // Compare Hal description's
  1204.     //
  1205.     if (lpHal)
  1206.     {
  1207.         if (lpHal->dwSize != sizeof (D3DDEVICEDESC))
  1208.             return FALSE;
  1209.         // Check ColorModel
  1210.         if (lpHal->dwFlags & D3DDD_COLORMODEL)
  1211.         {
  1212.             // If it does more than we are interested in that's OK
  1213.             if ((lpHal->dcmColorModel & d3dHalDesc.dcmColorModel) != 
  1214.                 lpHal->dcmColorModel)
  1215.                 return FALSE;
  1216.         }
  1217.         // Check Device Caps
  1218.         if (lpHal->dwFlags & D3DDD_DEVCAPS)
  1219.         {
  1220.             // If it does more than we are asking, that's OK
  1221.             if ((lpHal->dwDevCaps & d3dHalDesc.dwDevCaps) !=
  1222.                 lpHal->dwDevCaps)
  1223.                 return FALSE;
  1224.         }
  1225.         // Check transform caps
  1226.         if (lpHal->dwFlags & D3DDD_TRANSFORMCAPS)
  1227.         {
  1228.             // Note: Flesh this out later
  1229.         }
  1230.         // Check Clipping 
  1231.         if (lpHal->dwFlags & D3DDD_BCLIPPING)
  1232.         {
  1233.             if (lpHal->bClipping != d3dHalDesc.bClipping)
  1234.                 return FALSE;
  1235.         }
  1236.         // Check lighting caps
  1237.         if (lpHal->dwFlags & D3DDD_LIGHTINGCAPS)
  1238.         {
  1239.             // Note: Flesh this out later
  1240.         }
  1241.         
  1242.         // Check line caps
  1243.         if (lpHal->dwFlags & D3DDD_LINECAPS)
  1244.         {
  1245.             // Note: Flesh this out later
  1246.         }
  1247.         // Check triangle caps
  1248.         if (lpHal->dwFlags & D3DDD_TRICAPS)
  1249.         {
  1250.             // Note: Flesh this out later
  1251.         }
  1252.         // Check Render Surface bit depth
  1253.         if (lpHal->dwDeviceRenderBitDepth)
  1254.         {
  1255.              if (lpHal->dwDeviceRenderBitDepth != d3dHalDesc.dwDeviceRenderBitDepth)
  1256.                 return FALSE;
  1257.         }
  1258.         // Check Z-Buffer surface bit depth
  1259.         if (lpHal->dwDeviceZBufferBitDepth)
  1260.         {
  1261.             if (lpHal->dwDeviceZBufferBitDepth != d3dHalDesc.dwDeviceZBufferBitDepth)
  1262.                 return FALSE;
  1263.         }
  1264.         // Check Max buffer size
  1265.         if (lpHal->dwFlags & D3DDD_MAXBUFFERSIZE)
  1266.         {
  1267.             // Only worry, if it is smaller than what we want
  1268.             if (lpHal->dwMaxBufferSize > d3dHalDesc.dwMaxBufferSize)
  1269.                 return FALSE;
  1270.         }
  1271.         // Check Max Vertex count
  1272.         if (lpHal->dwFlags & D3DDD_MAXVERTEXCOUNT)
  1273.         {
  1274.             // Only worry, if it is smaller than what we want
  1275.             if (lpHal->dwMaxVertexCount > d3dHalDesc.dwMaxVertexCount)
  1276.                 return FALSE;
  1277.         }
  1278.     }
  1279.     
  1280.     //
  1281.     // Compare Hel description's
  1282.     //
  1283.     if (lpHel)
  1284.     {
  1285.         if (lpHel->dwSize != sizeof (D3DDEVICEDESC))
  1286.             return FALSE;
  1287.         // Check ColorModel
  1288.         if (lpHel->dwFlags & D3DDD_COLORMODEL)
  1289.         {
  1290.             // If it does more than we are interested in that's OK
  1291.             if ((lpHel->dcmColorModel & d3dHelDesc.dcmColorModel) != 
  1292.                 lpHel->dcmColorModel)
  1293.                 return FALSE;
  1294.         }
  1295.         // Check Device Caps
  1296.         if (lpHel->dwFlags & D3DDD_DEVCAPS)
  1297.         {
  1298.             // If it does more than we are asking, that's OK
  1299.             if ((lpHel->dwDevCaps & d3dHelDesc.dwDevCaps) !=
  1300.                 lpHel->dwDevCaps)
  1301.                 return FALSE;
  1302.         }
  1303.         // Check transform caps
  1304.         if (lpHel->dwFlags & D3DDD_TRANSFORMCAPS)
  1305.         {
  1306.             // Note: Flesh this out later
  1307.         }
  1308.         // Check Clipping 
  1309.         if (lpHel->dwFlags & D3DDD_BCLIPPING)
  1310.         {
  1311.             if (lpHel->bClipping != d3dHelDesc.bClipping)
  1312.                 return FALSE;
  1313.         }
  1314.         // Check lighting caps
  1315.         if (lpHel->dwFlags & D3DDD_LIGHTINGCAPS)
  1316.         {
  1317.             // Note: Flesh this out later
  1318.         }
  1319.         
  1320.         // Check line caps
  1321.         if (lpHel->dwFlags & D3DDD_LINECAPS)
  1322.         {
  1323.             // Note: Flesh this out later
  1324.         }
  1325.         // Check triangle caps
  1326.         if (lpHel->dwFlags & D3DDD_TRICAPS)
  1327.         {
  1328.             // Note: Flesh this out later
  1329.         }
  1330.         // Check Render Surface bit depth
  1331.         if (lpHel->dwDeviceRenderBitDepth)
  1332.         {
  1333.              if (lpHel->dwDeviceRenderBitDepth != d3dHelDesc.dwDeviceRenderBitDepth)
  1334.                 return FALSE;
  1335.         }
  1336.         // Check Z-Buffer surface bit depth
  1337.         if (lpHel->dwDeviceZBufferBitDepth)
  1338.         {
  1339.             if (lpHel->dwDeviceZBufferBitDepth != d3dHelDesc.dwDeviceZBufferBitDepth)
  1340.                 return FALSE;
  1341.         }
  1342.         // Check Max buffer size
  1343.         if (lpHel->dwFlags & D3DDD_MAXBUFFERSIZE)
  1344.         {
  1345.             // Only worry, if it is smaller than what we want
  1346.             if (lpHel->dwMaxBufferSize > d3dHelDesc.dwMaxBufferSize)
  1347.                 return FALSE;
  1348.         }
  1349.         // Check Max Vertex count
  1350.         if (lpHel->dwFlags & D3DDD_MAXVERTEXCOUNT)
  1351.         {
  1352.             // Only worry, if it is smaller than what we want
  1353.             if (lpHel->dwMaxVertexCount > d3dHelDesc.dwMaxVertexCount)
  1354.                 return FALSE;
  1355.         }
  1356.     }
  1357.     // Success
  1358.     return TRUE;
  1359. } // End D3DDevInfo::Match
  1360.   
  1361.   
  1362. /*
  1363. **-----------------------------------------------------------------------------
  1364. **  Name:       D3DDevInfo::Create
  1365. **  Purpose:    Creates a new D3D Device 
  1366. **-----------------------------------------------------------------------------
  1367. */
  1368. HRESULT D3DDevInfo::Create (
  1369.     LPGUID          lpD3DGuid,
  1370.     LPTSTR          lpD3DName, 
  1371.     LPTSTR          lpD3DDesc, 
  1372.     LPD3DDEVICEDESC lpD3DHal, 
  1373.     LPD3DDEVICEDESC lpD3DHel)
  1374. {
  1375.     // Copy GUID
  1376.     if (! lpD3DGuid)
  1377.     {
  1378.         // Error, Invalid device
  1379.         return DDERR_INVALIDPARAMS;
  1380.     }
  1381.     guid = *lpD3DGuid;
  1382.     
  1383. // Copy Name
  1384. LPTSTR szTemp;
  1385.     if (! lpD3DName)
  1386.     {
  1387. szTemp = TEXT("UNKNOWN");
  1388.     }
  1389.     else
  1390.     {
  1391.         szTemp = lpD3DName;
  1392.     }
  1393.     DWORD cLen = _tcslen (szTemp);
  1394. DWORD cbSize = (cLen + 1) * sizeof(TCHAR);
  1395. szName = (LPTSTR) malloc (cbSize);
  1396. if (szName)
  1397. {
  1398. _tcsncpy (szName, szTemp, cLen);
  1399. szName[cLen] = 0;
  1400. }
  1401.     
  1402.     // Copy Description
  1403.     if (! lpD3DDesc)
  1404.     {
  1405. szTemp = TEXT("UNKNOWN");
  1406.     }
  1407.     else
  1408.     {
  1409.         szTemp = lpD3DDesc;
  1410.     }
  1411.     cLen = _tcslen (szTemp);
  1412. cbSize = (cLen + 1) * sizeof(TCHAR);
  1413. szDesc = (LPTSTR) malloc (cbSize);
  1414. if (szDesc)
  1415. {
  1416. _tcsncpy (szDesc, szTemp, cLen);
  1417. szDesc[cLen] = 0;
  1418. }
  1419.     // Copy D3D info
  1420.     if (lpD3DHal)
  1421.     {
  1422.         d3dHalDesc = *lpD3DHal;
  1423.     }
  1424.     if (lpD3DHel)
  1425.     {
  1426.         d3dHelDesc = *lpD3DHel;
  1427.     }
  1428. // Mark Texture format list as not loaded
  1429. cFormats = 0L;
  1430. turnFormatsLoadedOff ();
  1431. // Mark as valid
  1432.     validOn ();
  1433.     return DD_OK;
  1434. } // End D3DDevInfo::Create
  1435. /*
  1436. **-----------------------------------------------------------------------------
  1437. **  Name:       D3DDevInfo::Destroy
  1438. **  Purpose:    Cleanup any memory or interfaces
  1439. **-----------------------------------------------------------------------------
  1440. */
  1441. void D3DDevInfo::Destroy (void)
  1442. {
  1443. // Destroy Texture Formats
  1444. DestroyFormats ();
  1445. // Clean up strings
  1446. if (szDesc)
  1447. {
  1448. free (szDesc);
  1449. szDesc = NULL;
  1450. }
  1451. if (szName)
  1452. {
  1453. free (szName);
  1454. szName = NULL;
  1455. }
  1456. lpPrev = NULL;
  1457. lpNext = NULL;
  1458. } // End D3DDevInfo::Destroy
  1459.   
  1460. /*
  1461. **-----------------------------------------------------------------------------
  1462. **  Name:       D3DDevInfo::LoadFormats
  1463. **  Purpose:    Loads texture formats
  1464. **  Notes:
  1465. **
  1466. ** In order to load texture formats, we need to have a valid D3D Device
  1467. ** Getting a D3D Device directly complicates the Driver Manager code.
  1468. **
  1469. ** So we will defer loading texture formats until we have created a valid 
  1470. **  D3D device in D3DWindow::InitRender and then call this function to 
  1471. **  Load all the texture formats.
  1472. **
  1473. **-----------------------------------------------------------------------------
  1474. */
  1475. HRESULT D3DDevInfo::LoadFormats (LPDIRECT3DDEVICE2 lpD3DDevice)
  1476. {
  1477. // Have we already loaded the texture formats
  1478. if (! formatsLoaded ())
  1479. {
  1480. HRESULT hResult;
  1481.     DD_CB_INFO cbInfo;
  1482. // Check Parameters
  1483. if (! lpD3DDevice)
  1484. {
  1485. hResult = APPERR_INVALIDPARAMS;
  1486. REPORTERR (hResult);
  1487. return hResult;
  1488. }
  1489. // Enumerate all Texture Formats for this device
  1490. cbInfo.fResult  = TRUE;
  1491. cbInfo.lpExtra  = (void *)this;
  1492. cbInfo.cCount   = 0L;
  1493. hResult = lpD3DDevice->EnumTextureFormats (TextureFormatEnumCallback, 
  1494.    (void *)&cbInfo);
  1495. if (FAILED(hResult))
  1496. {
  1497. // Error
  1498. REPORTERR (hResult);
  1499. return hResult;
  1500. }
  1501. // Double check count
  1502. if ((! cbInfo.fResult) || (cbInfo.cCount == 0) || (cFormats != cbInfo.cCount))
  1503. {
  1504. hResult = APPERR_GENERIC;
  1505. REPORTERR (hResult);
  1506. return hResult;
  1507. }
  1508. // Mark texture formats as loaded
  1509. turnFormatsLoadedOn ();
  1510. }
  1511. // Success
  1512. return DD_OK;
  1513. } // D3DDevInfo::LoadFormats
  1514. /*
  1515. **-----------------------------------------------------------------------------
  1516. **  Name:       D3DDevInfo::DestroyFormats
  1517. **  Purpose:    Destroys texture formats
  1518. **-----------------------------------------------------------------------------
  1519. */
  1520.   
  1521. HRESULT D3DDevInfo::DestroyFormats (void)
  1522. {
  1523. if (formatsLoaded ())
  1524. {
  1525. LPDDModeInfo lpCurr, lpNext, lpPrev;
  1526. lpCurr = lpFormatRoot;
  1527. // Walk linked list and destroy all Format nodes
  1528. while (lpCurr)
  1529. {
  1530. lpNext = lpCurr->lpNext;
  1531. lpPrev = lpCurr->lpPrev;
  1532. // Remove node from List
  1533. if (lpPrev)
  1534. lpPrev->lpNext = lpNext;
  1535. else
  1536. lpFormatRoot = lpNext;
  1537. if (lpNext)
  1538. lpNext->lpPrev = lpPrev;
  1539. else
  1540. lpFormatTail = lpPrev;
  1541. // Destroy this node
  1542. lpCurr->lpNext = NULL;
  1543. lpCurr->lpPrev = NULL;
  1544. delete lpCurr;
  1545. // Move to next node in list
  1546. lpCurr = lpNext;
  1547. }
  1548. cFormats  = 0L;
  1549. lpFormatRoot = NULL;
  1550. lpFormatTail = NULL;
  1551. // Mark as unloaded
  1552. turnFormatsLoadedOff ();
  1553. }
  1554. // Success
  1555. return DD_OK;
  1556. } // End D3DDevInfo::DestroyFormats 
  1557.   
  1558. /*
  1559. **-----------------------------------------------------------------------------
  1560. **  Name:       D3DDevInfo::AddFormat
  1561. **  Purpose:    add new texture format to format list
  1562. **-----------------------------------------------------------------------------
  1563. */
  1564. HRESULT D3DDevInfo::AddFormat (LPDDModeInfo lpFormatNew)
  1565. {
  1566. // Check Parameters
  1567. if (! lpFormatNew)
  1568. {
  1569. // Error, Invalid parameters
  1570. return DDERR_INVALIDPARAMS;
  1571. }
  1572. // Add to tail of Format List
  1573. lpFormatNew->lpPrev = lpFormatTail;
  1574. lpFormatNew->lpNext = NULL;
  1575. // Update tail
  1576. if (lpFormatTail)
  1577. lpFormatTail->lpNext = lpFormatNew;
  1578. lpFormatTail = lpFormatNew;
  1579. // Update Root
  1580. if (! lpFormatRoot)
  1581. lpFormatRoot = lpFormatNew;
  1582. // Update count
  1583. cFormats++;
  1584. // Success
  1585. return DD_OK;
  1586. } // End D3DDevInfo::AddFormat
  1587.   
  1588. /*
  1589. **-----------------------------------------------------------------------------
  1590. **  Name:       D3DDevInfo::DelFormat
  1591. **  Purpose:    removes texture format from format list
  1592. **-----------------------------------------------------------------------------
  1593. */
  1594. HRESULT D3DDevInfo::DelFormat (LPDDModeInfo lpFormatDel)
  1595. {
  1596. // Check parameters
  1597. if (lpFormatDel)
  1598. {
  1599. // Error
  1600. return DDERR_INVALIDPARAMS;
  1601. }
  1602. // Remove this Mode From mode list
  1603.     LPDDModeInfo lpPrevMode = lpFormatDel->lpPrev;
  1604.     LPDDModeInfo lpNextMode = lpFormatDel->lpNext;
  1605.     if (lpPrevMode)
  1606.         lpPrevMode->lpNext = lpNextMode;
  1607.     else
  1608.         lpFormatRoot = lpNextMode;
  1609.     if (lpNextMode)
  1610. lpNextMode->lpPrev = lpPrevMode;
  1611. else
  1612. lpFormatTail = lpPrevMode;
  1613.     // Destroy format node
  1614. lpFormatDel->lpPrev = NULL;
  1615.     lpFormatDel->lpNext = NULL;
  1616.     delete lpFormatDel;
  1617. // Update count
  1618. cFormats--;
  1619. // Success
  1620. return DD_OK;
  1621. } // End D3DDevInfo::DelFormat
  1622.   
  1623. /*
  1624. **-----------------------------------------------------------------------------
  1625. **  Name:       D3DDevInfo::FindFormat
  1626. **  Purpose:    finds specified texture format
  1627. **-----------------------------------------------------------------------------
  1628. */
  1629. LPDDModeInfo D3DDevInfo::FindFormat (
  1630. LPDDPIXELFORMAT lpddpf, /* In: Texture Format Desc */
  1631. LPDDModeInfo *  lpNextBest, /* Out: Second best match */
  1632. LPDDModeInfo    lpStart) /* In: start from this node */
  1633. {
  1634. LPDDModeInfo lpCurrFormat, lpNextFormat;
  1635. // Get Starting node
  1636. if (! lpStart)
  1637. lpCurrFormat = lpFormatRoot;
  1638. else
  1639. lpCurrFormat = lpStart;
  1640. if (lpNextBest)
  1641. *lpNextBest = lpCurrFormat;
  1642. // Search format list for best match
  1643.     while (lpCurrFormat)
  1644. {
  1645. lpNextFormat = lpCurrFormat->lpNext;
  1646.         if (lpCurrFormat->Match (*lpddpf))
  1647.         {
  1648.             return lpCurrFormat;
  1649.         }
  1650. lpCurrFormat = lpNextFormat;
  1651.     }
  1652.     // Failure, user may use lpNextBest instead
  1653.     return NULL;
  1654. } // End D3DDevInfo::FindFormat
  1655.   
  1656. /*
  1657. **-----------------------------------------------------------------------------
  1658. **  Name:       D3DDevInfo::FindFormat
  1659. **  Purpose:    finds specified texture format from requested BPP
  1660. **-----------------------------------------------------------------------------
  1661. */
  1662. LPDDModeInfo D3DDevInfo::FindFormat (
  1663. DWORD bpp, /* In: requested BPP */
  1664. LPDDModeInfo *  lpNextBest, /* Out: Second best match */
  1665. LPDDModeInfo    lpStart) /* In: start from this node */
  1666. {
  1667. LPDDModeInfo lpCurrFormat, lpNextFormat;
  1668. // Get Starting node
  1669. if (! lpStart)
  1670. lpCurrFormat = lpFormatRoot;
  1671. else
  1672. lpCurrFormat = lpStart;
  1673. if (lpNextBest)
  1674. *lpNextBest = lpCurrFormat;
  1675. // Search format list for best match
  1676.     while (lpCurrFormat)
  1677. {
  1678. lpNextFormat = lpCurrFormat->lpNext;
  1679.         if (lpCurrFormat->Match (bpp))
  1680.         {
  1681.             return lpCurrFormat;
  1682.         }
  1683. lpCurrFormat = lpNextFormat;
  1684.     }
  1685.     // Failure, user may use lpNextBest instead
  1686.     return NULL;
  1687. } // End D3DDevInfo::FindFormat
  1688.   
  1689. /*
  1690. **-----------------------------------------------------------------------------
  1691. **  Name:       D3DDevInfo::EnumFormats
  1692. **  Purpose:    Enumerate Formats in this Device
  1693. **-----------------------------------------------------------------------------
  1694. */
  1695. DWORD D3DDevInfo::EnumFormats (const D3DDEV_ENUMINFO & eiInfo)
  1696. {
  1697.     DWORD           dwResult = ENUM_FAILURE;
  1698. LPDDModeInfo lpCurrFormat, lpNextFormat;
  1699.     // Check Match Callback function
  1700.     if (! eiInfo.fpcbEnum)
  1701.     {
  1702.         // Error, invalid callback
  1703.         return ENUM_ERROR;
  1704.     }
  1705. // Get Starting node
  1706. if (eiInfo.lpStart)
  1707. lpCurrFormat = (LPDDModeInfo)(eiInfo.lpStart);
  1708. else
  1709. lpCurrFormat = lpFormatRoot;
  1710. // Do callback on each node in list
  1711. while (lpCurrFormat)
  1712. {
  1713. lpNextFormat = lpCurrFormat->lpNext;
  1714.         // Call Enum Mode Callback
  1715.         dwResult = (*eiInfo.fpcbEnum)((LPVOID)this, lpCurrFormat, eiInfo.dwExtra);
  1716.         // Check for early exit
  1717.         if (dwResult & ENUM_STOP)
  1718.         {
  1719.             // Return result code
  1720.             return (dwResult & ~ENUM_STOP);
  1721.         }
  1722.    }
  1723.     // Failure
  1724.     return (dwResult & ~ENUM_STOP);
  1725. } // End D3DDevInfo::EnumFormats
  1726. /*
  1727. **-----------------------------------------------------------------------------
  1728. **  DDDrvInfo Methods
  1729. **-----------------------------------------------------------------------------
  1730. */
  1731.     
  1732. /*
  1733. **-----------------------------------------------------------------------------
  1734. **  Name:       DDDrvInfo::Create
  1735. **  Purpose:    Create a new Driver description
  1736. **  Notes:
  1737. ** 1.  If the driver doesn't support D3D we treat it as an invalid driver.
  1738. **-----------------------------------------------------------------------------
  1739. */
  1740. HRESULT DDDrvInfo::Create (
  1741. GUID FAR *      lpGuid,
  1742.     LPTSTR          lpDriverName, 
  1743.     LPTSTR          lpDriverDesc)
  1744. {
  1745.     HRESULT         hResult;
  1746.     LPDIRECTDRAW    lpDD  = NULL;
  1747.     LPDIRECTDRAW2   lpDD2 = NULL;
  1748.     LPDIRECT3D2     lpD3D = NULL;
  1749.     if (isValid ())
  1750.     {
  1751.         // Programmer Error, already valid, call Fini to cleanup
  1752.         return FALSE;
  1753.     }
  1754.     // Copy GUID
  1755.     if (! lpGuid)
  1756.     {
  1757.         primaryOn ();
  1758.     }
  1759.     else
  1760.     {
  1761.         guid = *lpGuid;
  1762.     }
  1763.     // Copy Name
  1764. LPTSTR szTemp;
  1765.     if (! lpDriverName)
  1766. {
  1767. szTemp = TEXT("UNKNOWN");
  1768. }
  1769.     else
  1770.     {
  1771. szTemp = lpDriverName;
  1772.     }
  1773. DWORD cLen = _tcslen (szTemp);
  1774. DWORD cbSize = (cLen + 1) * sizeof(TCHAR);
  1775. szName = (LPTSTR) malloc (cbSize);
  1776. if (szName)
  1777. {
  1778. _tcsncpy (szName, szTemp, cLen);
  1779. szName[cLen] = 0;
  1780. }
  1781.     // Copy Desc
  1782.     if (! lpDriverDesc)
  1783. {
  1784. szTemp = TEXT("UNKNOWN");
  1785. }
  1786.     else
  1787.     {
  1788. szTemp = lpDriverDesc;
  1789.     }
  1790. cLen = _tcslen (szTemp);
  1791. cbSize = (cLen + 1) * sizeof(TCHAR);
  1792. szDesc = (LPTSTR) malloc (cbSize);
  1793. if (szDesc)
  1794. {
  1795. _tcsncpy (szDesc, szTemp, cLen);
  1796. szDesc[cLen] = 0;
  1797. }
  1798.     // Create DirectDraw Object
  1799.     hResult = DirectDrawCreate (lpGuid, &lpDD, NULL);
  1800.     if FAILED (hResult)
  1801.     {
  1802.         // Error
  1803.         REPORTERR (hResult);
  1804.         goto lblCLEANUP;
  1805.     }
  1806.     
  1807.     // Get The DirectDraw2 Interface
  1808.     hResult = lpDD->QueryInterface ((REFIID)IID_IDirectDraw2, (void **)&lpDD2);
  1809.     if (FAILED(hResult))
  1810.     {
  1811.         // Error
  1812.         REPORTERR (hResult);
  1813.         goto lblCLEANUP;
  1814.     }
  1815.     // Get The Direct3D Interface
  1816.     hResult = lpDD->QueryInterface ((REFIID)IID_IDirect3D2, (void **)&lpD3D);
  1817.     if (FAILED(hResult))
  1818.     {
  1819.         // Error
  1820.         REPORTERR (hResult);
  1821.         goto lblCLEANUP;
  1822.     }
  1823.     // Get The Driver Caps
  1824.     ddHalCaps.dwSize = sizeof(DDCAPS);
  1825.     ddHelCaps.dwSize = sizeof(DDCAPS);
  1826.     hResult = lpDD2->GetCaps (&ddHalCaps, &ddHelCaps);
  1827.     if (FAILED(hResult))
  1828.     {
  1829.         // Error
  1830.         REPORTERR (hResult);
  1831.         goto lblCLEANUP;
  1832.     }
  1833. // Enumerate all Modes for this DD Driver
  1834. cModes = 0L;
  1835. turnModesLoadedOff ();
  1836. hResult = LoadModes (lpDD2);
  1837. if (FAILED (hResult))
  1838. goto lblCLEANUP;
  1839. // Enumerate all D3D Devices for this driver
  1840. cDevices = 0L;
  1841. turnDevicesLoadedOff ();
  1842. hResult = LoadDevices (lpD3D);
  1843. if (FAILED (hResult))
  1844. goto lblCLEANUP;
  1845.         
  1846.     // Mark as Valid Driver
  1847.     validOn ();
  1848.     // Success
  1849.     hResult = DD_OK;
  1850. lblCLEANUP:
  1851.     // Cleanup the Interfaces before leaving
  1852.     if (lpD3D) 
  1853.     {
  1854.         lpD3D->Release ();
  1855.         lpD3D = NULL;
  1856.     }
  1857.     if (lpDD2) 
  1858.     {
  1859.         lpDD2->Release ();
  1860.         lpDD2 = NULL;
  1861.     }
  1862.     if (lpDD)
  1863.     {
  1864.         lpDD->Release ();
  1865.         lpDD = NULL;
  1866.     }
  1867.     return hResult;
  1868. } // End DDDrvInfo::Create
  1869.   
  1870. /*
  1871. **-----------------------------------------------------------------------------
  1872. **  Name:       DDDrvInfo::Destroy
  1873. **  Purpose:    Cleanup any memory or interfaces
  1874. **-----------------------------------------------------------------------------
  1875. */
  1876. void DDDrvInfo::Destroy (void)
  1877. {
  1878. // Destroy all Modes and Devices
  1879. DestroyDevices ();
  1880. DestroyModes ();
  1881. // Clean up strings
  1882. if (szDesc)
  1883. {
  1884. free (szDesc);
  1885. szDesc = NULL;
  1886. }
  1887. if (szName)
  1888. {
  1889. free (szName);
  1890. szName = NULL;
  1891. }
  1892. lpPrev = NULL;
  1893. lpNext = NULL;
  1894.     // Mark as an invalid driver
  1895.     validOff ();
  1896. } // End DDDrvInfo::Destroy
  1897.   
  1898. /*
  1899. **-----------------------------------------------------------------------------
  1900. **  Name:       DDDrvInfo::Match
  1901. **  Purpose:    checks for match with specified guid
  1902. **-----------------------------------------------------------------------------
  1903. */
  1904. BOOL DDDrvInfo::Match (LPGUID lpGuid)
  1905. {
  1906.     if (! isValid())
  1907.         return FALSE;
  1908.     if (! lpGuid)
  1909.     {
  1910.         if (isPrimary())
  1911.             return TRUE;
  1912.     }
  1913.     else
  1914.     {
  1915.         if (*lpGuid == guid)
  1916.             return TRUE;
  1917.     }
  1918.     return FALSE;
  1919. } // End DDDrvInfo::Match
  1920.   
  1921. /*
  1922. **-----------------------------------------------------------------------------
  1923. **  Name:       DDDrvInfo::Match
  1924. **  Purpose:    checks for match with specified hal,hel caps
  1925. **-----------------------------------------------------------------------------
  1926. */
  1927. BOOL DDDrvInfo::Match (LPDDCAPS lpHal, LPDDCAPS lpHel)
  1928. {
  1929.     if (! isValid())
  1930.         return FALSE;
  1931.     if ((! lpHal) && (! lpHel))
  1932.         return FALSE;
  1933.     // Check for match with hal caps
  1934.     if (lpHal)
  1935.     {
  1936.         // Flesh out later
  1937.     }
  1938.     if (lpHal)
  1939.     {
  1940.         // Flesh out later
  1941.     }
  1942.     // Success
  1943.     return TRUE;
  1944. } // End DDDrvInfo::Match
  1945.   
  1946. /*
  1947. **-----------------------------------------------------------------------------
  1948. **  Name:       DDDrvInfo::LoadModes
  1949. **  Purpose:    Load all modes associated with this DD Driver
  1950. **-----------------------------------------------------------------------------
  1951. */
  1952. HRESULT DDDrvInfo::LoadModes (LPDIRECTDRAW2 lpDD2)
  1953. {
  1954. // Have we already loaded the modes
  1955. if (! modesLoaded ())
  1956. {
  1957. HRESULT hResult;
  1958.     DD_CB_INFO cbInfo;
  1959. // Check Parameters
  1960. if (! lpDD2)
  1961. {
  1962. hResult = APPERR_INVALIDPARAMS;
  1963. REPORTERR (hResult);
  1964. return hResult;
  1965. }
  1966.     // Enumerate all modes for this driver
  1967. cbInfo.fResult  = TRUE;
  1968. cbInfo.lpExtra  = (void *)this;
  1969. cbInfo.cCount   = 0L;
  1970. hResult = lpDD2->EnumDisplayModes (0L, NULL, &cbInfo, 
  1971.                                            ModeEnumCallback);
  1972. if (FAILED(hResult))
  1973. {
  1974. // Error
  1975. REPORTERR (hResult);
  1976. return hResult;
  1977. }
  1978. // Double check count
  1979. if ((! cbInfo.fResult) || (cbInfo.cCount == 0) || (cModes != cbInfo.cCount))
  1980. {
  1981. hResult = APPERR_GENERIC;
  1982. REPORTERR (hResult);
  1983. return hResult;
  1984. }
  1985. // Mark Modes as loaded
  1986. turnModesLoadedOn ();
  1987. }
  1988. // Success
  1989. return DD_OK;
  1990. } // D3DDevInfo::LoadModes
  1991. /*
  1992. **-----------------------------------------------------------------------------
  1993. **  Name:       DDDrvInfo::DestroyModes
  1994. **  Purpose:    Destroys all Modes in Mode List
  1995. **-----------------------------------------------------------------------------
  1996. */
  1997.   
  1998. HRESULT DDDrvInfo::DestroyModes (void)
  1999. {
  2000. LPDDModeInfo lpCurr, lpNext, lpPrev;
  2001. lpCurr = lpModeRoot;
  2002. // Walk linked list and destroy all Mode nodes
  2003. while (lpCurr)
  2004. {
  2005. lpNext = lpCurr->lpNext;
  2006. lpPrev = lpCurr->lpPrev;
  2007. // Remove node from List
  2008. if (lpPrev)
  2009. lpPrev->lpNext = lpNext;
  2010. else
  2011. lpModeRoot = lpNext;
  2012. if (lpNext)
  2013. lpNext->lpPrev = lpPrev;
  2014. else
  2015. lpModeTail = lpPrev;
  2016. // Destroy this node
  2017. lpCurr->lpNext = NULL;
  2018. lpCurr->lpPrev = NULL;
  2019. delete lpCurr;
  2020. // Move to next node in list
  2021. lpCurr = lpNext;
  2022. }
  2023. cModes    = 0L;
  2024. lpModeRoot = NULL;
  2025. lpModeTail = NULL;
  2026. turnModesLoadedOff ();
  2027. // Success
  2028. return DD_OK;
  2029. } // End DDDrvInfo::DestroyModes
  2030.   
  2031.   
  2032. /*
  2033. **-----------------------------------------------------------------------------
  2034. **  Name:       DDDrvInfo::AddMode
  2035. **  Purpose:    add new mode to mode list
  2036. **  Notes: 1
  2037. **-----------------------------------------------------------------------------
  2038. */
  2039. HRESULT DDDrvInfo::AddMode (LPDDModeInfo lpModeNew)
  2040. {
  2041. // Check Parameters
  2042. if (! lpModeNew)
  2043. {
  2044. // Error, Invalid parameters
  2045. return DDERR_INVALIDPARAMS;
  2046. }
  2047. // Add to tail of Mode List
  2048. lpModeNew->lpPrev = lpModeTail;
  2049. lpModeNew->lpNext = NULL;
  2050. // Update tail
  2051. if (lpModeTail)
  2052. lpModeTail->lpNext = lpModeNew;
  2053. lpModeTail = lpModeNew;
  2054. // Update Root
  2055. if (! lpModeRoot)
  2056. lpModeRoot = lpModeNew;
  2057. // Update count
  2058. cModes++;
  2059. // Success
  2060. return DD_OK;
  2061. } // End DDDrvInfo::AddMode
  2062.   
  2063. /*
  2064. **-----------------------------------------------------------------------------
  2065. **  Name:       DDDrvInfo::DelMode
  2066. **  Purpose:    removes mode from mode list
  2067. **-----------------------------------------------------------------------------
  2068. */
  2069. HRESULT DDDrvInfo::DelMode (LPDDModeInfo lpModeDel)
  2070. {
  2071. // Check parameters
  2072. if (lpModeDel)
  2073. {
  2074. // Error
  2075. return DDERR_INVALIDPARAMS;
  2076. }
  2077. // Remove this Mode From mode list
  2078.     LPDDModeInfo lpPrevMode = lpModeDel->lpPrev;
  2079.     LPDDModeInfo lpNextMode = lpModeDel->lpNext;
  2080.     if (lpPrevMode)
  2081.         lpPrevMode->lpNext = lpNextMode;
  2082.     else
  2083.         lpModeRoot = lpNextMode;
  2084.     if (lpNextMode)
  2085. lpNextMode->lpPrev = lpPrevMode;
  2086. else
  2087. lpModeTail = lpPrevMode;
  2088. lpModeDel->lpPrev = NULL;
  2089.     lpModeDel->lpNext = NULL;
  2090.     // Destroy mode node
  2091.     delete lpModeDel;
  2092. // Update count
  2093. cModes--;
  2094. // Success
  2095. return DD_OK;
  2096. } // End DDDrvInfo::DelMode
  2097.   
  2098.   
  2099. /*
  2100. **-----------------------------------------------------------------------------
  2101. **  Name:       DDDrvInfo::FindMode
  2102. **  Purpose:    finds specified mode
  2103. **-----------------------------------------------------------------------------
  2104. */
  2105. LPDDModeInfo DDDrvInfo::FindMode (
  2106. DWORD dwW, /* In:  Match this width */
  2107. DWORD dwH, /* In:  Match this Height */
  2108. DWORD dwBPP, /* In:  Match this Bits Per Pixel */
  2109. DWORD           dwRefresh, /* In:  Not supported yet... */
  2110. LPDDModeInfo * lpNextBest, /* Out: Return next best match */
  2111. LPDDModeInfo    lpStart)  /* In:  Start search from this mode */
  2112. {
  2113. LPDDModeInfo lpCurrMode, lpNextMode;
  2114. // Get Starting node
  2115. if (! lpStart)
  2116. lpCurrMode = lpModeRoot;
  2117. else
  2118. lpCurrMode = lpStart;
  2119. if (lpNextBest)
  2120. *lpNextBest = lpCurrMode;
  2121. // Search mode list for best match
  2122.     while (lpCurrMode)
  2123. {
  2124. lpNextMode = lpCurrMode->lpNext;
  2125.         if (lpCurrMode->Match (dwW, dwH, dwBPP))
  2126.         {
  2127. return lpCurrMode;
  2128.         }
  2129.         else if (lpCurrMode->Match (640, 480, 8))
  2130.         {
  2131. if (lpNextBest)
  2132. *lpNextBest = lpCurrMode;
  2133.         }
  2134. lpCurrMode = lpNextMode;
  2135.     }
  2136.     // Failure, user may use lpNextBest instead
  2137.     return NULL;
  2138. } // End DDDrvInfo::FindMode 
  2139.   
  2140. /*
  2141. **-----------------------------------------------------------------------------
  2142. **  Name:       DDDrvInfo::FindMode
  2143. **  Purpose:    finds specified mode
  2144. **-----------------------------------------------------------------------------
  2145. */
  2146. LPDDModeInfo DDDrvInfo::FindMode (
  2147. LPDDSURFACEDESC lpddsd, /* In: Mode Desc */
  2148. LPDDModeInfo *  lpNextBest, /* Out: Second best match */
  2149. LPDDModeInfo    lpStart) /* In: start from this node */
  2150. {
  2151. LPDDModeInfo lpCurrMode, lpNextMode;
  2152. // Get Starting node
  2153. if (! lpStart)
  2154. lpCurrMode = lpModeRoot;
  2155. else
  2156. lpCurrMode = lpStart;
  2157. if (lpNextBest)
  2158. *lpNextBest = lpCurrMode;
  2159. // Search mode list for best match
  2160.     while (lpCurrMode)
  2161. {
  2162. lpNextMode = lpCurrMode->lpNext;
  2163.         if (lpCurrMode->Match (*lpddsd))
  2164.         {
  2165.             return lpCurrMode;
  2166.         }
  2167.         else if (lpCurrMode->Match (640, 480, 8))
  2168.         {
  2169. if (lpNextBest)
  2170. *lpNextBest = lpCurrMode;
  2171.         }
  2172.     }
  2173.     // Failure, user may use lpNextBest instead
  2174.     return NULL;
  2175. } // End DDDrvInfo::FindMode 
  2176.   
  2177. /*
  2178. **-----------------------------------------------------------------------------
  2179. **  Name:       DDDrvInfo::EnumModes
  2180. **  Purpose:    Enumerate modes in this Driver
  2181. **-----------------------------------------------------------------------------
  2182. */
  2183. DWORD DDDrvInfo::EnumModes (const DDDRV_ENUMINFO & eiInfo)
  2184. {
  2185.     DWORD           dwResult = ENUM_FAILURE;
  2186. LPDDModeInfo lpCurrMode, lpNextMode;
  2187.     // Check Match Callback function
  2188.     if (! eiInfo.fpcbEnum)
  2189.     {
  2190.         // Error, invalid callback
  2191.         return ENUM_ERROR;
  2192.     }
  2193. // Get Starting node
  2194. if (eiInfo.lpStart)
  2195. lpCurrMode = (LPDDModeInfo)(eiInfo.lpStart);
  2196. else
  2197. lpCurrMode = lpModeRoot;
  2198. // Do callback on each node in list
  2199. while (lpCurrMode)
  2200. {
  2201. lpNextMode = lpCurrMode->lpNext;
  2202.         // Call Enum Mode Callback
  2203.         dwResult = (*eiInfo.fpcbEnum)((LPVOID)this, lpCurrMode, eiInfo.dwExtra);
  2204.         // Check for early exit
  2205.         if (dwResult & ENUM_STOP)
  2206.         {
  2207.             // Return result code
  2208.             return (dwResult & ~ENUM_STOP);
  2209.         }
  2210.    }
  2211.     // Failure
  2212.     return (dwResult & ~ENUM_STOP);
  2213. } // End DDDrvInfo::EnumModes
  2214. /*
  2215. **-----------------------------------------------------------------------------
  2216. **  Name:       DDDrvInfo::LoadDevices
  2217. **  Purpose:    Load all Devices associated with this DD Driver
  2218. **-----------------------------------------------------------------------------
  2219. */
  2220. HRESULT DDDrvInfo::LoadDevices (LPDIRECT3D2 lpD3D2)
  2221. {
  2222. // Have we already loaded the D3D Devices for this driver
  2223. if (! devicesLoaded ())
  2224. {
  2225. HRESULT hResult;
  2226.     DD_CB_INFO cbInfo;
  2227. // Check Parameters
  2228. if (! lpD3D2)
  2229. {
  2230. hResult = APPERR_INVALIDPARAMS;
  2231. REPORTERR (hResult);
  2232. return hResult;
  2233. }
  2234.     cbInfo.fResult  = TRUE;
  2235.     cbInfo.lpExtra  = (void *)this;
  2236. cbInfo.cCount   = 0L;
  2237. hResult = lpD3D2->EnumDevices (DeviceEnumCallback, &cbInfo);
  2238. if (FAILED(hResult))
  2239. {
  2240. REPORTERR (hResult);
  2241. return hResult;
  2242. }
  2243. // Double check count
  2244. if ((! cbInfo.fResult) || (cbInfo.cCount == 0) || (cDevices != cbInfo.cCount))
  2245. {
  2246. hResult = APPERR_GENERIC;
  2247. REPORTERR (hResult);
  2248. return hResult;
  2249. }
  2250. // Mark Devices as loaded
  2251. turnDevicesLoadedOn ();
  2252. }
  2253. // Success
  2254. return DD_OK;
  2255. } // DDDrvInfo::LoadDevices
  2256.   
  2257.   
  2258. /*
  2259. **-----------------------------------------------------------------------------
  2260. **  Name:       DDDrvInfo::DestroyDevices
  2261. **  Purpose:    Destroys all Devices in Device List
  2262. **-----------------------------------------------------------------------------
  2263. */
  2264.   
  2265. HRESULT DDDrvInfo::DestroyDevices (void)
  2266. {
  2267. LPD3DDevInfo lpCurr, lpNext, lpPrev;
  2268. lpCurr = lpDeviceRoot;
  2269. // Walk linked list and destroy all D3D Device nodes
  2270. while (lpCurr)
  2271. {
  2272. lpNext = lpCurr->lpNext;
  2273. lpPrev = lpCurr->lpPrev;
  2274. // Remove node from List
  2275. if (lpPrev)
  2276. lpPrev->lpNext = lpNext;
  2277. else
  2278. lpDeviceRoot = lpNext;
  2279. if (lpNext)
  2280. lpNext->lpPrev = lpPrev;
  2281. else
  2282. lpDeviceTail = lpPrev;
  2283. // Destroy this node
  2284. lpCurr->lpNext = NULL;
  2285. lpCurr->lpPrev = NULL;
  2286. delete lpCurr;
  2287. // Move to next node in list
  2288. lpCurr = lpNext;
  2289. }
  2290. cDevices    = 0L;
  2291. lpDeviceRoot = NULL;
  2292. lpDeviceTail = NULL;
  2293. turnDevicesLoadedOff ();
  2294. // Success
  2295. return DD_OK;
  2296. } // End DDDrvInfo::DestroyDevices
  2297.   
  2298.   
  2299. /*
  2300. **-----------------------------------------------------------------------------
  2301. **  Name:       DDDrvInfo::AddDevice
  2302. **  Purpose:    add new D3D device to device list
  2303. **-----------------------------------------------------------------------------
  2304. */
  2305. HRESULT DDDrvInfo::AddDevice (LPD3DDevInfo lpDevNew)
  2306. {
  2307. // Check Parameters
  2308. if (! lpDevNew)
  2309. {
  2310. // Error, Invalid parameters
  2311. return DDERR_INVALIDPARAMS;
  2312. }
  2313. // Add to tail of Mode List
  2314. lpDevNew->lpPrev = lpDeviceTail;
  2315. lpDevNew->lpNext = NULL;
  2316. // Update tail
  2317. if (lpDeviceTail)
  2318. lpDeviceTail->lpNext = lpDevNew;
  2319. lpDeviceTail = lpDevNew;
  2320. // Update Root
  2321. if (! lpDeviceRoot)
  2322. lpDeviceRoot = lpDevNew;
  2323. // Update count
  2324. cDevices++;
  2325. // Success
  2326. return DD_OK;
  2327. } // End DDDrvInfo::AddDevice
  2328.   
  2329. /*
  2330. **-----------------------------------------------------------------------------
  2331. **  Name:       DDDrvInfo::DelDevice
  2332. **  Purpose:    removes D3D device from Device list
  2333. **-----------------------------------------------------------------------------
  2334. */
  2335. HRESULT DDDrvInfo::DelDevice (LPD3DDevInfo lpDevDel)
  2336. {
  2337. // Check parameters
  2338. if (lpDevDel)
  2339. {
  2340. // Error
  2341. return DDERR_INVALIDPARAMS;
  2342. }
  2343. // Remove this Mode From mode list
  2344.     LPD3DDevInfo lpPrevDev = lpDevDel->lpPrev;
  2345.     LPD3DDevInfo lpNextDev = lpDevDel->lpNext;
  2346.     if (lpPrevDev)
  2347.         lpPrevDev->lpNext = lpNextDev;
  2348.     else
  2349.         lpDeviceRoot = lpNextDev;
  2350.     if (lpNextDev)
  2351. lpNextDev->lpPrev = lpPrevDev;
  2352. else
  2353. lpDeviceTail = lpPrevDev;
  2354. lpDevDel->lpPrev = NULL;
  2355.     lpDevDel->lpNext = NULL;
  2356.     // Destroy mode node
  2357.     delete lpDevDel;
  2358. // Update count
  2359. cDevices--;
  2360. // Success
  2361. return DD_OK;
  2362. } // End DDDrvInfo::DelDevice
  2363.   
  2364.   
  2365. /*
  2366. **-----------------------------------------------------------------------------
  2367. **  Name:       DDDrvInfo::FindDevice
  2368. **  Purpose:    finds specified D3D Device
  2369. **-----------------------------------------------------------------------------
  2370. */
  2371. LPD3DDevInfo DDDrvInfo::FindDevice (
  2372. LPGUID lpGuid, 
  2373. LPD3DDevInfo *  lpNextBest,
  2374. LPD3DDevInfo lpStart)
  2375. {
  2376. LPD3DDevInfo lpCurrDev, lpNextDev;
  2377. LPD3DDevInfo    lpHardware = NULL;
  2378. LPD3DDevInfo lpMMX = NULL;
  2379. LPD3DDevInfo    lpRGB = NULL;
  2380. LPD3DDevInfo    lpFirst = NULL;
  2381. if (lpNextBest)
  2382. *lpNextBest = NULL;
  2383. // Get Root
  2384. if (! lpStart)
  2385. lpCurrDev = lpDeviceRoot;
  2386. else
  2387. lpCurrDev = lpStart;
  2388. lpFirst = lpCurrDev;
  2389. // Search mode list for best match
  2390.     while (lpCurrDev)
  2391. {
  2392. lpNextDev = lpCurrDev->lpNext;
  2393.         if (lpCurrDev->Match (lpGuid))
  2394.         {
  2395. return lpCurrDev;
  2396.         }
  2397.         
  2398. if (lpCurrDev->isHardware ())
  2399.         {
  2400. if (! lpHardware)
  2401. lpHardware = lpCurrDev;
  2402.         }
  2403. if (lpCurrDev->guid == IID_IDirect3DRGBDevice)
  2404. {
  2405. if (! lpRGB)
  2406. lpRGB = lpCurrDev;
  2407. }
  2408. if (lpCurrDev->guid == IID_IDirect3DMMXDevice)
  2409. {
  2410. if (! lpMMX)
  2411. lpMMX = lpCurrDev;
  2412. }
  2413. lpCurrDev = lpNextDev;
  2414.     }
  2415. if (lpNextBest)
  2416. {
  2417. if (lpHardware)
  2418. *lpNextBest = lpHardware;
  2419. else if (lpRGB)
  2420. *lpNextBest = lpRGB;
  2421. else if (lpMMX)
  2422. *lpNextBest = lpMMX;
  2423. else if (lpFirst)
  2424. *lpNextBest = lpFirst;
  2425. }
  2426.     // Failure, user may use lpNextBest instead
  2427.     return NULL;
  2428. } // End DDDrvInfo::FindDevice
  2429. /*
  2430. **-----------------------------------------------------------------------------
  2431. **  Name:       DDDrvInfo::FindDevice
  2432. **  Purpose:    finds specified D3D Device
  2433. **-----------------------------------------------------------------------------
  2434. */
  2435. LPD3DDevInfo DDDrvInfo::FindDevice (
  2436.     LPD3DDEVICEDESC lpHal, 
  2437.     LPD3DDEVICEDESC lpHel,
  2438.     LPD3DDevInfo * lpNextBest,
  2439. LPD3DDevInfo lpStart)
  2440. {
  2441. LPD3DDevInfo lpCurrDev, lpNextDev;
  2442. LPD3DDevInfo    lpHardware = NULL;
  2443. LPD3DDevInfo lpMMX = NULL;
  2444. LPD3DDevInfo    lpRGB = NULL;
  2445. LPD3DDevInfo    lpFirst = NULL;
  2446. if (lpNextBest)
  2447. *lpNextBest = NULL;
  2448. // Get Root
  2449. if (! lpStart)
  2450. lpCurrDev = lpDeviceRoot;
  2451. else
  2452. lpCurrDev = lpStart;
  2453. lpFirst = lpCurrDev;
  2454. // Search mode list for best match
  2455.     while (lpCurrDev)
  2456. {
  2457. lpNextDev = lpCurrDev->lpNext;
  2458.         if (lpCurrDev->Match (lpHal, lpHel))
  2459.         {
  2460. return lpCurrDev;
  2461.         }
  2462.         
  2463. if (lpCurrDev->isHardware ())
  2464.         {
  2465. if (! lpHardware)
  2466. lpHardware = lpCurrDev;
  2467.         }
  2468. if (lpCurrDev->guid == IID_IDirect3DRGBDevice)
  2469. {
  2470. if (! lpRGB)
  2471. lpRGB = lpCurrDev;
  2472. }
  2473. if (lpCurrDev->guid == IID_IDirect3DMMXDevice)
  2474. {
  2475. if (! lpMMX)
  2476. lpMMX = lpCurrDev;
  2477. }
  2478. lpCurrDev = lpNextDev;
  2479.     }
  2480. if (lpNextBest)
  2481. {
  2482. if (lpHardware)
  2483. *lpNextBest = lpHardware;
  2484. else if (lpRGB)
  2485. *lpNextBest = lpRGB;
  2486. else if (lpMMX)
  2487. *lpNextBest = lpMMX;
  2488. else if (lpFirst)
  2489. *lpNextBest = lpFirst;
  2490. }
  2491.     // Failure
  2492.     return NULL;
  2493. } // End DDDrvInfo::FindDevice
  2494.   
  2495. /*
  2496. **-----------------------------------------------------------------------------
  2497. **  Name:       DDDrvInfo::FindDeviceSupportsMode
  2498. **  Purpose:    finds specified D3D Device that is compatible
  2499. ** with specified mode
  2500. **  Notes;
  2501. **
  2502. ** 1.  First looks for an exact match that is compatible
  2503. **  2.  Looks for a hardware device that is compatible
  2504. ** 3.  Looks for any device that is compatible
  2505. **
  2506. **-----------------------------------------------------------------------------
  2507. */
  2508. LPD3DDevInfo DDDrvInfo::FindDeviceSupportsMode (
  2509. LPGUID lpGuid, 
  2510.     LPDDModeInfo lpMode,
  2511. LPD3DDevInfo *  lpNextBest,
  2512. LPD3DDevInfo lpStart)
  2513. {
  2514. LPD3DDevInfo lpCurrDev, lpNextDev;
  2515. // Check parameters
  2516. if (! lpMode)
  2517. {
  2518. // Error, Invalid parameters
  2519. if (lpNextBest)
  2520. *lpNextBest = NULL;
  2521. return NULL;
  2522. }
  2523. // Get Root
  2524. if (! lpStart)
  2525. lpCurrDev = lpDeviceRoot;
  2526. else
  2527. lpCurrDev = lpStart;
  2528. if (lpNextBest)
  2529. {
  2530. if (lpMode->ModeSupported (lpCurrDev))
  2531. *lpNextBest = lpCurrDev;
  2532. }
  2533. // Search mode list for best match
  2534.     while (lpCurrDev)
  2535. {
  2536. lpNextDev = lpCurrDev->lpNext;
  2537.         if (lpCurrDev->Match (lpGuid))
  2538.         {
  2539. if (lpMode->ModeSupported (lpCurrDev))
  2540. return lpCurrDev;
  2541.         }
  2542.         else if (lpCurrDev->isHardware ())
  2543.         {
  2544. if (lpNextBest)
  2545. {
  2546. if (lpMode->ModeSupported (lpCurrDev))
  2547. *lpNextBest = lpCurrDev;
  2548. }
  2549.         }
  2550. else if (lpMode->ModeSupported (lpCurrDev))
  2551. {
  2552. if (lpNextBest)
  2553. *lpNextBest = lpCurrDev;
  2554. }
  2555. lpCurrDev = lpNextDev;
  2556.     }
  2557.     // Failure, user may use lpNextBest instead
  2558.     return NULL;
  2559. } // End DDDrvInfo::FindDeviceSupportsMode
  2560.   
  2561. /*
  2562. **-----------------------------------------------------------------------------
  2563. **  Name:       DDDrvInfo::FindModeSupportsDevice
  2564. **  Purpose:    finds specified mode that is compatible
  2565. ** with specified D3D device
  2566. **
  2567. ** 1.  First trys for an exact mode, if it is compatible
  2568. ** 2.  Then looks for 640, 480, 16, if it is compatible
  2569. **  3.  Then looks for any mode that is compatible
  2570. **
  2571. **-----------------------------------------------------------------------------
  2572. */
  2573. LPDDModeInfo DDDrvInfo::FindModeSupportsDevice (
  2574. DWORD dwW, 
  2575. DWORD dwH, 
  2576. DWORD dwBPP,
  2577. DWORD dwRefresh, /* In: Not supported yet ... */
  2578. LPD3DDevInfo lpDevice,
  2579. LPDDModeInfo * lpNextBest,
  2580. LPDDModeInfo lpStart)
  2581. {
  2582. LPDDModeInfo lpCurrMode, lpNextMode;
  2583. // Check parameters
  2584. if (! lpDevice)
  2585. {
  2586. // Error, Invalid parameters
  2587. if (lpNextBest)
  2588. *lpNextBest = NULL;
  2589. return NULL;
  2590. }
  2591. // Get Root
  2592. if (! lpStart)
  2593. lpCurrMode = lpModeRoot;
  2594. else
  2595. lpCurrMode = lpStart;
  2596. if (lpNextBest)
  2597. {
  2598. if (lpCurrMode->ModeSupported (lpDevice))
  2599. *lpNextBest = lpCurrMode;
  2600. }
  2601. // Search mode list for best match
  2602.     while (lpCurrMode)
  2603. {
  2604. lpNextMode = lpCurrMode->lpNext;
  2605.         if (lpCurrMode->Match (dwW, dwH, dwBPP))
  2606.         {
  2607. if (lpCurrMode->ModeSupported (lpDevice))
  2608. return lpCurrMode;
  2609.         }
  2610.         else if (lpCurrMode->Match (640, 480, 16))
  2611.         {
  2612. if (lpNextBest)
  2613. {
  2614. if (lpCurrMode->ModeSupported (lpDevice))
  2615. *lpNextBest = lpCurrMode;
  2616. }
  2617.         }
  2618. else if (lpCurrMode->ModeSupported (lpDevice))
  2619. {
  2620. if (lpNextBest)
  2621. *lpNextBest = lpCurrMode;
  2622. }
  2623. lpCurrMode = lpNextMode;
  2624.     }
  2625.     // Failure, user may use lpNextBest instead
  2626.     return NULL;
  2627. } // End DDDrvInfo::FindModeSupportsDevice
  2628.   
  2629. /*
  2630. **-----------------------------------------------------------------------------
  2631. **  Name:       DDDrvInfo::EnumDevices
  2632. **  Purpose:    Enumerate D3D devices in driver
  2633. **-----------------------------------------------------------------------------
  2634. */
  2635. DWORD DDDrvInfo::EnumDevices (const DDDRV_ENUMINFO & eiInfo)
  2636. {
  2637.     DWORD           dwResult = ENUM_FAILURE;
  2638. LPD3DDevInfo lpCurrDev, lpNextDev;
  2639.     // Check Match Callback function
  2640.     if (! eiInfo.fpcbEnum)
  2641.     {
  2642.         // Error, invalid callback
  2643.         return ENUM_ERROR;
  2644.     }
  2645. // Get Starting node
  2646. if (eiInfo.lpStart)
  2647. lpCurrDev = (LPD3DDevInfo)(eiInfo.lpStart);
  2648. else
  2649. lpCurrDev = lpDeviceRoot;
  2650. // Do callback on each node in list
  2651. while (lpCurrDev)
  2652. {
  2653. lpNextDev = lpCurrDev->lpNext;
  2654. dwResult = (*eiInfo.fpcbEnum)((LPVOID)this, lpCurrDev, eiInfo.dwExtra);
  2655.         // Check for early exit
  2656.         if (dwResult & ENUM_STOP)
  2657. {
  2658.             // Return result code
  2659.             return (dwResult & ~ENUM_STOP);
  2660. }
  2661. lpCurrDev = lpNextDev;
  2662. }
  2663.     // Failure
  2664.     return (dwResult & ~ENUM_STOP);
  2665. } // End DDDrvInfo::EnumDevices
  2666.   
  2667. /*
  2668. **-----------------------------------------------------------------------------
  2669. **  Name:       DDDrvInfo::GetGuid
  2670. ** Purpose:
  2671. **-----------------------------------------------------------------------------
  2672. */
  2673. LPGUID DDDrvInfo::GetGuid (void)
  2674. {
  2675. if (isPrimary ())
  2676. return NULL;
  2677. else
  2678. return &guid;
  2679. } // End DDDrvInfo::GetGuid
  2680.   
  2681. /*
  2682. **-----------------------------------------------------------------------------
  2683. **  DDDrvMgr Methods
  2684. **-----------------------------------------------------------------------------
  2685. */
  2686.   
  2687. /*
  2688. **-----------------------------------------------------------------------------
  2689. **  Name:       DDDrvMgr::Init
  2690. **  Purpose:    Grovel all DD driver info in system 
  2691. **              and store in global DDInfo structures
  2692. **-----------------------------------------------------------------------------
  2693. */
  2694. HRESULT DDDrvMgr::Init (void)
  2695. {
  2696.     if (! isInitialized ())
  2697.     {        
  2698.         HRESULT         hResult;
  2699. g_cDrivers = 0L;
  2700. // Load all drivers in system
  2701. hResult = LoadDrivers ();
  2702. if (FAILED (hResult))
  2703. return hResult;
  2704.         // Mark as initialized
  2705.         initOn ();
  2706.     }
  2707. // Success
  2708.     return DD_OK;
  2709. } // End DDDrvMgr::Init
  2710.   
  2711.   
  2712. /*
  2713. **-----------------------------------------------------------------------------
  2714. **  Name:       DDDrvMgr::Fini
  2715. **  Purpose:    Cleanup all global DDInfo structures
  2716. **-----------------------------------------------------------------------------
  2717. */
  2718. HRESULT DDDrvMgr::Fini (void)
  2719. {
  2720.     if (isInitialized ())
  2721.     {
  2722. DestroyDrivers ();
  2723.         // Mark as not initialized
  2724.         initOff ();
  2725.     }
  2726. // Success
  2727.     return DD_OK;
  2728. } // End DDDrvMgr::Fini
  2729. /*
  2730. **-----------------------------------------------------------------------------
  2731. **  Name:       DDDrvMgr::LoadDrivers
  2732. **  Purpose:    Load all DD Drivers in system
  2733. **-----------------------------------------------------------------------------
  2734. */
  2735. HRESULT DDDrvMgr::LoadDrivers (void)
  2736. {
  2737. HRESULT hResult;
  2738.     DD_CB_INFO cbInfo;
  2739.     // Initialize all valid drivers in system
  2740.     cbInfo.fResult  = TRUE;
  2741.     cbInfo.cCount   = 0L;
  2742.     cbInfo.lpExtra  = (void *)NULL;
  2743.     hResult = DirectDrawEnumerate (DriverEnumCallback, &cbInfo);
  2744. if (FAILED(hResult))
  2745. {
  2746. REPORTERR (hResult);
  2747. return hResult;
  2748. }
  2749. // Double check count
  2750. if ((! cbInfo.fResult) || (cbInfo.cCount == 0) || (g_cDrivers != cbInfo.cCount))
  2751. {
  2752. hResult = APPERR_GENERIC;
  2753. REPORTERR (hResult);
  2754. return hResult;
  2755. }
  2756. // Success
  2757. return DD_OK;
  2758. } // DDDrvMgr::LoadDrivers
  2759.   
  2760.   
  2761. /*
  2762. **-----------------------------------------------------------------------------
  2763. **  Name:       DDDrvMgr::DestroyDrivers
  2764. **  Purpose:    Destroys all Drivers in Driver List
  2765. **-----------------------------------------------------------------------------
  2766. */
  2767.   
  2768. HRESULT DDDrvMgr::DestroyDrivers (void)
  2769. {
  2770. LPDDDrvInfo lpCurr, lpNext, lpPrev;
  2771. lpCurr = g_lpDriverRoot;
  2772. // Walk linked list and destroy all D3D Device nodes
  2773. while (lpCurr)
  2774. {
  2775. lpNext = lpCurr->lpNext;
  2776. lpPrev = lpCurr->lpPrev;
  2777. // Remove node from List
  2778. if (lpPrev)
  2779. lpPrev->lpNext = lpNext;
  2780. else
  2781. g_lpDriverRoot = lpNext;
  2782. if (lpNext)
  2783. lpNext->lpPrev = lpPrev;
  2784. else
  2785. g_lpDriverTail = lpPrev;
  2786. // Destroy this node
  2787. lpCurr->lpNext = NULL;
  2788. lpCurr->lpPrev = NULL;
  2789. delete lpCurr;
  2790. // Move to next node in list
  2791. lpCurr = lpNext;
  2792. }
  2793. g_cDrivers  = 0L;
  2794. g_lpDriverRoot = NULL;
  2795. g_lpDriverTail = NULL;
  2796. // Success
  2797. return DD_OK;
  2798. } // End DDDrvMgr::DestroyDrivers
  2799.   
  2800. /*
  2801. **-----------------------------------------------------------------------------
  2802. **  Name:       DDDrvMgr::DDDrvMgr
  2803. **  Purpose:    Default constructor
  2804. **-----------------------------------------------------------------------------
  2805. */
  2806. DDDrvMgr::DDDrvMgr (void)
  2807. {
  2808.     lpCurrDriver    = NULL;
  2809.     lpCurrMode = NULL;
  2810.     lpCurrDevice = NULL;
  2811. } // End DDDrvMgr::DDDrvMgr
  2812.   
  2813. /*
  2814. **-----------------------------------------------------------------------------
  2815. **  Name:       DDDrvMgr::~DDDrvMgr
  2816. **-----------------------------------------------------------------------------
  2817. */
  2818. DDDrvMgr::~DDDrvMgr (void)
  2819. {
  2820. } // End DDDrvMgr::~DDDrvMgr
  2821.   
  2822. /*
  2823. **-----------------------------------------------------------------------------
  2824. **  Name:       DDDrvMgr::AddDriver
  2825. **  Purpose:    add new driver to driver list
  2826. **-----------------------------------------------------------------------------
  2827. */
  2828. HRESULT DDDrvMgr::AddDriver (LPDDDrvInfo lpDrvNew)
  2829. {
  2830. // Check Parameters
  2831. if (! lpDrvNew)
  2832. {
  2833. // Error, Invalid parameters
  2834. return DDERR_INVALIDPARAMS;
  2835. }
  2836. // Add to tail of Mode List
  2837. lpDrvNew->lpPrev = DDDrvMgr::g_lpDriverTail;
  2838. lpDrvNew->lpNext = NULL;
  2839. // Update tail
  2840. if (DDDrvMgr::g_lpDriverTail)
  2841. DDDrvMgr::g_lpDriverTail->lpNext = lpDrvNew;
  2842. DDDrvMgr::g_lpDriverTail = lpDrvNew;
  2843. // Update Root
  2844. if (! DDDrvMgr::g_lpDriverRoot)
  2845. DDDrvMgr::g_lpDriverRoot = lpDrvNew;
  2846. // Update count
  2847. g_cDrivers++;
  2848. // Success
  2849. return DD_OK;
  2850. } // End DDDrvMgr::AddDriver
  2851.   
  2852. /*
  2853. **-----------------------------------------------------------------------------
  2854. **  Name:       DDDrvMgr::DelDriver
  2855. **  Purpose:    removes driver from driver list
  2856. **-----------------------------------------------------------------------------
  2857. */
  2858. HRESULT DDDrvMgr::DelDriver (LPDDDrvInfo lpDrvDel)
  2859. {
  2860. // Check parameters
  2861. if (lpDrvDel)
  2862. {
  2863. // Error
  2864. return DDERR_INVALIDPARAMS;
  2865. }
  2866. // Remove this Mode From mode list
  2867.     LPDDDrvInfo lpPrevDrv = lpDrvDel->lpPrev;
  2868.     LPDDDrvInfo lpNextDrv = lpDrvDel->lpNext;
  2869.     if (lpPrevDrv)
  2870.         lpPrevDrv->lpNext = lpNextDrv;
  2871.     else
  2872. DDDrvMgr::g_lpDriverRoot = lpNextDrv;
  2873.     if (lpNextDrv)
  2874. lpNextDrv->lpPrev = lpPrevDrv;
  2875. else
  2876. DDDrvMgr::g_lpDriverTail = lpPrevDrv;
  2877. lpDrvDel->lpPrev = NULL;
  2878.     lpDrvDel->lpNext = NULL;
  2879.     // Destroy mode node
  2880.     delete lpDrvDel;
  2881. // Update count
  2882. g_cDrivers--;
  2883. // Success
  2884. return DD_OK;
  2885. } // End DDDrvMgr::DelDriver
  2886.   
  2887.   
  2888. /*
  2889. **-----------------------------------------------------------------------------
  2890. **  Name:       DDDrvMgr::FindDriver
  2891. **  Purpose:    Finds driver corresponding to guid
  2892. **-----------------------------------------------------------------------------
  2893. */
  2894. LPDDDrvInfo DDDrvMgr::FindDriver (
  2895. LPGUID lpGuid, 
  2896. LPDDDrvInfo * lpNextBest,
  2897. LPDDDrvInfo lpStart)
  2898. {
  2899.     LPDDDrvInfo lpCurrDrv, lpNextDrv;
  2900.     
  2901. #ifdef DEBUG
  2902.     if (! isInitialized ())
  2903.     {
  2904.         // Error, not initialized
  2905.         return NULL;
  2906.     }
  2907. #endif
  2908.     // Get Start node
  2909. if (! lpStart)
  2910. lpCurrDrv = DDDrvMgr::g_lpDriverRoot;
  2911. else
  2912. lpCurrDrv = lpStart;
  2913. if (lpNextBest)
  2914. *lpNextBest = lpCurrDrv;
  2915. while (lpCurrDrv)
  2916. {
  2917. lpNextDrv = lpCurrDrv->lpNext;
  2918. if (lpCurrDrv->Match (lpGuid))
  2919. {
  2920. // Success
  2921. return lpCurrDrv;
  2922. }
  2923. else if (lpCurrDrv->isPrimary ())
  2924. {
  2925. if (lpNextBest)
  2926. *lpNextBest = lpCurrDrv;
  2927. }
  2928. lpCurrDrv = lpNextDrv;
  2929. }
  2930.     
  2931.     // Failure, user could use next best instead
  2932.     return NULL;
  2933. } // End DDDrvMgr::FindDriver
  2934.         
  2935.   
  2936. /*
  2937. **-----------------------------------------------------------------------------
  2938. **  Name:       DDDrvMgr::FindDriver
  2939. **  Purpose:    Finds driver corresponding to specified device caps
  2940. **-----------------------------------------------------------------------------
  2941. */
  2942. LPDDDrvInfo DDDrvMgr::FindDriver (
  2943.     LPDDCAPS   lpHal, 
  2944.     LPDDCAPS   lpHel, 
  2945.     LPDDDrvInfo * lpNextBest,
  2946. LPDDDrvInfo   lpStart)
  2947. {
  2948.     LPDDDrvInfo lpCurrDrv, lpNextDrv;
  2949.     
  2950.     // Get Start node
  2951. if (! lpStart)
  2952. lpCurrDrv = DDDrvMgr::g_lpDriverRoot;
  2953. else
  2954. lpCurrDrv = lpStart;
  2955. if (lpNextBest)
  2956. *lpNextBest = lpCurrDrv;
  2957. while (lpCurrDrv)
  2958. {
  2959. lpNextDrv = lpCurrDrv->lpNext;
  2960. if (lpCurrDrv->Match (lpHal, lpHel))
  2961. {
  2962. // Success
  2963. return lpCurrDrv;
  2964. }
  2965. else if (lpCurrDrv->isPrimary ())
  2966. {
  2967. if (lpNextBest)
  2968. *lpNextBest = lpCurrDrv;
  2969. }
  2970. lpCurrDrv = lpNextDrv;
  2971. }
  2972.     
  2973.     // Failure, user could use next best instead
  2974.     return NULL;
  2975. } // End DDDrvMgr::FindDriver
  2976.   
  2977.   
  2978. /*
  2979. **-----------------------------------------------------------------------------
  2980. **  Name:       DDDrvMgr::EnumDrivers
  2981. **  Purpose:    Enumerate drivers
  2982. **-----------------------------------------------------------------------------
  2983. */
  2984. DWORD DDDrvMgr::EnumDrivers (const DDDRV_ENUMINFO & eiInfo)
  2985. {
  2986.     DWORD dwResult = ENUM_FAILURE;
  2987. LPDDDrvInfo lpCurrDrv, lpNextDrv;
  2988.     // Check Match Callback function
  2989.     if (! eiInfo.fpcbEnum)
  2990.     {
  2991.         // Error, invalid callback
  2992.         return ENUM_ERROR;
  2993.     }
  2994. // Get starting node
  2995.     if (eiInfo.lpStart)
  2996. lpCurrDrv = (LPDDDrvInfo)(eiInfo.lpStart);
  2997. else
  2998. lpCurrDrv = DDDrvMgr::g_lpDriverRoot;
  2999.     // for each driver, call user defined match callback function
  3000. while (lpCurrDrv)
  3001. {
  3002.         lpNextDrv = lpCurrDrv->lpNext;
  3003.         // Call Enum Drivers Callback
  3004.         dwResult = (*eiInfo.fpcbEnum)((LPVOID)lpCurrDrv, NULL, eiInfo.dwExtra);
  3005.         // Check for early exit
  3006.         if (dwResult & ENUM_STOP)
  3007.         {
  3008.             // Return result code
  3009.             return (dwResult & ~ENUM_STOP);
  3010.         }
  3011.    }
  3012.     // Failure
  3013.     return (dwResult & ~ENUM_STOP);
  3014. } // End DDDrvMgr::EnumDrivers
  3015. /*
  3016. **-----------------------------------------------------------------------------
  3017. **  End of File
  3018. **-----------------------------------------------------------------------------
  3019. */