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.

613 lines
19 KiB

  1. #include "StdAfx.h"
  2. #if 0
  3. //-----------------------------------------------------------------------------
  4. // File: D3DFrame.cpp
  5. //
  6. // Desc: Class functions to implement a Direct3D app framework.
  7. //
  8. // Copyright (c) 1995-1999 by Microsoft, all rights reserved
  9. //-----------------------------------------------------------------------------
  10. //#define STRICT
  11. //#include <windows.h>
  12. //#include <tchar.h>
  13. #include "D3DFrame.h"
  14. #include "D3DUtil.h"
  15. //-----------------------------------------------------------------------------
  16. // Name: CD3DFramework7()
  17. // Desc: The constructor. Clears static variables
  18. //-----------------------------------------------------------------------------
  19. CD3DFramework7::CD3DFramework7()
  20. {
  21. m_hWnd = NULL;
  22. m_bIsFullscreen = FALSE;
  23. m_bIsStereo = FALSE;
  24. m_dwRenderWidth = 0L;
  25. m_dwRenderHeight = 0L;
  26. m_pddsFrontBuffer = NULL;
  27. m_pddsBackBuffer = NULL;
  28. m_pddsBackBufferLeft = NULL;
  29. m_pddsZBuffer = NULL;
  30. m_pd3dDevice = NULL;
  31. m_pDD = NULL;
  32. m_pD3D = NULL;
  33. m_dwDeviceMemType = NULL;
  34. }
  35. //-----------------------------------------------------------------------------
  36. // Name: ~CD3DFramework7()
  37. // Desc: The destructor. Deletes all objects
  38. //-----------------------------------------------------------------------------
  39. CD3DFramework7::~CD3DFramework7()
  40. {
  41. DestroyObjects();
  42. }
  43. //-----------------------------------------------------------------------------
  44. // Name: DestroyObjects()
  45. // Desc: Cleans everything up upon deletion. This code returns an error
  46. // if any of the objects have remaining reference counts.
  47. //-----------------------------------------------------------------------------
  48. HRESULT CD3DFramework7::DestroyObjects()
  49. {
  50. LONG nDD = 0L; // Number of outstanding DDraw references
  51. LONG nD3D = 0L; // Number of outstanding D3DDevice references
  52. if (m_pDD)
  53. {
  54. m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
  55. }
  56. // Do a safe check for releasing the D3DDEVICE. RefCount must be zero.
  57. if (m_pd3dDevice)
  58. if (0 < (nD3D = m_pd3dDevice->Release()))
  59. DEBUG_MSG(_T("Error: D3DDevice object is still referenced!"));
  60. m_pd3dDevice = NULL;
  61. SAFE_RELEASE(m_pddsBackBuffer);
  62. SAFE_RELEASE(m_pddsBackBufferLeft);
  63. SAFE_RELEASE(m_pddsZBuffer);
  64. SAFE_RELEASE(m_pddsFrontBuffer);
  65. SAFE_RELEASE(m_pD3D);
  66. if (m_pDD)
  67. {
  68. // Do a safe check for releasing DDRAW. RefCount must be zero.
  69. if (0 < (nDD = m_pDD->Release()))
  70. DEBUG_MSG(_T("Error: DDraw object is still referenced!"));
  71. }
  72. m_pDD = NULL;
  73. // Return successful, unless there are outstanding DD or D3DDevice refs.
  74. return (nDD==0 && nD3D==0) ? S_OK : D3DFWERR_NONZEROREFCOUNT;
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Name: Initialize()
  78. // Desc: Creates the internal objects for the framework
  79. //-----------------------------------------------------------------------------
  80. HRESULT CD3DFramework7::Initialize(HWND hWnd, GUID* pDriverGUID,
  81. GUID* pDeviceGUID, DDSURFACEDESC2* pMode,
  82. DWORD dwFlags)
  83. {
  84. HRESULT hr;
  85. // Check params. Note: A NULL mode is valid for windowed modes only.
  86. if ((NULL==hWnd) || (NULL==pDeviceGUID) ||
  87. (NULL==pMode && (dwFlags&D3DFW_FULLSCREEN)))
  88. return E_INVALIDARG;
  89. // Setup state for windowed/fullscreen mode
  90. m_hWnd = hWnd;
  91. m_bIsStereo = FALSE;
  92. m_bIsFullscreen = (dwFlags & D3DFW_FULLSCREEN) ? TRUE : FALSE;
  93. // Support stereoscopic viewing for fullscreen modes which support it
  94. if ((dwFlags & D3DFW_STEREO) && (dwFlags & D3DFW_FULLSCREEN))
  95. if (pMode->ddsCaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT)
  96. m_bIsStereo = TRUE;
  97. // Create the D3D rendering environment (surfaces, device, viewport, etc.)
  98. if (FAILED(hr = CreateEnvironment(pDriverGUID, pDeviceGUID, pMode,
  99. dwFlags)))
  100. {
  101. DestroyObjects();
  102. return hr;
  103. }
  104. return S_OK;
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Name: CreateEnvironment()
  108. // Desc: Creates the internal objects for the framework
  109. //-----------------------------------------------------------------------------
  110. HRESULT CD3DFramework7::CreateEnvironment(GUID* pDriverGUID, GUID* pDeviceGUID,
  111. DDSURFACEDESC2* pMode, DWORD dwFlags)
  112. {
  113. HRESULT hr;
  114. // Select the default memory type, for whether the device is HW or SW
  115. if (IsEqualIID(*pDeviceGUID, IID_IDirect3DHALDevice))
  116. m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
  117. else if (IsEqualIID(*pDeviceGUID, IID_IDirect3DTnLHalDevice))
  118. m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
  119. else
  120. m_dwDeviceMemType = DDSCAPS_SYSTEMMEMORY;
  121. // Create the DDraw object
  122. hr = CreateDirectDraw(pDriverGUID, dwFlags);
  123. if (FAILED(hr))
  124. return hr;
  125. // Create the front and back buffers, and attach a clipper
  126. if (dwFlags & D3DFW_FULLSCREEN)
  127. hr = CreateFullscreenBuffers(pMode);
  128. else
  129. hr = CreateWindowedBuffers();
  130. if (FAILED(hr))
  131. return hr;
  132. // Create the Direct3D object and the Direct3DDevice object
  133. hr = CreateDirect3D(pDeviceGUID);
  134. if (FAILED(hr))
  135. return hr;
  136. // Create and attach the zbuffer
  137. if (dwFlags & D3DFW_ZBUFFER)
  138. hr = CreateZBuffer(pDeviceGUID);
  139. if (FAILED(hr))
  140. return hr;
  141. return S_OK;
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Name: EnumZBufferFormatsCallback()
  145. // Desc: Simply returns the first matching enumerated z-buffer format
  146. //-----------------------------------------------------------------------------
  147. static HRESULT WINAPI EnumZBufferFormatsCallback(DDPIXELFORMAT* pddpf,
  148. VOID* pContext)
  149. {
  150. DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
  151. if (pddpfOut->dwRGBBitCount == pddpf->dwRGBBitCount)
  152. {
  153. (*pddpfOut) = (*pddpf);
  154. return D3DENUMRET_CANCEL;
  155. }
  156. return D3DENUMRET_OK;
  157. }
  158. //-----------------------------------------------------------------------------
  159. // Name: CreateDirectDraw()
  160. // Desc: Create the DirectDraw interface
  161. //-----------------------------------------------------------------------------
  162. HRESULT CD3DFramework7::CreateDirectDraw(GUID* pDriverGUID, DWORD dwFlags)
  163. {
  164. // Create the DirectDraw interface, and query for the DD7 interface
  165. if (FAILED(DirectDrawCreateEx(pDriverGUID, (VOID**)&m_pDD,
  166. IID_IDirectDraw7, NULL)))
  167. {
  168. DEBUG_MSG(_T("Could not create DirectDraw"));
  169. return D3DFWERR_NODIRECTDRAW;
  170. }
  171. // Set the Windows cooperative level
  172. DWORD dwCoopFlags = DDSCL_NORMAL;
  173. if (m_bIsFullscreen)
  174. dwCoopFlags = DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN;
  175. // By defualt, set the flag to allow D3D to optimize floating point calcs
  176. if (0L == (dwFlags & D3DFW_NO_FPUSETUP))
  177. dwCoopFlags |= DDSCL_FPUSETUP;
  178. if (FAILED(m_pDD->SetCooperativeLevel(m_hWnd, dwCoopFlags)))
  179. {
  180. DEBUG_MSG(_T("Couldn't set coop level"));
  181. return D3DFWERR_COULDNTSETCOOPLEVEL;
  182. }
  183. // Check that we are NOT in a palettized display. That case will fail,
  184. // since the framework doesn't use palettes.
  185. DDSURFACEDESC2 ddsd;
  186. ddsd.dwSize = sizeof(ddsd);
  187. m_pDD->GetDisplayMode(&ddsd);
  188. if (ddsd.ddpfPixelFormat.dwRGBBitCount <= 8)
  189. return D3DFWERR_INVALIDMODE;
  190. return S_OK;
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Name: CreateFullscreenBuffers()
  194. // Desc: Creates the primary and (optional) backbuffer for rendering.
  195. // Windowed mode and fullscreen mode are handled differently.
  196. //-----------------------------------------------------------------------------
  197. HRESULT CD3DFramework7::CreateFullscreenBuffers(DDSURFACEDESC2* pddsd)
  198. {
  199. HRESULT hr;
  200. // Get the dimensions of the screen bounds
  201. // Store the rectangle which contains the renderer
  202. SetRect(&m_rcScreenRect, 0, 0, pddsd->dwWidth, pddsd->dwHeight);
  203. m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
  204. m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
  205. // Set the display mode to the requested dimensions. Check for
  206. // 320x200x8 modes, and set flag to avoid using ModeX
  207. DWORD dwModeFlags = 0;
  208. if ((320==m_dwRenderWidth) && (200==m_dwRenderHeight) &&
  209. (8==pddsd->ddpfPixelFormat.dwRGBBitCount))
  210. dwModeFlags |= DDSDM_STANDARDVGAMODE;
  211. if (FAILED(m_pDD->SetDisplayMode(m_dwRenderWidth, m_dwRenderHeight,
  212. pddsd->ddpfPixelFormat.dwRGBBitCount,
  213. pddsd->dwRefreshRate, dwModeFlags)))
  214. {
  215. DEBUG_MSG(_T("Can't set display mode"));
  216. return D3DFWERR_BADDISPLAYMODE;
  217. }
  218. // Setup to create the primary surface w/backbuffer
  219. DDSURFACEDESC2 ddsd;
  220. ZeroMemory(&ddsd, sizeof(ddsd));
  221. ddsd.dwSize = sizeof(ddsd);
  222. ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
  223. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE |
  224. DDSCAPS_FLIP | DDSCAPS_COMPLEX;
  225. ddsd.dwBackBufferCount = 1;
  226. // Support for stereoscopic viewing
  227. if (m_bIsStereo)
  228. {
  229. ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  230. ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_STEREOSURFACELEFT;
  231. }
  232. // Create the primary surface
  233. if (FAILED(hr = m_pDD->CreateSurface(&ddsd, &m_pddsFrontBuffer, NULL)))
  234. {
  235. DEBUG_MSG(_T("Error: Can't create primary surface"));
  236. if (hr != DDERR_OUTOFVIDEOMEMORY)
  237. return D3DFWERR_NOPRIMARY;
  238. DEBUG_MSG(_T("Error: Out of video memory"));
  239. return DDERR_OUTOFVIDEOMEMORY;
  240. }
  241. // Get the backbuffer, which was created along with the primary.
  242. DDSCAPS2 ddscaps = { DDSCAPS_BACKBUFFER, 0, 0, 0 };
  243. if (FAILED(hr = m_pddsFrontBuffer->GetAttachedSurface(&ddscaps,
  244. &m_pddsBackBuffer)))
  245. {
  246. DEBUG_ERR(hr, _T("Error: Can't get the backbuffer"));
  247. return D3DFWERR_NOBACKBUFFER;
  248. }
  249. // Increment the backbuffer count (for consistency with windowed mode)
  250. m_pddsBackBuffer->AddRef();
  251. // Support for stereoscopic viewing
  252. if (m_bIsStereo)
  253. {
  254. // Get the left backbuffer, which was created along with the primary.
  255. DDSCAPS2 ddscaps = { 0, DDSCAPS2_STEREOSURFACELEFT, 0, 0 };
  256. if (FAILED(hr = m_pddsBackBuffer->GetAttachedSurface(&ddscaps,
  257. &m_pddsBackBufferLeft)))
  258. {
  259. DEBUG_ERR(hr, _T("Error: Can't get the left backbuffer"));
  260. return D3DFWERR_NOBACKBUFFER;
  261. }
  262. m_pddsBackBufferLeft->AddRef();
  263. }
  264. return S_OK;
  265. }
  266. //-----------------------------------------------------------------------------
  267. // Name: CreateWindowedBuffers()
  268. // Desc: Creates the primary and (optional) backbuffer for rendering.
  269. // Windowed mode and fullscreen mode are handled differently.
  270. //-----------------------------------------------------------------------------
  271. HRESULT CD3DFramework7::CreateWindowedBuffers()
  272. {
  273. HRESULT hr;
  274. // Get the dimensions of the viewport and screen bounds
  275. GetClientRect(m_hWnd, &m_rcScreenRect);
  276. ClientToScreen(m_hWnd, (POINT*)&m_rcScreenRect.left);
  277. ClientToScreen(m_hWnd, (POINT*)&m_rcScreenRect.right);
  278. m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
  279. m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
  280. // Create the primary surface
  281. DDSURFACEDESC2 ddsd;
  282. ZeroMemory(&ddsd, sizeof(ddsd));
  283. ddsd.dwSize = sizeof(ddsd);
  284. ddsd.dwFlags = DDSD_CAPS;
  285. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  286. if (FAILED(hr = m_pDD->CreateSurface(&ddsd, &m_pddsFrontBuffer, NULL)))
  287. {
  288. DEBUG_MSG(_T("Error: Can't create primary surface"));
  289. if (hr != DDERR_OUTOFVIDEOMEMORY)
  290. return D3DFWERR_NOPRIMARY;
  291. DEBUG_MSG(_T("Error: Out of video memory"));
  292. return DDERR_OUTOFVIDEOMEMORY;
  293. }
  294. // If in windowed-mode, create a clipper object
  295. LPDIRECTDRAWCLIPPER pcClipper;
  296. if (FAILED(hr = m_pDD->CreateClipper(0, &pcClipper, NULL)))
  297. {
  298. DEBUG_MSG(_T("Error: Couldn't create clipper"));
  299. return D3DFWERR_NOCLIPPER;
  300. }
  301. // Associate the clipper with the window
  302. pcClipper->SetHWnd(0, m_hWnd);
  303. m_pddsFrontBuffer->SetClipper(pcClipper);
  304. SAFE_RELEASE(pcClipper);
  305. // Create a backbuffer
  306. ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
  307. ddsd.dwWidth = m_dwRenderWidth;
  308. ddsd.dwHeight = m_dwRenderHeight;
  309. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
  310. if (FAILED(hr = m_pDD->CreateSurface(&ddsd, &m_pddsBackBuffer, NULL)))
  311. {
  312. DEBUG_ERR(hr, _T("Error: Couldn't create the backbuffer"));
  313. if (hr != DDERR_OUTOFVIDEOMEMORY)
  314. return D3DFWERR_NOBACKBUFFER;
  315. DEBUG_MSG(_T("Error: Out of video memory"));
  316. return DDERR_OUTOFVIDEOMEMORY;
  317. }
  318. return S_OK;
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Name: CreateDirect3D()
  322. // Desc: Create the Direct3D interface
  323. //-----------------------------------------------------------------------------
  324. HRESULT CD3DFramework7::CreateDirect3D(GUID* pDeviceGUID)
  325. {
  326. // Query DirectDraw for access to Direct3D
  327. if (FAILED(m_pDD->QueryInterface(IID_IDirect3D7, (VOID**)&m_pD3D)))
  328. {
  329. DEBUG_MSG(_T("Couldn't get the Direct3D interface"));
  330. return D3DFWERR_NODIRECT3D;
  331. }
  332. // Create the device
  333. if (FAILED(m_pD3D->CreateDevice(*pDeviceGUID, m_pddsBackBuffer,
  334. &m_pd3dDevice)))
  335. {
  336. DEBUG_MSG(_T("Couldn't create the D3DDevice"));
  337. return D3DFWERR_NO3DDEVICE;
  338. }
  339. // Finally, set the viewport for the newly created device
  340. D3DVIEWPORT7 vp = { 0, 0, m_dwRenderWidth, m_dwRenderHeight, 0.0f, 1.0f };
  341. if (FAILED(m_pd3dDevice->SetViewport(&vp)))
  342. {
  343. DEBUG_MSG(_T("Error: Couldn't set current viewport to device"));
  344. return D3DFWERR_NOVIEWPORT;
  345. }
  346. return S_OK;
  347. }
  348. //-----------------------------------------------------------------------------
  349. // Name: CreateZBuffer()
  350. // Desc: Internal function called by Create() to make and attach a zbuffer
  351. // to the renderer
  352. //-----------------------------------------------------------------------------
  353. HRESULT CD3DFramework7::CreateZBuffer(GUID* pDeviceGUID)
  354. {
  355. HRESULT hr;
  356. // Check if the device supports z-bufferless hidden surface removal. If so,
  357. // we don't really need a z-buffer
  358. D3DDEVICEDESC7 ddDesc;
  359. m_pd3dDevice->GetCaps(&ddDesc);
  360. if (ddDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR)
  361. return S_OK;
  362. // Get z-buffer dimensions from the render target
  363. DDSURFACEDESC2 ddsd;
  364. ddsd.dwSize = sizeof(ddsd);
  365. m_pddsBackBuffer->GetSurfaceDesc(&ddsd);
  366. // Setup the surface desc for the z-buffer.
  367. ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
  368. ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_dwDeviceMemType;
  369. ddsd.ddpfPixelFormat.dwSize = 0; // Tag the pixel format as unitialized
  370. // Get an appropiate pixel format from enumeration of the formats. On the
  371. // first pass, we look for a zbuffer dpeth which is equal to the frame
  372. // buffer depth (as some cards unfornately require this).
  373. m_pD3D->EnumZBufferFormats(*pDeviceGUID, EnumZBufferFormatsCallback,
  374. (VOID*)&ddsd.ddpfPixelFormat);
  375. if (0 == ddsd.ddpfPixelFormat.dwSize)
  376. {
  377. // Try again, just accepting any 16-bit zbuffer
  378. ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
  379. m_pD3D->EnumZBufferFormats(*pDeviceGUID, EnumZBufferFormatsCallback,
  380. (VOID*)&ddsd.ddpfPixelFormat);
  381. if (0 == ddsd.ddpfPixelFormat.dwSize)
  382. {
  383. DEBUG_MSG(_T("Device doesn't support requested zbuffer format"));
  384. return D3DFWERR_NOZBUFFER;
  385. }
  386. }
  387. // Create and attach a z-buffer
  388. if (FAILED(hr = m_pDD->CreateSurface(&ddsd, &m_pddsZBuffer, NULL)))
  389. {
  390. DEBUG_MSG(_T("Error: Couldn't create a ZBuffer surface"));
  391. if (hr != DDERR_OUTOFVIDEOMEMORY)
  392. return D3DFWERR_NOZBUFFER;
  393. DEBUG_MSG(_T("Error: Out of video memory"));
  394. return DDERR_OUTOFVIDEOMEMORY;
  395. }
  396. if (FAILED(m_pddsBackBuffer->AddAttachedSurface(m_pddsZBuffer)))
  397. {
  398. DEBUG_MSG(_T("Error: Couldn't attach zbuffer to render surface"));
  399. return D3DFWERR_NOZBUFFER;
  400. }
  401. // For stereoscopic viewing, attach zbuffer to left surface as well
  402. if (m_bIsStereo)
  403. {
  404. if (FAILED(m_pddsBackBufferLeft->AddAttachedSurface(m_pddsZBuffer)))
  405. {
  406. DEBUG_MSG(_T("Error: Couldn't attach zbuffer to left render surface"));
  407. return D3DFWERR_NOZBUFFER;
  408. }
  409. }
  410. // Finally, this call rebuilds internal structures
  411. if (FAILED(m_pd3dDevice->SetRenderTarget(m_pddsBackBuffer, 0L)))
  412. {
  413. DEBUG_MSG(_T("Error: SetRenderTarget() failed after attaching zbuffer!"));
  414. return D3DFWERR_NOZBUFFER;
  415. }
  416. return S_OK;
  417. }
  418. //-----------------------------------------------------------------------------
  419. // Name: RestoreSurfaces()
  420. // Desc: Checks for lost surfaces and restores them if lost. Note: Don't
  421. // restore render surface, since it's just a duplicate ptr.
  422. //-----------------------------------------------------------------------------
  423. HRESULT CD3DFramework7::RestoreSurfaces()
  424. {
  425. // Restore all surfaces (including video memory vertex buffers)
  426. m_pDD->RestoreAllSurfaces();
  427. return S_OK;
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Name: Move()
  431. // Desc: Moves the screen rect for windowed renderers
  432. //-----------------------------------------------------------------------------
  433. VOID CD3DFramework7::Move(INT x, INT y)
  434. {
  435. if (TRUE == m_bIsFullscreen)
  436. return;
  437. SetRect(&m_rcScreenRect, x, y, x + m_dwRenderWidth, y + m_dwRenderHeight);
  438. }
  439. //-----------------------------------------------------------------------------
  440. // Name: FlipToGDISurface()
  441. // Desc: Puts the GDI surface in front of the primary, so that dialog
  442. // boxes and other windows drawing funcs may happen.
  443. //-----------------------------------------------------------------------------
  444. HRESULT CD3DFramework7::FlipToGDISurface(BOOL bDrawFrame)
  445. {
  446. if (m_pDD && m_bIsFullscreen)
  447. {
  448. m_pDD->FlipToGDISurface();
  449. if (bDrawFrame)
  450. {
  451. DrawMenuBar(m_hWnd);
  452. RedrawWindow(m_hWnd, NULL, NULL, RDW_FRAME);
  453. }
  454. }
  455. return S_OK;
  456. }
  457. //-----------------------------------------------------------------------------
  458. // Name: ShowFrame()
  459. // Desc: Show the frame on the primary surface, via a blt or a flip.
  460. //-----------------------------------------------------------------------------
  461. HRESULT CD3DFramework7::ShowFrame()
  462. {
  463. if (NULL == m_pddsFrontBuffer)
  464. return D3DFWERR_NOTINITIALIZED;
  465. if (m_bIsFullscreen)
  466. {
  467. // We are in fullscreen mode, so perform a flip.
  468. if (m_bIsStereo)
  469. return m_pddsFrontBuffer->Flip(NULL, DDFLIP_WAIT | DDFLIP_STEREO);
  470. else
  471. return m_pddsFrontBuffer->Flip(NULL, DDFLIP_WAIT);
  472. }
  473. else
  474. {
  475. // We are in windowed mode, so perform a blit.
  476. return m_pddsFrontBuffer->Blt(&m_rcScreenRect, m_pddsBackBuffer,
  477. NULL, DDBLT_WAIT, NULL);
  478. }
  479. }
  480. #endif