home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / pplane / drvmgr.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  86KB  |  3,665 lines

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