Enumerating the Direct3D Devices

[Previous] [Next]

The last step of the DriverEnumCallback routine is to call IDirect3D7::EnumDevices to enumerate all the Direct3D devices for the current DirectDraw device. Since this is a Direct3D method, we first need to get an IDirect3D7 interface pointer. This pointer is acquired in Step 2 of DriverEnumCallback by calling QueryInterface on the IDirectDraw7 object. The IDirect3D7::EnumDevices method is defined as follows:

 HRESULT EnumDevices(   LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback,    LPVOID lpUserArg                                  ); 

ParameterDescription
lpEnumDevicesCallbackAddress of the D3DEnumDevicesCallback7 callback function that the enumeration procedure will call every time a match is found
LpUserArgAddress of application-defined data passed to the callback function

In a similar technique to DirectDrawEnumerateEx and IDirectDraw7::EnumDisplayModes, IDirect3D7::EnumDevices calls a user-specified callback function for each Direct3D device. The Direct3D Framework's Direct3D device callback routine (in d3denum.cpp) is called DeviceEnumCallback. This function is defined as follows:

 //------------------------------------------------------------------- // Name: DeviceEnumCallback // Desc: Callback function for enumerating devices //------------------------------------------------------------------- static HRESULT WINAPI DeviceEnumCallback( TCHAR* strDesc,                                           TCHAR* strName,                                           D3DDEVICEDESC7* pDesc,                                           VOID* pParentInfo ) {     // Keep track of the number of devices that were enumerated.     g_dwNumDevicesEnumerated++;     D3DEnum_DeviceInfo* pDriverInfo =         (D3DEnum_DeviceInfo*)pParentInfo;     D3DEnum_DeviceInfo* pDeviceInfo = &g_pDeviceList[g_dwNumDevices];     ZeroMemory( pDeviceInfo, sizeof(D3DEnum_DeviceInfo) );     // Select either the HAL or the HEL device desc:     pDeviceInfo->bHardware =         pDesc->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION;     memcpy( &pDeviceInfo->ddDeviceDesc, pDesc,             sizeof(D3DDEVICEDESC7) );     // Set up device information for this device.     pDeviceInfo->bDesktopCompatible = pDriverInfo->bDesktopCompatible;     pDeviceInfo->ddDriverCaps       = pDriverInfo->ddDriverCaps;     pDeviceInfo->ddHELCaps          = pDriverInfo->ddHELCaps;     pDeviceInfo->guidDevice         = pDesc->deviceGUID;     pDeviceInfo->pDeviceGUID        = &pDeviceInfo->guidDevice;     pDeviceInfo->pddsdModes         =          new DDSURFACEDESC2[pDriverInfo->dwNumModes];     // Copy the driver GUID and description for the device.     if( pDriverInfo->pDriverGUID )     {         pDeviceInfo->guidDriver  = pDriverInfo->guidDriver;         pDeviceInfo->pDriverGUID = &pDeviceInfo->guidDriver;         lstrcpyn( pDeviceInfo->strDesc, pDriverInfo->strDesc, 39 );     }     else     {         pDeviceInfo->pDriverGUID = NULL;         lstrcpyn( pDeviceInfo->strDesc, strName, 39 );     }     // Avoid duplicates: enumerate hardware devices only for      // secondary DirectDraw drivers.     if( NULL != pDeviceInfo->pDriverGUID &&         FALSE == pDeviceInfo->bHardware )             return D3DENUMRET_OK;     // Give the application a chance to accept or reject this device.     if( g_fnAppConfirmFn )         if( FAILED( g_fnAppConfirmFn( &pDeviceInfo->ddDriverCaps,                                       &pDeviceInfo->ddDeviceDesc ) ) )             return D3DENUMRET_OK;     // Build a list of supported modes for the device.     for( DWORD i=0; i<pDriverInfo->dwNumModes; i++ )     {         DDSURFACEDESC2 ddsdMode = pDriverInfo->pddsdModes[i];         DWORD dwRenderDepths =              pDeviceInfo->ddDeviceDesc.dwDeviceRenderBitDepth;         DWORD dwDepth =              ddsdMode.ddpfPixelFormat.dwRGBBitCount;         // Accept modes that are compatible with the device.         if( ( ( dwDepth == 32 ) && ( dwRenderDepths & DDBD_32 ) ) ||             ( ( dwDepth == 24 ) && ( dwRenderDepths & DDBD_24 ) ) ||             ( ( dwDepth == 16 ) && ( dwRenderDepths & DDBD_16 ) ) )         {             // Copy compatible modes to the list of device-supported             // modes.             pDeviceInfo->pddsdModes[pDeviceInfo->dwNumModes++] =                  ddsdMode;             // Record whether the device has any stereo modes.             if( ddsdMode.ddsCaps.dwCaps2 &                  DDSCAPS2_STEREOSURFACELEFT )                 pDeviceInfo->bStereoCompatible = TRUE;         }     }     // Bail if the device has no supported modes.     if( 0 == pDeviceInfo->dwNumModes )         return D3DENUMRET_OK;     // Find a 640 x 480 x 16 mode for the default full-screen mode.     for( i=0; i<pDeviceInfo->dwNumModes; i++ )     {         if( ( pDeviceInfo->pddsdModes[i].dwWidth == 640 ) &&             ( pDeviceInfo->pddsdModes[i].dwHeight == 480 ) &&             ( pDeviceInfo->                 pddsdModes[i].ddpfPixelFormat.dwRGBBitCount == 16 ) )         {             pDeviceInfo->ddsdFullscreenMode =                  pDeviceInfo->pddsdModes[i];             pDeviceInfo->dwCurrentMode      = i;         }     }     // Select whether the device is initially windowed.     pDeviceInfo->bWindowed = pDeviceInfo->bDesktopCompatible;     // Accept the device and return.     g_dwNumDevices++;     return D3DENUMRET_OK; } 

