Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

948 lines
30 KiB

  1. #include "stdafx.h"
  2. #if 0
  3. //-----------------------------------------------------------------------------
  4. // File: D3DApp.cpp
  5. //
  6. // Desc: Application class for the Direct3D samples framework library.
  7. //
  8. // Copyright (c) 1998-1999 Microsoft Corporation. All rights reserved.
  9. //-----------------------------------------------------------------------------
  10. #define STRICT
  11. #include <windows.h>
  12. #include <pbt.h>
  13. #include <mmsystem.h>
  14. #include <stdio.h>
  15. #include <tchar.h>
  16. #include "D3DApp.h"
  17. //-----------------------------------------------------------------------------
  18. // Internal function prototypes and variables
  19. //-----------------------------------------------------------------------------
  20. enum APPMSGTYPE { MSG_NONE, MSGERR_APPMUSTEXIT, MSGWARN_SWITCHEDTOSOFTWARE };
  21. static INT CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM);
  22. static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  23. static CD3DApplication* g_pD3DApp;
  24. //-----------------------------------------------------------------------------
  25. // Name: CD3DApplication()
  26. // Desc:
  27. //-----------------------------------------------------------------------------
  28. CD3DApplication::CD3DApplication()
  29. {
  30. m_pFramework = NULL;
  31. m_hWnd = NULL;
  32. m_pDD = NULL;
  33. m_pD3D = NULL;
  34. m_pd3dDevice = NULL;
  35. m_pddsRenderTarget = NULL;
  36. m_pddsRenderTargetLeft = NULL;
  37. m_bActive = FALSE;
  38. m_bReady = FALSE;
  39. m_bFrameMoving = TRUE;
  40. m_bSingleStep = FALSE;
  41. m_strWindowTitle = TEXT("Direct3D Application");
  42. m_bAppUseZBuffer = FALSE;
  43. m_bAppUseStereo = FALSE;
  44. m_bShowStats = FALSE;
  45. m_fnConfirmDevice = NULL;
  46. g_pD3DApp = this;
  47. }
  48. //-----------------------------------------------------------------------------
  49. // Name: Create()
  50. // Desc:
  51. //-----------------------------------------------------------------------------
  52. HRESULT CD3DApplication::Create(HINSTANCE hInst, TCHAR* strCmdLine)
  53. {
  54. HRESULT hr;
  55. // Enumerate available D3D devices. The callback is used so the app can
  56. // confirm/reject each enumerated device depending on its capabilities.
  57. if (FAILED(hr = D3DEnum_EnumerateDevices(m_fnConfirmDevice)))
  58. {
  59. DisplayFrameworkError(hr, MSGERR_APPMUSTEXIT);
  60. return hr;
  61. }
  62. // Select a device. Ask for a hardware device that renders in a window.
  63. if (FAILED(hr = D3DEnum_SelectDefaultDevice(&m_pDeviceInfo)))
  64. {
  65. DisplayFrameworkError(hr, MSGERR_APPMUSTEXIT);
  66. return hr;
  67. }
  68. // Initialize the app's custom scene stuff
  69. if (FAILED(hr = OneTimeSceneInit()))
  70. {
  71. DisplayFrameworkError(hr, MSGERR_APPMUSTEXIT);
  72. return hr;
  73. }
  74. // Create a new CD3DFramework class. This class does all of our D3D
  75. // initialization and manages the common D3D objects.
  76. if (NULL == (m_pFramework = new CD3DFramework7()))
  77. {
  78. DisplayFrameworkError(E_OUTOFMEMORY, MSGERR_APPMUSTEXIT);
  79. return E_OUTOFMEMORY;
  80. }
  81. // Register the window class
  82. WNDCLASS wndClass = { 0, WndProc, 0, 0, hInst,
  83. LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIN_ICON)),
  84. LoadCursor(NULL, IDC_ARROW),
  85. (HBRUSH)GetStockObject(WHITE_BRUSH),
  86. NULL, TEXT("D3D Window") };
  87. RegisterClass(&wndClass);
  88. // Create the render window
  89. m_hWnd = CreateWindow(TEXT("D3D Window"), m_strWindowTitle,
  90. WS_OVERLAPPEDWINDOW|WS_VISIBLE,
  91. CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0L,
  92. LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU)),
  93. hInst, 0L);
  94. UpdateWindow(m_hWnd);
  95. // Initialize the 3D environment for the app
  96. if (FAILED(hr = Initialize3DEnvironment()))
  97. {
  98. DisplayFrameworkError(hr, MSGERR_APPMUSTEXIT);
  99. Cleanup3DEnvironment();
  100. return E_FAIL;
  101. }
  102. // Setup the app so it can support single-stepping
  103. m_dwBaseTime = timeGetTime();
  104. // The app is ready to go
  105. m_bReady = TRUE;
  106. return S_OK;
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Name: Run()
  110. // Desc: Message-processing loop. Idle time is used to render the scene.
  111. //-----------------------------------------------------------------------------
  112. INT CD3DApplication::Run()
  113. {
  114. // Load keyboard accelerators
  115. HACCEL hAccel = LoadAccelerators(NULL, MAKEINTRESOURCE(IDR_MAIN_ACCEL));
  116. // Now we're ready to recieve and process Windows messages.
  117. BOOL bGotMsg;
  118. MSG msg;
  119. PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
  120. while(WM_QUIT != msg.message)
  121. {
  122. // Use PeekMessage() if the app is active, so we can use idle time to
  123. // render the scene. Else, use GetMessage() to avoid eating CPU time.
  124. if (m_bActive)
  125. bGotMsg = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);
  126. else
  127. bGotMsg = GetMessage(&msg, NULL, 0U, 0U);
  128. if (bGotMsg)
  129. {
  130. // Translate and dispatch the message
  131. if (0 == TranslateAccelerator(m_hWnd, hAccel, &msg))
  132. {
  133. TranslateMessage(&msg);
  134. DispatchMessage(&msg);
  135. }
  136. }
  137. else
  138. {
  139. // Render a frame during idle time (no messages are waiting)
  140. if (m_bActive && m_bReady)
  141. {
  142. if (FAILED(Render3DEnvironment()))
  143. DestroyWindow(m_hWnd);
  144. }
  145. }
  146. }
  147. return msg.wParam;
  148. }
  149. //-----------------------------------------------------------------------------
  150. // Name: WndProc()
  151. // Desc: Static msg handler which passes messages to the application class.
  152. //-----------------------------------------------------------------------------
  153. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  154. {
  155. if (g_pD3DApp)
  156. return g_pD3DApp->MsgProc(hWnd, uMsg, wParam, lParam);
  157. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  158. }
  159. //-----------------------------------------------------------------------------
  160. // Name: AboutProc()
  161. // Desc: Minimal message proc function for the about box
  162. //-----------------------------------------------------------------------------
  163. BOOL CALLBACK AboutProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM)
  164. {
  165. if (WM_COMMAND == uMsg)
  166. if (IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam))
  167. EndDialog(hWnd, TRUE);
  168. return WM_INITDIALOG == uMsg ? TRUE : FALSE;
  169. }
  170. //-----------------------------------------------------------------------------
  171. // Name: MsgProc()
  172. // Desc: Message handling function.
  173. //-----------------------------------------------------------------------------
  174. LRESULT CD3DApplication::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam,
  175. LPARAM lParam)
  176. {
  177. HRESULT hr;
  178. switch(uMsg)
  179. {
  180. case WM_PAINT:
  181. // Handle paint messages when the app is not ready
  182. if (m_pFramework && !m_bReady)
  183. {
  184. if (m_pDeviceInfo->bWindowed)
  185. m_pFramework->ShowFrame();
  186. else
  187. m_pFramework->FlipToGDISurface(TRUE);
  188. }
  189. break;
  190. case WM_MOVE:
  191. // If in windowed mode, move the Framework's window
  192. if (m_pFramework && m_bActive && m_bReady && m_pDeviceInfo->bWindowed)
  193. m_pFramework->Move((SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
  194. break;
  195. case WM_SIZE:
  196. // Check to see if we are losing our window...
  197. if (SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam)
  198. m_bActive = FALSE;
  199. else
  200. m_bActive = TRUE;
  201. // A new window size will require a new backbuffer
  202. // size, so the 3D structures must be changed accordingly.
  203. if (m_bActive && m_bReady && m_pDeviceInfo->bWindowed)
  204. {
  205. m_bReady = FALSE;
  206. if (FAILED(hr = Change3DEnvironment()))
  207. return 0;
  208. m_bReady = TRUE;
  209. }
  210. break;
  211. case WM_SETCURSOR:
  212. // Prevent a cursor in fullscreen mode
  213. if (m_bActive && m_bReady && !m_pDeviceInfo->bWindowed)
  214. {
  215. SetCursor(NULL);
  216. return 1;
  217. }
  218. break;
  219. case WM_ENTERMENULOOP:
  220. // Pause the app when menus are displayed
  221. Pause(TRUE);
  222. break;
  223. case WM_EXITMENULOOP:
  224. Pause(FALSE);
  225. break;
  226. case WM_ENTERSIZEMOVE:
  227. // Halt frame movement while the app is sizing or moving
  228. if (m_bFrameMoving)
  229. m_dwStopTime = timeGetTime();
  230. break;
  231. case WM_EXITSIZEMOVE:
  232. if (m_bFrameMoving)
  233. m_dwBaseTime += timeGetTime() - m_dwStopTime;
  234. break;
  235. case WM_CONTEXTMENU:
  236. // Handle the app's context menu (via right mouse click)
  237. TrackPopupMenuEx(
  238. GetSubMenu(LoadMenu(0, MAKEINTRESOURCE(IDR_POPUP)), 0),
  239. TPM_VERTICAL, LOWORD(lParam), HIWORD(lParam), hWnd, NULL);
  240. break;
  241. case WM_NCHITTEST:
  242. // Prevent the user from selecting the menu in fullscreen mode
  243. if (!m_pDeviceInfo->bWindowed)
  244. return HTCLIENT;
  245. break;
  246. case WM_POWERBROADCAST:
  247. switch(wParam)
  248. {
  249. case PBT_APMQUERYSUSPEND:
  250. // At this point, the app should save any data for open
  251. // network connections, files, etc.., and prepare to go into
  252. // a suspended mode.
  253. return OnQuerySuspend((DWORD)lParam);
  254. case PBT_APMRESUMESUSPEND:
  255. // At this point, the app should recover any data, network
  256. // connections, files, etc.., and resume running from when
  257. // the app was suspended.
  258. return OnResumeSuspend((DWORD)lParam);
  259. }
  260. break;
  261. case WM_SYSCOMMAND:
  262. // Prevent moving/sizing and power loss in fullscreen mode
  263. switch(wParam)
  264. {
  265. case SC_MOVE:
  266. case SC_SIZE:
  267. case SC_MAXIMIZE:
  268. case SC_MONITORPOWER:
  269. if (FALSE == m_pDeviceInfo->bWindowed)
  270. return 1;
  271. break;
  272. }
  273. break;
  274. case WM_COMMAND:
  275. switch(LOWORD(wParam))
  276. {
  277. case IDM_TOGGLESTART:
  278. // Toggle frame movement
  279. m_bFrameMoving = !m_bFrameMoving;
  280. if (m_bFrameMoving)
  281. m_dwBaseTime += timeGetTime() - m_dwStopTime;
  282. else
  283. m_dwStopTime = timeGetTime();
  284. break;
  285. case IDM_SINGLESTEP:
  286. // Single-step frame movement
  287. if (FALSE == m_bFrameMoving)
  288. m_dwBaseTime += timeGetTime() - (m_dwStopTime + 100);
  289. m_dwStopTime = timeGetTime();
  290. m_bFrameMoving = FALSE;
  291. m_bSingleStep = TRUE;
  292. break;
  293. case IDM_CHANGEDEVICE:
  294. // Display the device-selection dialog box.
  295. if (m_bActive && m_bReady)
  296. {
  297. Pause(TRUE);
  298. if (SUCCEEDED(D3DEnum_UserChangeDevice(&m_pDeviceInfo)))
  299. {
  300. if (FAILED(hr = Change3DEnvironment()))
  301. return 0;
  302. }
  303. Pause(FALSE);
  304. }
  305. return 0;
  306. case IDM_TOGGLEFULLSCREEN:
  307. // Toggle the fullscreen/window mode
  308. if (m_bActive && m_bReady)
  309. {
  310. m_bReady = FALSE;
  311. m_pDeviceInfo->bWindowed = !m_pDeviceInfo->bWindowed;
  312. if (FAILED(hr = Change3DEnvironment()))
  313. return 0;
  314. m_bReady = TRUE;
  315. }
  316. return 0;
  317. case IDM_ABOUT:
  318. // Display the About box
  319. Pause(TRUE);
  320. DialogBox((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
  321. MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc);
  322. Pause(FALSE);
  323. return 0;
  324. case IDM_EXIT:
  325. // Recieved key/menu command to exit app
  326. SendMessage(hWnd, WM_CLOSE, 0, 0);
  327. return 0;
  328. }
  329. break;
  330. case WM_GETMINMAXINFO:
  331. ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
  332. ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
  333. break;
  334. case WM_CLOSE:
  335. DestroyWindow(hWnd);
  336. return 0;
  337. case WM_DESTROY:
  338. Cleanup3DEnvironment();
  339. PostQuitMessage(0);
  340. return 0;
  341. }
  342. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Name: Initialize3DEnvironment()
  346. // Desc: Initializes the sample framework, then calls the app-specific function
  347. // to initialize device specific objects. This code is structured to
  348. // handled any errors that may occur duing initialization
  349. //-----------------------------------------------------------------------------
  350. HRESULT CD3DApplication::Initialize3DEnvironment()
  351. {
  352. HRESULT hr;
  353. DWORD dwFrameworkFlags = 0L;
  354. dwFrameworkFlags |= (!m_pDeviceInfo->bWindowed ? D3DFW_FULLSCREEN : 0L);
  355. dwFrameworkFlags |= (m_pDeviceInfo->bStereo ? D3DFW_STEREO : 0L);
  356. dwFrameworkFlags |= (m_bAppUseZBuffer ? D3DFW_ZBUFFER : 0L);
  357. // Initialize the D3D framework
  358. if (SUCCEEDED(hr = m_pFramework->Initialize(m_hWnd,
  359. m_pDeviceInfo->pDriverGUID, m_pDeviceInfo->pDeviceGUID,
  360. &m_pDeviceInfo->ddsdFullscreenMode, dwFrameworkFlags)))
  361. {
  362. m_pDD = m_pFramework->GetDirectDraw();
  363. m_pD3D = m_pFramework->GetDirect3D();
  364. m_pd3dDevice = m_pFramework->GetD3DDevice();
  365. m_pddsRenderTarget = m_pFramework->GetRenderSurface();
  366. m_pddsRenderTargetLeft = m_pFramework->GetRenderSurfaceLeft();
  367. m_ddsdRenderTarget.dwSize = sizeof(m_ddsdRenderTarget);
  368. m_pddsRenderTarget->GetSurfaceDesc(&m_ddsdRenderTarget);
  369. // Let the app run its startup code which creates the 3d scene.
  370. if (SUCCEEDED(hr = InitDeviceObjects()))
  371. return S_OK;
  372. else
  373. {
  374. DeleteDeviceObjects();
  375. m_pFramework->DestroyObjects();
  376. }
  377. }
  378. // If we get here, the first initialization passed failed. If that was with a
  379. // hardware device, try again using a software rasterizer instead.
  380. if (m_pDeviceInfo->bHardware)
  381. {
  382. // Try again with a software rasterizer
  383. DisplayFrameworkError(hr, MSGWARN_SWITCHEDTOSOFTWARE);
  384. D3DEnum_SelectDefaultDevice(&m_pDeviceInfo, D3DENUM_SOFTWAREONLY);
  385. return Initialize3DEnvironment();
  386. }
  387. return hr;
  388. }
  389. //-----------------------------------------------------------------------------
  390. // Name: Change3DEnvironment()
  391. // Desc: Handles driver, device, and/or mode changes for the app.
  392. //-----------------------------------------------------------------------------
  393. HRESULT CD3DApplication::Change3DEnvironment()
  394. {
  395. HRESULT hr;
  396. static BOOL bOldWindowedState = TRUE;
  397. static DWORD dwSavedStyle;
  398. static RECT rcSaved;
  399. // Release all scene objects that will be re-created for the new device
  400. DeleteDeviceObjects();
  401. // Release framework objects, so a new device can be created
  402. if (FAILED(hr = m_pFramework->DestroyObjects()))
  403. {
  404. DisplayFrameworkError(hr, MSGERR_APPMUSTEXIT);
  405. SendMessage(m_hWnd, WM_CLOSE, 0, 0);
  406. return hr;
  407. }
  408. // Check if going from fullscreen to windowed mode, or vice versa.
  409. if (bOldWindowedState != m_pDeviceInfo->bWindowed)
  410. {
  411. if (m_pDeviceInfo->bWindowed)
  412. {
  413. // Coming from fullscreen mode, so restore window properties
  414. SetWindowLong(m_hWnd, GWL_STYLE, dwSavedStyle);
  415. SetWindowPos(m_hWnd, HWND_NOTOPMOST, rcSaved.left, rcSaved.top,
  416. (rcSaved.right - rcSaved.left),
  417. (rcSaved.bottom - rcSaved.top), SWP_SHOWWINDOW);
  418. }
  419. else
  420. {
  421. // Going to fullscreen mode, save/set window properties as needed
  422. dwSavedStyle = GetWindowLong(m_hWnd, GWL_STYLE);
  423. GetWindowRect(m_hWnd, &rcSaved);
  424. SetWindowLong(m_hWnd, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE);
  425. }
  426. bOldWindowedState = m_pDeviceInfo->bWindowed;
  427. }
  428. // Inform the framework class of the driver change. It will internally
  429. // re-create valid surfaces, a d3ddevice, etc.
  430. if (FAILED(hr = Initialize3DEnvironment()))
  431. {
  432. DisplayFrameworkError(hr, MSGERR_APPMUSTEXIT);
  433. SendMessage(m_hWnd, WM_CLOSE, 0, 0);
  434. return hr;
  435. }
  436. // If the app is paused, trigger the rendering of the current frame
  437. if (FALSE == m_bFrameMoving)
  438. {
  439. m_bSingleStep = TRUE;
  440. m_dwBaseTime += timeGetTime() - m_dwStopTime;
  441. m_dwStopTime = timeGetTime();
  442. }
  443. return S_OK;
  444. }
  445. //-----------------------------------------------------------------------------
  446. // Name: Render3DEnvironment()
  447. // Desc: Draws the scene.
  448. //-----------------------------------------------------------------------------
  449. HRESULT CD3DApplication::Render3DEnvironment()
  450. {
  451. HRESULT hr;
  452. // Check the cooperative level before rendering
  453. if (FAILED(hr = m_pDD->TestCooperativeLevel()))
  454. {
  455. switch(hr)
  456. {
  457. case DDERR_EXCLUSIVEMODEALREADYSET:
  458. case DDERR_NOEXCLUSIVEMODE:
  459. // Do nothing because some other app has exclusive mode
  460. return S_OK;
  461. case DDERR_WRONGMODE:
  462. // The display mode changed on us. Resize accordingly
  463. if (m_pDeviceInfo->bWindowed)
  464. return Change3DEnvironment();
  465. break;
  466. }
  467. return hr;
  468. }
  469. // Get the relative time, in seconds
  470. FLOAT fTime = (timeGetTime() - m_dwBaseTime) * 0.001f;
  471. // FrameMove (animate) the scene
  472. if (m_bFrameMoving || m_bSingleStep)
  473. {
  474. if (FAILED(hr = FrameMove(fTime)))
  475. return hr;
  476. m_bSingleStep = FALSE;
  477. }
  478. // If the display is in a stereo mode, render the scene from the left eye
  479. // first, then the right eye.
  480. if (m_bAppUseStereo && m_pDeviceInfo->bStereo && !m_pDeviceInfo->bWindowed)
  481. {
  482. // Render the scene from the left eye
  483. m_pd3dDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &m_matLeftView);
  484. if (FAILED(hr = m_pd3dDevice->SetRenderTarget(m_pddsRenderTargetLeft, 0)))
  485. return hr;
  486. if (FAILED(hr = Render()))
  487. return hr;
  488. //Render the scene from the right eye
  489. m_pd3dDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &m_matRightView);
  490. if (FAILED(hr = m_pd3dDevice->SetRenderTarget(m_pddsRenderTarget, 0)))
  491. return hr;
  492. if (FAILED(hr = Render()))
  493. return hr;
  494. }
  495. else
  496. {
  497. // Set center viewing matrix if app is stereo-enabled
  498. if (m_bAppUseStereo)
  499. m_pd3dDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &m_matView);
  500. // Render the scene as normal
  501. if (FAILED(hr = Render()))
  502. return hr;
  503. }
  504. // Show the frame rate, etc.
  505. if (m_bShowStats)
  506. ShowStats();
  507. // Show the frame on the primary surface.
  508. if (FAILED(hr = m_pFramework->ShowFrame()))
  509. {
  510. if (DDERR_SURFACELOST != hr)
  511. return hr;
  512. m_pFramework->RestoreSurfaces();
  513. RestoreSurfaces();
  514. }
  515. return S_OK;
  516. }
  517. //-----------------------------------------------------------------------------
  518. // Name: Cleanup3DEnvironment()
  519. // Desc: Cleanup scene objects
  520. //-----------------------------------------------------------------------------
  521. VOID CD3DApplication::Cleanup3DEnvironment()
  522. {
  523. m_bActive = FALSE;
  524. m_bReady = FALSE;
  525. if (m_pFramework)
  526. {
  527. DeleteDeviceObjects();
  528. SAFE_DELETE(m_pFramework);
  529. FinalCleanup();
  530. }
  531. D3DEnum_FreeResources();
  532. }
  533. //-----------------------------------------------------------------------------
  534. // Name: Pause()
  535. // Desc: Called in to toggle the pause state of the app. This function
  536. // brings the GDI surface to the front of the display, so drawing
  537. // output like message boxes and menus may be displayed.
  538. //-----------------------------------------------------------------------------
  539. VOID CD3DApplication::Pause(BOOL bPause)
  540. {
  541. static DWORD dwAppPausedCount = 0L;
  542. dwAppPausedCount += (bPause ? +1 : -1);
  543. m_bReady = (dwAppPausedCount ? FALSE : TRUE);
  544. // Handle the first pause request (of many, nestable pause requests)
  545. if (bPause && (1 == dwAppPausedCount))
  546. {
  547. // Get a surface for the GDI
  548. if (m_pFramework)
  549. m_pFramework->FlipToGDISurface(TRUE);
  550. // Stop the scene from animating
  551. if (m_bFrameMoving)
  552. m_dwStopTime = timeGetTime();
  553. }
  554. if (0 == dwAppPausedCount)
  555. {
  556. // Restart the scene
  557. if (m_bFrameMoving)
  558. m_dwBaseTime += timeGetTime() - m_dwStopTime;
  559. }
  560. }
  561. //-----------------------------------------------------------------------------
  562. // Name: OnQuerySuspend()
  563. // Desc: Called when the app receives a PBT_APMQUERYSUSPEND message, meaning
  564. // the computer is about to be suspended. At this point, the app should
  565. // save any data for open network connections, files, etc.., and prepare
  566. // to go into a suspended mode.
  567. //-----------------------------------------------------------------------------
  568. LRESULT CD3DApplication::OnQuerySuspend(DWORD dwFlags)
  569. {
  570. Pause(TRUE);
  571. return TRUE;
  572. }
  573. //-----------------------------------------------------------------------------
  574. // Name: OnResumeSuspend()
  575. // Desc: Called when the app receives a PBT_APMRESUMESUSPEND message, meaning
  576. // the computer has just resumed from a suspended state. At this point,
  577. // the app should recover any data, network connections, files, etc..,
  578. // and resume running from when the app was suspended.
  579. //-----------------------------------------------------------------------------
  580. LRESULT CD3DApplication::OnResumeSuspend(DWORD dwData)
  581. {
  582. Pause(FALSE);
  583. return TRUE;
  584. }
  585. //-----------------------------------------------------------------------------
  586. // Name: ShowStats()
  587. // Desc: Shows frame rate and dimensions of the rendering device.
  588. //-----------------------------------------------------------------------------
  589. VOID CD3DApplication::ShowStats()
  590. {
  591. static FLOAT fFPS = 0.0f;
  592. static FLOAT fLastTime = 0.0f;
  593. static DWORD dwFrames = 0L;
  594. // Keep track of the time lapse and frame count
  595. FLOAT fTime = timeGetTime() * 0.001f; // Get current time in seconds
  596. ++dwFrames;
  597. // Update the frame rate once per second
  598. if (fTime - fLastTime > 1.0f)
  599. {
  600. fFPS = dwFrames / (fTime - fLastTime);
  601. fLastTime = fTime;
  602. dwFrames = 0L;
  603. }
  604. // Setup the text buffer to write out dimensions
  605. TCHAR buffer[80];
  606. sprintf(buffer, TEXT("%7.02f fps (%dx%dx%d)"), fFPS,
  607. m_ddsdRenderTarget.dwWidth, m_ddsdRenderTarget.dwHeight,
  608. m_ddsdRenderTarget.ddpfPixelFormat.dwRGBBitCount);
  609. OutputText(0, 0, buffer);
  610. }
  611. //-----------------------------------------------------------------------------
  612. // Name: OutputText()
  613. // Desc: Draws text on the window.
  614. //-----------------------------------------------------------------------------
  615. VOID CD3DApplication::OutputText(DWORD x, DWORD y, TCHAR* str)
  616. {
  617. HDC hDC;
  618. // Get a DC for the surface. Then, write out the buffer
  619. if (m_pddsRenderTarget)
  620. {
  621. if (SUCCEEDED(m_pddsRenderTarget->GetDC(&hDC)))
  622. {
  623. SetTextColor(hDC, RGB(255,255,0));
  624. SetBkMode(hDC, TRANSPARENT);
  625. ExtTextOut(hDC, x, y, 0, NULL, str, lstrlen(str), NULL);
  626. m_pddsRenderTarget->ReleaseDC(hDC);
  627. }
  628. }
  629. // Do the same for the left surface (in case of stereoscopic viewing).
  630. if (m_pddsRenderTargetLeft)
  631. {
  632. if (SUCCEEDED(m_pddsRenderTargetLeft->GetDC(&hDC)))
  633. {
  634. // Use a different color to help distinguish left eye view
  635. SetTextColor(hDC, RGB(255,0,255));
  636. SetBkMode(hDC, TRANSPARENT);
  637. ExtTextOut(hDC, x, y, 0, NULL, str, lstrlen(str), NULL);
  638. m_pddsRenderTargetLeft->ReleaseDC(hDC);
  639. }
  640. }
  641. }
  642. //-----------------------------------------------------------------------------
  643. // Name: DisplayFrameworkError()
  644. // Desc: Displays error messages in a message box
  645. //-----------------------------------------------------------------------------
  646. VOID CD3DApplication::DisplayFrameworkError(HRESULT hr, DWORD dwType)
  647. {
  648. TCHAR strMsg[512];
  649. switch(hr)
  650. {
  651. case D3DENUMERR_NODIRECTDRAW:
  652. lstrcpy(strMsg, TEXT("Could not create DirectDraw!"));
  653. break;
  654. case D3DENUMERR_NOCOMPATIBLEDEVICES:
  655. lstrcpy(strMsg, TEXT("Could not find any compatible Direct3D\n"
  656. "devices."));
  657. break;
  658. case D3DENUMERR_SUGGESTREFRAST:
  659. lstrcpy(strMsg, TEXT("Could not find any compatible devices.\n\n"
  660. "Try enabling the reference rasterizer using\n"
  661. "EnableRefRast.reg."));
  662. break;
  663. case D3DENUMERR_ENUMERATIONFAILED:
  664. lstrcpy(strMsg, TEXT("Enumeration failed. Your system may be in an\n"
  665. "unstable state and need to be rebooted"));
  666. break;
  667. case D3DFWERR_INITIALIZATIONFAILED:
  668. lstrcpy(strMsg, TEXT("Generic initialization error.\n\nEnable "
  669. "debug output for detailed information."));
  670. break;
  671. case D3DFWERR_NODIRECTDRAW:
  672. lstrcpy(strMsg, TEXT("No DirectDraw"));
  673. break;
  674. case D3DFWERR_NODIRECT3D:
  675. lstrcpy(strMsg, TEXT("No Direct3D"));
  676. break;
  677. case D3DFWERR_INVALIDMODE:
  678. lstrcpy(strMsg, TEXT("This sample requires a 16-bit (or higher) "
  679. "display mode\nto run in a window.\n\nPlease "
  680. "switch your desktop settings accordingly."));
  681. break;
  682. case D3DFWERR_COULDNTSETCOOPLEVEL:
  683. lstrcpy(strMsg, TEXT("Could not set Cooperative Level"));
  684. break;
  685. case D3DFWERR_NO3DDEVICE:
  686. lstrcpy(strMsg, TEXT("Could not create the Direct3DDevice object."));
  687. if (MSGWARN_SWITCHEDTOSOFTWARE == dwType)
  688. lstrcat(strMsg, TEXT("\nThe 3D hardware chipset may not support"
  689. "\nrendering in the current display mode."));
  690. break;
  691. case D3DFWERR_NOZBUFFER:
  692. lstrcpy(strMsg, TEXT("No ZBuffer"));
  693. break;
  694. case D3DFWERR_INVALIDZBUFFERDEPTH:
  695. lstrcpy(strMsg, TEXT("Invalid Z-buffer depth. Try switching modes\n"
  696. "from 16- to 32-bit (or vice versa)"));
  697. break;
  698. case D3DFWERR_NOVIEWPORT:
  699. lstrcpy(strMsg, TEXT("No Viewport"));
  700. break;
  701. case D3DFWERR_NOPRIMARY:
  702. lstrcpy(strMsg, TEXT("No primary"));
  703. break;
  704. case D3DFWERR_NOCLIPPER:
  705. lstrcpy(strMsg, TEXT("No Clipper"));
  706. break;
  707. case D3DFWERR_BADDISPLAYMODE:
  708. lstrcpy(strMsg, TEXT("Bad display mode"));
  709. break;
  710. case D3DFWERR_NOBACKBUFFER:
  711. lstrcpy(strMsg, TEXT("No backbuffer"));
  712. break;
  713. case D3DFWERR_NONZEROREFCOUNT:
  714. lstrcpy(strMsg, TEXT("A DDraw object has a non-zero reference\n"
  715. "count (meaning it was not properly cleaned up)."));
  716. break;
  717. case D3DFWERR_NORENDERTARGET:
  718. lstrcpy(strMsg, TEXT("No render target"));
  719. break;
  720. case E_OUTOFMEMORY:
  721. lstrcpy(strMsg, TEXT("Not enough memory!"));
  722. break;
  723. case DDERR_OUTOFVIDEOMEMORY:
  724. lstrcpy(strMsg, TEXT("There was insufficient video memory "
  725. "to use the\nhardware device."));
  726. break;
  727. default:
  728. lstrcpy(strMsg, TEXT("Generic application error.\n\nEnable "
  729. "debug output for detailed information."));
  730. }
  731. if (MSGERR_APPMUSTEXIT == dwType)
  732. {
  733. lstrcat(strMsg, TEXT("\n\nThis sample will now exit."));
  734. MessageBox(NULL, strMsg, m_strWindowTitle, MB_ICONERROR|MB_OK);
  735. }
  736. else
  737. {
  738. if (MSGWARN_SWITCHEDTOSOFTWARE == dwType)
  739. lstrcat(strMsg, TEXT("\n\nSwitching to software rasterizer."));
  740. MessageBox(NULL, strMsg, m_strWindowTitle, MB_ICONWARNING|MB_OK);
  741. }
  742. }
  743. //-----------------------------------------------------------------------------
  744. // Name: SetViewParams()
  745. // Desc: Sets the parameters to be used by the SetViewMatrix() function. You
  746. // must call this function rather than setting the D3D view matrix
  747. // yourself in order for stereo modes to work properly.
  748. //-----------------------------------------------------------------------------
  749. VOID CD3DApplication::SetViewParams(D3DVECTOR* vEyePt, D3DVECTOR* vLookatPt,
  750. D3DVECTOR* vUpVec, FLOAT fEyeDistance)
  751. {
  752. // Adjust camera position for left or right eye along the axis
  753. // perpendicular to the view direction vector and the up vector.
  754. D3DVECTOR vView = (*vLookatPt) - (*vEyePt);
  755. vView = CrossProduct(vView, (*vUpVec));
  756. vView = Normalize(vView) * fEyeDistance;
  757. D3DVECTOR vLeftEyePt = (*vEyePt) + vView;
  758. D3DVECTOR vRightEyePt = (*vEyePt) - vView;
  759. // Set the view matrices
  760. D3DUtil_SetViewMatrix(m_matLeftView, vLeftEyePt, *vLookatPt, *vUpVec);
  761. D3DUtil_SetViewMatrix(m_matRightView, vRightEyePt, *vLookatPt, *vUpVec);
  762. D3DUtil_SetViewMatrix(m_matView, *vEyePt, *vLookatPt, *vUpVec);
  763. }
  764. #endif