1 //--------------------------------------------------------------------------------------
2 // File: DXUTEnum.cpp
3 //
4 // Enumerates D3D adapters, devices, modes, etc.
5 //
6 // Copyright (c) Microsoft Corporation. All rights reserved.
7 //--------------------------------------------------------------------------------------
8 #include "dxstdafx.h"
9 #undef min // use __min instead
10 #undef max // use __max instead
11 
12 
13 //--------------------------------------------------------------------------------------
14 // Forward declarations
15 //--------------------------------------------------------------------------------------
16 static int __cdecl SortModesCallback( const void* arg1, const void* arg2 );
17 UINT DXUTStencilBits( D3DFORMAT fmt );
18 UINT DXUTDepthBits( D3DFORMAT fmt );
19 UINT DXUTAlphaChannelBits( D3DFORMAT fmt );
20 UINT DXUTColorChannelBits( D3DFORMAT fmt );
DXUTGetEnumeration()21 CD3DEnumeration* DXUTGetEnumeration()
22 {
23     // Using an accessor function gives control of the construction order
24     static CD3DEnumeration d3denum;
25     return &d3denum;
26 }
27 
28 
29 //--------------------------------------------------------------------------------------
CD3DEnumeration()30 CD3DEnumeration::CD3DEnumeration()
31 {
32     m_pD3D = NULL;
33     m_IsDeviceAcceptableFunc = NULL;
34     m_pIsDeviceAcceptableFuncUserContext = NULL;
35     m_bRequirePostPixelShaderBlending = true;
36 
37     m_nMinWidth = 640;
38     m_nMinHeight = 480;
39     m_nMaxWidth = UINT_MAX;
40     m_nMaxHeight = UINT_MAX;
41 
42     m_nRefreshMin = 0;
43     m_nRefreshMax = UINT_MAX;
44 
45     m_nMultisampleQualityMax = 0xFFFF;
46 
47     ResetPossibleDepthStencilFormats();
48     ResetPossibleMultisampleTypeList();
49     ResetPossiblePresentIntervalList();
50     SetPossibleVertexProcessingList( true, true, true, false );
51 }
52 
53 
54 //--------------------------------------------------------------------------------------
~CD3DEnumeration()55 CD3DEnumeration::~CD3DEnumeration()
56 {
57     ClearAdapterInfoList();
58 }
59 
60 
61 
62 //--------------------------------------------------------------------------------------
63 // Enumerates available D3D adapters, devices, modes, etc.
64 //--------------------------------------------------------------------------------------
Enumerate(IDirect3D9 * pD3D,LPDXUTCALLBACKISDEVICEACCEPTABLE IsDeviceAcceptableFunc,void * pIsDeviceAcceptableFuncUserContext)65 HRESULT CD3DEnumeration::Enumerate( IDirect3D9* pD3D,
66                                     LPDXUTCALLBACKISDEVICEACCEPTABLE IsDeviceAcceptableFunc,
67                                     void* pIsDeviceAcceptableFuncUserContext )
68 {
69     if( pD3D == NULL )
70     {
71         pD3D = DXUTGetD3DObject();
72         if( pD3D == NULL )
73             return DXUTERR_NODIRECT3D;
74     }
75 
76     m_pD3D = pD3D;
77     m_IsDeviceAcceptableFunc = IsDeviceAcceptableFunc;
78     m_pIsDeviceAcceptableFuncUserContext = pIsDeviceAcceptableFuncUserContext;
79 
80     HRESULT hr;
81     ClearAdapterInfoList();
82     CGrowableArray<D3DFORMAT> adapterFormatList;
83 
84     const D3DFORMAT allowedAdapterFormatArray[] =
85     {
86         D3DFMT_X8R8G8B8,
87         D3DFMT_X1R5G5B5,
88         D3DFMT_R5G6B5,
89         D3DFMT_A2R10G10B10
90     };
91     const UINT allowedAdapterFormatArrayCount  = sizeof(allowedAdapterFormatArray) / sizeof(allowedAdapterFormatArray[0]);
92 
93     UINT numAdapters = pD3D->GetAdapterCount();
94     for (UINT adapterOrdinal = 0; adapterOrdinal < numAdapters; adapterOrdinal++)
95     {
96         CD3DEnumAdapterInfo* pAdapterInfo = new CD3DEnumAdapterInfo;
97         if( pAdapterInfo == NULL )
98             return E_OUTOFMEMORY;
99 
100         pAdapterInfo->AdapterOrdinal = adapterOrdinal;
101         pD3D->GetAdapterIdentifier(adapterOrdinal, 0, &pAdapterInfo->AdapterIdentifier);
102 
103         // Get list of all display modes on this adapter.
104         // Also build a temporary list of all display adapter formats.
105         adapterFormatList.RemoveAll();
106 
107         for( UINT iFormatList = 0; iFormatList < allowedAdapterFormatArrayCount; iFormatList++ )
108         {
109             D3DFORMAT allowedAdapterFormat = allowedAdapterFormatArray[iFormatList];
110             UINT numAdapterModes = pD3D->GetAdapterModeCount( adapterOrdinal, allowedAdapterFormat );
111             for (UINT mode = 0; mode < numAdapterModes; mode++)
112             {
113                 D3DDISPLAYMODE displayMode;
114                 pD3D->EnumAdapterModes( adapterOrdinal, allowedAdapterFormat, mode, &displayMode );
115 
116                 if( displayMode.Width < m_nMinWidth ||
117                     displayMode.Height < m_nMinHeight ||
118                     displayMode.Width > m_nMaxWidth ||
119                     displayMode.Height > m_nMaxHeight ||
120                     displayMode.RefreshRate < m_nRefreshMin ||
121                     displayMode.RefreshRate > m_nRefreshMax )
122                 {
123                     continue;
124                 }
125 
126                 pAdapterInfo->displayModeList.Add( displayMode );
127 
128                 if( !adapterFormatList.Contains(displayMode.Format) )
129                     adapterFormatList.Add( displayMode.Format );
130             }
131 
132         }
133 
134         D3DDISPLAYMODE displayMode;
135         pD3D->GetAdapterDisplayMode( adapterOrdinal, &displayMode );
136         if( !adapterFormatList.Contains(displayMode.Format) )
137             adapterFormatList.Add( displayMode.Format );
138 
139         // Sort displaymode list
140         ::qsort( pAdapterInfo->displayModeList.GetData(),
141                pAdapterInfo->displayModeList.GetSize(), sizeof( D3DDISPLAYMODE ),
142                SortModesCallback );
143 
144         // Get info for each device on this adapter
145         if( FAILED( EnumerateDevices( pAdapterInfo, &adapterFormatList ) ) )
146         {
147             delete pAdapterInfo;
148             continue;
149         }
150 
151         // If at least one device on this adapter is available and compatible
152         // with the app, add the adapterInfo to the list
153         if( pAdapterInfo->deviceInfoList.GetSize() > 0 )
154         {
155             hr = m_AdapterInfoList.Add( pAdapterInfo );
156             if( FAILED(hr) )
157                 return hr;
158         } else
159             delete pAdapterInfo;
160     }
161 
162     bool bUniqueDesc = true;
163     CD3DEnumAdapterInfo* pAdapterInfo;
164     for( int i=0; i<m_AdapterInfoList.GetSize(); i++ )
165     {
166         CD3DEnumAdapterInfo* pAdapterInfo1 = m_AdapterInfoList.GetAt(i);
167 
168         for( int j=i+1; j<m_AdapterInfoList.GetSize(); j++ )
169         {
170             CD3DEnumAdapterInfo* pAdapterInfo2 = m_AdapterInfoList.GetAt(j);
171             if( _stricmp( pAdapterInfo1->AdapterIdentifier.Description,
172                           pAdapterInfo2->AdapterIdentifier.Description ) == 0 )
173             {
174                 bUniqueDesc = false;
175                 break;
176             }
177         }
178 
179         if( !bUniqueDesc )
180             break;
181     }
182 
183     for( int i=0; i<m_AdapterInfoList.GetSize(); i++ )
184     {
185         pAdapterInfo = m_AdapterInfoList.GetAt(i);
186 
187         MultiByteToWideChar( CP_ACP, 0,
188                              pAdapterInfo->AdapterIdentifier.Description, -1,
189                              pAdapterInfo->szUniqueDescription, 100 );
190         pAdapterInfo->szUniqueDescription[100] = 0;
191 
192         if( !bUniqueDesc )
193         {
194             WCHAR sz[100];
195             StringCchPrintf( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal );
196             StringCchCat( pAdapterInfo->szUniqueDescription, 256, sz );
197 
198         }
199     }
200 
201     return S_OK;
202 }
203 
204 
205 
206 //--------------------------------------------------------------------------------------
207 // Enumerates D3D devices for a particular adapter.
208 //--------------------------------------------------------------------------------------
EnumerateDevices(CD3DEnumAdapterInfo * pAdapterInfo,CGrowableArray<D3DFORMAT> * pAdapterFormatList)209 HRESULT CD3DEnumeration::EnumerateDevices( CD3DEnumAdapterInfo* pAdapterInfo, CGrowableArray<D3DFORMAT>* pAdapterFormatList )
210 {
211     HRESULT hr;
212 
213     const D3DDEVTYPE devTypeArray[] =
214     {
215         D3DDEVTYPE_HAL,
216         D3DDEVTYPE_SW,
217         D3DDEVTYPE_REF
218     };
219     const UINT devTypeArrayCount = sizeof(devTypeArray) / sizeof(devTypeArray[0]);
220 
221     // Enumerate each Direct3D device type
222     for( UINT iDeviceType = 0; iDeviceType < devTypeArrayCount; iDeviceType++ )
223     {
224         CD3DEnumDeviceInfo* pDeviceInfo = new CD3DEnumDeviceInfo;
225         if( pDeviceInfo == NULL )
226             return E_OUTOFMEMORY;
227 
228         // Fill struct w/ AdapterOrdinal and D3DDEVTYPE
229         pDeviceInfo->DeviceType = devTypeArray[iDeviceType];
230 
231         // Store device caps
232         if( FAILED( hr = m_pD3D->GetDeviceCaps( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType,
233                                                 &pDeviceInfo->Caps ) ) )
234         {
235             delete pDeviceInfo;
236             continue;
237         }
238 
239         // Create a temp device to verify that it is really possible to create a REF device
240         // [the developer DirectX redist has to be installed]
241         D3DDISPLAYMODE Mode;
242         m_pD3D->GetAdapterDisplayMode(0, &Mode);
243         D3DPRESENT_PARAMETERS pp;
244         ZeroMemory( &pp, sizeof(D3DPRESENT_PARAMETERS) );
245         pp.BackBufferWidth  = 1;
246         pp.BackBufferHeight = 1;
247         pp.BackBufferFormat = Mode.Format;
248         pp.BackBufferCount  = 1;
249         pp.SwapEffect       = D3DSWAPEFFECT_COPY;
250         pp.Windowed         = TRUE;
251         pp.hDeviceWindow    = DXUTGetHWNDFocus();
252         IDirect3DDevice9 *pDevice = NULL;
253         if( FAILED( hr = m_pD3D->CreateDevice( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType, DXUTGetHWNDFocus(),
254                                           D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &pDevice ) ) )
255         {
256             if( hr == D3DERR_NOTAVAILABLE )
257             {
258                 delete pDeviceInfo;
259                 continue;
260             }
261         }
262         SAFE_RELEASE( pDevice );
263 
264         // Get info for each devicecombo on this device
265         if( FAILED( hr = EnumerateDeviceCombos( pAdapterInfo, pDeviceInfo, pAdapterFormatList ) ) )
266         {
267             delete pDeviceInfo;
268             continue;
269         }
270 
271         // If at least one devicecombo for this device is found,
272         // add the deviceInfo to the list
273         if (pDeviceInfo->deviceSettingsComboList.GetSize() > 0 )
274             pAdapterInfo->deviceInfoList.Add( pDeviceInfo );
275         else
276             delete pDeviceInfo;
277     }
278 
279     return S_OK;
280 }
281 
282 
283 
284 //--------------------------------------------------------------------------------------
285 // Enumerates DeviceCombos for a particular device.
286 //--------------------------------------------------------------------------------------
EnumerateDeviceCombos(CD3DEnumAdapterInfo * pAdapterInfo,CD3DEnumDeviceInfo * pDeviceInfo,CGrowableArray<D3DFORMAT> * pAdapterFormatList)287 HRESULT CD3DEnumeration::EnumerateDeviceCombos( CD3DEnumAdapterInfo* pAdapterInfo, CD3DEnumDeviceInfo* pDeviceInfo, CGrowableArray<D3DFORMAT>* pAdapterFormatList )
288 {
289     const D3DFORMAT backBufferFormatArray[] =
290     {
291         D3DFMT_A8R8G8B8,
292         D3DFMT_X8R8G8B8,
293         D3DFMT_A2R10G10B10,
294         D3DFMT_R5G6B5,
295         D3DFMT_A1R5G5B5,
296         D3DFMT_X1R5G5B5
297     };
298     const UINT backBufferFormatArrayCount = sizeof(backBufferFormatArray) / sizeof(backBufferFormatArray[0]);
299 
300     // See which adapter formats are supported by this device
301     for( int iFormat=0; iFormat<pAdapterFormatList->GetSize(); iFormat++ )
302     {
303         D3DFORMAT adapterFormat = pAdapterFormatList->GetAt(iFormat);
304 
305         for( UINT iBackBufferFormat = 0; iBackBufferFormat < backBufferFormatArrayCount; iBackBufferFormat++ )
306         {
307             D3DFORMAT backBufferFormat = backBufferFormatArray[iBackBufferFormat];
308 
309             for( int nWindowed = 0; nWindowed < 2; nWindowed++)
310             {
311                 if( !nWindowed && pAdapterInfo->displayModeList.GetSize() == 0 )
312                     continue;
313 
314                 if (FAILED( m_pD3D->CheckDeviceType( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType,
315                                                      adapterFormat, backBufferFormat, nWindowed )))
316                 {
317                     continue;
318                 }
319 
320                 if( m_bRequirePostPixelShaderBlending )
321                 {
322                     // If the backbuffer format doesn't support D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
323                     // then alpha test, pixel fog, render-target blending, color write enable, and dithering.
324                     // are not supported.
325                     if( FAILED( m_pD3D->CheckDeviceFormat( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType,
326                                                            adapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
327                                                            D3DRTYPE_TEXTURE, backBufferFormat ) ) )
328                     {
329                         continue;
330                     }
331                 }
332 
333                 // If an application callback function has been provided, make sure this device
334                 // is acceptable to the app.
335                 if( m_IsDeviceAcceptableFunc != NULL )
336                 {
337                     if( !m_IsDeviceAcceptableFunc( &pDeviceInfo->Caps, adapterFormat, backBufferFormat, FALSE != nWindowed, m_pIsDeviceAcceptableFuncUserContext ) )
338                         continue;
339                 }
340 
341                 // At this point, we have an adapter/device/adapterformat/backbufferformat/iswindowed
342                 // DeviceCombo that is supported by the system and acceptable to the app. We still
343                 // need to find one or more suitable depth/stencil buffer format,
344                 // multisample type, and present interval.
345                 CD3DEnumDeviceSettingsCombo* pDeviceCombo = new CD3DEnumDeviceSettingsCombo;
346                 if( pDeviceCombo == NULL )
347                     return E_OUTOFMEMORY;
348 
349                 pDeviceCombo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal;
350                 pDeviceCombo->DeviceType = pDeviceInfo->DeviceType;
351                 pDeviceCombo->AdapterFormat = adapterFormat;
352                 pDeviceCombo->BackBufferFormat = backBufferFormat;
353                 pDeviceCombo->Windowed = (nWindowed != 0);
354 
355                 BuildDepthStencilFormatList( pDeviceCombo );
356                 BuildMultiSampleTypeList( pDeviceCombo );
357                 if (pDeviceCombo->multiSampleTypeList.GetSize() == 0)
358                 {
359                     delete pDeviceCombo;
360                     continue;
361                 }
362                 BuildDSMSConflictList( pDeviceCombo );
363                 BuildPresentIntervalList(pDeviceInfo, pDeviceCombo );
364                 pDeviceCombo->pAdapterInfo = pAdapterInfo;
365                 pDeviceCombo->pDeviceInfo = pDeviceInfo;
366 
367                 pDeviceInfo->deviceSettingsComboList.Add( pDeviceCombo );
368 
369             }
370         }
371     }
372 
373     return S_OK;
374 }
375 
376 
377 
378 //--------------------------------------------------------------------------------------
379 // Adds all depth/stencil formats that are compatible with the device
380 //       and app to the given D3DDeviceCombo.
381 //--------------------------------------------------------------------------------------
BuildDepthStencilFormatList(CD3DEnumDeviceSettingsCombo * pDeviceCombo)382 void CD3DEnumeration::BuildDepthStencilFormatList( CD3DEnumDeviceSettingsCombo* pDeviceCombo )
383 {
384     D3DFORMAT depthStencilFmt;
385     for( int idsf = 0; idsf < m_DepthStecilPossibleList.GetSize(); idsf++ )
386     {
387         depthStencilFmt = m_DepthStecilPossibleList.GetAt(idsf);
388         if (SUCCEEDED(m_pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal,
389                 pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat,
390                 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFmt)))
391         {
392             if (SUCCEEDED(m_pD3D->CheckDepthStencilMatch(pDeviceCombo->AdapterOrdinal,
393                     pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat,
394                     pDeviceCombo->BackBufferFormat, depthStencilFmt)))
395             {
396                 pDeviceCombo->depthStencilFormatList.Add( depthStencilFmt );
397             }
398         }
399     }
400 }
401 
402 
403 
404 
405 //--------------------------------------------------------------------------------------
406 // Adds all multisample types that are compatible with the device and app to
407 //       the given D3DDeviceCombo.
408 //--------------------------------------------------------------------------------------
BuildMultiSampleTypeList(CD3DEnumDeviceSettingsCombo * pDeviceCombo)409 void CD3DEnumeration::BuildMultiSampleTypeList( CD3DEnumDeviceSettingsCombo* pDeviceCombo )
410 {
411     D3DMULTISAMPLE_TYPE msType;
412     DWORD msQuality;
413     for( int imst = 0; imst < m_MultiSampleTypeList.GetSize(); imst++ )
414     {
415         msType = m_MultiSampleTypeList.GetAt(imst);
416         if( SUCCEEDED( m_pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal,
417                 pDeviceCombo->DeviceType, pDeviceCombo->BackBufferFormat,
418                 pDeviceCombo->Windowed, msType, &msQuality ) ) )
419         {
420             pDeviceCombo->multiSampleTypeList.Add( msType );
421             if( msQuality > m_nMultisampleQualityMax+1 )
422                 msQuality = m_nMultisampleQualityMax+1;
423             pDeviceCombo->multiSampleQualityList.Add( msQuality );
424         }
425     }
426 }
427 
428 
429 
430 
431 //--------------------------------------------------------------------------------------
432 // Find any conflicts between the available depth/stencil formats and
433 //       multisample types.
434 //--------------------------------------------------------------------------------------
BuildDSMSConflictList(CD3DEnumDeviceSettingsCombo * pDeviceCombo)435 void CD3DEnumeration::BuildDSMSConflictList( CD3DEnumDeviceSettingsCombo* pDeviceCombo )
436 {
437     CD3DEnumDSMSConflict DSMSConflict;
438 
439     for( int iDS=0; iDS<pDeviceCombo->depthStencilFormatList.GetSize(); iDS++ )
440     {
441         D3DFORMAT dsFmt = pDeviceCombo->depthStencilFormatList.GetAt(iDS);
442 
443         for( int iMS=0; iMS<pDeviceCombo->multiSampleTypeList.GetSize(); iMS++ )
444         {
445             D3DMULTISAMPLE_TYPE msType = pDeviceCombo->multiSampleTypeList.GetAt(iMS);
446 
447             if( FAILED( m_pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType,
448                                                             dsFmt, pDeviceCombo->Windowed, msType, NULL ) ) )
449             {
450                 DSMSConflict.DSFormat = dsFmt;
451                 DSMSConflict.MSType = msType;
452                 pDeviceCombo->DSMSConflictList.Add( DSMSConflict );
453             }
454         }
455     }
456 }
457 
458 
459 
460 //--------------------------------------------------------------------------------------
461 // Adds all present intervals that are compatible with the device and app
462 //       to the given D3DDeviceCombo.
463 //--------------------------------------------------------------------------------------
BuildPresentIntervalList(CD3DEnumDeviceInfo * pDeviceInfo,CD3DEnumDeviceSettingsCombo * pDeviceCombo)464 void CD3DEnumeration::BuildPresentIntervalList( CD3DEnumDeviceInfo* pDeviceInfo,
465                                                 CD3DEnumDeviceSettingsCombo* pDeviceCombo )
466 {
467     UINT pi;
468     for( int ipi = 0; ipi < m_PresentIntervalList.GetSize(); ipi++ )
469     {
470         pi = m_PresentIntervalList.GetAt(ipi);
471         if( pDeviceCombo->Windowed )
472         {
473             if( pi == D3DPRESENT_INTERVAL_TWO ||
474                 pi == D3DPRESENT_INTERVAL_THREE ||
475                 pi == D3DPRESENT_INTERVAL_FOUR )
476             {
477                 // These intervals are not supported in windowed mode.
478                 continue;
479             }
480         }
481         // Note that D3DPRESENT_INTERVAL_DEFAULT is zero, so you
482         // can't do a caps check for it -- it is always available.
483         if( pi == D3DPRESENT_INTERVAL_DEFAULT ||
484             (pDeviceInfo->Caps.PresentationIntervals & pi) )
485         {
486             pDeviceCombo->presentIntervalList.Add( pi );
487         }
488     }
489 }
490 
491 
492 
493 //--------------------------------------------------------------------------------------
494 // Release all the allocated CD3DEnumAdapterInfo objects and empty the list
495 //--------------------------------------------------------------------------------------
ClearAdapterInfoList()496 void CD3DEnumeration::ClearAdapterInfoList()
497 {
498     CD3DEnumAdapterInfo* pAdapterInfo;
499     for( int i=0; i<m_AdapterInfoList.GetSize(); i++ )
500     {
501         pAdapterInfo = m_AdapterInfoList.GetAt(i);
502         delete pAdapterInfo;
503     }
504 
505     m_AdapterInfoList.RemoveAll();
506 }
507 
508 
509 
510 //--------------------------------------------------------------------------------------
511 // Call GetAdapterInfoList() after Enumerate() to get a STL vector of
512 //       CD3DEnumAdapterInfo*
513 //--------------------------------------------------------------------------------------
GetAdapterInfoList()514 CGrowableArray<CD3DEnumAdapterInfo*>* CD3DEnumeration::GetAdapterInfoList()
515 {
516     return &m_AdapterInfoList;
517 }
518 
519 
520 
521 //--------------------------------------------------------------------------------------
GetAdapterInfo(UINT AdapterOrdinal)522 CD3DEnumAdapterInfo* CD3DEnumeration::GetAdapterInfo( UINT AdapterOrdinal )
523 {
524     for( int iAdapter=0; iAdapter<m_AdapterInfoList.GetSize(); iAdapter++ )
525     {
526         CD3DEnumAdapterInfo* pAdapterInfo = m_AdapterInfoList.GetAt(iAdapter);
527         if( pAdapterInfo->AdapterOrdinal == AdapterOrdinal )
528             return pAdapterInfo;
529     }
530 
531     return NULL;
532 }
533 
534 
535 //--------------------------------------------------------------------------------------
GetDeviceInfo(UINT AdapterOrdinal,D3DDEVTYPE DeviceType)536 CD3DEnumDeviceInfo* CD3DEnumeration::GetDeviceInfo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType )
537 {
538     CD3DEnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
539     if( pAdapterInfo )
540     {
541         for( int iDeviceInfo=0; iDeviceInfo<pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ )
542         {
543             CD3DEnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt(iDeviceInfo);
544             if( pDeviceInfo->DeviceType == DeviceType )
545                 return pDeviceInfo;
546         }
547     }
548 
549     return NULL;
550 }
551 
552 
553 //--------------------------------------------------------------------------------------
554 //
555 //--------------------------------------------------------------------------------------
GetDeviceSettingsCombo(UINT AdapterOrdinal,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed)556 CD3DEnumDeviceSettingsCombo* CD3DEnumeration::GetDeviceSettingsCombo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed )
557 {
558     CD3DEnumDeviceInfo* pDeviceInfo = GetDeviceInfo( AdapterOrdinal, DeviceType );
559     if( pDeviceInfo )
560     {
561         for( int iDeviceCombo=0; iDeviceCombo<pDeviceInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ )
562         {
563             CD3DEnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt(iDeviceCombo);
564             if( pDeviceSettingsCombo->AdapterFormat == AdapterFormat &&
565                 pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat &&
566                 pDeviceSettingsCombo->Windowed == bWindowed )
567                 return pDeviceSettingsCombo;
568         }
569     }
570 
571     return NULL;
572 }
573 
574 
575 //--------------------------------------------------------------------------------------
576 // Returns the number of color channel bits in the specified D3DFORMAT
577 //--------------------------------------------------------------------------------------
DXUTColorChannelBits(D3DFORMAT fmt)578 UINT DXUTColorChannelBits( D3DFORMAT fmt )
579 {
580     switch( fmt )
581     {
582         case D3DFMT_R8G8B8:
583             return 8;
584         case D3DFMT_A8R8G8B8:
585             return 8;
586         case D3DFMT_X8R8G8B8:
587             return 8;
588         case D3DFMT_R5G6B5:
589             return 5;
590         case D3DFMT_X1R5G5B5:
591             return 5;
592         case D3DFMT_A1R5G5B5:
593             return 5;
594         case D3DFMT_A4R4G4B4:
595             return 4;
596         case D3DFMT_R3G3B2:
597             return 2;
598         case D3DFMT_A8R3G3B2:
599             return 2;
600         case D3DFMT_X4R4G4B4:
601             return 4;
602         case D3DFMT_A2B10G10R10:
603             return 10;
604         case D3DFMT_A8B8G8R8:
605             return 8;
606         case D3DFMT_A2R10G10B10:
607             return 10;
608         case D3DFMT_A16B16G16R16:
609             return 16;
610         default:
611             return 0;
612     }
613 }
614 
615 
616 
617 
618 //--------------------------------------------------------------------------------------
619 // Returns the number of alpha channel bits in the specified D3DFORMAT
620 //--------------------------------------------------------------------------------------
DXUTAlphaChannelBits(D3DFORMAT fmt)621 UINT DXUTAlphaChannelBits( D3DFORMAT fmt )
622 {
623     switch( fmt )
624     {
625         case D3DFMT_R8G8B8:
626             return 0;
627         case D3DFMT_A8R8G8B8:
628             return 8;
629         case D3DFMT_X8R8G8B8:
630             return 0;
631         case D3DFMT_R5G6B5:
632             return 0;
633         case D3DFMT_X1R5G5B5:
634             return 0;
635         case D3DFMT_A1R5G5B5:
636             return 1;
637         case D3DFMT_A4R4G4B4:
638             return 4;
639         case D3DFMT_R3G3B2:
640             return 0;
641         case D3DFMT_A8R3G3B2:
642             return 8;
643         case D3DFMT_X4R4G4B4:
644             return 0;
645         case D3DFMT_A2B10G10R10:
646             return 2;
647         case D3DFMT_A8B8G8R8:
648             return 8;
649         case D3DFMT_A2R10G10B10:
650             return 2;
651         case D3DFMT_A16B16G16R16:
652             return 16;
653         default:
654             return 0;
655     }
656 }
657 
658 
659 
660 
661 //--------------------------------------------------------------------------------------
662 // Returns the number of depth bits in the specified D3DFORMAT
663 //--------------------------------------------------------------------------------------
DXUTDepthBits(D3DFORMAT fmt)664 UINT DXUTDepthBits( D3DFORMAT fmt )
665 {
666     switch( fmt )
667     {
668         case D3DFMT_D32F_LOCKABLE:
669         case D3DFMT_D32:
670             return 32;
671 
672         case D3DFMT_D24X8:
673         case D3DFMT_D24S8:
674         case D3DFMT_D24X4S4:
675         case D3DFMT_D24FS8:
676             return 24;
677 
678         case D3DFMT_D16_LOCKABLE:
679         case D3DFMT_D16:
680             return 16;
681 
682         case D3DFMT_D15S1:
683             return 15;
684 
685         default:
686             return 0;
687     }
688 }
689 
690 
691 
692 
693 //--------------------------------------------------------------------------------------
694 // Returns the number of stencil bits in the specified D3DFORMAT
695 //--------------------------------------------------------------------------------------
DXUTStencilBits(D3DFORMAT fmt)696 UINT DXUTStencilBits( D3DFORMAT fmt )
697 {
698     switch( fmt )
699     {
700         case D3DFMT_D16_LOCKABLE:
701         case D3DFMT_D16:
702         case D3DFMT_D32F_LOCKABLE:
703         case D3DFMT_D32:
704         case D3DFMT_D24X8:
705             return 0;
706 
707         case D3DFMT_D15S1:
708             return 1;
709 
710         case D3DFMT_D24X4S4:
711             return 4;
712 
713         case D3DFMT_D24S8:
714         case D3DFMT_D24FS8:
715             return 8;
716 
717         default:
718             return 0;
719     }
720 }
721 
722 
723 
724 //--------------------------------------------------------------------------------------
725 // Used to sort D3DDISPLAYMODEs
726 //--------------------------------------------------------------------------------------
SortModesCallback(const void * arg1,const void * arg2)727 static int __cdecl SortModesCallback( const void* arg1, const void* arg2 )
728 {
729     D3DDISPLAYMODE* pdm1 = (D3DDISPLAYMODE*)arg1;
730     D3DDISPLAYMODE* pdm2 = (D3DDISPLAYMODE*)arg2;
731 
732     if (pdm1->Width > pdm2->Width)
733         return 1;
734     if (pdm1->Width < pdm2->Width)
735         return -1;
736     if (pdm1->Height > pdm2->Height)
737         return 1;
738     if (pdm1->Height < pdm2->Height)
739         return -1;
740     if (pdm1->Format > pdm2->Format)
741         return 1;
742     if (pdm1->Format < pdm2->Format)
743         return -1;
744     if (pdm1->RefreshRate > pdm2->RefreshRate)
745         return 1;
746     if (pdm1->RefreshRate < pdm2->RefreshRate)
747         return -1;
748     return 0;
749 }
750 
751 
752 
753 //--------------------------------------------------------------------------------------
~CD3DEnumAdapterInfo(void)754 CD3DEnumAdapterInfo::~CD3DEnumAdapterInfo( void )
755 {
756     CD3DEnumDeviceInfo* pDeviceInfo;
757     for( int i=0; i<deviceInfoList.GetSize(); i++ )
758     {
759         pDeviceInfo = deviceInfoList.GetAt(i);
760         delete pDeviceInfo;
761     }
762     deviceInfoList.RemoveAll();
763 }
764 
765 
766 
767 
768 //--------------------------------------------------------------------------------------
~CD3DEnumDeviceInfo(void)769 CD3DEnumDeviceInfo::~CD3DEnumDeviceInfo( void )
770 {
771     CD3DEnumDeviceSettingsCombo* pDeviceCombo;
772     for( int i=0; i<deviceSettingsComboList.GetSize(); i++ )
773     {
774         pDeviceCombo = deviceSettingsComboList.GetAt(i);
775         delete pDeviceCombo;
776     }
777     deviceSettingsComboList.RemoveAll();
778 }
779 
780 
781 //--------------------------------------------------------------------------------------
ResetPossibleDepthStencilFormats()782 void CD3DEnumeration::ResetPossibleDepthStencilFormats()
783 {
784     m_DepthStecilPossibleList.RemoveAll();
785     m_DepthStecilPossibleList.Add( D3DFMT_D16 );
786     m_DepthStecilPossibleList.Add( D3DFMT_D15S1 );
787     m_DepthStecilPossibleList.Add( D3DFMT_D24X8 );
788     m_DepthStecilPossibleList.Add( D3DFMT_D24S8 );
789     m_DepthStecilPossibleList.Add( D3DFMT_D24X4S4 );
790     m_DepthStecilPossibleList.Add( D3DFMT_D32 );
791 }
792 
793 
794 //--------------------------------------------------------------------------------------
GetPossibleDepthStencilFormatList()795 CGrowableArray<D3DFORMAT>* CD3DEnumeration::GetPossibleDepthStencilFormatList()
796 {
797     return &m_DepthStecilPossibleList;
798 }
799 
800 
801 //--------------------------------------------------------------------------------------
GetPossibleMultisampleTypeList()802 CGrowableArray<D3DMULTISAMPLE_TYPE>* CD3DEnumeration::GetPossibleMultisampleTypeList()
803 {
804     return &m_MultiSampleTypeList;
805 }
806 
807 
808 //--------------------------------------------------------------------------------------
ResetPossibleMultisampleTypeList()809 void CD3DEnumeration::ResetPossibleMultisampleTypeList()
810 {
811     m_MultiSampleTypeList.RemoveAll();
812     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_NONE );
813     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_NONMASKABLE );
814     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_2_SAMPLES );
815     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_3_SAMPLES );
816     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_4_SAMPLES );
817     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_5_SAMPLES );
818     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_6_SAMPLES );
819     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_7_SAMPLES );
820     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_8_SAMPLES );
821     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_9_SAMPLES );
822     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_10_SAMPLES );
823     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_11_SAMPLES );
824     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_12_SAMPLES );
825     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_13_SAMPLES );
826     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_14_SAMPLES );
827     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_15_SAMPLES );
828     m_MultiSampleTypeList.Add( D3DMULTISAMPLE_16_SAMPLES );
829 }
830 
831 
832 //--------------------------------------------------------------------------------------
GetPossibleVertexProcessingList(bool * pbSoftwareVP,bool * pbHardwareVP,bool * pbPureHarewareVP,bool * pbMixedVP)833 void CD3DEnumeration::GetPossibleVertexProcessingList( bool* pbSoftwareVP, bool* pbHardwareVP, bool* pbPureHarewareVP, bool* pbMixedVP )
834 {
835     *pbSoftwareVP = m_bSoftwareVP;
836     *pbHardwareVP = m_bHardwareVP;
837     *pbPureHarewareVP = m_bPureHarewareVP;
838     *pbMixedVP = m_bMixedVP;
839 }
840 
841 
842 //--------------------------------------------------------------------------------------
SetPossibleVertexProcessingList(bool bSoftwareVP,bool bHardwareVP,bool bPureHarewareVP,bool bMixedVP)843 void CD3DEnumeration::SetPossibleVertexProcessingList( bool bSoftwareVP, bool bHardwareVP, bool bPureHarewareVP, bool bMixedVP )
844 {
845     m_bSoftwareVP = bSoftwareVP;
846     m_bHardwareVP = bHardwareVP;
847     m_bPureHarewareVP = bPureHarewareVP;
848     m_bMixedVP = bMixedVP;
849 }
850 
851 
852 //--------------------------------------------------------------------------------------
GetPossiblePresentIntervalList()853 CGrowableArray<UINT>* CD3DEnumeration::GetPossiblePresentIntervalList()
854 {
855     return &m_PresentIntervalList;
856 }
857 
858 
859 //--------------------------------------------------------------------------------------
ResetPossiblePresentIntervalList()860 void CD3DEnumeration::ResetPossiblePresentIntervalList()
861 {
862     m_PresentIntervalList.RemoveAll();
863     m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_IMMEDIATE );
864     m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_DEFAULT );
865     m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_ONE );
866     m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_TWO );
867     m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_THREE );
868     m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_FOUR );
869 }
870 
871 
872 //--------------------------------------------------------------------------------------
SetResolutionMinMax(UINT nMinWidth,UINT nMinHeight,UINT nMaxWidth,UINT nMaxHeight)873 void CD3DEnumeration::SetResolutionMinMax( UINT nMinWidth, UINT nMinHeight,
874                                            UINT nMaxWidth, UINT nMaxHeight )
875 {
876     m_nMinWidth = nMinWidth;
877     m_nMinHeight = nMinHeight;
878     m_nMaxWidth = nMaxWidth;
879     m_nMaxHeight = nMaxHeight;
880 }
881 
882 
883 //--------------------------------------------------------------------------------------
SetRefreshMinMax(UINT nMin,UINT nMax)884 void CD3DEnumeration::SetRefreshMinMax( UINT nMin, UINT nMax )
885 {
886     m_nRefreshMin = nMin;
887     m_nRefreshMax = nMax;
888 }
889 
890 
891 //--------------------------------------------------------------------------------------
SetMultisampleQualityMax(UINT nMax)892 void CD3DEnumeration::SetMultisampleQualityMax( UINT nMax )
893 {
894     if( nMax > 0xFFFF )
895         nMax = 0xFFFF;
896     m_nMultisampleQualityMax = nMax;
897 }
898 
899