DXUT.cpp
上传用户:junlon
上传日期:2022-01-05
资源大小:39075k
文件大小:227k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. //--------------------------------------------------------------------------------------
  2. // File: DXUT.cpp
  3. //
  4. // Copyright (c) Microsoft Corporation. All rights reserved.
  5. //--------------------------------------------------------------------------------------
  6. #include "dxstdafx.h"
  7. #define DXUT_MIN_WINDOW_SIZE_X 200
  8. #define DXUT_MIN_WINDOW_SIZE_Y 200
  9. #undef min // use __min instead inside this source file
  10. #undef max // use __max instead inside this source file
  11. //--------------------------------------------------------------------------------------
  12. // Thread safety 
  13. //--------------------------------------------------------------------------------------
  14. CRITICAL_SECTION g_cs;  
  15. bool g_bThreadSafe = true;
  16. //--------------------------------------------------------------------------------------
  17. // Automatically enters & leaves the CS upon object creation/deletion
  18. //--------------------------------------------------------------------------------------
  19. class DXUTLock
  20. {
  21. public:
  22.     inline DXUTLock()  { if( g_bThreadSafe ) EnterCriticalSection( &g_cs ); }
  23.     inline ~DXUTLock() { if( g_bThreadSafe ) LeaveCriticalSection( &g_cs ); }
  24. };
  25. //--------------------------------------------------------------------------------------
  26. // Helper macros to build member functions that access member variables with thread safety
  27. //--------------------------------------------------------------------------------------
  28. #define SET_ACCESSOR( x, y )       inline void Set##y( x t )  { DXUTLock l; m_state.m_##y = t; };
  29. #define GET_ACCESSOR( x, y )       inline x Get##y() { DXUTLock l; return m_state.m_##y; };
  30. #define GET_SET_ACCESSOR( x, y )   SET_ACCESSOR( x, y ) GET_ACCESSOR( x, y )
  31. #define SETP_ACCESSOR( x, y )      inline void Set##y( x* t )  { DXUTLock l; m_state.m_##y = *t; };
  32. #define GETP_ACCESSOR( x, y )      inline x* Get##y() { DXUTLock l; return &m_state.m_##y; };
  33. #define GETP_SETP_ACCESSOR( x, y ) SETP_ACCESSOR( x, y ) GETP_ACCESSOR( x, y )
  34. //--------------------------------------------------------------------------------------
  35. // Stores timer callback info
  36. //--------------------------------------------------------------------------------------
  37. struct DXUT_TIMER
  38. {
  39.     LPDXUTCALLBACKTIMER pCallbackTimer;
  40.     void* pCallbackUserContext;
  41.     float fTimeoutInSecs;
  42.     float fCountdown;
  43.     bool  bEnabled;
  44.     UINT  nID;
  45. };
  46. //--------------------------------------------------------------------------------------
  47. // Stores DXUT state and data access is done with thread safety (if g_bThreadSafe==true)
  48. //--------------------------------------------------------------------------------------
  49. class DXUTState
  50. {
  51. protected:
  52.     struct STATE
  53.     {
  54.         IDirect3D9*          m_D3D;                     // the main D3D object
  55.         IDirect3DDevice9*    m_D3DDevice;               // the D3D rendering device
  56.         CD3DEnumeration*     m_D3DEnumeration;          // CD3DEnumeration object
  57.         DXUTDeviceSettings*  m_CurrentDeviceSettings;   // current device settings
  58.         D3DSURFACE_DESC      m_BackBufferSurfaceDesc;   // back buffer surface description
  59.         D3DCAPS9             m_Caps;                    // D3D caps for current device
  60.         HWND  m_HWNDFocus;                  // the main app focus window
  61.         HWND  m_HWNDDeviceFullScreen;       // the main app device window in fullscreen mode
  62.         HWND  m_HWNDDeviceWindowed;         // the main app device window in windowed mode
  63.         HMONITOR m_AdapterMonitor;          // the monitor of the adapter 
  64.         HMENU m_Menu;                       // handle to menu
  65.         UINT m_FullScreenBackBufferWidthAtModeChange;  // back buffer size of fullscreen mode right before switching to windowed mode.  Used to restore to same resolution when toggling back to fullscreen
  66.         UINT m_FullScreenBackBufferHeightAtModeChange; // back buffer size of fullscreen mode right before switching to windowed mode.  Used to restore to same resolution when toggling back to fullscreen
  67.         UINT m_WindowBackBufferWidthAtModeChange;  // back buffer size of windowed mode right before switching to fullscreen mode.  Used to restore to same resolution when toggling back to windowed mode
  68.         UINT m_WindowBackBufferHeightAtModeChange; // back buffer size of windowed mode right before switching to fullscreen mode.  Used to restore to same resolution when toggling back to windowed mode
  69.         DWORD m_WindowedStyleAtModeChange;  // window style
  70.         WINDOWPLACEMENT m_WindowedPlacement; // record of windowed HWND position/show state/etc
  71.         bool  m_TopmostWhileWindowed;       // if true, the windowed HWND is topmost 
  72.         bool  m_Minimized;                  // if true, the HWND is minimized
  73.         bool  m_Maximized;                  // if true, the HWND is maximized
  74.         bool  m_MinimizedWhileFullscreen;   // if true, the HWND is minimized due to a focus switch away when fullscreen mode
  75.         bool  m_IgnoreSizeChange;           // if true, DXUT won't reset the device upon HWND size change
  76.         double m_Time;                      // current time in seconds
  77.         double m_AbsoluteTime;              // absolute time in seconds
  78.         float m_ElapsedTime;                // time elapsed since last frame
  79.         HINSTANCE m_HInstance;              // handle to the app instance
  80.         double m_LastStatsUpdateTime;       // last time the stats were updated
  81.         DWORD m_LastStatsUpdateFrames;      // frames count since last time the stats were updated
  82.         float m_FPS;                        // frames per second
  83.         int   m_CurrentFrameNumber;         // the current frame number
  84.         HHOOK m_KeyboardHook;               // handle to keyboard hook
  85.         bool  m_AllowShortcutKeysWhenFullscreen; // if true, when fullscreen enable shortcut keys (Windows keys, StickyKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut) 
  86.         bool  m_AllowShortcutKeysWhenWindowed;   // if true, when windowed enable shortcut keys (Windows keys, StickyKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut) 
  87.         bool  m_AllowShortcutKeys;          // if true, then shortcut keys are currently disabled (Windows key, etc)
  88.         bool  m_CallDefWindowProc;          // if true, DXUTStaticWndProc will call DefWindowProc for unhandled messages. Applications rendering to a dialog may need to set this to false.
  89.         STICKYKEYS m_StartupStickyKeys;     // StickyKey settings upon startup so they can be restored later
  90.         TOGGLEKEYS m_StartupToggleKeys;     // ToggleKey settings upon startup so they can be restored later
  91.         FILTERKEYS m_StartupFilterKeys;     // FilterKey settings upon startup so they can be restored later
  92.         bool  m_HandleDefaultHotkeys;       // if true, then DXUT will handle some default hotkeys
  93.         bool  m_HandleAltEnter;             // if true, then DXUT will handle Alt-Enter
  94.         bool  m_ShowMsgBoxOnError;          // if true, then msgboxes are displayed upon errors
  95.         bool  m_NoStats;                    // if true, then DXUTGetFrameStats() and DXUTGetDeviceStats() will return blank strings
  96.         bool  m_ClipCursorWhenFullScreen;   // if true, then DXUT will keep the cursor from going outside the window when full screen
  97.         bool  m_ShowCursorWhenFullScreen;   // if true, then DXUT will show a cursor when full screen
  98.         bool  m_ConstantFrameTime;          // if true, then elapsed frame time will always be 0.05f seconds which is good for debugging or automated capture
  99.         float m_TimePerFrame;               // the constant time per frame in seconds, only valid if m_ConstantFrameTime==true
  100.         bool  m_WireframeMode;              // if true, then D3DRS_FILLMODE==D3DFILL_WIREFRAME else D3DRS_FILLMODE==D3DFILL_SOLID 
  101.         bool  m_AutoChangeAdapter;          // if true, then the adapter will automatically change if the window is different monitor
  102.         bool  m_WindowCreatedWithDefaultPositions; // if true, then CW_USEDEFAULT was used and the window should be moved to the right adapter
  103.         int   m_ExitCode;                   // the exit code to be returned to the command line
  104.         bool  m_DXUTInited;                 // if true, then DXUTInit() has succeeded
  105.         bool  m_WindowCreated;              // if true, then DXUTCreateWindow() or DXUTSetWindow() has succeeded
  106.         bool  m_DeviceCreated;              // if true, then DXUTCreateDevice*() or DXUTSetDevice() has succeeded
  107.         bool  m_DXUTInitCalled;             // if true, then DXUTInit() was called
  108.         bool  m_WindowCreateCalled;         // if true, then DXUTCreateWindow() or DXUTSetWindow() was called
  109.         bool  m_DeviceCreateCalled;         // if true, then DXUTCreateDevice*() or DXUTSetDevice() was called
  110.         bool  m_DeviceObjectsCreated;       // if true, then DeviceCreated callback has been called (if non-NULL)
  111.         bool  m_DeviceObjectsReset;         // if true, then DeviceReset callback has been called (if non-NULL)
  112.         bool  m_InsideDeviceCallback;       // if true, then the framework is inside an app device callback
  113.         bool  m_InsideMainloop;             // if true, then the framework is inside the main loop
  114.         bool  m_Active;                     // if true, then the app is the active top level window
  115.         bool  m_TimePaused;                 // if true, then time is paused
  116.         bool  m_RenderingPaused;            // if true, then rendering is paused
  117.         int   m_PauseRenderingCount;        // pause rendering ref count
  118.         int   m_PauseTimeCount;             // pause time ref count
  119.         bool  m_DeviceLost;                 // if true, then the device is lost and needs to be reset
  120.         bool  m_NotifyOnMouseMove;          // if true, include WM_MOUSEMOVE in mousecallback
  121.         bool  m_Automation;                 // if true, automation is enabled
  122.         bool  m_InSizeMove;                 // if true, app is inside a WM_ENTERSIZEMOVE
  123.         UINT  m_TimerLastID;               // last ID of the DXUT timer
  124.         int   m_OverrideAdapterOrdinal;     // if != -1, then override to use this adapter ordinal
  125.         bool  m_OverrideWindowed;           // if true, then force to start windowed
  126.         bool  m_OverrideFullScreen;         // if true, then force to start full screen
  127.         int   m_OverrideStartX;             // if != -1, then override to this X position of the window
  128.         int   m_OverrideStartY;             // if != -1, then override to this Y position of the window
  129.         int   m_OverrideWidth;              // if != 0, then override to this width
  130.         int   m_OverrideHeight;             // if != 0, then override to this height
  131.         bool  m_OverrideForceHAL;           // if true, then force to HAL device (failing if one doesn't exist)
  132.         bool  m_OverrideForceREF;           // if true, then force to REF device (failing if one doesn't exist)
  133.         bool  m_OverrideForcePureHWVP;      // if true, then force to use pure HWVP (failing if device doesn't support it)
  134.         bool  m_OverrideForceHWVP;          // if true, then force to use HWVP (failing if device doesn't support it)
  135.         bool  m_OverrideForceSWVP;          // if true, then force to use SWVP 
  136.         bool  m_OverrideConstantFrameTime;  // if true, then force to constant frame time
  137.         float m_OverrideConstantTimePerFrame; // the constant time per frame in seconds if m_OverrideConstantFrameTime==true
  138.         int   m_OverrideQuitAfterFrame;     // if != 0, then it will force the app to quit after that frame
  139.         int   m_OverrideForceVsync;         // if == 0, then it will force the app to use D3DPRESENT_INTERVAL_IMMEDIATE, if == 1 force use of D3DPRESENT_INTERVAL_DEFAULT
  140.         bool  m_OverrideRelaunchMCE;          // if true, then force relaunch of MCE at exit
  141.         LPDXUTCALLBACKISDEVICEACCEPTABLE    m_IsDeviceAcceptableFunc;   // is device acceptable callback
  142.         LPDXUTCALLBACKMODIFYDEVICESETTINGS  m_ModifyDeviceSettingsFunc; // modify device settings callback
  143.         LPDXUTCALLBACKDEVICECREATED         m_DeviceCreatedFunc;        // device created callback
  144.         LPDXUTCALLBACKDEVICERESET           m_DeviceResetFunc;          // device reset callback
  145.         LPDXUTCALLBACKDEVICELOST            m_DeviceLostFunc;           // device lost callback
  146.         LPDXUTCALLBACKDEVICEDESTROYED       m_DeviceDestroyedFunc;      // device destroyed callback
  147.         LPDXUTCALLBACKFRAMEMOVE             m_FrameMoveFunc;            // frame move callback
  148.         LPDXUTCALLBACKFRAMERENDER           m_FrameRenderFunc;          // frame render callback
  149.         LPDXUTCALLBACKKEYBOARD              m_KeyboardFunc;             // keyboard callback
  150.         LPDXUTCALLBACKMOUSE                 m_MouseFunc;                // mouse callback
  151.         LPDXUTCALLBACKMSGPROC               m_WindowMsgFunc;            // window messages callback
  152.         void*                               m_IsDeviceAcceptableFuncUserContext;   // user context for is device acceptable callback
  153.         void*                               m_ModifyDeviceSettingsFuncUserContext; // user context for modify device settings callback
  154.         void*                               m_DeviceCreatedUserContext;            // user context for device created callback
  155.         void*                               m_DeviceCreatedFuncUserContext;        // user context for device created callback
  156.         void*                               m_DeviceResetFuncUserContext;          // user context for device reset callback
  157.         void*                               m_DeviceLostFuncUserContext;           // user context for device lost callback
  158.         void*                               m_DeviceDestroyedFuncUserContext;      // user context for device destroyed callback
  159.         void*                               m_FrameMoveFuncUserContext;            // user context for frame move callback
  160.         void*                               m_FrameRenderFuncUserContext;          // user context for frame render callback
  161.         void*                               m_KeyboardFuncUserContext;             // user context for keyboard callback
  162.         void*                               m_MouseFuncUserContext;                // user context for mouse callback
  163.         void*                               m_WindowMsgFuncUserContext;            // user context for window messages callback
  164.         bool                         m_Keys[256];                       // array of key state
  165.         bool                         m_MouseButtons[5];                 // array of mouse states
  166.         CGrowableArray<DXUT_TIMER>*  m_TimerList;                       // list of DXUT_TIMER structs
  167.         WCHAR                        m_StaticFrameStats[256];           // static part of frames stats 
  168.         WCHAR                        m_FPSStats[64];                    // fps stats
  169.         WCHAR                        m_FrameStats[256];                 // frame stats (fps, width, etc)
  170.         WCHAR                        m_DeviceStats[256];                // device stats (description, device type, etc)
  171.         WCHAR                        m_WindowTitle[256];                // window title
  172.     };
  173.     
  174.     STATE m_state;
  175. public:
  176.     DXUTState()  { Create(); }
  177.     ~DXUTState() { Destroy(); }
  178.     void Create()
  179.     {
  180.         // Make sure these are created before DXUTState so they 
  181.         // destroyed last because DXUTState cleanup needs them
  182.         DXUTGetGlobalResourceCache();
  183.         ZeroMemory( &m_state, sizeof(STATE) ); 
  184.         g_bThreadSafe = true; 
  185.         InitializeCriticalSection( &g_cs ); 
  186.         m_state.m_OverrideStartX = -1; 
  187.         m_state.m_OverrideStartY = -1; 
  188.         m_state.m_OverrideAdapterOrdinal = -1; 
  189.         m_state.m_OverrideForceVsync = -1;
  190.         m_state.m_AutoChangeAdapter = true; 
  191.         m_state.m_ShowMsgBoxOnError = true;
  192.         m_state.m_AllowShortcutKeysWhenWindowed = true;
  193.         m_state.m_Active = true;
  194.         m_state.m_CallDefWindowProc = true;
  195.     }
  196.     void Destroy()
  197.     {
  198.         DXUTShutdown();
  199.         DeleteCriticalSection( &g_cs ); 
  200.     }
  201.     // Macros to define access functions for thread safe access into m_state 
  202.     GET_SET_ACCESSOR( IDirect3D9*, D3D );
  203.     GET_SET_ACCESSOR( IDirect3DDevice9*, D3DDevice );
  204.     GET_SET_ACCESSOR( CD3DEnumeration*, D3DEnumeration );   
  205.     GET_SET_ACCESSOR( DXUTDeviceSettings*, CurrentDeviceSettings );   
  206.     GETP_SETP_ACCESSOR( D3DSURFACE_DESC, BackBufferSurfaceDesc );
  207.     GETP_SETP_ACCESSOR( D3DCAPS9, Caps );
  208.     GET_SET_ACCESSOR( HWND, HWNDFocus );
  209.     GET_SET_ACCESSOR( HWND, HWNDDeviceFullScreen );
  210.     GET_SET_ACCESSOR( HWND, HWNDDeviceWindowed );
  211.     GET_SET_ACCESSOR( HMONITOR, AdapterMonitor );
  212.     GET_SET_ACCESSOR( HMENU, Menu );   
  213.     GET_SET_ACCESSOR( UINT, FullScreenBackBufferWidthAtModeChange );
  214.     GET_SET_ACCESSOR( UINT, FullScreenBackBufferHeightAtModeChange );
  215.     GET_SET_ACCESSOR( UINT, WindowBackBufferWidthAtModeChange );
  216.     GET_SET_ACCESSOR( UINT, WindowBackBufferHeightAtModeChange );
  217.     GETP_SETP_ACCESSOR( WINDOWPLACEMENT, WindowedPlacement );
  218.     GET_SET_ACCESSOR( DWORD, WindowedStyleAtModeChange );
  219.     GET_SET_ACCESSOR( bool, TopmostWhileWindowed );
  220.     GET_SET_ACCESSOR( bool, Minimized );
  221.     GET_SET_ACCESSOR( bool, Maximized );
  222.     GET_SET_ACCESSOR( bool, MinimizedWhileFullscreen );
  223.     GET_SET_ACCESSOR( bool, IgnoreSizeChange );   
  224.     GET_SET_ACCESSOR( double, Time );
  225.     GET_SET_ACCESSOR( double, AbsoluteTime );
  226.     GET_SET_ACCESSOR( float, ElapsedTime );
  227.     GET_SET_ACCESSOR( HINSTANCE, HInstance );
  228.     GET_SET_ACCESSOR( double, LastStatsUpdateTime );   
  229.     GET_SET_ACCESSOR( DWORD, LastStatsUpdateFrames );   
  230.     GET_SET_ACCESSOR( float, FPS );    
  231.     GET_SET_ACCESSOR( int, CurrentFrameNumber );
  232.     GET_SET_ACCESSOR( HHOOK, KeyboardHook );
  233.     GET_SET_ACCESSOR( bool, AllowShortcutKeysWhenFullscreen );
  234.     GET_SET_ACCESSOR( bool, AllowShortcutKeysWhenWindowed );
  235.     GET_SET_ACCESSOR( bool, AllowShortcutKeys );
  236.     GET_SET_ACCESSOR( bool, CallDefWindowProc );
  237.     GET_SET_ACCESSOR( STICKYKEYS, StartupStickyKeys );
  238.     GET_SET_ACCESSOR( TOGGLEKEYS, StartupToggleKeys );
  239.     GET_SET_ACCESSOR( FILTERKEYS, StartupFilterKeys );
  240.     GET_SET_ACCESSOR( bool, HandleDefaultHotkeys );
  241.     GET_SET_ACCESSOR( bool, HandleAltEnter );
  242.     GET_SET_ACCESSOR( bool, ShowMsgBoxOnError );
  243.     GET_SET_ACCESSOR( bool, NoStats );
  244.     GET_SET_ACCESSOR( bool, ClipCursorWhenFullScreen );   
  245.     GET_SET_ACCESSOR( bool, ShowCursorWhenFullScreen );
  246.     GET_SET_ACCESSOR( bool, ConstantFrameTime );
  247.     GET_SET_ACCESSOR( float, TimePerFrame );
  248.     GET_SET_ACCESSOR( bool, WireframeMode );   
  249.     GET_SET_ACCESSOR( bool, AutoChangeAdapter );
  250.     GET_SET_ACCESSOR( bool, WindowCreatedWithDefaultPositions );
  251.     GET_SET_ACCESSOR( int, ExitCode );
  252.     GET_SET_ACCESSOR( bool, DXUTInited );
  253.     GET_SET_ACCESSOR( bool, WindowCreated );
  254.     GET_SET_ACCESSOR( bool, DeviceCreated );
  255.     GET_SET_ACCESSOR( bool, DXUTInitCalled );
  256.     GET_SET_ACCESSOR( bool, WindowCreateCalled );
  257.     GET_SET_ACCESSOR( bool, DeviceCreateCalled );
  258.     GET_SET_ACCESSOR( bool, InsideDeviceCallback );
  259.     GET_SET_ACCESSOR( bool, InsideMainloop );
  260.     GET_SET_ACCESSOR( bool, DeviceObjectsCreated );
  261.     GET_SET_ACCESSOR( bool, DeviceObjectsReset );
  262.     GET_SET_ACCESSOR( bool, Active );
  263.     GET_SET_ACCESSOR( bool, RenderingPaused );
  264.     GET_SET_ACCESSOR( bool, TimePaused );
  265.     GET_SET_ACCESSOR( int, PauseRenderingCount );
  266.     GET_SET_ACCESSOR( int, PauseTimeCount );
  267.     GET_SET_ACCESSOR( bool, DeviceLost );
  268.     GET_SET_ACCESSOR( bool, NotifyOnMouseMove );
  269.     GET_SET_ACCESSOR( bool, Automation );
  270.     GET_SET_ACCESSOR( bool, InSizeMove );
  271.     GET_SET_ACCESSOR( UINT, TimerLastID );
  272.     GET_SET_ACCESSOR( int, OverrideAdapterOrdinal );
  273.     GET_SET_ACCESSOR( bool, OverrideWindowed );
  274.     GET_SET_ACCESSOR( bool, OverrideFullScreen );
  275.     GET_SET_ACCESSOR( int, OverrideStartX );
  276.     GET_SET_ACCESSOR( int, OverrideStartY );
  277.     GET_SET_ACCESSOR( int, OverrideWidth );
  278.     GET_SET_ACCESSOR( int, OverrideHeight );
  279.     GET_SET_ACCESSOR( bool, OverrideForceHAL );
  280.     GET_SET_ACCESSOR( bool, OverrideForceREF );
  281.     GET_SET_ACCESSOR( bool, OverrideForcePureHWVP );
  282.     GET_SET_ACCESSOR( bool, OverrideForceHWVP );
  283.     GET_SET_ACCESSOR( bool, OverrideForceSWVP );
  284.     GET_SET_ACCESSOR( bool, OverrideConstantFrameTime );
  285.     GET_SET_ACCESSOR( float, OverrideConstantTimePerFrame );
  286.     GET_SET_ACCESSOR( int, OverrideQuitAfterFrame );
  287.     GET_SET_ACCESSOR( int, OverrideForceVsync );
  288.     GET_SET_ACCESSOR( bool, OverrideRelaunchMCE );
  289.     GET_SET_ACCESSOR( LPDXUTCALLBACKISDEVICEACCEPTABLE, IsDeviceAcceptableFunc );
  290.     GET_SET_ACCESSOR( LPDXUTCALLBACKMODIFYDEVICESETTINGS, ModifyDeviceSettingsFunc );
  291.     GET_SET_ACCESSOR( LPDXUTCALLBACKDEVICECREATED, DeviceCreatedFunc );
  292.     GET_SET_ACCESSOR( LPDXUTCALLBACKDEVICERESET, DeviceResetFunc );
  293.     GET_SET_ACCESSOR( LPDXUTCALLBACKDEVICELOST, DeviceLostFunc );
  294.     GET_SET_ACCESSOR( LPDXUTCALLBACKDEVICEDESTROYED, DeviceDestroyedFunc );
  295.     GET_SET_ACCESSOR( LPDXUTCALLBACKFRAMEMOVE, FrameMoveFunc );
  296.     GET_SET_ACCESSOR( LPDXUTCALLBACKFRAMERENDER, FrameRenderFunc );
  297.     GET_SET_ACCESSOR( LPDXUTCALLBACKKEYBOARD, KeyboardFunc );
  298.     GET_SET_ACCESSOR( LPDXUTCALLBACKMOUSE, MouseFunc );
  299.     GET_SET_ACCESSOR( LPDXUTCALLBACKMSGPROC, WindowMsgFunc );
  300.     GET_SET_ACCESSOR( void*, IsDeviceAcceptableFuncUserContext );
  301.     GET_SET_ACCESSOR( void*, ModifyDeviceSettingsFuncUserContext );
  302.     GET_SET_ACCESSOR( void*, DeviceCreatedFuncUserContext );
  303.     GET_SET_ACCESSOR( void*, DeviceResetFuncUserContext );
  304.     GET_SET_ACCESSOR( void*, DeviceLostFuncUserContext );
  305.     GET_SET_ACCESSOR( void*, DeviceDestroyedFuncUserContext );
  306.     GET_SET_ACCESSOR( void*, FrameMoveFuncUserContext );
  307.     GET_SET_ACCESSOR( void*, FrameRenderFuncUserContext );
  308.     GET_SET_ACCESSOR( void*, KeyboardFuncUserContext );
  309.     GET_SET_ACCESSOR( void*, MouseFuncUserContext );
  310.     GET_SET_ACCESSOR( void*, WindowMsgFuncUserContext );
  311.     GET_SET_ACCESSOR( CGrowableArray<DXUT_TIMER>*, TimerList );   
  312.     GET_ACCESSOR( bool*, Keys );
  313.     GET_ACCESSOR( bool*, MouseButtons );
  314.     GET_ACCESSOR( WCHAR*, StaticFrameStats );
  315.     GET_ACCESSOR( WCHAR*, FPSStats );
  316.     GET_ACCESSOR( WCHAR*, FrameStats );
  317.     GET_ACCESSOR( WCHAR*, DeviceStats );    
  318.     GET_ACCESSOR( WCHAR*, WindowTitle );
  319. };
  320. //--------------------------------------------------------------------------------------
  321. // Global state class
  322. //--------------------------------------------------------------------------------------
  323. DXUTState& GetDXUTState()
  324. {
  325.     // Using an accessor function gives control of the construction order
  326.     static DXUTState state;
  327.     return state;
  328. }
  329. //--------------------------------------------------------------------------------------
  330. // Internal functions forward declarations
  331. //--------------------------------------------------------------------------------------
  332. typedef IDirect3D9* (WINAPI* LPDIRECT3DCREATE9)(UINT SDKVersion);
  333. typedef DECLSPEC_IMPORT UINT (WINAPI* LPTIMEBEGINPERIOD)( UINT uPeriod );
  334. int     DXUTMapButtonToArrayIndex( BYTE vButton );
  335. void    DXUTSetProcessorAffinity();
  336. void    DXUTParseCommandLine();
  337. CD3DEnumeration* DXUTPrepareEnumerationObject( bool bEnumerate = false );
  338. void    DXUTBuildOptimalDeviceSettings( DXUTDeviceSettings* pOptimalDeviceSettings, DXUTDeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions );
  339. bool    DXUTDoesDeviceComboMatchPreserveOptions( CD3DEnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTDeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions );
  340. float   DXUTRankDeviceCombo( CD3DEnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTDeviceSettings* pDeviceSettingsIn, D3DDISPLAYMODE* pAdapterDesktopDisplayMode );
  341. void    DXUTBuildValidDeviceSettings( DXUTDeviceSettings* pDeviceSettings, CD3DEnumDeviceSettingsCombo* pBestDeviceSettingsCombo, DXUTDeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions );
  342. HRESULT DXUTFindValidResolution( CD3DEnumDeviceSettingsCombo* pBestDeviceSettingsCombo, D3DDISPLAYMODE displayModeIn, D3DDISPLAYMODE* pBestDisplayMode );
  343. HRESULT DXUTFindAdapterFormat( UINT AdapterOrdinal, D3DDEVTYPE DeviceType, D3DFORMAT BackBufferFormat, BOOL Windowed, D3DFORMAT* pAdapterFormat );
  344. HRESULT DXUTChangeDevice( DXUTDeviceSettings* pNewDeviceSettings, IDirect3DDevice9* pd3dDeviceFromApp, bool bForceRecreate, bool bClipWindowToSingleAdapter );
  345. void    DXUTUpdateDeviceSettingsWithOverrides( DXUTDeviceSettings* pNewDeviceSettings );
  346. HRESULT DXUTCreate3DEnvironment( IDirect3DDevice9* pd3dDeviceFromApp );
  347. HRESULT DXUTReset3DEnvironment();
  348. void    DXUTRender3DEnvironment();
  349. void    DXUTCleanup3DEnvironment( bool bReleaseSettings = true );
  350. void    DXUTUpdateFrameStats();
  351. void    DXUTUpdateDeviceStats( D3DDEVTYPE DeviceType, DWORD BehaviorFlags, D3DADAPTER_IDENTIFIER9* pAdapterIdentifier );
  352. void    DXUTUpdateStaticFrameStats();
  353. void    DXUTHandleTimers();
  354. bool    DXUTIsNextArg( WCHAR*& strCmdLine, WCHAR* strArg );
  355. bool    DXUTGetCmdParam( WCHAR*& strCmdLine, WCHAR* strFlag );
  356. void    DXUTDisplayErrorMessage( HRESULT hr );
  357. LRESULT CALLBACK DXUTStaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  358. void    DXUTCheckForWindowSizeChange();
  359. void    DXUTCheckForWindowChangingMonitors();
  360. UINT    DXUTColorChannelBits( D3DFORMAT fmt );
  361. UINT    DXUTStencilBits( D3DFORMAT fmt );
  362. UINT    DXUTDepthBits( D3DFORMAT fmt );
  363. HRESULT DXUTGetAdapterOrdinalFromMonitor( HMONITOR hMonitor, UINT* pAdapterOrdinal );
  364. void    DXUTAllowShortcutKeys( bool bAllowKeys );
  365. void    DXUTUpdateBackBufferDesc();
  366. void    DXUTSetupCursor();
  367. HRESULT DXUTSetDeviceCursor( IDirect3DDevice9* pd3dDevice, HCURSOR hCursor, bool bAddWatermark );
  368. //--------------------------------------------------------------------------------------
  369. // External callback setup functions
  370. //--------------------------------------------------------------------------------------
  371. void DXUTSetCallbackDeviceCreated( LPDXUTCALLBACKDEVICECREATED pCallbackDeviceCreated, void* pUserContext ) { GetDXUTState().SetDeviceCreatedFunc( pCallbackDeviceCreated ); GetDXUTState().SetDeviceCreatedFuncUserContext( pUserContext ); }
  372. void DXUTSetCallbackDeviceReset( LPDXUTCALLBACKDEVICERESET pCallbackDeviceReset, void* pUserContext )       { GetDXUTState().SetDeviceResetFunc( pCallbackDeviceReset );  GetDXUTState().SetDeviceResetFuncUserContext( pUserContext ); }
  373. void DXUTSetCallbackDeviceLost( LPDXUTCALLBACKDEVICELOST pCallbackDeviceLost, void* pUserContext )          { GetDXUTState().SetDeviceLostFunc( pCallbackDeviceLost );  GetDXUTState().SetDeviceLostFuncUserContext( pUserContext ); }
  374. void DXUTSetCallbackDeviceDestroyed( LPDXUTCALLBACKDEVICEDESTROYED pCallbackDeviceDestroyed, void* pUserContext ) { GetDXUTState().SetDeviceDestroyedFunc( pCallbackDeviceDestroyed );  GetDXUTState().SetDeviceDestroyedFuncUserContext( pUserContext ); }
  375. void DXUTSetCallbackDeviceChanging( LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallbackModifyDeviceSettings, void* pUserContext ) { GetDXUTState().SetModifyDeviceSettingsFunc( pCallbackModifyDeviceSettings );  GetDXUTState().SetModifyDeviceSettingsFuncUserContext( pUserContext ); }
  376. void DXUTSetCallbackFrameMove( LPDXUTCALLBACKFRAMEMOVE pCallbackFrameMove, void* pUserContext ) { GetDXUTState().SetFrameMoveFunc( pCallbackFrameMove );  GetDXUTState().SetFrameMoveFuncUserContext( pUserContext ); }
  377. void DXUTSetCallbackFrameRender( LPDXUTCALLBACKFRAMERENDER pCallbackFrameRender, void* pUserContext )       { GetDXUTState().SetFrameRenderFunc( pCallbackFrameRender );  GetDXUTState().SetFrameRenderFuncUserContext( pUserContext ); }
  378. void DXUTSetCallbackKeyboard( LPDXUTCALLBACKKEYBOARD pCallbackKeyboard, void* pUserContext )                { GetDXUTState().SetKeyboardFunc( pCallbackKeyboard );  GetDXUTState().SetKeyboardFuncUserContext( pUserContext ); }
  379. void DXUTSetCallbackMouse( LPDXUTCALLBACKMOUSE pCallbackMouse, bool bIncludeMouseMove, void* pUserContext ) { GetDXUTState().SetMouseFunc( pCallbackMouse ); GetDXUTState().SetNotifyOnMouseMove( bIncludeMouseMove );  GetDXUTState().SetMouseFuncUserContext( pUserContext ); }
  380. void DXUTSetCallbackMsgProc( LPDXUTCALLBACKMSGPROC pCallbackMsgProc, void* pUserContext )                   { GetDXUTState().SetWindowMsgFunc( pCallbackMsgProc );  GetDXUTState().SetWindowMsgFuncUserContext( pUserContext ); }
  381. //--------------------------------------------------------------------------------------
  382. // Optionally parses the command line and sets if default hotkeys are handled
  383. //
  384. //       Possible command line parameters are:
  385. //          -adapter:#              forces app to use this adapter # (fails if the adapter doesn't exist)
  386. //          -windowed               forces app to start windowed
  387. //          -fullscreen             forces app to start full screen
  388. //          -forcehal               forces app to use HAL (fails if HAL doesn't exist)
  389. //          -forceref               forces app to use REF (fails if REF doesn't exist)
  390. //          -forcepurehwvp          forces app to use pure HWVP (fails if device doesn't support it)
  391. //          -forcehwvp              forces app to use HWVP (fails if device doesn't support it)
  392. //          -forceswvp              forces app to use SWVP 
  393. //          -forcevsync:#           if # is 0, forces app to use D3DPRESENT_INTERVAL_IMMEDIATE otherwise force use of D3DPRESENT_INTERVAL_DEFAULT 
  394. //          -width:#                forces app to use # for width. for full screen, it will pick the closest possible supported mode
  395. //          -height:#               forces app to use # for height. for full screen, it will pick the closest possible supported mode
  396. //          -startx:#               forces app to use # for the x coord of the window position for windowed mode
  397. //          -starty:#               forces app to use # for the y coord of the window position for windowed mode
  398. //          -constantframetime:#    forces app to use constant frame time, where # is the time/frame in seconds
  399. //          -quitafterframe:x       forces app to quit after # frames
  400. //          -noerrormsgboxes        prevents the display of message boxes generated by the framework so the application can be run without user interaction
  401. //          -nostats                prevents the display of the stats
  402. //          -relaunchmce            re-launches the MCE UI after the app exits
  403. //          -automation             every CDXUTDialog created will have EnableKeyboardInput(true) called, enabling UI navigation with keyboard
  404. //                                  This is useful when automating application testing.
  405. //
  406. //      Hotkeys handled by default are:
  407. //          Alt-Enter           toggle between full screen & windowed (hotkey always enabled)
  408. //          ESC                 exit app 
  409. //          F3                  toggle HAL/REF
  410. //          F8                  toggle wire-frame mode
  411. //          Pause               pause time
  412. //--------------------------------------------------------------------------------------
  413. HRESULT DXUTInit( bool bParseCommandLine, bool bHandleDefaultHotkeys, bool bShowMsgBoxOnError, bool bHandleAltEnter )
  414. {
  415.     GetDXUTState().SetDXUTInitCalled( true );
  416.     // Not always needed, but lets the app create GDI dialogs
  417.     InitCommonControls();
  418.     // Save the current sticky/toggle/filter key settings so DXUT can restore them later
  419.     STICKYKEYS sk = {sizeof(STICKYKEYS), 0};
  420.     SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &sk, 0);
  421.     GetDXUTState().SetStartupStickyKeys( sk );
  422.     TOGGLEKEYS tk = {sizeof(TOGGLEKEYS), 0};
  423.     SystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(TOGGLEKEYS), &tk, 0);
  424.     GetDXUTState().SetStartupToggleKeys( tk );
  425.     FILTERKEYS fk = {sizeof(FILTERKEYS), 0};
  426.     SystemParametersInfo(SPI_GETFILTERKEYS, sizeof(FILTERKEYS), &fk, 0);
  427.     GetDXUTState().SetStartupFilterKeys( fk );
  428.     // Increase the accuracy of Sleep() without needing to link to winmm.lib
  429.     WCHAR wszPath[MAX_PATH+1];
  430.     if( GetSystemDirectory( wszPath, MAX_PATH+1 ) )
  431.     {
  432.         StringCchCat( wszPath, MAX_PATH, L"\winmm.dll" );
  433.         HINSTANCE hInstWinMM = LoadLibrary( wszPath );
  434.         if( hInstWinMM ) 
  435.         {
  436.             LPTIMEBEGINPERIOD pTimeBeginPeriod = (LPTIMEBEGINPERIOD)GetProcAddress( hInstWinMM, "timeBeginPeriod" );
  437.             if( NULL != pTimeBeginPeriod )
  438.                 pTimeBeginPeriod(1);
  439.             FreeLibrary(hInstWinMM);
  440.         }
  441.     }
  442.     GetDXUTState().SetShowMsgBoxOnError( bShowMsgBoxOnError );
  443.     GetDXUTState().SetHandleDefaultHotkeys( bHandleDefaultHotkeys );
  444.     GetDXUTState().SetHandleAltEnter( bHandleAltEnter );
  445.     if( bParseCommandLine )
  446.         DXUTParseCommandLine();
  447.     // Verify D3DX version
  448.     if( !D3DXCheckVersion( D3D_SDK_VERSION, D3DX_SDK_VERSION ) )
  449.     {
  450.         DXUTDisplayErrorMessage( DXUTERR_INCORRECTVERSION );
  451.         return DXUT_ERR( L"D3DXCheckVersion", DXUTERR_INCORRECTVERSION );
  452.     }
  453.     // Create a Direct3D object if one has not already been created
  454.     IDirect3D9* pD3D = DXUTGetD3DObject();
  455.     if( pD3D == NULL )
  456.     {
  457.         // This may fail if DirectX 9 isn't installed
  458.         // This may fail if the DirectX headers are out of sync with the installed DirectX DLLs
  459.         pD3D = DXUT_Dynamic_Direct3DCreate9( D3D_SDK_VERSION );
  460.         GetDXUTState().SetD3D( pD3D );
  461.     }
  462.     if( pD3D == NULL )
  463.     {
  464.         // If still NULL, then something went wrong
  465.         DXUTDisplayErrorMessage( DXUTERR_NODIRECT3D );
  466.         return DXUT_ERR( L"Direct3DCreate9", DXUTERR_NODIRECT3D );
  467.     }
  468.     // Reset the timer
  469.     DXUTGetGlobalTimer()->Reset();
  470.     GetDXUTState().SetDXUTInited( true );
  471.     return S_OK;
  472. }
  473. //--------------------------------------------------------------------------------------
  474. // Parses the command line for parameters.  See DXUTInit() for list 
  475. //--------------------------------------------------------------------------------------
  476. void DXUTParseCommandLine()
  477. {
  478.     WCHAR* strCmdLine;
  479.     WCHAR strFlag[MAX_PATH];
  480.     int nNumArgs;
  481.     WCHAR** pstrArgList = CommandLineToArgvW( GetCommandLine(), &nNumArgs );
  482.     for( int iArg=1; iArg<nNumArgs; iArg++ )
  483.     {
  484.         strCmdLine = pstrArgList[iArg];
  485.         // Handle flag args
  486.         if( *strCmdLine == L'/' || *strCmdLine == L'-' )
  487.         {
  488.             strCmdLine++;
  489.             if( DXUTIsNextArg( strCmdLine, L"adapter" ) )
  490.             {
  491.                 if( DXUTGetCmdParam( strCmdLine, strFlag ) )
  492.                 {
  493.                     int nAdapter = _wtoi(strFlag);
  494.                     GetDXUTState().SetOverrideAdapterOrdinal( nAdapter );
  495.                     continue;
  496.                 }
  497.             }
  498.             if( DXUTIsNextArg( strCmdLine, L"windowed" ) )
  499.             {
  500.                 GetDXUTState().SetOverrideWindowed( true );
  501.                 continue;
  502.             }
  503.             if( DXUTIsNextArg( strCmdLine, L"fullscreen" ) )
  504.             {
  505.                 GetDXUTState().SetOverrideFullScreen( true );
  506.                 continue;
  507.             }
  508.             if( DXUTIsNextArg( strCmdLine, L"forcehal" ) )
  509.             {
  510.                 GetDXUTState().SetOverrideForceHAL( true );
  511.                 continue;
  512.             }
  513.             if( DXUTIsNextArg( strCmdLine, L"forceref" ) )
  514.             {
  515.                 GetDXUTState().SetOverrideForceREF( true );
  516.                 continue;
  517.             }
  518.             if( DXUTIsNextArg( strCmdLine, L"forcepurehwvp" ) )
  519.             {
  520.                 GetDXUTState().SetOverrideForcePureHWVP( true );
  521.                 continue;
  522.             }
  523.             if( DXUTIsNextArg( strCmdLine, L"forcehwvp" ) )
  524.             {
  525.                 GetDXUTState().SetOverrideForceHWVP( true );
  526.                 continue;
  527.             }
  528.             if( DXUTIsNextArg( strCmdLine, L"forceswvp" ) )
  529.             {
  530.                 GetDXUTState().SetOverrideForceSWVP( true );
  531.                 continue;
  532.             }
  533.             if( DXUTIsNextArg( strCmdLine, L"forcevsync" ) )
  534.             {
  535.                 if( DXUTGetCmdParam( strCmdLine, strFlag ) )
  536.                 {
  537.                     int nOn = _wtoi(strFlag);
  538.                     GetDXUTState().SetOverrideForceVsync( nOn );
  539.                     continue;
  540.                 }
  541.             }
  542.             if( DXUTIsNextArg( strCmdLine, L"width" ) )
  543.             {
  544.                 if( DXUTGetCmdParam( strCmdLine, strFlag ) )
  545.                 {
  546.                     int nWidth = _wtoi(strFlag);
  547.                     GetDXUTState().SetOverrideWidth( nWidth );
  548.                     continue;
  549.                 }
  550.             }
  551.             if( DXUTIsNextArg( strCmdLine, L"height" ) )
  552.             {
  553.                 if( DXUTGetCmdParam( strCmdLine, strFlag ) )
  554.                 {
  555.                     int nHeight = _wtoi(strFlag);
  556.                     GetDXUTState().SetOverrideHeight( nHeight );
  557.                 continue;
  558.                 }
  559.             }
  560.             if( DXUTIsNextArg( strCmdLine, L"startx" ) )
  561.             {
  562.                 if( DXUTGetCmdParam( strCmdLine, strFlag ) )
  563.                 {
  564.                     int nX = _wtoi(strFlag);
  565.                     GetDXUTState().SetOverrideStartX( nX );
  566.                     continue;
  567.                 }
  568.             }
  569.             if( DXUTIsNextArg( strCmdLine, L"starty" ) )
  570.             {
  571.                 if( DXUTGetCmdParam( strCmdLine, strFlag ) )
  572.                 {
  573.                     int nY = _wtoi(strFlag);
  574.                     GetDXUTState().SetOverrideStartY( nY );
  575.                     continue;
  576.                 }
  577.             }
  578.             if( DXUTIsNextArg( strCmdLine, L"constantframetime" ) )
  579.             {
  580.                 float fTimePerFrame;
  581.                 if( DXUTGetCmdParam( strCmdLine, strFlag ) )
  582.                     fTimePerFrame = (float)wcstod( strFlag, NULL );
  583.                 else
  584.                     fTimePerFrame = 0.0333f;
  585.                 GetDXUTState().SetOverrideConstantFrameTime( true );
  586.                 GetDXUTState().SetOverrideConstantTimePerFrame( fTimePerFrame );
  587.                 DXUTSetConstantFrameTime( true, fTimePerFrame );
  588.                 continue;
  589.             }
  590.             if( DXUTIsNextArg( strCmdLine, L"quitafterframe" ) )
  591.             {
  592.                 if( DXUTGetCmdParam( strCmdLine, strFlag ) )
  593.                 {
  594.                     int nFrame = _wtoi(strFlag);
  595.                     GetDXUTState().SetOverrideQuitAfterFrame( nFrame );
  596.                     continue;
  597.                 }
  598.             }
  599.             if( DXUTIsNextArg( strCmdLine, L"noerrormsgboxes" ) )
  600.             {
  601.                 GetDXUTState().SetShowMsgBoxOnError( false );
  602.                 continue;
  603.             }
  604.             if( DXUTIsNextArg( strCmdLine, L"nostats" ) )
  605.             {
  606.                 GetDXUTState().SetNoStats( true );
  607.                 continue;
  608.             }
  609.             if( DXUTIsNextArg( strCmdLine, L"relaunchmce" ) )
  610.             {
  611.                 GetDXUTState().SetOverrideRelaunchMCE( true );
  612.                 continue;
  613.             }
  614.             if( DXUTIsNextArg( strCmdLine, L"automation" ) )
  615.             {
  616.                 GetDXUTState().SetAutomation( true );
  617.                 continue;
  618.             }
  619.         }
  620.         // Unrecognized flag
  621.         StringCchCopy( strFlag, 256, strCmdLine ); 
  622.         WCHAR* strSpace = strFlag;
  623.         while (*strSpace && (*strSpace > L' '))
  624.             strSpace++;
  625.         *strSpace = 0;
  626.         DXUTOutputDebugString( L"Unrecognized flag: %s", strFlag );
  627.         strCmdLine += wcslen(strFlag);
  628.     }
  629. }
  630. //--------------------------------------------------------------------------------------
  631. // Helper function for DXUTParseCommandLine
  632. //--------------------------------------------------------------------------------------
  633. bool DXUTIsNextArg( WCHAR*& strCmdLine, WCHAR* strArg )
  634. {
  635.     int nArgLen = (int) wcslen(strArg);
  636.     int nCmdLen = (int) wcslen(strCmdLine);
  637.     if( nCmdLen >= nArgLen && 
  638.         _wcsnicmp( strCmdLine, strArg, nArgLen ) == 0 && 
  639.         (strCmdLine[nArgLen] == 0 || strCmdLine[nArgLen] == L':') )
  640.     {
  641.         strCmdLine += nArgLen;
  642.         return true;
  643.     }
  644.     return false;
  645. }
  646. //--------------------------------------------------------------------------------------
  647. // Helper function for DXUTParseCommandLine.  Updates strCmdLine and strFlag 
  648. //      Example: if strCmdLine=="-width:1024 -forceref"
  649. // then after: strCmdLine==" -forceref" and strFlag=="1024"
  650. //--------------------------------------------------------------------------------------
  651. bool DXUTGetCmdParam( WCHAR*& strCmdLine, WCHAR* strFlag )
  652. {
  653.     if( *strCmdLine == L':' )
  654.     {       
  655.         strCmdLine++; // Skip ':'
  656.         // Place NULL terminator in strFlag after current token
  657.         StringCchCopy( strFlag, 256, strCmdLine );
  658.         WCHAR* strSpace = strFlag;
  659.         while (*strSpace && (*strSpace > L' '))
  660.             strSpace++;
  661.         *strSpace = 0;
  662.     
  663.         // Update strCmdLine
  664.         strCmdLine += wcslen(strFlag);
  665.         return true;
  666.     }
  667.     else
  668.     {
  669.         strFlag[0] = 0;
  670.         return false;
  671.     }
  672. }
  673. //--------------------------------------------------------------------------------------
  674. // Creates a window with the specified window title, icon, menu, and 
  675. // starting position.  If DXUTInit() has not already been called, it will
  676. // call it with the default parameters.  Instead of calling this, you can 
  677. // call DXUTSetWindow() to use an existing window.  
  678. //--------------------------------------------------------------------------------------
  679. HRESULT DXUTCreateWindow( const WCHAR* strWindowTitle, HINSTANCE hInstance, 
  680.                           HICON hIcon, HMENU hMenu, int x, int y )
  681. {
  682.     HRESULT hr;
  683.     // Not allowed to call this from inside the device callbacks
  684.     if( GetDXUTState().GetInsideDeviceCallback() )
  685.         return DXUT_ERR_MSGBOX( L"DXUTCreateWindow", E_FAIL );
  686.     GetDXUTState().SetWindowCreateCalled( true );
  687.     if( !GetDXUTState().GetDXUTInited() ) 
  688.     {
  689.         // If DXUTInit() was already called and failed, then fail.
  690.         // DXUTInit() must first succeed for this function to succeed
  691.         if( GetDXUTState().GetDXUTInitCalled() )
  692.             return E_FAIL; 
  693.         // If DXUTInit() hasn't been called, then automatically call it
  694.         // with default params
  695.         hr = DXUTInit();
  696.         if( FAILED(hr) )
  697.             return hr;
  698.     }
  699.     if( DXUTGetHWNDFocus() == NULL )
  700.     {
  701.         if( hInstance == NULL ) 
  702.             hInstance = (HINSTANCE)GetModuleHandle(NULL);
  703.         GetDXUTState().SetHInstance( hInstance );
  704.         WCHAR szExePath[MAX_PATH];
  705.         GetModuleFileName( NULL, szExePath, MAX_PATH );
  706.         if( hIcon == NULL ) // If the icon is NULL, then use the first one found in the exe
  707.             hIcon = ExtractIcon( hInstance, szExePath, 0 ); 
  708.         // Register the windows class
  709.         WNDCLASS wndClass;
  710.         wndClass.style = CS_DBLCLKS;
  711.         wndClass.lpfnWndProc = DXUTStaticWndProc;
  712.         wndClass.cbClsExtra = 0;
  713.         wndClass.cbWndExtra = 0;
  714.         wndClass.hInstance = hInstance;
  715.         wndClass.hIcon = hIcon;
  716.         wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
  717.         wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  718.         wndClass.lpszMenuName = NULL;
  719.         wndClass.lpszClassName = L"Direct3DWindowClass";
  720.         if( !RegisterClass( &wndClass ) )
  721.         {
  722.             DWORD dwError = GetLastError();
  723.             if( dwError != ERROR_CLASS_ALREADY_EXISTS )
  724.                 return DXUT_ERR_MSGBOX( L"RegisterClass", HRESULT_FROM_WIN32(dwError) );
  725.         }
  726.         RECT rc;
  727.         // Override the window's initial & size position if there were cmd line args
  728.         if( GetDXUTState().GetOverrideStartX() != -1 )
  729.             x = GetDXUTState().GetOverrideStartX();
  730.         if( GetDXUTState().GetOverrideStartY() != -1 )
  731.             y = GetDXUTState().GetOverrideStartY();
  732.         GetDXUTState().SetWindowCreatedWithDefaultPositions( false );
  733.         if( x == CW_USEDEFAULT && y == CW_USEDEFAULT )
  734.             GetDXUTState().SetWindowCreatedWithDefaultPositions( true );
  735.         // Find the window's initial size, but it might be changed later
  736.         int nDefaultWidth = 640;
  737.         int nDefaultHeight = 480;
  738.         if( GetDXUTState().GetOverrideWidth() != 0 )
  739.             nDefaultWidth = GetDXUTState().GetOverrideWidth();
  740.         if( GetDXUTState().GetOverrideHeight() != 0 )
  741.             nDefaultHeight = GetDXUTState().GetOverrideHeight();
  742.         SetRect( &rc, 0, 0, nDefaultWidth, nDefaultHeight );        
  743.         AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, ( hMenu != NULL ) ? true : false );
  744.         WCHAR* strCachedWindowTitle = GetDXUTState().GetWindowTitle();
  745.         StringCchCopy( strCachedWindowTitle, 256, strWindowTitle );
  746.         // Create the render window
  747.         HWND hWnd = CreateWindow( L"Direct3DWindowClass", strWindowTitle, WS_OVERLAPPEDWINDOW,
  748.                                x, y, (rc.right-rc.left), (rc.bottom-rc.top), 0,
  749.                                hMenu, hInstance, 0 );
  750.         if( hWnd == NULL )
  751.         {
  752.             DWORD dwError = GetLastError();
  753.             return DXUT_ERR_MSGBOX( L"CreateWindow", HRESULT_FROM_WIN32(dwError) );
  754.         }
  755.         GetDXUTState().SetWindowCreated( true );
  756.         GetDXUTState().SetHWNDFocus( hWnd );
  757.         GetDXUTState().SetHWNDDeviceFullScreen( hWnd );
  758.         GetDXUTState().SetHWNDDeviceWindowed( hWnd );
  759.     }
  760.     return S_OK;
  761. }
  762. //--------------------------------------------------------------------------------------
  763. // Sets a previously created window for the framework to use.  If DXUTInit() 
  764. // has not already been called, it will call it with the default parameters.  
  765. // Instead of calling this, you can call DXUTCreateWindow() to create a new window.  
  766. //--------------------------------------------------------------------------------------
  767. HRESULT DXUTSetWindow( HWND hWndFocus, HWND hWndDeviceFullScreen, HWND hWndDeviceWindowed, bool bHandleMessages )
  768. {
  769.     HRESULT hr;
  770.  
  771.     // Not allowed to call this from inside the device callbacks
  772.     if( GetDXUTState().GetInsideDeviceCallback() )
  773.         return DXUT_ERR_MSGBOX( L"DXUTCreateWindow", E_FAIL );
  774.     GetDXUTState().SetWindowCreateCalled( true );
  775.     // To avoid confusion, we do not allow any HWND to be NULL here.  The
  776.     // caller must pass in valid HWND for all three parameters.  The same
  777.     // HWND may be used for more than one parameter.
  778.     if( hWndFocus == NULL || hWndDeviceFullScreen == NULL || hWndDeviceWindowed == NULL )
  779.         return DXUT_ERR_MSGBOX( L"DXUTSetWindow", E_INVALIDARG );
  780.     // If subclassing the window, set the pointer to the local window procedure
  781.     if( bHandleMessages )
  782.     {
  783.         // Switch window procedures
  784. #ifdef _WIN64
  785.         LONG_PTR nResult = SetWindowLongPtr( hWndFocus, GWLP_WNDPROC, (LONG_PTR)DXUTStaticWndProc );
  786. #else
  787.         LONG_PTR nResult = SetWindowLongPtr( hWndFocus, GWLP_WNDPROC, (LONG)(LONG_PTR)DXUTStaticWndProc );
  788. #endif 
  789.  
  790.         DWORD dwError = GetLastError();
  791.         if( nResult == 0 )
  792.             return DXUT_ERR_MSGBOX( L"SetWindowLongPtr", HRESULT_FROM_WIN32(dwError) );
  793.     }
  794.  
  795.     if( !GetDXUTState().GetDXUTInited() ) 
  796.     {
  797.         // If DXUTInit() was already called and failed, then fail.
  798.         // DXUTInit() must first succeed for this function to succeed
  799.         if( GetDXUTState().GetDXUTInitCalled() )
  800.             return E_FAIL; 
  801.  
  802.         // If DXUTInit() hasn't been called, then automatically call it
  803.         // with default params
  804.         hr = DXUTInit();
  805.         if( FAILED(hr) )
  806.             return hr;
  807.     }
  808.  
  809.     WCHAR* strCachedWindowTitle = GetDXUTState().GetWindowTitle();
  810.     GetWindowText( hWndFocus, strCachedWindowTitle, 255 );
  811.     strCachedWindowTitle[255] = 0;
  812.    
  813.     HINSTANCE hInstance = (HINSTANCE) (LONG_PTR) GetWindowLongPtr( hWndFocus, GWLP_HINSTANCE ); 
  814.     GetDXUTState().SetHInstance( hInstance );
  815.     GetDXUTState().SetWindowCreatedWithDefaultPositions( false );
  816.     GetDXUTState().SetWindowCreated( true );
  817.     GetDXUTState().SetHWNDFocus( hWndFocus );
  818.     GetDXUTState().SetHWNDDeviceFullScreen( hWndDeviceFullScreen );
  819.     GetDXUTState().SetHWNDDeviceWindowed( hWndDeviceWindowed );
  820.     return S_OK;
  821. }
  822. //--------------------------------------------------------------------------------------
  823. // Creates a Direct3D device. If DXUTCreateWindow() or DXUTSetWindow() has not already 
  824. // been called, it will call DXUTCreateWindow() with the default parameters.  
  825. // Instead of calling this, you can call DXUTSetDevice() or DXUTCreateDeviceFromSettings() 
  826. //--------------------------------------------------------------------------------------
  827. HRESULT DXUTCreateDevice( UINT AdapterOrdinal, bool bWindowed, 
  828.                           int nSuggestedWidth, int nSuggestedHeight,
  829.                           LPDXUTCALLBACKISDEVICEACCEPTABLE pCallbackIsDeviceAcceptable,
  830.                           LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallbackModifyDeviceSettings,
  831.                           void* pUserContext )
  832. {
  833.     HRESULT hr;
  834.     // Not allowed to call this from inside the device callbacks
  835.     if( GetDXUTState().GetInsideDeviceCallback() )
  836.         return DXUT_ERR_MSGBOX( L"DXUTCreateWindow", E_FAIL );
  837.     // Record the function arguments in the global state 
  838.     GetDXUTState().SetIsDeviceAcceptableFunc( pCallbackIsDeviceAcceptable );
  839.     GetDXUTState().SetModifyDeviceSettingsFunc( pCallbackModifyDeviceSettings );
  840.     GetDXUTState().SetIsDeviceAcceptableFuncUserContext( pUserContext );
  841.     GetDXUTState().SetModifyDeviceSettingsFuncUserContext( pUserContext );
  842.     GetDXUTState().SetDeviceCreateCalled( true );
  843.     // If DXUTCreateWindow() or DXUTSetWindow() has not already been called, 
  844.     // then call DXUTCreateWindow() with the default parameters.         
  845.     if( !GetDXUTState().GetWindowCreated() ) 
  846.     {
  847.         // If DXUTCreateWindow() or DXUTSetWindow() was already called and failed, then fail.
  848.         // DXUTCreateWindow() or DXUTSetWindow() must first succeed for this function to succeed
  849.         if( GetDXUTState().GetWindowCreateCalled() )
  850.             return E_FAIL; 
  851.         // If DXUTCreateWindow() or DXUTSetWindow() hasn't been called, then 
  852.         // automatically call DXUTCreateWindow() with default params
  853.         hr = DXUTCreateWindow();
  854.         if( FAILED(hr) )
  855.             return hr;
  856.     }
  857.     // Force an enumeration with the new IsDeviceAcceptable callback
  858.     DXUTPrepareEnumerationObject( true );
  859.     DXUTMatchOptions matchOptions;
  860.     matchOptions.eAdapterOrdinal     = DXUTMT_PRESERVE_INPUT;
  861.     matchOptions.eDeviceType         = DXUTMT_IGNORE_INPUT;
  862.     matchOptions.eWindowed           = DXUTMT_PRESERVE_INPUT;
  863.     matchOptions.eAdapterFormat      = DXUTMT_IGNORE_INPUT;
  864.     matchOptions.eVertexProcessing   = DXUTMT_IGNORE_INPUT;
  865.     if( bWindowed || (nSuggestedWidth != 0 && nSuggestedHeight != 0) )
  866.         matchOptions.eResolution     = DXUTMT_CLOSEST_TO_INPUT;
  867.     else
  868.         matchOptions.eResolution     = DXUTMT_IGNORE_INPUT;
  869.     matchOptions.eBackBufferFormat   = DXUTMT_IGNORE_INPUT;
  870.     matchOptions.eBackBufferCount    = DXUTMT_IGNORE_INPUT;
  871.     matchOptions.eMultiSample        = DXUTMT_IGNORE_INPUT;
  872.     matchOptions.eSwapEffect         = DXUTMT_IGNORE_INPUT;
  873.     matchOptions.eDepthFormat        = DXUTMT_IGNORE_INPUT;
  874.     matchOptions.eStencilFormat      = DXUTMT_IGNORE_INPUT;
  875.     matchOptions.ePresentFlags       = DXUTMT_IGNORE_INPUT;
  876.     matchOptions.eRefreshRate        = DXUTMT_IGNORE_INPUT;
  877.     matchOptions.ePresentInterval    = DXUTMT_IGNORE_INPUT;
  878.     DXUTDeviceSettings deviceSettings;
  879.     ZeroMemory( &deviceSettings, sizeof(DXUTDeviceSettings) );
  880.     deviceSettings.AdapterOrdinal      = AdapterOrdinal;
  881.     deviceSettings.pp.Windowed         = bWindowed;
  882.     deviceSettings.pp.BackBufferWidth  = nSuggestedWidth;
  883.     deviceSettings.pp.BackBufferHeight = nSuggestedHeight;
  884.     // Override with settings from the command line
  885.     if( GetDXUTState().GetOverrideWidth() != 0 )
  886.         deviceSettings.pp.BackBufferWidth = GetDXUTState().GetOverrideWidth();
  887.     if( GetDXUTState().GetOverrideHeight() != 0 )
  888.         deviceSettings.pp.BackBufferHeight = GetDXUTState().GetOverrideHeight();
  889.     if( GetDXUTState().GetOverrideAdapterOrdinal() != -1 )
  890.         deviceSettings.AdapterOrdinal = GetDXUTState().GetOverrideAdapterOrdinal();
  891.     if( GetDXUTState().GetOverrideFullScreen() )
  892.     {
  893.         deviceSettings.pp.Windowed = FALSE;
  894.         if( GetDXUTState().GetOverrideWidth() == 0 && GetDXUTState().GetOverrideHeight() == 0 )
  895.             matchOptions.eResolution = DXUTMT_IGNORE_INPUT;
  896.     }
  897.     if( GetDXUTState().GetOverrideWindowed() )
  898.         deviceSettings.pp.Windowed = TRUE;
  899.     if( GetDXUTState().GetOverrideForceHAL() )
  900.     {
  901.         deviceSettings.DeviceType = D3DDEVTYPE_HAL;
  902.         matchOptions.eDeviceType = DXUTMT_PRESERVE_INPUT;
  903.     }
  904.     if( GetDXUTState().GetOverrideForceREF() )
  905.     {
  906.         deviceSettings.DeviceType = D3DDEVTYPE_REF;
  907.         matchOptions.eDeviceType = DXUTMT_PRESERVE_INPUT;
  908.     }
  909.     if( GetDXUTState().GetOverrideForcePureHWVP() )
  910.     {
  911.         deviceSettings.BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
  912.         matchOptions.eVertexProcessing = DXUTMT_PRESERVE_INPUT;
  913.     }
  914.     else if( GetDXUTState().GetOverrideForceHWVP() )
  915.     {
  916.         deviceSettings.BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  917.         matchOptions.eVertexProcessing = DXUTMT_PRESERVE_INPUT;
  918.     }
  919.     else if( GetDXUTState().GetOverrideForceSWVP() )
  920.     {
  921.         deviceSettings.BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  922.         matchOptions.eVertexProcessing = DXUTMT_PRESERVE_INPUT;
  923.     }
  924.     if( GetDXUTState().GetOverrideForceVsync() == 0 )
  925.     {
  926.         deviceSettings.pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  927.         matchOptions.ePresentInterval = DXUTMT_PRESERVE_INPUT;
  928.     }
  929.     else if( GetDXUTState().GetOverrideForceVsync() == 1 )
  930.     {
  931.         deviceSettings.pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
  932.         matchOptions.ePresentInterval = DXUTMT_PRESERVE_INPUT;
  933.     }
  934.     hr = DXUTFindValidDeviceSettings( &deviceSettings, &deviceSettings, &matchOptions );
  935.     if( FAILED(hr) ) // the call will fail if no valid devices were found
  936.     {
  937.         DXUTDisplayErrorMessage( hr );
  938.         return DXUT_ERR( L"DXUTFindValidDeviceSettings", hr );
  939.     }
  940.     // Change to a Direct3D device created from the new device settings.  
  941.     // If there is an existing device, then either reset or recreated the scene
  942.     hr = DXUTChangeDevice( &deviceSettings, NULL, false, true );
  943.     if( FAILED(hr) )
  944.         return hr;
  945.     return S_OK;
  946. }
  947. //--------------------------------------------------------------------------------------
  948. // Passes a previously created Direct3D device for use by the framework.  
  949. // If DXUTCreateWindow() has not already been called, it will call it with the 
  950. // default parameters.  Instead of calling this, you can call DXUTCreateDevice() or 
  951. // DXUTCreateDeviceFromSettings() 
  952. //--------------------------------------------------------------------------------------
  953. HRESULT DXUTSetDevice( IDirect3DDevice9* pd3dDevice )
  954. {
  955.     HRESULT hr;
  956.     if( pd3dDevice == NULL )
  957.         return DXUT_ERR_MSGBOX( L"DXUTSetDevice", E_INVALIDARG );
  958.     // Not allowed to call this from inside the device callbacks
  959.     if( GetDXUTState().GetInsideDeviceCallback() )
  960.         return DXUT_ERR_MSGBOX( L"DXUTCreateWindow", E_FAIL );
  961.     GetDXUTState().SetDeviceCreateCalled( true );
  962.     // If DXUTCreateWindow() or DXUTSetWindow() has not already been called, 
  963.     // then call DXUTCreateWindow() with the default parameters.         
  964.     if( !GetDXUTState().GetWindowCreated() ) 
  965.     {
  966.         // If DXUTCreateWindow() or DXUTSetWindow() was already called and failed, then fail.
  967.         // DXUTCreateWindow() or DXUTSetWindow() must first succeed for this function to succeed
  968.         if( GetDXUTState().GetWindowCreateCalled() )
  969.             return E_FAIL; 
  970.         // If DXUTCreateWindow() or DXUTSetWindow() hasn't been called, then 
  971.         // automatically call DXUTCreateWindow() with default params
  972.         hr = DXUTCreateWindow();
  973.         if( FAILED(hr) )
  974.             return hr;
  975.     }
  976.     DXUTDeviceSettings* pDeviceSettings = new DXUTDeviceSettings;
  977.     if( pDeviceSettings == NULL )
  978.         return E_OUTOFMEMORY;
  979.     ZeroMemory( pDeviceSettings, sizeof(DXUTDeviceSettings) );
  980.     // Get the present params from the swap chain
  981.     IDirect3DSurface9* pBackBuffer = NULL;
  982.     hr = pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
  983.     if( SUCCEEDED(hr) )
  984.     {
  985.         IDirect3DSwapChain9* pSwapChain = NULL;
  986.         hr = pBackBuffer->GetContainer( IID_IDirect3DSwapChain9, (void**) &pSwapChain );
  987.         if( SUCCEEDED(hr) )
  988.         {
  989.             pSwapChain->GetPresentParameters( &pDeviceSettings->pp );
  990.             SAFE_RELEASE( pSwapChain );
  991.         }
  992.         SAFE_RELEASE( pBackBuffer );
  993.     }
  994.     D3DDEVICE_CREATION_PARAMETERS d3dCreationParams;
  995.     pd3dDevice->GetCreationParameters( &d3dCreationParams );
  996.     // Fill out the rest of the device settings struct
  997.     pDeviceSettings->AdapterOrdinal = d3dCreationParams.AdapterOrdinal;
  998.     pDeviceSettings->DeviceType     = d3dCreationParams.DeviceType;
  999.     DXUTFindAdapterFormat( pDeviceSettings->AdapterOrdinal, pDeviceSettings->DeviceType, 
  1000.                            pDeviceSettings->pp.BackBufferFormat, pDeviceSettings->pp.Windowed, 
  1001.                            &pDeviceSettings->AdapterFormat );
  1002.     pDeviceSettings->BehaviorFlags  = d3dCreationParams.BehaviorFlags;
  1003.     // Change to the Direct3D device passed in
  1004.     hr = DXUTChangeDevice( pDeviceSettings, pd3dDevice, false, false );
  1005.     delete pDeviceSettings;
  1006.     if( FAILED(hr) ) 
  1007.         return hr;
  1008.     return S_OK;
  1009. }
  1010. //--------------------------------------------------------------------------------------
  1011. // Tells the framework to change to a device created from the passed in device settings
  1012. // If DXUTCreateWindow() has not already been called, it will call it with the 
  1013. // default parameters.  Instead of calling this, you can call DXUTCreateDevice() 
  1014. // or DXUTSetDevice() 
  1015. //--------------------------------------------------------------------------------------
  1016. HRESULT DXUTCreateDeviceFromSettings( DXUTDeviceSettings* pDeviceSettings, bool bPreserveInput, bool bClipWindowToSingleAdapter )
  1017. {
  1018.     HRESULT hr;
  1019.     GetDXUTState().SetDeviceCreateCalled( true );
  1020.     // If DXUTCreateWindow() or DXUTSetWindow() has not already been called, 
  1021.     // then call DXUTCreateWindow() with the default parameters.         
  1022.     if( !GetDXUTState().GetWindowCreated() ) 
  1023.     {
  1024.         // If DXUTCreateWindow() or DXUTSetWindow() was already called and failed, then fail.
  1025.         // DXUTCreateWindow() or DXUTSetWindow() must first succeed for this function to succeed
  1026.         if( GetDXUTState().GetWindowCreateCalled() )
  1027.             return E_FAIL; 
  1028.         // If DXUTCreateWindow() or DXUTSetWindow() hasn't been called, then 
  1029.         // automatically call DXUTCreateWindow() with default params
  1030.         hr = DXUTCreateWindow();
  1031.         if( FAILED(hr) )
  1032.             return hr;
  1033.     }
  1034.     if( !bPreserveInput )
  1035.     {
  1036.         // If not preserving the input, then find the closest valid to it
  1037.         DXUTMatchOptions matchOptions;
  1038.         matchOptions.eAdapterOrdinal     = DXUTMT_CLOSEST_TO_INPUT;
  1039.         matchOptions.eDeviceType         = DXUTMT_CLOSEST_TO_INPUT;
  1040.         matchOptions.eWindowed           = DXUTMT_CLOSEST_TO_INPUT;
  1041.         matchOptions.eAdapterFormat      = DXUTMT_CLOSEST_TO_INPUT;
  1042.         matchOptions.eVertexProcessing   = DXUTMT_CLOSEST_TO_INPUT;
  1043.         matchOptions.eResolution         = DXUTMT_CLOSEST_TO_INPUT;
  1044.         matchOptions.eBackBufferFormat   = DXUTMT_CLOSEST_TO_INPUT;
  1045.         matchOptions.eBackBufferCount    = DXUTMT_CLOSEST_TO_INPUT;
  1046.         matchOptions.eMultiSample        = DXUTMT_CLOSEST_TO_INPUT;
  1047.         matchOptions.eSwapEffect         = DXUTMT_CLOSEST_TO_INPUT;
  1048.         matchOptions.eDepthFormat        = DXUTMT_CLOSEST_TO_INPUT;
  1049.         matchOptions.eStencilFormat      = DXUTMT_CLOSEST_TO_INPUT;
  1050.         matchOptions.ePresentFlags       = DXUTMT_CLOSEST_TO_INPUT;
  1051.         matchOptions.eRefreshRate        = DXUTMT_CLOSEST_TO_INPUT;
  1052.         matchOptions.ePresentInterval    = DXUTMT_CLOSEST_TO_INPUT;
  1053.         hr = DXUTFindValidDeviceSettings( pDeviceSettings, pDeviceSettings, &matchOptions );
  1054.         if( FAILED(hr) ) // the call will fail if no valid devices were found
  1055.         {
  1056.             DXUTDisplayErrorMessage( hr );
  1057.             return DXUT_ERR( L"DXUTFindValidDeviceSettings", hr );
  1058.         }
  1059.     }
  1060.     // Change to a Direct3D device created from the new device settings.  
  1061.     // If there is an existing device, then either reset or recreate the scene
  1062.     hr = DXUTChangeDevice( pDeviceSettings, NULL, false, bClipWindowToSingleAdapter );
  1063.     if( FAILED(hr) )
  1064.         return hr;
  1065.     return S_OK;
  1066. }
  1067. //--------------------------------------------------------------------------------------
  1068. // Toggle between full screen and windowed
  1069. //--------------------------------------------------------------------------------------
  1070. HRESULT DXUTToggleFullScreen()
  1071. {
  1072.     HRESULT hr;
  1073.     // Get the current device settings and flip the windowed state then
  1074.     // find the closest valid device settings with this change
  1075.     DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings();
  1076.     deviceSettings.pp.Windowed = !deviceSettings.pp.Windowed;
  1077.     DXUTMatchOptions matchOptions;
  1078.     matchOptions.eAdapterOrdinal     = DXUTMT_PRESERVE_INPUT;
  1079.     matchOptions.eDeviceType         = DXUTMT_CLOSEST_TO_INPUT;
  1080.     matchOptions.eWindowed           = DXUTMT_PRESERVE_INPUT;
  1081.     matchOptions.eAdapterFormat      = DXUTMT_IGNORE_INPUT;
  1082.     matchOptions.eVertexProcessing   = DXUTMT_CLOSEST_TO_INPUT;
  1083.     matchOptions.eBackBufferFormat   = DXUTMT_IGNORE_INPUT;
  1084.     matchOptions.eBackBufferCount    = DXUTMT_CLOSEST_TO_INPUT;
  1085.     matchOptions.eMultiSample        = DXUTMT_CLOSEST_TO_INPUT;
  1086.     matchOptions.eSwapEffect         = DXUTMT_CLOSEST_TO_INPUT;
  1087.     matchOptions.eDepthFormat        = DXUTMT_CLOSEST_TO_INPUT;
  1088.     matchOptions.eStencilFormat      = DXUTMT_CLOSEST_TO_INPUT;
  1089.     matchOptions.ePresentFlags       = DXUTMT_CLOSEST_TO_INPUT;
  1090.     matchOptions.eRefreshRate        = DXUTMT_IGNORE_INPUT;
  1091.     matchOptions.ePresentInterval    = DXUTMT_CLOSEST_TO_INPUT;
  1092.     // Go back to previous state
  1093.     UINT nWidth  = ( deviceSettings.pp.Windowed ) ? GetDXUTState().GetWindowBackBufferWidthAtModeChange() : GetDXUTState().GetFullScreenBackBufferWidthAtModeChange();
  1094.     UINT nHeight = ( deviceSettings.pp.Windowed ) ? GetDXUTState().GetWindowBackBufferHeightAtModeChange() : GetDXUTState().GetFullScreenBackBufferHeightAtModeChange();
  1095.     if( nWidth > 0 && nHeight > 0 )
  1096.     {
  1097.         matchOptions.eResolution = DXUTMT_CLOSEST_TO_INPUT;
  1098.         deviceSettings.pp.BackBufferWidth = nWidth;
  1099.         deviceSettings.pp.BackBufferHeight = nHeight;
  1100.     }
  1101.     else
  1102.     {
  1103.         // No previous data, so just switch to defaults
  1104.         matchOptions.eResolution = DXUTMT_IGNORE_INPUT;
  1105.     }
  1106.     
  1107.     hr = DXUTFindValidDeviceSettings( &deviceSettings, &deviceSettings, &matchOptions );
  1108.     if( SUCCEEDED(hr) ) 
  1109.     {
  1110.         // Create a Direct3D device using the new device settings.  
  1111.         // If there is an existing device, then it will either reset or recreate the scene.
  1112.         hr = DXUTChangeDevice( &deviceSettings, NULL, false, false );
  1113.         // If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback so nothing changed
  1114.         if( FAILED(hr) && (hr != E_ABORT) )
  1115.         {
  1116.             // Failed creating device, try to switch back.
  1117.             deviceSettings.pp.Windowed = !deviceSettings.pp.Windowed;
  1118.             UINT nWidth  = ( deviceSettings.pp.Windowed ) ? GetDXUTState().GetWindowBackBufferWidthAtModeChange() : GetDXUTState().GetFullScreenBackBufferWidthAtModeChange();
  1119.             UINT nHeight = ( deviceSettings.pp.Windowed ) ? GetDXUTState().GetWindowBackBufferHeightAtModeChange() : GetDXUTState().GetFullScreenBackBufferHeightAtModeChange();
  1120.             if( nWidth > 0 && nHeight > 0 )
  1121.             {
  1122.                 matchOptions.eResolution = DXUTMT_CLOSEST_TO_INPUT;
  1123.                 deviceSettings.pp.BackBufferWidth = nWidth;
  1124.                 deviceSettings.pp.BackBufferHeight = nHeight;
  1125.             }
  1126.             else
  1127.             {
  1128.                 matchOptions.eResolution = DXUTMT_IGNORE_INPUT;
  1129.             }
  1130.             
  1131.             DXUTFindValidDeviceSettings( &deviceSettings, &deviceSettings, &matchOptions );
  1132.             HRESULT hr2 = DXUTChangeDevice( &deviceSettings, NULL, false, false );
  1133.             if( FAILED(hr2) )
  1134.             {
  1135.                 // If this failed, then shutdown
  1136.                 DXUTShutdown();
  1137.             }
  1138.         }
  1139.     }
  1140.     return hr;
  1141. }
  1142. //--------------------------------------------------------------------------------------
  1143. // Toggle between HAL and REF
  1144. //--------------------------------------------------------------------------------------
  1145. HRESULT DXUTToggleREF()
  1146. {
  1147.     HRESULT hr;
  1148.     DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings();
  1149.     if( deviceSettings.DeviceType == D3DDEVTYPE_HAL )
  1150.         deviceSettings.DeviceType = D3DDEVTYPE_REF;
  1151.     else if( deviceSettings.DeviceType == D3DDEVTYPE_REF )
  1152.         deviceSettings.DeviceType = D3DDEVTYPE_HAL;
  1153.     DXUTMatchOptions matchOptions;
  1154.     matchOptions.eAdapterOrdinal     = DXUTMT_PRESERVE_INPUT;
  1155.     matchOptions.eDeviceType         = DXUTMT_PRESERVE_INPUT;
  1156.     matchOptions.eWindowed           = DXUTMT_CLOSEST_TO_INPUT;
  1157.     matchOptions.eAdapterFormat      = DXUTMT_CLOSEST_TO_INPUT;
  1158.     matchOptions.eVertexProcessing   = DXUTMT_CLOSEST_TO_INPUT;
  1159.     matchOptions.eResolution         = DXUTMT_CLOSEST_TO_INPUT;
  1160.     matchOptions.eBackBufferFormat   = DXUTMT_CLOSEST_TO_INPUT;
  1161.     matchOptions.eBackBufferCount    = DXUTMT_CLOSEST_TO_INPUT;
  1162.     matchOptions.eMultiSample        = DXUTMT_CLOSEST_TO_INPUT;
  1163.     matchOptions.eSwapEffect         = DXUTMT_CLOSEST_TO_INPUT;
  1164.     matchOptions.eDepthFormat        = DXUTMT_CLOSEST_TO_INPUT;
  1165.     matchOptions.eStencilFormat      = DXUTMT_CLOSEST_TO_INPUT;
  1166.     matchOptions.ePresentFlags       = DXUTMT_CLOSEST_TO_INPUT;
  1167.     matchOptions.eRefreshRate        = DXUTMT_CLOSEST_TO_INPUT;
  1168.     matchOptions.ePresentInterval    = DXUTMT_CLOSEST_TO_INPUT;
  1169.     
  1170.     hr = DXUTFindValidDeviceSettings( &deviceSettings, &deviceSettings, &matchOptions );
  1171.     if( SUCCEEDED(hr) ) 
  1172.     {
  1173.         // Create a Direct3D device using the new device settings.  
  1174.         // If there is an existing device, then it will either reset or recreate the scene.
  1175.         hr = DXUTChangeDevice( &deviceSettings, NULL, false, false );
  1176.         // If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback so nothing changed
  1177.         if( FAILED( hr ) && (hr != E_ABORT) )
  1178.         {
  1179.             // Failed creating device, try to switch back.
  1180.             if( deviceSettings.DeviceType == D3DDEVTYPE_HAL )
  1181.                 deviceSettings.DeviceType = D3DDEVTYPE_REF;
  1182.             else if( deviceSettings.DeviceType == D3DDEVTYPE_REF )
  1183.                 deviceSettings.DeviceType = D3DDEVTYPE_HAL;
  1184.             DXUTFindValidDeviceSettings( &deviceSettings, &deviceSettings, &matchOptions );
  1185.             HRESULT hr2 = DXUTChangeDevice( &deviceSettings, NULL, false, false );
  1186.             if( FAILED(hr2) )
  1187.             {
  1188.                 // If this failed, then shutdown
  1189.                 DXUTShutdown();
  1190.             }
  1191.         }
  1192.     }
  1193.     return hr;
  1194. }
  1195. //--------------------------------------------------------------------------------------
  1196. // Internal helper function to prepare the enumeration object by creating it if it 
  1197. // didn't already exist and enumerating if desired.
  1198. //--------------------------------------------------------------------------------------
  1199. CD3DEnumeration* DXUTPrepareEnumerationObject( bool bEnumerate )
  1200. {
  1201.     // Create a new CD3DEnumeration object and enumerate all devices unless its already been done
  1202.     CD3DEnumeration* pd3dEnum = GetDXUTState().GetD3DEnumeration();
  1203.     if( pd3dEnum == NULL )
  1204.     {
  1205.         pd3dEnum = DXUTGetEnumeration(); 
  1206.         GetDXUTState().SetD3DEnumeration( pd3dEnum );
  1207.         bEnumerate = true;
  1208.     }
  1209.     if( bEnumerate )
  1210.     {
  1211.         // Enumerate for each adapter all of the supported display modes, 
  1212.         // device types, adapter formats, back buffer formats, window/full screen support, 
  1213.         // depth stencil formats, multisampling types/qualities, and presentations intervals.
  1214.         //
  1215.         // For each combination of device type (HAL/REF), adapter format, back buffer format, and
  1216.         // IsWindowed it will call the app's ConfirmDevice callback.  This allows the app
  1217.         // to reject or allow that combination based on its caps/etc.  It also allows the 
  1218.         // app to change the BehaviorFlags.  The BehaviorFlags defaults non-pure HWVP 
  1219.         // if supported otherwise it will default to SWVP, however the app can change this 
  1220.         // through the ConfirmDevice callback.
  1221.         IDirect3D9* pD3D = DXUTGetD3DObject();
  1222.         pd3dEnum->Enumerate( pD3D, GetDXUTState().GetIsDeviceAcceptableFunc(), GetDXUTState().GetIsDeviceAcceptableFuncUserContext() );
  1223.     }
  1224.     
  1225.     return pd3dEnum;
  1226. }
  1227. //--------------------------------------------------------------------------------------
  1228. // This function tries to find valid device settings based upon the input device settings 
  1229. // struct and the match options.  For each device setting a match option in the 
  1230. // DXUTMatchOptions struct specifies how the function makes decisions.  For example, if 
  1231. // the caller wants a HAL device with a back buffer format of D3DFMT_A2B10G10R10 but the 
  1232. // HAL device on the system does not support D3DFMT_A2B10G10R10 however a REF device is 
  1233. // installed that does, then the function has a choice to either use REF or to change to 
  1234. // a back buffer format to compatible with the HAL device.  The match options lets the 
  1235. // caller control how these choices are made.
  1236. //
  1237. // Each match option must be one of the following types: 
  1238. //      DXUTMT_IGNORE_INPUT: Uses the closest valid value to a default 
  1239. //      DXUTMT_PRESERVE_INPUT: Uses the input without change, but may cause no valid device to be found
  1240. //      DXUTMT_CLOSEST_TO_INPUT: Uses the closest valid value to the input 
  1241. //
  1242. // If pMatchOptions is NULL then, all of the match options are assumed to be DXUTMT_IGNORE_INPUT.  
  1243. // The function returns failure if no valid device settings can be found otherwise 
  1244. // the function returns success and the valid device settings are written to pOut.
  1245. //--------------------------------------------------------------------------------------
  1246. HRESULT DXUTFindValidDeviceSettings( DXUTDeviceSettings* pOut, DXUTDeviceSettings* pIn, 
  1247.                                      DXUTMatchOptions* pMatchOptions )
  1248. {
  1249.     if( pOut == NULL )
  1250.         return DXUT_ERR_MSGBOX( L"DXUTFindValidDeviceSettings", E_INVALIDARG );
  1251.     CD3DEnumeration* pd3dEnum = DXUTPrepareEnumerationObject( false );
  1252.     IDirect3D9*      pD3D     = DXUTGetD3DObject();
  1253.     // Default to DXUTMT_IGNORE_INPUT for everything unless pMatchOptions isn't NULL
  1254.     DXUTMatchOptions defaultMatchOptions;
  1255.     if( NULL == pMatchOptions )
  1256.     {
  1257.         ZeroMemory( &defaultMatchOptions, sizeof(DXUTMatchOptions) );
  1258.         pMatchOptions = &defaultMatchOptions;
  1259.     }
  1260.     // Build an optimal device settings structure based upon the match 
  1261.     // options.  If the match option is set to ignore, then a optimal default value is used.
  1262.     // The default value may not exist on the system, but later this will be taken 
  1263.     // into account.
  1264.     DXUTDeviceSettings optimalDeviceSettings;
  1265.     DXUTBuildOptimalDeviceSettings( &optimalDeviceSettings, pIn, pMatchOptions );
  1266.     // Find the best combination of:
  1267.     //      Adapter Ordinal
  1268.     //      Device Type
  1269.     //      Adapter Format
  1270.     //      Back Buffer Format
  1271.     //      Windowed
  1272.     // given what's available on the system and the match options combined with the device settings input.
  1273.     // This combination of settings is encapsulated by the CD3DEnumDeviceSettingsCombo class.
  1274.     float fBestRanking = -1.0f;
  1275.     CD3DEnumDeviceSettingsCombo* pBestDeviceSettingsCombo = NULL;
  1276.     D3DDISPLAYMODE adapterDesktopDisplayMode;
  1277.     CGrowableArray<CD3DEnumAdapterInfo*>* pAdapterList = pd3dEnum->GetAdapterInfoList();
  1278.     for( int iAdapter=0; iAdapter<pAdapterList->GetSize(); iAdapter++ )
  1279.     {
  1280.         CD3DEnumAdapterInfo* pAdapterInfo = pAdapterList->GetAt(iAdapter);
  1281.         // Get the desktop display mode of adapter 
  1282.         pD3D->GetAdapterDisplayMode( pAdapterInfo->AdapterOrdinal, &adapterDesktopDisplayMode );
  1283.         // Enum all the device types supported by this adapter to find the best device settings
  1284.         for( int iDeviceInfo=0; iDeviceInfo<pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ )
  1285.         {
  1286.             CD3DEnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt(iDeviceInfo);
  1287.             // Enum all the device settings combinations.  A device settings combination is 
  1288.             // a unique set of an adapter format, back buffer format, and IsWindowed.
  1289.             for( int iDeviceCombo=0; iDeviceCombo<pDeviceInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ )
  1290.             {
  1291.                 CD3DEnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt(iDeviceCombo);
  1292.                 // If windowed mode the adapter format has to be the same as the desktop 
  1293.                 // display mode format so skip any that don't match
  1294.                 if (pDeviceSettingsCombo->Windowed && (pDeviceSettingsCombo->AdapterFormat != adapterDesktopDisplayMode.Format))
  1295.                     continue;
  1296.                 // Skip any combo that doesn't meet the preserve match options
  1297.                 if( false == DXUTDoesDeviceComboMatchPreserveOptions( pDeviceSettingsCombo, pIn, pMatchOptions ) )
  1298.                     continue;           
  1299.                 // Get a ranking number that describes how closely this device combo matches the optimal combo
  1300.                 float fCurRanking = DXUTRankDeviceCombo( pDeviceSettingsCombo, &optimalDeviceSettings, &adapterDesktopDisplayMode );
  1301.                 // If this combo better matches the input device settings then save it
  1302.                 if( fCurRanking > fBestRanking )
  1303.                 {
  1304.                     pBestDeviceSettingsCombo = pDeviceSettingsCombo;
  1305.                     fBestRanking = fCurRanking;
  1306.                 }                
  1307.             }
  1308.         }
  1309.     }
  1310.     // If no best device combination was found then fail
  1311.     if( pBestDeviceSettingsCombo == NULL ) 
  1312.         return DXUTERR_NOCOMPATIBLEDEVICES;
  1313.     // Using the best device settings combo found, build valid device settings taking heed of 
  1314.     // the match options and the input device settings
  1315.     DXUTDeviceSettings validDeviceSettings;
  1316.     DXUTBuildValidDeviceSettings( &validDeviceSettings, pBestDeviceSettingsCombo, pIn, pMatchOptions );
  1317.     *pOut = validDeviceSettings;
  1318.     return S_OK;
  1319. }
  1320. //--------------------------------------------------------------------------------------
  1321. // Internal helper function to build a device settings structure based upon the match 
  1322. // options.  If the match option is set to ignore, then a optimal default value is used.
  1323. // The default value may not exist on the system, but later this will be taken 
  1324. // into account.
  1325. //--------------------------------------------------------------------------------------
  1326. void DXUTBuildOptimalDeviceSettings( DXUTDeviceSettings* pOptimalDeviceSettings, 
  1327.                                      DXUTDeviceSettings* pDeviceSettingsIn, 
  1328.                                      DXUTMatchOptions* pMatchOptions )
  1329. {
  1330.     IDirect3D9* pD3D = DXUTGetD3DObject();
  1331.     D3DDISPLAYMODE adapterDesktopDisplayMode;
  1332.     ZeroMemory( pOptimalDeviceSettings, sizeof(DXUTDeviceSettings) ); 
  1333.     //---------------------
  1334.     // Adapter ordinal
  1335.     //---------------------    
  1336.     if( pMatchOptions->eAdapterOrdinal == DXUTMT_IGNORE_INPUT )
  1337.         pOptimalDeviceSettings->AdapterOrdinal = D3DADAPTER_DEFAULT; 
  1338.     else
  1339.         pOptimalDeviceSettings->AdapterOrdinal = pDeviceSettingsIn->AdapterOrdinal;      
  1340.     //---------------------
  1341.     // Device type
  1342.     //---------------------
  1343.     if( pMatchOptions->eDeviceType == DXUTMT_IGNORE_INPUT )
  1344.         pOptimalDeviceSettings->DeviceType = D3DDEVTYPE_HAL; 
  1345.     else
  1346.         pOptimalDeviceSettings->DeviceType = pDeviceSettingsIn->DeviceType;
  1347.     //---------------------
  1348.     // Windowed
  1349.     //---------------------
  1350.     if( pMatchOptions->eWindowed == DXUTMT_IGNORE_INPUT )
  1351.         pOptimalDeviceSettings->pp.Windowed = TRUE; 
  1352.     else
  1353.         pOptimalDeviceSettings->pp.Windowed = pDeviceSettingsIn->pp.Windowed;
  1354.     //---------------------
  1355.     // Adapter format
  1356.     //---------------------
  1357.     if( pMatchOptions->eAdapterFormat == DXUTMT_IGNORE_INPUT )
  1358.     {
  1359.         // If windowed, default to the desktop display mode
  1360.         // If fullscreen, default to the desktop display mode for quick mode change or 
  1361.         // default to D3DFMT_X8R8G8B8 if the desktop display mode is < 32bit
  1362.         pD3D->GetAdapterDisplayMode( pOptimalDeviceSettings->AdapterOrdinal, &adapterDesktopDisplayMode );
  1363.         if( pOptimalDeviceSettings->pp.Windowed || DXUTColorChannelBits(adapterDesktopDisplayMode.Format) >= 8 )
  1364.             pOptimalDeviceSettings->AdapterFormat = adapterDesktopDisplayMode.Format;
  1365.         else
  1366.             pOptimalDeviceSettings->AdapterFormat = D3DFMT_X8R8G8B8;
  1367.     }
  1368.     else
  1369.     {
  1370.         pOptimalDeviceSettings->AdapterFormat = pDeviceSettingsIn->AdapterFormat;
  1371.     }
  1372.     //---------------------
  1373.     // Vertex processing
  1374.     //---------------------
  1375.     if( pMatchOptions->eVertexProcessing == DXUTMT_IGNORE_INPUT )
  1376.         pOptimalDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; 
  1377.     else
  1378.         pOptimalDeviceSettings->BehaviorFlags = pDeviceSettingsIn->BehaviorFlags;
  1379.     //---------------------
  1380.     // Resolution
  1381.     //---------------------
  1382.     if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT )
  1383.     {
  1384.         // If windowed, default to 640x480
  1385.         // If fullscreen, default to the desktop res for quick mode change
  1386.         if( pOptimalDeviceSettings->pp.Windowed )
  1387.         {
  1388.             pOptimalDeviceSettings->pp.BackBufferWidth = 640;
  1389.             pOptimalDeviceSettings->pp.BackBufferHeight = 480;
  1390.         }
  1391.         else
  1392.         {
  1393.             pD3D->GetAdapterDisplayMode( pOptimalDeviceSettings->AdapterOrdinal, &adapterDesktopDisplayMode );
  1394.             pOptimalDeviceSettings->pp.BackBufferWidth = adapterDesktopDisplayMode.Width;
  1395.             pOptimalDeviceSettings->pp.BackBufferHeight = adapterDesktopDisplayMode.Height;
  1396.         }
  1397.     }
  1398.     else
  1399.     {
  1400.         pOptimalDeviceSettings->pp.BackBufferWidth = pDeviceSettingsIn->pp.BackBufferWidth;
  1401.         pOptimalDeviceSettings->pp.BackBufferHeight = pDeviceSettingsIn->pp.BackBufferHeight;
  1402.     }
  1403.     //---------------------
  1404.     // Back buffer format
  1405.     //---------------------
  1406.     if( pMatchOptions->eBackBufferFormat == DXUTMT_IGNORE_INPUT )
  1407.         pOptimalDeviceSettings->pp.BackBufferFormat = pOptimalDeviceSettings->AdapterFormat; // Default to match the adapter format
  1408.     else
  1409.         pOptimalDeviceSettings->pp.BackBufferFormat = pDeviceSettingsIn->pp.BackBufferFormat;
  1410.     //---------------------
  1411.     // Back buffer count
  1412.     //---------------------
  1413.     if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT )
  1414.         pOptimalDeviceSettings->pp.BackBufferCount = 2; // Default to triple buffering for perf gain
  1415.     else
  1416.         pOptimalDeviceSettings->pp.BackBufferCount = pDeviceSettingsIn->pp.BackBufferCount;
  1417.    
  1418.     //---------------------
  1419.     // Multisample
  1420.     //---------------------
  1421.     if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT )
  1422.     {
  1423.         // Default to no multisampling 
  1424.         pOptimalDeviceSettings->pp.MultiSampleType = D3DMULTISAMPLE_NONE;
  1425.         pOptimalDeviceSettings->pp.MultiSampleQuality = 0; 
  1426.     }
  1427.     else
  1428.     {
  1429.         pOptimalDeviceSettings->pp.MultiSampleType = pDeviceSettingsIn->pp.MultiSampleType;
  1430.         pOptimalDeviceSettings->pp.MultiSampleQuality = pDeviceSettingsIn->pp.MultiSampleQuality;
  1431.     }
  1432.     //---------------------
  1433.     // Swap effect
  1434.     //---------------------
  1435.     if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT )
  1436.         pOptimalDeviceSettings->pp.SwapEffect = D3DSWAPEFFECT_DISCARD; 
  1437.     else
  1438.         pOptimalDeviceSettings->pp.SwapEffect = pDeviceSettingsIn->pp.SwapEffect;
  1439.     //---------------------
  1440.     // Depth stencil 
  1441.     //---------------------
  1442.     if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT &&
  1443.         pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT )
  1444.     {
  1445.         UINT nBackBufferBits = DXUTColorChannelBits( pOptimalDeviceSettings->pp.BackBufferFormat );
  1446.         if( nBackBufferBits >= 8 )
  1447.             pOptimalDeviceSettings->pp.AutoDepthStencilFormat = D3DFMT_D32; 
  1448.         else
  1449.             pOptimalDeviceSettings->pp.AutoDepthStencilFormat = D3DFMT_D16; 
  1450.     }
  1451.     else
  1452.     {
  1453.         pOptimalDeviceSettings->pp.AutoDepthStencilFormat = pDeviceSettingsIn->pp.AutoDepthStencilFormat;
  1454.     }
  1455.     //---------------------
  1456.     // Present flags
  1457.     //---------------------
  1458.     if( pMatchOptions->ePresentFlags == DXUTMT_IGNORE_INPUT )
  1459.         pOptimalDeviceSettings->pp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
  1460.     else
  1461.         pOptimalDeviceSettings->pp.Flags = pDeviceSettingsIn->pp.Flags;
  1462.     //---------------------
  1463.     // Refresh rate
  1464.     //---------------------
  1465.     if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT )
  1466.         pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz = 0;
  1467.     else
  1468.         pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz = pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz;
  1469.     //---------------------
  1470.     // Present interval
  1471.     //---------------------
  1472.     if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT )
  1473.     {
  1474.         // For windowed and fullscreen, default to D3DPRESENT_INTERVAL_DEFAULT
  1475.         // which will wait for the vertical retrace period to prevent tearing.
  1476.         // For benchmarking, use D3DPRESENT_INTERVAL_DEFAULT  which will
  1477.         // will wait not for the vertical retrace period but may introduce tearing.
  1478.         pOptimalDeviceSettings->pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
  1479.     }
  1480.     else
  1481.     {
  1482.         pOptimalDeviceSettings->pp.PresentationInterval = pDeviceSettingsIn->pp.PresentationInterval;
  1483.     }
  1484. }
  1485. //--------------------------------------------------------------------------------------
  1486. // Returns false for any CD3DEnumDeviceSettingsCombo that doesn't meet the preserve 
  1487. // match options against the input pDeviceSettingsIn.
  1488. //--------------------------------------------------------------------------------------
  1489. bool DXUTDoesDeviceComboMatchPreserveOptions( CD3DEnumDeviceSettingsCombo* pDeviceSettingsCombo, 
  1490.                                                  DXUTDeviceSettings* pDeviceSettingsIn, 
  1491.                                                  DXUTMatchOptions* pMatchOptions )
  1492. {
  1493.     //---------------------
  1494.     // Adapter ordinal
  1495.     //---------------------
  1496.     if( pMatchOptions->eAdapterOrdinal == DXUTMT_PRESERVE_INPUT && 
  1497.         (pDeviceSettingsCombo->AdapterOrdinal != pDeviceSettingsIn->AdapterOrdinal) )
  1498.         return false;
  1499.     //---------------------
  1500.     // Device type
  1501.     //---------------------
  1502.     if( pMatchOptions->eDeviceType == DXUTMT_PRESERVE_INPUT && 
  1503.         (pDeviceSettingsCombo->DeviceType != pDeviceSettingsIn->DeviceType) )
  1504.         return false;
  1505.     //---------------------
  1506.     // Windowed
  1507.     //---------------------
  1508.     if( pMatchOptions->eWindowed == DXUTMT_PRESERVE_INPUT && 
  1509.         (pDeviceSettingsCombo->Windowed != pDeviceSettingsIn->pp.Windowed) )
  1510.         return false;
  1511.     //---------------------
  1512.     // Adapter format
  1513.     //---------------------
  1514.     if( pMatchOptions->eAdapterFormat == DXUTMT_PRESERVE_INPUT && 
  1515.         (pDeviceSettingsCombo->AdapterFormat != pDeviceSettingsIn->AdapterFormat) )
  1516.         return false;
  1517.     //---------------------
  1518.     // Vertex processing
  1519.     //---------------------
  1520.     // If keep VP and input has HWVP, then skip if this combo doesn't have HWTL 
  1521.     if( pMatchOptions->eVertexProcessing == DXUTMT_PRESERVE_INPUT && 
  1522.         ((pDeviceSettingsIn->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0) && 
  1523.         ((pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0) )
  1524.         return false;
  1525.     //---------------------
  1526.     // Resolution
  1527.     //---------------------
  1528.     // If keep resolution then check that width and height supported by this combo
  1529.     if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT )
  1530.     {
  1531.         bool bFound = false;
  1532.         for( int i=0; i< pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); i++ )
  1533.         {
  1534.             D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( i );
  1535.             if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat )
  1536.                 continue; // Skip this display mode if it doesn't match the combo's adapter format
  1537.             if( displayMode.Width == pDeviceSettingsIn->pp.BackBufferWidth &&
  1538.                 displayMode.Height == pDeviceSettingsIn->pp.BackBufferHeight )
  1539.             {
  1540.                 bFound = true;
  1541.                 break;
  1542.             }
  1543.         }
  1544.         // If the width and height are not supported by this combo, return false
  1545.         if( !bFound )
  1546.             return false;
  1547.     }
  1548.     //---------------------
  1549.     // Back buffer format
  1550.     //---------------------
  1551.     if( pMatchOptions->eBackBufferFormat == DXUTMT_PRESERVE_INPUT && 
  1552.         pDeviceSettingsCombo->BackBufferFormat != pDeviceSettingsIn->pp.BackBufferFormat )
  1553.         return false;
  1554.     //---------------------
  1555.     // Back buffer count
  1556.     //---------------------
  1557.     // No caps for the back buffer count
  1558.     //---------------------
  1559.     // Multisample
  1560.     //---------------------
  1561.     if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT )
  1562.     {
  1563.         bool bFound = false;
  1564.         for( int i=0; i<pDeviceSettingsCombo->multiSampleTypeList.GetSize(); i++ )
  1565.         {
  1566.             D3DMULTISAMPLE_TYPE msType = pDeviceSettingsCombo->multiSampleTypeList.GetAt(i);
  1567.             DWORD msQuality  = pDeviceSettingsCombo->multiSampleQualityList.GetAt(i);
  1568.             if( msType == pDeviceSettingsIn->pp.MultiSampleType &&
  1569.                 msQuality >= pDeviceSettingsIn->pp.MultiSampleQuality )
  1570.             {
  1571.                 bFound = true;
  1572.                 break;
  1573.             }
  1574.         }
  1575.         // If multisample type/quality not supported by this combo, then return false
  1576.         if( !bFound )
  1577.             return false;
  1578.     }
  1579.         
  1580.     //---------------------
  1581.     // Swap effect
  1582.     //---------------------
  1583.     // No caps for swap effects
  1584.     //---------------------
  1585.     // Depth stencil 
  1586.     //---------------------
  1587.     // If keep depth stencil format then check that the depth stencil format is supported by this combo
  1588.     if( pMatchOptions->eDepthFormat == DXUTMT_PRESERVE_INPUT &&
  1589.         pMatchOptions->eStencilFormat == DXUTMT_PRESERVE_INPUT )
  1590.     {
  1591.         if( pDeviceSettingsIn->pp.AutoDepthStencilFormat != D3DFMT_UNKNOWN &&
  1592.             !pDeviceSettingsCombo->depthStencilFormatList.Contains( pDeviceSettingsIn->pp.AutoDepthStencilFormat ) )
  1593.             return false;
  1594.     }
  1595.     // If keep depth format then check that the depth format is supported by this combo
  1596.     if( pMatchOptions->eDepthFormat == DXUTMT_PRESERVE_INPUT &&
  1597.         pDeviceSettingsIn->pp.AutoDepthStencilFormat != D3DFMT_UNKNOWN )
  1598.     {
  1599.         bool bFound = false;
  1600.         UINT dwDepthBits = DXUTDepthBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat );
  1601.         for( int i=0; i<pDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
  1602.         {
  1603.             D3DFORMAT depthStencilFmt = pDeviceSettingsCombo->depthStencilFormatList.GetAt(i);
  1604.             UINT dwCurDepthBits = DXUTDepthBits( depthStencilFmt );
  1605.             if( dwCurDepthBits - dwDepthBits == 0)
  1606.                 bFound = true;
  1607.         }
  1608.         if( !bFound )
  1609.             return false;
  1610.     }
  1611.     // If keep depth format then check that the depth format is supported by this combo
  1612.     if( pMatchOptions->eStencilFormat == DXUTMT_PRESERVE_INPUT &&
  1613.         pDeviceSettingsIn->pp.AutoDepthStencilFormat != D3DFMT_UNKNOWN )
  1614.     {
  1615.         bool bFound = false;
  1616.         UINT dwStencilBits = DXUTStencilBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat );
  1617.         for( int i=0; i<pDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
  1618.         {
  1619.             D3DFORMAT depthStencilFmt = pDeviceSettingsCombo->depthStencilFormatList.GetAt(i);
  1620.             UINT dwCurStencilBits = DXUTStencilBits( depthStencilFmt );
  1621.             if( dwCurStencilBits - dwStencilBits == 0)
  1622.                 bFound = true;
  1623.         }
  1624.         if( !bFound )
  1625.             return false;
  1626.     }
  1627.     //---------------------
  1628.     // Present flags
  1629.     //---------------------
  1630.     // No caps for the present flags
  1631.     //---------------------
  1632.     // Refresh rate
  1633.     //---------------------
  1634.     // If keep refresh rate then check that the resolution is supported by this combo
  1635.     if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT )
  1636.     {
  1637.         bool bFound = false;
  1638.         for( int i=0; i<pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); i++ )
  1639.         {
  1640.             D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( i );
  1641.             if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat )
  1642.                 continue;
  1643.             if( displayMode.RefreshRate == pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz )
  1644.             {
  1645.                 bFound = true;
  1646.                 break;
  1647.             }
  1648.         }
  1649.         // If refresh rate not supported by this combo, then return false
  1650.         if( !bFound )
  1651.             return false;
  1652.     }
  1653.     //---------------------
  1654.     // Present interval
  1655.     //---------------------
  1656.     // If keep present interval then check that the present interval is supported by this combo
  1657.     if( pMatchOptions->ePresentInterval == DXUTMT_PRESERVE_INPUT &&
  1658.         !pDeviceSettingsCombo->presentIntervalList.Contains( pDeviceSettingsIn->pp.PresentationInterval ) )
  1659.         return false;
  1660.     return true;
  1661. }
  1662. //--------------------------------------------------------------------------------------
  1663. // Returns a ranking number that describes how closely this device 
  1664. // combo matches the optimal combo based on the match options and the optimal device settings
  1665. //--------------------------------------------------------------------------------------
  1666. float DXUTRankDeviceCombo( CD3DEnumDeviceSettingsCombo* pDeviceSettingsCombo, 
  1667.                            DXUTDeviceSettings* pOptimalDeviceSettings,
  1668.                            D3DDISPLAYMODE* pAdapterDesktopDisplayMode )
  1669. {
  1670.     float fCurRanking = 0.0f; 
  1671.     // Arbitrary weights.  Gives preference to the ordinal, device type, and windowed
  1672.     const float fAdapterOrdinalWeight   = 1000.0f;
  1673.     const float fDeviceTypeWeight       = 100.0f;
  1674.     const float fWindowWeight           = 10.0f;
  1675.     const float fAdapterFormatWeight    = 1.0f;
  1676.     const float fVertexProcessingWeight = 1.0f;
  1677.     const float fResolutionWeight       = 1.0f;
  1678.     const float fBackBufferFormatWeight = 1.0f;
  1679.     const float fMultiSampleWeight      = 1.0f;
  1680.     const float fDepthStencilWeight     = 1.0f;
  1681.     const float fRefreshRateWeight      = 1.0f;
  1682.     const float fPresentIntervalWeight  = 1.0f;
  1683.     //---------------------
  1684.     // Adapter ordinal
  1685.     //---------------------
  1686.     if( pDeviceSettingsCombo->AdapterOrdinal == pOptimalDeviceSettings->AdapterOrdinal )
  1687.         fCurRanking += fAdapterOrdinalWeight;
  1688.     //---------------------
  1689.     // Device type
  1690.     //---------------------
  1691.     if( pDeviceSettingsCombo->DeviceType == pOptimalDeviceSettings->DeviceType )
  1692.         fCurRanking += fDeviceTypeWeight;
  1693.     // Slightly prefer HAL 
  1694.     if( pDeviceSettingsCombo->DeviceType == D3DDEVTYPE_HAL )
  1695.         fCurRanking += 0.1f; 
  1696.     //---------------------
  1697.     // Windowed
  1698.     //---------------------
  1699.     if( pDeviceSettingsCombo->Windowed == pOptimalDeviceSettings->pp.Windowed )
  1700.         fCurRanking += fWindowWeight;
  1701.     //---------------------
  1702.     // Adapter format
  1703.     //---------------------
  1704.     if( pDeviceSettingsCombo->AdapterFormat == pOptimalDeviceSettings->AdapterFormat )
  1705.     {
  1706.         fCurRanking += fAdapterFormatWeight;
  1707.     }
  1708.     else
  1709.     {
  1710.         int nBitDepthDelta = abs( (long) DXUTColorChannelBits(pDeviceSettingsCombo->AdapterFormat) -
  1711.                                   (long) DXUTColorChannelBits(pOptimalDeviceSettings->AdapterFormat) );
  1712.         float fScale = __max(0.9f - (float)nBitDepthDelta*0.2f, 0.0f);
  1713.         fCurRanking += fScale * fAdapterFormatWeight;
  1714.     }
  1715.     if( !pDeviceSettingsCombo->Windowed )
  1716.     {
  1717.         // Slightly prefer when it matches the desktop format or is D3DFMT_X8R8G8B8
  1718.         bool bAdapterOptimalMatch;
  1719.         if( DXUTColorChannelBits(pAdapterDesktopDisplayMode->Format) >= 8 )
  1720.             bAdapterOptimalMatch = (pDeviceSettingsCombo->AdapterFormat == pAdapterDesktopDisplayMode->Format);
  1721.         else
  1722.             bAdapterOptimalMatch = (pDeviceSettingsCombo->AdapterFormat == D3DFMT_X8R8G8B8);
  1723.         if( bAdapterOptimalMatch )
  1724.             fCurRanking += 0.1f;
  1725.     }
  1726.     //---------------------
  1727.     // Vertex processing
  1728.     //---------------------
  1729.     if( (pOptimalDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 || 
  1730.         (pOptimalDeviceSettings->BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) != 0 )
  1731.     {
  1732.         if( (pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0 )
  1733.             fCurRanking += fVertexProcessingWeight;
  1734.     }
  1735.     // Slightly prefer HW T&L
  1736.     if( (pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0 )
  1737.         fCurRanking += 0.1f;
  1738.     //---------------------
  1739.     // Resolution
  1740.     //---------------------
  1741.     bool bResolutionFound = false;
  1742.     for( int idm = 0; idm < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); idm++ )
  1743.     {
  1744.         D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( idm );
  1745.         if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat )
  1746.             continue;
  1747.         if( displayMode.Width == pOptimalDeviceSettings->pp.BackBufferWidth &&
  1748.             displayMode.Height == pOptimalDeviceSettings->pp.BackBufferHeight )
  1749.             bResolutionFound = true;
  1750.     }
  1751.     if( bResolutionFound )
  1752.         fCurRanking += fResolutionWeight;
  1753.     //---------------------
  1754.     // Back buffer format
  1755.     //---------------------
  1756.     if( pDeviceSettingsCombo->BackBufferFormat == pOptimalDeviceSettings->pp.BackBufferFormat )
  1757.     {
  1758.         fCurRanking += fBackBufferFormatWeight;
  1759.     }
  1760.     else
  1761.     {
  1762.         int nBitDepthDelta = abs( (long) DXUTColorChannelBits(pDeviceSettingsCombo->BackBufferFormat) -
  1763.                                   (long) DXUTColorChannelBits(pOptimalDeviceSettings->pp.BackBufferFormat) );
  1764.         float fScale = __max(0.9f - (float)nBitDepthDelta*0.2f, 0.0f);
  1765.         fCurRanking += fScale * fBackBufferFormatWeight;
  1766.     }
  1767.     // Check if this back buffer format is the same as 
  1768.     // the adapter format since this is preferred.
  1769.     bool bAdapterMatchesBB = (pDeviceSettingsCombo->BackBufferFormat == pDeviceSettingsCombo->AdapterFormat);
  1770.     if( bAdapterMatchesBB )
  1771.         fCurRanking += 0.1f;
  1772.     //---------------------
  1773.     // Back buffer count
  1774.     //---------------------
  1775.     // No caps for the back buffer count
  1776.     //---------------------
  1777.     // Multisample
  1778.     //---------------------
  1779.     bool bMultiSampleFound = false;
  1780.     for( int i=0; i<pDeviceSettingsCombo->multiSampleTypeList.GetSize(); i++ )
  1781.     {
  1782.         D3DMULTISAMPLE_TYPE msType = pDeviceSettingsCombo->multiSampleTypeList.GetAt(i);
  1783.         DWORD msQuality  = pDeviceSettingsCombo->multiSampleQualityList.GetAt(i);
  1784.         if( msType == pOptimalDeviceSettings->pp.MultiSampleType &&
  1785.             msQuality >= pOptimalDeviceSettings->pp.MultiSampleQuality )
  1786.         {
  1787.             bMultiSampleFound = true;
  1788.             break;
  1789.         }
  1790.     }
  1791.     if( bMultiSampleFound )
  1792.         fCurRanking += fMultiSampleWeight;
  1793.         
  1794.     //---------------------
  1795.     // Swap effect
  1796.     //---------------------
  1797.     // No caps for swap effects
  1798.     //---------------------
  1799.     // Depth stencil 
  1800.     //---------------------
  1801.     if( pDeviceSettingsCombo->depthStencilFormatList.Contains( pOptimalDeviceSettings->pp.AutoDepthStencilFormat ) )
  1802.         fCurRanking += fDepthStencilWeight;
  1803.     //---------------------
  1804.     // Present flags
  1805.     //---------------------
  1806.     // No caps for the present flags
  1807.     //---------------------
  1808.     // Refresh rate
  1809.     //---------------------
  1810.     bool bRefreshFound = false;
  1811.     for( int idm = 0; idm < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); idm++ )
  1812.     {
  1813.         D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( idm );
  1814.         if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat )
  1815.             continue;
  1816.         if( displayMode.RefreshRate == pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz )
  1817.             bRefreshFound = true;
  1818.     }
  1819.     if( bRefreshFound )
  1820.         fCurRanking += fRefreshRateWeight;
  1821.     //---------------------
  1822.     // Present interval
  1823.     //---------------------
  1824.     // If keep present interval then check that the present interval is supported by this combo
  1825.     if( pDeviceSettingsCombo->presentIntervalList.Contains( pOptimalDeviceSettings->pp.PresentationInterval ) )
  1826.         fCurRanking += fPresentIntervalWeight;
  1827.     return fCurRanking;
  1828. }
  1829. //--------------------------------------------------------------------------------------
  1830. // Builds valid device settings using the match options, the input device settings, and the 
  1831. // best device settings combo found.
  1832. //--------------------------------------------------------------------------------------
  1833. void DXUTBuildValidDeviceSettings( DXUTDeviceSettings* pValidDeviceSettings, 
  1834.                                    CD3DEnumDeviceSettingsCombo* pBestDeviceSettingsCombo, 
  1835.                                    DXUTDeviceSettings* pDeviceSettingsIn, 
  1836.                                    DXUTMatchOptions* pMatchOptions )
  1837. {
  1838.     IDirect3D9* pD3D = DXUTGetD3DObject();
  1839.     D3DDISPLAYMODE adapterDesktopDisplayMode;
  1840.     pD3D->GetAdapterDisplayMode( pBestDeviceSettingsCombo->AdapterOrdinal, &adapterDesktopDisplayMode );
  1841.     // For each setting pick the best, taking into account the match options and 
  1842.     // what's supported by the device
  1843.     //---------------------
  1844.     // Adapter Ordinal
  1845.     //---------------------
  1846.     // Just using pBestDeviceSettingsCombo->AdapterOrdinal
  1847.     //---------------------
  1848.     // Device Type
  1849.     //---------------------
  1850.     // Just using pBestDeviceSettingsCombo->DeviceType
  1851.     //---------------------
  1852.     // Windowed 
  1853.     //---------------------
  1854.     // Just using pBestDeviceSettingsCombo->Windowed
  1855.     //---------------------
  1856.     // Adapter Format
  1857.     //---------------------
  1858.     // Just using pBestDeviceSettingsCombo->AdapterFormat
  1859.     //---------------------
  1860.     // Vertex processing
  1861.     //---------------------
  1862.     DWORD dwBestBehaviorFlags = 0;
  1863.     if( pMatchOptions->eVertexProcessing == DXUTMT_PRESERVE_INPUT )   
  1864.     {
  1865.         dwBestBehaviorFlags = pDeviceSettingsIn->BehaviorFlags;
  1866.     }
  1867.     else if( pMatchOptions->eVertexProcessing == DXUTMT_IGNORE_INPUT )    
  1868.     {
  1869.         // The framework defaults to HWVP if available otherwise use SWVP
  1870.         if ((pBestDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0)
  1871.             dwBestBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
  1872.         else
  1873.             dwBestBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  1874.     }
  1875.     else // if( pMatchOptions->eVertexProcessing == DXUTMT_CLOSEST_TO_INPUT )    
  1876.     {
  1877.         // Default to input, and fallback to SWVP if HWVP not available 
  1878.         dwBestBehaviorFlags = pDeviceSettingsIn->BehaviorFlags;
  1879.         if ((pBestDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 && 
  1880.             ( (dwBestBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 || 
  1881.               (dwBestBehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) != 0) )
  1882.         {
  1883.             dwBestBehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  1884.             dwBestBehaviorFlags &= ~D3DCREATE_MIXED_VERTEXPROCESSING;
  1885.             dwBestBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  1886.         }
  1887.         // One of these must be selected
  1888.         if( (dwBestBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) == 0 &&
  1889.             (dwBestBehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) == 0 &&
  1890.             (dwBestBehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) == 0 )
  1891.         {
  1892.             if ((pBestDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0)
  1893.                 dwBestBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
  1894.             else
  1895.                 dwBestBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  1896.         }
  1897.     }
  1898.     //---------------------
  1899.     // Resolution
  1900.     //---------------------
  1901.     D3DDISPLAYMODE bestDisplayMode;  
  1902.     if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT )   
  1903.     {
  1904.         bestDisplayMode.Width = pDeviceSettingsIn->pp.BackBufferWidth;
  1905.         bestDisplayMode.Height = pDeviceSettingsIn->pp.BackBufferHeight;
  1906.     }
  1907.     else 
  1908.     {
  1909.         D3DDISPLAYMODE displayModeIn;  
  1910.         if( pMatchOptions->eResolution == DXUTMT_CLOSEST_TO_INPUT &&
  1911.             pDeviceSettingsIn )   
  1912.         {
  1913.             displayModeIn.Width = pDeviceSettingsIn->pp.BackBufferWidth;
  1914.             displayModeIn.Height = pDeviceSettingsIn->pp.BackBufferHeight;
  1915.         }
  1916.         else // if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT )   
  1917.         {
  1918.             if( pBestDeviceSettingsCombo->Windowed )
  1919.             {
  1920.                 // The framework defaults to 640x480 for windowed
  1921.                 displayModeIn.Width = 640;
  1922.                 displayModeIn.Height = 480;
  1923.             }
  1924.             else
  1925.             {
  1926.                 // The framework defaults to desktop resolution for fullscreen to try to avoid slow mode change
  1927.                 displayModeIn.Width = adapterDesktopDisplayMode.Width;
  1928.                 displayModeIn.Height = adapterDesktopDisplayMode.Height;
  1929.             }
  1930.         }
  1931.         // Call a helper function to find the closest valid display mode to the optimal 
  1932.         DXUTFindValidResolution( pBestDeviceSettingsCombo, displayModeIn, &bestDisplayMode );
  1933.     }
  1934.     //---------------------
  1935.     // Back Buffer Format
  1936.     //---------------------
  1937.     // Just using pBestDeviceSettingsCombo->BackBufferFormat
  1938.     //---------------------
  1939.     // Back buffer count
  1940.     //---------------------
  1941.     UINT bestBackBufferCount;
  1942.     if( pMatchOptions->eBackBufferCount == DXUTMT_PRESERVE_INPUT )   
  1943.     {
  1944.         bestBackBufferCount = pDeviceSettingsIn->pp.BackBufferCount;
  1945.     }
  1946.     else if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT )   
  1947.     {
  1948.         // The framework defaults to triple buffering 
  1949.         bestBackBufferCount = 2;
  1950.     }
  1951.     else // if( pMatchOptions->eBackBufferCount == DXUTMT_CLOSEST_TO_INPUT )   
  1952.     {
  1953.         bestBackBufferCount = pDeviceSettingsIn->pp.BackBufferCount;
  1954.         if( bestBackBufferCount > 3 )
  1955.             bestBackBufferCount = 3;
  1956.         if( bestBackBufferCount < 1 )
  1957.             bestBackBufferCount = 1;
  1958.     }
  1959.     
  1960.     //---------------------
  1961.     // Multisample
  1962.     //---------------------
  1963.     D3DMULTISAMPLE_TYPE bestMultiSampleType;
  1964.     DWORD bestMultiSampleQuality;
  1965.     if( pDeviceSettingsIn && pDeviceSettingsIn->pp.SwapEffect != D3DSWAPEFFECT_DISCARD )
  1966.     {
  1967.         // Swap effect is not set to discard so multisampling has to off
  1968.         bestMultiSampleType = D3DMULTISAMPLE_NONE;
  1969.         bestMultiSampleQuality = 0;
  1970.     }
  1971.     else
  1972.     {
  1973.         if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT )   
  1974.         {
  1975.             bestMultiSampleType    = pDeviceSettingsIn->pp.MultiSampleType;
  1976.             bestMultiSampleQuality = pDeviceSettingsIn->pp.MultiSampleQuality;
  1977.         }
  1978.         else if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT )   
  1979.         {
  1980.             // Default to no multisampling (always supported)
  1981.             bestMultiSampleType = D3DMULTISAMPLE_NONE;
  1982.             bestMultiSampleQuality = 0;
  1983.         }
  1984.         else if( pMatchOptions->eMultiSample == DXUTMT_CLOSEST_TO_INPUT )   
  1985.         {
  1986.             // Default to no multisampling (always supported)
  1987.             bestMultiSampleType = D3DMULTISAMPLE_NONE;
  1988.             bestMultiSampleQuality = 0;
  1989.             for( int i=0; i < pBestDeviceSettingsCombo->multiSampleTypeList.GetSize(); i++ )
  1990.             {
  1991.                 D3DMULTISAMPLE_TYPE type = pBestDeviceSettingsCombo->multiSampleTypeList.GetAt(i);
  1992.                 DWORD qualityLevels = pBestDeviceSettingsCombo->multiSampleQualityList.GetAt(i);
  1993.                 
  1994.                 // Check whether supported type is closer to the input than our current best
  1995.                 if( abs(type - pDeviceSettingsIn->pp.MultiSampleType) < abs(bestMultiSampleType - pDeviceSettingsIn->pp.MultiSampleType) )
  1996.                 {
  1997.                     bestMultiSampleType = type; 
  1998.                     bestMultiSampleQuality = __min( qualityLevels-1, pDeviceSettingsIn->pp.MultiSampleQuality );
  1999.                 }
  2000.             }
  2001.         }
  2002.         else
  2003.         {
  2004.             // Error case
  2005.             bestMultiSampleType = D3DMULTISAMPLE_NONE;
  2006.             bestMultiSampleQuality = 0;
  2007.         }
  2008.     }
  2009.     //---------------------
  2010.     // Swap effect
  2011.     //---------------------
  2012.     D3DSWAPEFFECT bestSwapEffect;
  2013.     if( pMatchOptions->eSwapEffect == DXUTMT_PRESERVE_INPUT )   
  2014.     {
  2015.         bestSwapEffect = pDeviceSettingsIn->pp.SwapEffect;
  2016.     }
  2017.     else if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT )   
  2018.     {
  2019.         bestSwapEffect = D3DSWAPEFFECT_DISCARD;
  2020.     }
  2021.     else // if( pMatchOptions->eSwapEffect == DXUTMT_CLOSEST_TO_INPUT )   
  2022.     {
  2023.         bestSwapEffect = pDeviceSettingsIn->pp.SwapEffect;
  2024.         // Swap effect has to be one of these 3
  2025.         if( bestSwapEffect != D3DSWAPEFFECT_DISCARD &&
  2026.             bestSwapEffect != D3DSWAPEFFECT_FLIP &&
  2027.             bestSwapEffect != D3DSWAPEFFECT_COPY )
  2028.         {
  2029.             bestSwapEffect = D3DSWAPEFFECT_DISCARD;
  2030.         }
  2031.     }
  2032.     //---------------------
  2033.     // Depth stencil 
  2034.     //---------------------
  2035.     D3DFORMAT bestDepthStencilFormat;
  2036.     BOOL bestEnableAutoDepthStencil;
  2037.     CGrowableArray< int > depthStencilRanking;
  2038.     depthStencilRanking.SetSize( pBestDeviceSettingsCombo->depthStencilFormatList.GetSize() );
  2039.     UINT dwBackBufferBitDepth = DXUTColorChannelBits( pBestDeviceSettingsCombo->BackBufferFormat );       
  2040.     UINT dwInputDepthBitDepth = 0;
  2041.     if( pDeviceSettingsIn )
  2042.         dwInputDepthBitDepth = DXUTDepthBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat );
  2043.     for( int i=0; i<pBestDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
  2044.     {
  2045.         D3DFORMAT curDepthStencilFmt = pBestDeviceSettingsCombo->depthStencilFormatList.GetAt(i);
  2046.         DWORD dwCurDepthBitDepth = DXUTDepthBits( curDepthStencilFmt );
  2047.         int nRanking;
  2048.         if( pMatchOptions->eDepthFormat == DXUTMT_PRESERVE_INPUT )
  2049.         {                       
  2050.             // Need to match bit depth of input
  2051.             if(dwCurDepthBitDepth == dwInputDepthBitDepth)
  2052.                 nRanking = 0;
  2053.             else
  2054.                 nRanking = 10000;
  2055.         }
  2056.         else if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT )
  2057.         {
  2058.             // Prefer match of backbuffer bit depth
  2059.             nRanking = abs((int)dwCurDepthBitDepth - (int)dwBackBufferBitDepth*4);
  2060.         }
  2061.         else // if( pMatchOptions->eDepthFormat == DXUTMT_CLOSEST_TO_INPUT )
  2062.         {
  2063.             // Prefer match of input depth format bit depth
  2064.             nRanking = abs((int)dwCurDepthBitDepth - (int)dwInputDepthBitDepth);
  2065.         }
  2066.         depthStencilRanking.Add( nRanking );
  2067.     }
  2068.     UINT dwInputStencilBitDepth = 0;
  2069.     if( pDeviceSettingsIn )
  2070.         dwInputStencilBitDepth = DXUTStencilBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat );
  2071.     for( int i=0; i<pBestDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
  2072.     {
  2073.         D3DFORMAT curDepthStencilFmt = pBestDeviceSettingsCombo->depthStencilFormatList.GetAt(i);
  2074.         int nRanking = depthStencilRanking.GetAt(i);
  2075.         DWORD dwCurStencilBitDepth = DXUTStencilBits( curDepthStencilFmt );
  2076.         if( pMatchOptions->eStencilFormat == DXUTMT_PRESERVE_INPUT )
  2077.         {                       
  2078.             // Need to match bit depth of input
  2079.             if(dwCurStencilBitDepth == dwInputStencilBitDepth)
  2080.                 nRanking += 0;
  2081.             else
  2082.                 nRanking += 10000;
  2083.         }
  2084.         else if( pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT )
  2085.         {
  2086.             // Prefer 0 stencil bit depth
  2087.             nRanking += dwCurStencilBitDepth;
  2088.         }
  2089.         else // if( pMatchOptions->eStencilFormat == DXUTMT_CLOSEST_TO_INPUT )
  2090.         {
  2091.             // Prefer match of input stencil format bit depth
  2092.             nRanking += abs((int)dwCurStencilBitDepth - (int)dwInputStencilBitDepth);
  2093.         }
  2094.         depthStencilRanking.SetAt( i, nRanking );
  2095.     }
  2096.     int nBestRanking = 100000;
  2097.     int nBestIndex = -1;
  2098.     for( int i=0; i<pBestDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
  2099.     {
  2100.         int nRanking = depthStencilRanking.GetAt(i);
  2101.         if( nRanking < nBestRanking )
  2102.         {
  2103.             nBestRanking = nRanking;
  2104.             nBestIndex = i;
  2105.         }
  2106.     }
  2107.     if( nBestIndex >= 0 )
  2108.     {
  2109.         bestDepthStencilFormat = pBestDeviceSettingsCombo->depthStencilFormatList.GetAt(nBestIndex);
  2110.         bestEnableAutoDepthStencil = true;
  2111.     }
  2112.     else
  2113.     {
  2114.         bestDepthStencilFormat = D3DFMT_UNKNOWN;
  2115.         bestEnableAutoDepthStencil = false;
  2116.     }
  2117.     //---------------------
  2118.     // Present flags
  2119.     //---------------------
  2120.     DWORD dwBestFlags;
  2121.     if( pMatchOptions->ePresentFlags == DXUTMT_PRESERVE_INPUT )   
  2122.     {
  2123.         dwBestFlags = pDeviceSettingsIn->pp.Flags;
  2124.     }
  2125.     else if( pMatchOptions->ePresentFlags == DXUTMT_IGNORE_INPUT )   
  2126.     {
  2127.         dwBestFlags = 0;
  2128.         if( bestEnableAutoDepthStencil )
  2129.             dwBestFlags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;            
  2130.     }
  2131.     else // if( pMatchOptions->ePresentFlags == DXUTMT_CLOSEST_TO_INPUT )   
  2132.     {
  2133.         dwBestFlags = pDeviceSettingsIn->pp.Flags;
  2134.         if( bestEnableAutoDepthStencil )
  2135.             dwBestFlags |= D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
  2136.     }
  2137.     //---------------------
  2138.     // Refresh rate
  2139.     //---------------------
  2140.     if( pBestDeviceSettingsCombo->Windowed )
  2141.     {
  2142.         // Must be 0 for windowed
  2143.         bestDisplayMode.RefreshRate = 0;
  2144.     }
  2145.     else
  2146.     {
  2147.         if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT )   
  2148.         {
  2149.             bestDisplayMode.RefreshRate = pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz;
  2150.         }
  2151.         else 
  2152.         {
  2153.             UINT refreshRateMatch;
  2154.             if( pMatchOptions->eRefreshRate == DXUTMT_CLOSEST_TO_INPUT )   
  2155.             {
  2156.                 refreshRateMatch = pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz;
  2157.             }
  2158.             else // if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT )   
  2159.             {
  2160.                 refreshRateMatch = adapterDesktopDisplayMode.RefreshRate;
  2161.             }
  2162.             bestDisplayMode.RefreshRate = 0;
  2163.             if( refreshRateMatch != 0 )
  2164.             {
  2165.                 int nBestRefreshRanking = 100000;
  2166.                 CGrowableArray<D3DDISPLAYMODE>* pDisplayModeList = &pBestDeviceSettingsCombo->pAdapterInfo->displayModeList;
  2167.                 for( int iDisplayMode=0; iDisplayMode<pDisplayModeList->GetSize(); iDisplayMode++ )
  2168.                 {
  2169.                     D3DDISPLAYMODE displayMode = pDisplayModeList->GetAt(iDisplayMode);                
  2170.                     if( displayMode.Format != pBestDeviceSettingsCombo->AdapterFormat || 
  2171.                         displayMode.Height != bestDisplayMode.Height ||
  2172.                         displayMode.Width != bestDisplayMode.Width )
  2173.                         continue; // Skip display modes that don't match 
  2174.                     // Find the delta between the current refresh rate and the optimal refresh rate 
  2175.                     int nCurRanking = abs((int)displayMode.RefreshRate - (int)refreshRateMatch);
  2176.                                         
  2177.                     if( nCurRanking < nBestRefreshRanking )
  2178.                     {
  2179.                         bestDisplayMode.RefreshRate = displayMode.RefreshRate;
  2180.                         nBestRefreshRanking = nCurRanking;
  2181.                         // Stop if perfect match found
  2182.                         if( nBestRefreshRanking == 0 )
  2183.                             break;
  2184.                     }
  2185.                 }
  2186.             }
  2187.         }
  2188.     }
  2189.     //---------------------
  2190.     // Present interval
  2191.     //---------------------
  2192.     UINT bestPresentInterval;
  2193.     if( pMatchOptions->ePresentInterval == DXUTMT_PRESERVE_INPUT )   
  2194.     {
  2195.         bestPresentInterval = pDeviceSettingsIn->pp.PresentationInterval;
  2196.     }
  2197.     else if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT )   
  2198.     {
  2199.         // For windowed and fullscreen, default to D3DPRESENT_INTERVAL_DEFAULT
  2200.         // which will wait for the vertical retrace period to prevent tearing.
  2201.         // For benchmarking, use D3DPRESENT_INTERVAL_DEFAULT  which will
  2202.         // will wait not for the vertical retrace period but may introduce tearing.
  2203.         bestPresentInterval = D3DPRESENT_INTERVAL_DEFAULT;
  2204.     }
  2205.     else // if( pMatchOptions->ePresentInterval == DXUTMT_CLOSEST_TO_INPUT )   
  2206.     {
  2207.         if( pBestDeviceSettingsCombo->presentIntervalList.Contains( pDeviceSettingsIn->pp.PresentationInterval ) )
  2208.         {
  2209.             bestPresentInterval = pDeviceSettingsIn->pp.PresentationInterval;
  2210.         }
  2211.         else
  2212.         {
  2213.             bestPresentInterval = D3DPRESENT_INTERVAL_DEFAULT;
  2214.         }
  2215.     }
  2216.     // Fill the device settings struct
  2217.     ZeroMemory( pValidDeviceSettings, sizeof(DXUTDeviceSettings) );
  2218.     pValidDeviceSettings->AdapterOrdinal                 = pBestDeviceSettingsCombo->AdapterOrdinal;
  2219.     pValidDeviceSettings->DeviceType                     = pBestDeviceSettingsCombo->DeviceType;
  2220.     pValidDeviceSettings->AdapterFormat                  = pBestDeviceSettingsCombo->AdapterFormat;
  2221.     pValidDeviceSettings->BehaviorFlags                  = dwBestBehaviorFlags;
  2222.     pValidDeviceSettings->pp.BackBufferWidth             = bestDisplayMode.Width;
  2223.     pValidDeviceSettings->pp.BackBufferHeight            = bestDisplayMode.Height;
  2224.     pValidDeviceSettings->pp.BackBufferFormat            = pBestDeviceSettingsCombo->BackBufferFormat;
  2225.     pValidDeviceSettings->pp.BackBufferCount             = bestBackBufferCount;
  2226.     pValidDeviceSettings->pp.MultiSampleType             = bestMultiSampleType;  
  2227.     pValidDeviceSettings->pp.MultiSampleQuality          = bestMultiSampleQuality;
  2228.     pValidDeviceSettings->pp.SwapEffect                  = bestSwapEffect;
  2229.     pValidDeviceSettings->pp.hDeviceWindow               = pBestDeviceSettingsCombo->Windowed ? DXUTGetHWNDDeviceWindowed() : DXUTGetHWNDDeviceFullScreen();
  2230.     pValidDeviceSettings->pp.Windowed                    = pBestDeviceSettingsCombo->Windowed;
  2231.     pValidDeviceSettings->pp.EnableAutoDepthStencil      = bestEnableAutoDepthStencil;  
  2232.     pValidDeviceSettings->pp.AutoDepthStencilFormat      = bestDepthStencilFormat;
  2233.     pValidDeviceSettings->pp.Flags                       = dwBestFlags;                   
  2234.     pValidDeviceSettings->pp.FullScreen_RefreshRateInHz  = bestDisplayMode.RefreshRate;
  2235.     pValidDeviceSettings->pp.PresentationInterval        = bestPresentInterval;
  2236. }
  2237. //--------------------------------------------------------------------------------------
  2238. // Internal helper function to find the closest allowed display mode to the optimal 
  2239. //--------------------------------------------------------------------------------------
  2240. HRESULT DXUTFindValidResolution( CD3DEnumDeviceSettingsCombo* pBestDeviceSettingsCombo, 
  2241.                                 D3DDISPLAYMODE displayModeIn, D3DDISPLAYMODE* pBestDisplayMode )
  2242. {
  2243.     D3DDISPLAYMODE bestDisplayMode;
  2244.     ZeroMemory( &bestDisplayMode, sizeof(D3DDISPLAYMODE) );
  2245.     
  2246.     if( pBestDeviceSettingsCombo->Windowed )
  2247.     {
  2248.         // In windowed mode, all resolutions are valid but restritions still apply 
  2249.         // on the size of the window.  See DXUTChangeDevice() for details
  2250.         *pBestDisplayMode = displayModeIn;
  2251.     }
  2252.     else
  2253.     {
  2254.         int nBestRanking = 100000;
  2255.         int nCurRanking;
  2256.         CGrowableArray<D3DDISPLAYMODE>* pDisplayModeList = &pBestDeviceSettingsCombo->pAdapterInfo->displayModeList;
  2257.         for( int iDisplayMode=0; iDisplayMode<pDisplayModeList->GetSize(); iDisplayMode++ )
  2258.         {
  2259.             D3DDISPLAYMODE displayMode = pDisplayModeList->GetAt(iDisplayMode);
  2260.             // Skip display modes that don't match the combo's adapter format
  2261.             if( displayMode.Format != pBestDeviceSettingsCombo->AdapterFormat )
  2262.                 continue;
  2263.             // Find the delta between the current width/height and the optimal width/height
  2264.             nCurRanking = abs((int)displayMode.Width - (int)displayModeIn.Width) + 
  2265.                           abs((int)displayMode.Height- (int)displayModeIn.Height);
  2266.             if( nCurRanking < nBestRanking )
  2267.             {
  2268.                 bestDisplayMode = displayMode;
  2269.                 nBestRanking = nCurRanking;
  2270.                 // Stop if perfect match found
  2271.                 if( nBestRanking == 0 )
  2272.                     break;
  2273.             }
  2274.         }
  2275.         if( bestDisplayMode.Width == 0 )
  2276.         {
  2277.             *pBestDisplayMode = displayModeIn;
  2278.             return E_FAIL; // No valid display modes found
  2279.         }
  2280.         *pBestDisplayMode = bestDisplayMode;
  2281.     }