This code is basically doing two things. First, it gives the application a chance to reject the device if it is not adequate for the program's needs. Second, it stores the information about the Direct3D device in its data structure.

Remember AppConfirmFn, the parameter passed to D3DEnum_EnumerateDevices? If you pass a pointer to a device confirmation function as this parameter, DeviceEnumCallback will call that function for each Direct3D device that it enumerates. Your device confirmation function can decide whether the Direct3D device is suitable for your program. If you decide that it isn't a good device, you can have your device confirmation function return a failure code, and DeviceEnumCallback will not add the Direct3D device to its list of devices.

The class CD3DApplication defines a member variable, m_fnConfirmDevice, which can point to your confirmation function. CMyD3DApplication inherits this member variable because CMyD3DApplication is derived from CD3DApplication. So you can provide a device confirmation function in CMyD3DApplication and then set m_fnConfirmDevice to its address in CMyD3DApplication's constructor. In the RoadRage code, we're not requesting any special features such as mipmapping, so we can set m_fnConfirmDevice to NULL.

Here's how you would specify special capabilities during enumeration, such as multitexturing:

 m_fnConfirmDevice = ConfirmDevice; 

And this is what the ConfirmDevice function definition would look like:

 //------------------------------------------------------------------- // Name: ConfirmDevice // Desc: Called during device initialization, this code checks the  //       device for some minimum set of capabilities. //------------------------------------------------------------------- HRESULT CMyD3DApplication::ConfirmDevice( DDCAPS* pddDriverCaps,                                   D3DDEVICEDESC7* pd3dDeviceDesc ) {     // Accept devices that support multiple textures. If no device,      // support multiple textures, accept devices that support alpha      // blending to emulate multitexturing with multipass rendering.     if( pd3dDeviceDesc->wMaxSimultaneousTextures > 1 )         return S_OK;     if( pd3dDeviceDesc->dpcTriCaps.dwDestBlendCaps          & D3DPBLENDCAPS_SRCCOLOR )         if( pd3dDeviceDesc->dpcTriCaps.dwSrcBlendCaps              & D3DPBLENDCAPS_ZERO )             return S_OK;     return E_FAIL; } 



Inside Direct3D
Inside Direct3D (Dv-Mps Inside)
ISBN: 0735606137
EAN: 2147483647
Year: 1999
Pages: 131

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net