Enumeration Callback Function

The EnumDeviceCallback function is invoked for each Direct3D device installed on the system. For each device we retrieve its identifying GUID, a name and description, a description of its hardware and software capabilities, and an unused user argument.

The EnumDeviceCallback function uses the following algorithm to choose an appropriate Direct3D device:

  1. Discard any devices which don't match the current display depth.
  2. Discard any devices which can't do Gouraud-shaded triangles.
  3. If a hardware device is found which matches points one and two, use it. However, if we are running in debug mode we will skip hardware.
  4. Otherwise favor Mono/Ramp mode software renderers over RGB ones; until MMX is widespread, Mono will be faster.

This callback function is invoked by the ChooseDevice enumeration function, which is described in Enumeration Function.

Note that the first parameter passed to this callback function, lpGUID, is NULL for the primary device. All other devices should have a non-NULL pointer. You should consider saving the actual GUID for the device you choose, not the pointer to the GUID, in case the pointer is accidentally corrupted.

static HRESULT WINAPI 
EnumDeviceCallback(LPGUID          lpGUID, 
                   LPSTR           lpszDeviceDesc, 
                   LPSTR           lpszDeviceName, 
                   LPD3DDEVICEDESC lpd3dHWDeviceDesc, 
                   LPD3DDEVICEDESC lpd3dSWDeviceDesc, 
                   LPVOID          lpUserArg) 
{ 
    BOOL            fIsHardware; 
    LPD3DDEVICEDESC lpd3dDeviceDesc; 
 
        // Call the USE_PARAM macro on the unused parameter to 
        // avoid compiler warnings. 
 
    USE_PARAM(lpUserArg); 
 
        // If there is no hardware support the color model is zero. 
 
    fIsHardware     = (0 != lpd3dHWDeviceDesc->dcmColorModel); 
    lpd3dDeviceDesc = (fIsHardware ? lpd3dHWDeviceDesc : 
                                     lpd3dSWDeviceDesc); 
 
        // If we are in debug mode and this is a hardware device, 
        // skip it. 
 
    if (fDebug && fIsHardware) 
        return D3DENUMRET_OK; 
 
        // Does the device render at the depth we want? 
 
    if (0 == (lpd3dDeviceDesc->dwDeviceRenderBitDepth & 
              dwDeviceBitDepth)) 
    { 
                // If not, skip this device. 
 
        return D3DENUMRET_OK; 
    } 
 
        // The device must support Gouraud-shaded triangles. 
 
    if (D3DCOLOR_MONO == lpd3dDeviceDesc->dcmColorModel) 
    { 
        if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps & 
              D3DPSHADECAPS_COLORGOURAUDMONO)) 
        { 
                        // No Gouraud shading. Skip this device. 
 
            return D3DENUMRET_OK; 
        } 
    } 
    else 
    { 
        if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps & 
              D3DPSHADECAPS_COLORGOURAUDRGB)) 
        { 
                        // No Gouraud shading. Skip this device. 
 
            return D3DENUMRET_OK; 
        } 
    } 
 
    if (!fIsHardware && fDeviceFound && 
           (D3DCOLOR_RGB == lpd3dDeviceDesc->dcmColorModel)) 
    { 
                // If this is software RGB and we already have found 
                // a software monochromatic renderer, we are not 
                // interested. Skip this device. 
 
        return D3DENUMRET_OK; 
    } 
 
        // This is a device we are interested in. Save the details. 
 
    fDeviceFound = TRUE; 
    CopyMemory(&guidDevice, lpGUID, sizeof(GUID)); 
    strcpy(szDeviceDesc, lpszDeviceDesc); 
    strcpy(szDeviceName, lpszDeviceName); 
    CopyMemory(&d3dHWDeviceDesc, lpd3dHWDeviceDesc, 
               sizeof(D3DDEVICEDESC)); 
    CopyMemory(&d3dSWDeviceDesc, lpd3dSWDeviceDesc, 
               sizeof(D3DDEVICEDESC)); 
 
        // If this is a hardware device, we have found 
        // what we are looking for. 
 
    if (fIsHardware) 
        return D3DENUMRET_CANCEL; 
 
        // Otherwise, keep looking. 
 
    return D3DENUMRET_OK; 
}