]> icculus.org git repositories - btb/d2x.git/blob - arch/win32/d3dframe/d3denum.cpp
remove needless sleep on linux hmiplay startup (d1x r1.6)
[btb/d2x.git] / arch / win32 / d3dframe / d3denum.cpp
1 //-----------------------------------------------------------------------------
2 // File: D3DEnum.cpp
3 //
4 // Desc: Class enumerate through the DirectDraw drivers, Direct3D devices,
5 //       and the display modes available to each device.
6 //
7 //
8 // Copyright (c) 1997-1998 Microsoft Corporation. All rights reserved
9 //-----------------------------------------------------------------------------
10
11 #include <stdio.h>
12
13 // HACK!!!!!
14 #include <windows.h>
15 #ifndef SM_CMONITORS
16 #define SM_CMONITORS
17 DECLARE_HANDLE(HMONITOR);
18 #endif
19
20 #include "D3DEnum.h"
21 #include "D3DUtil.h"
22
23
24
25
26 //-----------------------------------------------------------------------------
27 // Constants and function prototypes for the user select driver dialog
28 //-----------------------------------------------------------------------------
29 DLGTEMPLATE*  _BuildDriverSelectTemplate();
30 BOOL CALLBACK _DriverSelectProc( HWND, UINT, WPARAM, LPARAM );
31
32
33
34
35 //-----------------------------------------------------------------------------
36 // Global data for the enumerator functions
37 //-----------------------------------------------------------------------------
38 static LPDIRECTDRAW4 g_pDD                = NULL;  // Used for callbacks
39 static BOOL          g_bRefRastEnumerated = FALSE; // For the reference rast
40 static BOOL          g_bDevicesEnumerated = FALSE; // Used during enumeration
41
42 D3DEnum_DriverInfo*  g_pFirstDriver   = NULL; // List of DD drivers
43 D3DEnum_DriverInfo*  g_pDefaultDriver = NULL; // Default driver
44 D3DEnum_DriverInfo*  g_pCurrentDriver = NULL; // The selected DD driver
45
46 static HRESULT (*g_fnAppConfirmFn)(DDCAPS*, D3DDEVICEDESC*) = NULL;
47
48
49
50
51 //-----------------------------------------------------------------------------
52 // Local callback functions used during enumeration
53 //-----------------------------------------------------------------------------
54
55
56 //-----------------------------------------------------------------------------
57 // Name: EnumDisplayModesCallback()
58 // Desc: Callback function called for each display mode. Each available
59 //       display mode is added to a list for further choosing from the app.
60 //-----------------------------------------------------------------------------
61 static HRESULT WINAPI EnumDisplayModesCallback( DDSURFACEDESC2* pddsd,
62                                                 VOID* pvContext )
63 {
64     // Check parameters
65     if( NULL==pddsd || NULL==pvContext )
66         return DDENUMRET_CANCEL;
67
68     D3DEnum_DeviceInfo* pDevice = (D3DEnum_DeviceInfo*)pvContext;
69     D3DEnum_ModeInfo*   pNewMode;
70     DWORD dwBitDepth  = pDevice->ddDesc.dwDeviceRenderBitDepth;
71     DWORD dwModeDepth = pddsd->ddpfPixelFormat.dwRGBBitCount;
72
73         // Check mode for compatability with device. Skip 8-bit modes.
74     if( (32==dwModeDepth) && (0==(dwBitDepth&DDBD_32)) ) return DDENUMRET_OK;
75     if( (24==dwModeDepth) && (0==(dwBitDepth&DDBD_24)) ) return DDENUMRET_OK;
76     if( (16==dwModeDepth) && (0==(dwBitDepth&DDBD_16)) ) return DDENUMRET_OK;
77         if( ( 8==dwModeDepth) ) return DDENUMRET_OK;
78
79     // Create a new mode structure
80     if( NULL == ( pNewMode = new D3DEnum_ModeInfo ) )
81         return DDENUMRET_CANCEL;
82
83     // Initialize the new mode structure
84     ZeroMemory( pNewMode, sizeof(D3DEnum_ModeInfo) );
85     memcpy( &pNewMode->ddsd, pddsd, sizeof(DDSURFACEDESC2) );
86     sprintf( pNewMode->strDesc, TEXT("%ld x %ld x %ld"), pddsd->dwWidth,
87                                 pddsd->dwHeight, dwModeDepth );
88
89     // Link the new mode struct in the list of other display modes
90         D3DEnum_ModeInfo** pMode = &pDevice->pFirstMode;
91         while( *pMode )
92                 pMode = &((*pMode)->pNext);
93         (*pMode) = pNewMode;
94         
95     // If this is a 640x480x16 mode, save it as the default mode
96     if( ( 640 == pddsd->dwWidth ) && ( 480 == pddsd->dwHeight ) &&
97         ( 16 == pddsd->ddpfPixelFormat.dwRGBBitCount ) )
98         pDevice->pCurrentMode = pNewMode;
99         
100         if( NULL == pDevice->pCurrentMode )
101         pDevice->pCurrentMode = pNewMode;
102
103     return DDENUMRET_OK;
104 }
105
106
107
108
109 //-----------------------------------------------------------------------------
110 // Name: Enum3DDevicesCallback()
111 // Desc: Callback function called for each DirectX 3D device. The driver's
112 //       attributes are added to the list of available drivers.
113 //-----------------------------------------------------------------------------
114 static HRESULT WINAPI Enum3DDevicesCallback( GUID* pGUID, LPSTR strDesc, 
115                                 LPSTR strName, LPD3DDEVICEDESC pHALDesc, 
116                                 LPD3DDEVICEDESC pHELDesc, LPVOID pvContext )
117 {
118     D3DEnum_DriverInfo* pDriver = (D3DEnum_DriverInfo*)pvContext;
119     D3DEnum_DeviceInfo* pNewDevice;
120
121     // Check params
122     if( NULL==pGUID || NULL==pHALDesc || NULL==pHELDesc || NULL==pDriver )
123         return D3DENUMRET_CANCEL;
124
125     // Handle specific device GUIDs. NullDevice renders nothing
126     if( IsEqualGUID( *pGUID, IID_IDirect3DNullDevice ) )
127         return D3DENUMRET_OK;
128
129         // Set a flag so we know enumeration is working. This is just a feature to
130         // help return more informative return codes later on.
131     g_bDevicesEnumerated = TRUE;
132
133         // Get info about this device.
134     BOOL           bIsHardware = ( 0 != pHALDesc->dwFlags );
135         D3DDEVICEDESC* pDesc       = bIsHardware ? pHALDesc : pHELDesc;
136
137     // Only enumerate software rasterizers for the primary device (which has
138         // a NULL GUID). This is to avoid duplicates
139     if( pDriver->pGUID != NULL )
140             if( FALSE == bIsHardware )
141                         return D3DENUMRET_OK;
142
143
144         // Give the app a chance to accept or reject this device, based on
145         // what feature set it supports
146         if( g_fnAppConfirmFn )
147                 if( FAILED( g_fnAppConfirmFn( &pDriver->ddDriverCaps, pDesc ) ) )
148                         return D3DENUMRET_OK;
149
150     // Create a new D3D Driver struct
151     if( NULL == ( pNewDevice = new D3DEnum_DeviceInfo ) )
152         return D3DENUMRET_CANCEL;
153     ZeroMemory( pNewDevice, sizeof(D3DEnum_DeviceInfo) );
154
155     // Copy remaining device attributes
156     memcpy( &pNewDevice->guid, pGUID, sizeof(GUID) );
157     pNewDevice->pGUID = &pNewDevice->guid;
158     strncpy( pNewDevice->strName, strName, 39 );
159     memcpy( &pNewDevice->ddDesc, pDesc, sizeof(D3DDEVICEDESC) );
160     pNewDevice->bIsHardware = bIsHardware;
161
162     if( pNewDevice->bIsHardware )
163         pDriver->pCurrentDevice = pNewDevice;
164     else
165         {
166                 if( NULL == pDriver->pCurrentDevice )
167                         if( D3DCOLOR_RGB & pHELDesc->dcmColorModel )
168                                 pDriver->pCurrentDevice = pNewDevice;
169         }
170
171     // Enumerate the display modes
172     g_pDD->EnumDisplayModes( 0, NULL, pNewDevice, EnumDisplayModesCallback );
173
174         // Get the display mode's depth
175         DDSURFACEDESC2 ddsd;
176         ddsd.dwSize = sizeof(DDSURFACEDESC2);
177         g_pDD->GetDisplayMode( &ddsd );
178         DWORD dwDisplayBPP = ddsd.ddpfPixelFormat.dwRGBBitCount;
179
180         // Set the initial bWindowed flag if the device can render in a window and
181         // supports the current display mode
182         if( pDriver->ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED )
183         {
184                 for( D3DEnum_ModeInfo* pMode=pNewDevice->pFirstMode; pMode;
185                          pMode = pMode->pNext )
186                 {
187                         if( pMode->ddsd.ddpfPixelFormat.dwRGBBitCount == dwDisplayBPP )
188                         {
189                                 pNewDevice->bCompatbileWithDesktop = TRUE;
190                     if( NULL == pDriver->pGUID )
191                                         pNewDevice->bWindowed = TRUE;
192                         }
193                 }
194         }
195
196         if( pNewDevice->pFirstMode )
197     {
198                 // Link it with the other D3D drivers in the DD Driver struct
199                 D3DEnum_DeviceInfo** pDevice = &pDriver->pFirstDevice;
200                 while( *pDevice )
201                         pDevice = &((*pDevice)->pNext);
202                 (*pDevice) = pNewDevice;
203         }
204         else
205                 // Device has no modes, so delete it
206                 delete pNewDevice;
207
208     if( IsEqualGUID( *pGUID, IID_IDirect3DRefDevice ) )
209         g_bRefRastEnumerated = TRUE;
210
211     return D3DENUMRET_OK;
212 }
213
214
215
216
217 //-----------------------------------------------------------------------------
218 // Name: DirectDrawEnumCallbackEx()
219 // Desc: Callback function called for each DirectDraw driver. Unless we have
220 //       multimon or a type of card which uses a separate 2D card in
221 //       conjunction with the 3D card, this is only done once.
222 //-----------------------------------------------------------------------------
223 static BOOL WINAPI DirectDrawEnumCallbackEx( GUID FAR* pGUID, LPSTR strDesc,
224                                                                                          LPSTR strName, VOID*,
225                                                                                          HMONITOR hMonitor )
226 {
227     // Use the GUID to create the DirectDraw object, so that information
228     // can be extracted from it.
229         LPDIRECTDRAW pDD;
230     if( FAILED( DirectDrawCreate( pGUID, &pDD, 0L ) ) )
231     {
232                 DEBUG_MSG( TEXT("Can't create DDraw during enumeration!") );
233         return D3DENUMRET_OK;
234         }
235
236     // Query the DirectDraw driver for access to Direct3D.
237     if( FAILED( pDD->QueryInterface( IID_IDirectDraw4, (VOID**)&g_pDD ) ) )
238         {
239         DEBUG_MSG( TEXT("Can't query IDirectDraw4 during enumeration!") );
240                 pDD->Release();
241                 return D3DENUMRET_OK;
242         }
243         pDD->Release();
244
245     // Query the DirectDraw driver for access to Direct3D.
246     LPDIRECT3D3 pD3D;
247     if( FAILED( g_pDD->QueryInterface( IID_IDirect3D3, (VOID**)&pD3D ) ) )
248         {
249         DEBUG_MSG( TEXT("Can't query IDirect3D3 during enumeration!") );
250                 g_pDD->Release();
251                 return D3DENUMRET_OK;
252         }
253
254     // Copy the DDDriver info into a new DriverInfo struct
255     D3DEnum_DriverInfo* pNewDriver = new D3DEnum_DriverInfo;
256     if( NULL == pNewDriver )
257                 return D3DENUMRET_CANCEL;
258
259     ZeroMemory( pNewDriver, sizeof(D3DEnum_DriverInfo) );
260
261     // Copy the GUID (if specified) and the driver name
262     if( NULL != pGUID  )
263     {
264         memcpy( &pNewDriver->guid, pGUID, sizeof(GUID) );
265         pNewDriver->pGUID = &pNewDriver->guid;
266     }
267     strncpy( pNewDriver->strDesc, strDesc, 39 );
268     strncpy( pNewDriver->strName, strName, 39 );
269         pNewDriver->hMonitor = hMonitor;
270
271     // Get the caps bits for the driver
272     pNewDriver->ddDriverCaps.dwSize = sizeof(DDCAPS);
273     pNewDriver->ddHELCaps.dwSize    = sizeof(DDCAPS);
274     g_pDD->GetCaps( &pNewDriver->ddDriverCaps, &pNewDriver->ddHELCaps );
275
276         // Now, enumerate all the 3D devices
277     pD3D->EnumDevices( Enum3DDevicesCallback, pNewDriver );
278
279         if( pNewDriver->pFirstDevice )
280         {
281             // Link the new DDDriver with the global list
282                 D3DEnum_DriverInfo** pDriver = &g_pFirstDriver;
283                 while( *pDriver )
284                         pDriver = &((*pDriver)->pNext);
285                 (*pDriver) = pNewDriver;
286
287                 // Decide if this is a good default driver
288                 if( NULL == pGUID )
289                         g_pCurrentDriver = pNewDriver;
290         }
291         else
292                 // Driver has no devices, so delete it
293                 delete pNewDriver;
294
295     pD3D->Release();
296     g_pDD->Release();
297     return DDENUMRET_OK;
298 }
299
300
301
302
303 //-----------------------------------------------------------------------------
304 // Name: DirectDrawEnumCallback()
305 // Desc: Non-mulitmon version of the ddraw enumeration callback
306 //-----------------------------------------------------------------------------
307 static BOOL WINAPI DirectDrawEnumCallback( GUID FAR* pGUID, LPSTR strDesc,
308                                            LPSTR strName, VOID* )
309 {
310         return DirectDrawEnumCallbackEx( pGUID, strDesc, strName, NULL, NULL );
311 }
312
313
314
315
316 //-----------------------------------------------------------------------------
317 // Name: D3DEnum_FreeResources()
318 // Desc: Frees all resources used for driver enumeration
319 //-----------------------------------------------------------------------------
320 VOID D3DEnum_FreeResources()
321 {
322     // Loop through each driver, and delete everything
323     while( g_pFirstDriver )
324     {
325         D3DEnum_DriverInfo* pDriverVictim = g_pFirstDriver;
326         g_pFirstDriver = g_pFirstDriver->pNext;
327
328         while( pDriverVictim->pFirstDevice )
329         {
330             D3DEnum_DeviceInfo* pDeviceVictim = pDriverVictim->pFirstDevice;
331             pDriverVictim->pFirstDevice = pDeviceVictim->pNext;
332    
333             while( pDeviceVictim->pFirstMode )
334             {
335                 D3DEnum_ModeInfo* pModeVictim = pDeviceVictim->pFirstMode;
336                 pDeviceVictim->pFirstMode = pModeVictim->pNext;
337                 delete pModeVictim;
338             }
339             delete pDeviceVictim;
340         }
341         delete pDriverVictim;
342     }
343 }
344
345
346
347
348 //-----------------------------------------------------------------------------
349 // Name: RefreshListForDesktopCompatibility()
350 // Desc: Loops through list of devices, and marks a flag for whether the device
351 //       is compatible with the desktop bit depth.
352 //-----------------------------------------------------------------------------
353 static VOID RefreshListForDesktopCompatibility()
354 {
355         // Get the currect display mode description
356         LPDIRECTDRAW  pDD;
357         DDSURFACEDESC ddsd;
358         if( FAILED( DirectDrawCreate( NULL, &pDD, NULL ) ) )
359                 return;
360         ddsd.dwSize = sizeof(DDSURFACEDESC);
361         pDD->GetDisplayMode( &ddsd );
362         pDD->Release();
363
364         // Get the display mode's depth
365         DWORD dwDisplayBPP = ddsd.ddpfPixelFormat.dwRGBBitCount;
366
367         // Loop through the devices, and check if any modes works with the current
368         // display setting
369         for( D3DEnum_DriverInfo* pDriver = g_pFirstDriver; pDriver;
370              pDriver = pDriver->pNext )
371         {
372                 for( D3DEnum_DeviceInfo* pDevice=pDriver->pFirstDevice; pDevice;
373                          pDevice = pDevice->pNext )
374                 {
375                         pDevice->bCompatbileWithDesktop = FALSE;
376
377                         for( D3DEnum_ModeInfo* pMode=pDevice->pFirstMode; pMode;
378                                  pMode = pMode->pNext )
379                         {
380                                 if( pMode->ddsd.ddpfPixelFormat.dwRGBBitCount == dwDisplayBPP )
381                                         pDevice->bCompatbileWithDesktop = TRUE;
382                         }
383                 }
384         }
385 }
386
387
388
389 //-----------------------------------------------------------------------------
390 // Name: D3DEnum_EnumerateDevices()
391 // Desc: Enumerates all drivers, devices, and modes. The optional app-supplied
392 //       callback is called for each enumerated device, to confirm that the
393 //       device supports the feature set required by the app.
394 //-----------------------------------------------------------------------------
395 HRESULT D3DEnum_EnumerateDevices( 
396                                                         HRESULT (*AppConfirmFn)(DDCAPS*, D3DDEVICEDESC*) )
397 {
398         g_fnAppConfirmFn     = AppConfirmFn;
399     g_bRefRastEnumerated = FALSE;
400
401         // We need to manually get the procedure address for the DDrawEnumEx()
402         // function.
403         HMODULE hDDrawDLL = GetModuleHandle("DDRAW.DLL");
404         if( NULL == hDDrawDLL )
405         {
406                 DEBUG_MSG( TEXT("Can't load DDRAW.DLL!") );
407                 return D3DENUMERR_NODIRECTDRAW;
408         }
409
410         // Find the DDraw enumeration function, and call it
411         LPDIRECTDRAWENUMERATEEX pDDrawEnumFn = (LPDIRECTDRAWENUMERATEEX)
412                              GetProcAddress( hDDrawDLL, "DirectDrawEnumerateExA" );
413
414         if( pDDrawEnumFn )
415                 pDDrawEnumFn( DirectDrawEnumCallbackEx, NULL,
416                                           DDENUM_ATTACHEDSECONDARYDEVICES |
417                                           DDENUM_DETACHEDSECONDARYDEVICES |
418                                           DDENUM_NONDISPLAYDEVICES );
419         else
420         DirectDrawEnumerate( DirectDrawEnumCallback, NULL );
421
422         // Select a driver. Ask for a hardware device that renders in a window
423         return D3DEnum_SelectDefaultDriver( NULL );
424 }
425
426
427
428
429 //-----------------------------------------------------------------------------
430 // Name: D3DEnum_SelectDefaultDriver()
431 // Desc: Picks a default driver according to the passed in flags.
432 //-----------------------------------------------------------------------------
433 HRESULT D3DEnum_SelectDefaultDriver( DWORD dwFlags )
434 {
435         // Refresh the list of devices to mark which devices (if any) are
436         // compatible with the current desktop (ie. can render in a window).
437         RefreshListForDesktopCompatibility();
438
439         // If a specific driver was requested, perform that search here
440         if( dwFlags & 0x0000003c )
441         {
442                 for( D3DEnum_DriverInfo* pDriver = g_pFirstDriver; pDriver;
443                          pDriver = pDriver->pNext )
444                 {
445                         for( D3DEnum_DeviceInfo* pDevice = pDriver->pFirstDevice; pDevice;
446                                  pDevice = pDevice->pNext )
447                         {
448                                 BOOL bFound = FALSE;
449
450                             if( IsEqualGUID( *pDevice->pGUID, IID_IDirect3DRGBDevice ) )
451                                 {
452                                         if( dwFlags & D3DENUM_RGBEMULATION )
453                                                 bFound = TRUE;
454                                 }
455                             else if( IsEqualGUID( *pDevice->pGUID, IID_IDirect3DRefDevice ) )
456                                 {
457                                         if( dwFlags & D3DENUM_REFERENCERAST )
458                                                 bFound = TRUE;
459                                 }
460                                 else
461                                 {
462                                         if( dwFlags & D3DENUM_PRIMARYHAL )
463                                                 if( pDriver == g_pFirstDriver )
464                                                         bFound = TRUE;
465                                         if( dwFlags & D3DENUM_SECONDARYHAL )
466                                                 if( pDriver != g_pFirstDriver )
467                                                         bFound = TRUE;
468                                 }
469                                 
470                                 if( bFound )
471                                 {
472                                         g_pCurrentDriver = pDriver;
473                                         g_pCurrentDriver->pCurrentDevice = pDevice;
474                                         return S_OK;
475                                 }
476                         }
477                 }
478                 return D3DENUMERR_NOTFOUND;
479         }
480
481         // Do 4 passes, looping through drivers, devices and modes. The 1st pass
482         // searches for hardware. The 2nd pass looks for software devices. The
483         // final two passes allow fullscreen modes.
484         for( WORD pass=0; pass<4; pass++ )
485         {
486                 BOOL bSeekHardware = ( pass & 0x1 ) ? FALSE : TRUE;
487                 BOOL bSeekWindowed = ( pass & 0x2 ) ? FALSE : TRUE;
488                 
489                 // Skip the passes we aren't allowing
490                 if( (TRUE==bSeekHardware) && (dwFlags&D3DENUM_SOFTWAREONLY) )                   
491                         continue;
492                 if( (TRUE==bSeekWindowed) && (dwFlags&D3DENUM_FULLSCREENONLY) )                 
493                         continue;
494
495                 for( D3DEnum_DriverInfo* pDriver = g_pFirstDriver; pDriver;
496                      pDriver = pDriver->pNext )
497                 {
498                         DDCAPS* pCaps = &pDriver->ddDriverCaps;
499
500                         if( bSeekWindowed )
501                                 if( 0 == ( pCaps->dwCaps2 & DDCAPS2_CANRENDERWINDOWED ) )
502                                         continue;
503
504                         for( D3DEnum_DeviceInfo* pDevice = pDriver->pFirstDevice; pDevice;
505                              pDevice = pDevice->pNext )
506                         {
507                                 if( bSeekHardware != pDevice->bIsHardware )
508                                         continue;
509                                 if( bSeekWindowed && FALSE == pDevice->bCompatbileWithDesktop )
510                                         continue;
511
512                                 pDevice->bWindowed = bSeekWindowed;
513                                 g_pCurrentDriver   = pDriver;
514                                 g_pCurrentDriver->pCurrentDevice = pDevice;
515
516                                 return S_OK;
517                         }
518                 }
519         }
520
521         // No compatible devices were found. Return an error code
522     if( FALSE == g_bDevicesEnumerated )
523                 return D3DENUMERR_ENUMERATIONFAILED; // Enumeration really did fail
524     if( FALSE == g_bRefRastEnumerated )
525                 return D3DENUMERR_SUGGESTREFRAST;    // Suggest enabling the RefRast
526         
527         return D3DENUMERR_NOCOMPATIBLEDEVICES;
528 }
529
530
531
532
533 //-----------------------------------------------------------------------------
534 // Name: D3DEnum_UserDlgSelectDriver()
535 // Desc: Displays a dialog box for the user to select a driver/device/mode.
536 //       The return values are akin to the Windows DialogBox() function.
537 //-----------------------------------------------------------------------------
538 INT D3DEnum_UserDlgSelectDriver( HWND hwndParent, BOOL bCurrentlyWindowed )
539 {
540         INT nResult = -1;
541
542     // Check in case drivers weren't properly enumerated beforehand.
543     if( NULL == g_pCurrentDriver )
544         return -1;
545
546         // Refresh the list of devices to mark which devices (if any) are
547         // compatible with the current desktop (ie. can render in a window).
548         RefreshListForDesktopCompatibility();
549
550         // Match the current windowed-vs-fullscreen state
551         g_pCurrentDriver->pCurrentDevice->bWindowed = bCurrentlyWindowed;
552
553     // Pop up a dialog box for the user's choice of driver/device/mode
554     HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndParent, 
555                                                     GWL_HINSTANCE );
556
557     // Create dynamic dialog template
558     DLGTEMPLATE* pDlgSelect = _BuildDriverSelectTemplate();
559     if( pDlgSelect )
560         {
561             // Create dialog box from template
562                 nResult = DialogBoxIndirectParam( hInstance, pDlgSelect, hwndParent,
563                                           (DLGPROC)_DriverSelectProc, 0L );
564             delete pDlgSelect;
565         }
566
567     return nResult;
568 }
569
570
571
572
573 //-----------------------------------------------------------------------------
574 // Name: D3DEnum_GetSelectedDriver()
575 // Desc: Returns the currently selected driver, device, and display mode
576 //-----------------------------------------------------------------------------
577 HRESULT D3DEnum_GetSelectedDriver( LPGUID* ppDriverGUID, LPGUID* ppDeviceGUID, 
578                                    LPDDSURFACEDESC2* ppddsd, BOOL* pbWindowed,
579                                                                    BOOL* pbIsHardware )
580
581 {
582     // Check parans
583     if( (!ppDriverGUID) || (!ppDeviceGUID) )
584         return E_INVALIDARG;
585
586     // Abort if things weren't setup correctly
587     if( NULL == g_pCurrentDriver )
588         return D3DENUMERR_ENUMERATIONFAILED;
589
590     // Copy the driver and device GUID ptrs
591     (*ppDriverGUID) = g_pCurrentDriver->pGUID;
592     (*ppDeviceGUID) = g_pCurrentDriver->pCurrentDevice->pGUID;
593         
594         if( ppddsd )
595                 (*ppddsd) = &g_pCurrentDriver->pCurrentDevice->pCurrentMode->ddsd;
596         if( pbWindowed )
597                 (*pbWindowed) = g_pCurrentDriver->pCurrentDevice->bWindowed;
598         if( pbIsHardware )
599                 (*pbIsHardware) = g_pCurrentDriver->pCurrentDevice->bIsHardware;
600
601         return S_OK;
602 }
603
604
605
606
607 //-----------------------------------------------------------------------------
608 // Name: D3DEnum_GetSelectedDriver()
609 // Desc: Returns the currently selected driver, device, and display mode
610 //-----------------------------------------------------------------------------
611 HRESULT D3DEnum_GetSelectedDriver( D3DEnum_DriverInfo** ppDriverInfo,
612                                                                    D3DEnum_DeviceInfo** ppDeviceInfo )
613
614 {
615     // Abort if things weren't setup correctly
616     if( NULL == g_pCurrentDriver )
617         return D3DENUMERR_ENUMERATIONFAILED;
618
619     // Copy the driver and device info ptrs
620     if( ppDriverInfo ) *ppDriverInfo = g_pCurrentDriver;
621     if( ppDeviceInfo ) *ppDeviceInfo = g_pCurrentDriver->pCurrentDevice;
622         
623         return S_OK;
624 }
625
626
627
628
629 //-----------------------------------------------------------------------------
630 // Name: D3DEnum_GetFirstDriver()
631 // Desc: Returns a ptr to the first DriverInfo structure in the list.
632 //-----------------------------------------------------------------------------
633 D3DEnum_DriverInfo* D3DEnum_GetFirstDriver()
634 {
635     return g_pFirstDriver;
636 }
637
638
639
640
641