1 //-----------------------------------------------------------------------------
4 // Desc: Class to manage the Direct3D environment objects such as buffers,
5 // viewports, and 3D devices.
7 // The class is initialized with the Initialize() function, after which
8 // the Get????() functions can be used to access the objects needed for
9 // rendering. If the device or display needs to be changed, the
10 // ChangeDevice() function can be called. If the display window is moved
11 // the changes need to be reported with the Move() function.
13 // After rendering a frame, the ShowFrame() function filps or blits the
14 // backbuffer contents to the primary. If surfaces are lost, they can be
15 // restored with the RestoreSurfaces() function. Finally, if normal
16 // Windows output is needed, the FlipToGDISurface() provides a GDI
17 // surface to draw on.
20 // Copyright (c) 1995-1998 by Microsoft, all rights reserved
21 //-----------------------------------------------------------------------------
30 //-----------------------------------------------------------------------------
31 // Name: EnumZBufferFormatsCallback()
32 // Desc: Enumeration function to report valid pixel formats for z-buffers.
33 //-----------------------------------------------------------------------------
34 static HRESULT WINAPI EnumZBufferFormatsCallback( DDPIXELFORMAT* pddpf,
37 if( NULL==pddpf || NULL==pddpfDesired )
38 return D3DENUMRET_CANCEL;
40 // If the current pixel format's match the desired ones (DDPF_ZBUFFER and
41 // possibly DDPF_STENCILBUFFER), lets copy it and return. This function is
42 // not choosy...it accepts the first valid format that comes along.
43 if( pddpf->dwFlags == ((DDPIXELFORMAT*)pddpfDesired)->dwFlags )
45 memcpy( pddpfDesired, pddpf, sizeof(DDPIXELFORMAT) );
47 // We're happy with a 16-bit z-buffer. Otherwise, keep looking.
48 if( pddpf->dwZBufferBitDepth == 16 )
49 return D3DENUMRET_CANCEL;
58 //-----------------------------------------------------------------------------
59 // Name: CD3DFramework()
60 // Desc: The constructor. Clears static variables
61 //-----------------------------------------------------------------------------
62 CD3DFramework::CD3DFramework()
65 m_bIsFullscreen = FALSE;
67 m_dwRenderHeight = 0L;
68 m_pddsFrontBuffer = NULL;
69 m_pddsBackBuffer = NULL;
70 m_pddsRenderTarget = NULL;
76 m_dwDeviceMemType = NULL;
82 //-----------------------------------------------------------------------------
83 // Name: ~CD3DFramework()
84 // Desc: The destructor. Deletes all objects
85 //-----------------------------------------------------------------------------
86 CD3DFramework::~CD3DFramework()
94 //-----------------------------------------------------------------------------
95 // Name: DestroyObjects()
96 // Desc: Cleans everything up upon deletion. This code returns an error
97 // if any of the objects have remaining reference counts.
98 //-----------------------------------------------------------------------------
99 HRESULT CD3DFramework::DestroyObjects()
101 LONG nDD = 0L; // Number of outstanding DDraw references
102 LONG nD3D = 0L; // Number of outstanding D3DDevice references
104 SAFE_RELEASE( m_pvViewport );
106 // Do a safe check for releasing the D3DDEVICE. RefCount must be zero.
108 if( 0 < ( nD3D = m_pd3dDevice->Release() ) )
109 DEBUG_MSG( TEXT("Error: D3DDevice object is still referenced!") );
112 // In windowed mode, release the explicity created backbuffer.
113 if( FALSE == m_bIsFullscreen )
114 SAFE_RELEASE( m_pddsBackBuffer );
115 SAFE_RELEASE( m_pddsRenderTarget ); //Note: release before frontbuffer
116 SAFE_RELEASE( m_pddsZBuffer );
117 SAFE_RELEASE( m_pddsFrontBuffer );
118 SAFE_RELEASE( m_pD3D );
120 // Do a safe check for releasing DDRAW. RefCount must be zero.
123 m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL );
125 if( 0 < ( nDD = m_pDD->Release() ) )
126 DEBUG_MSG( TEXT("Error: DDraw object is still referenced!") );
130 // Return successful, unless there are outstanding DD or D3DDevice refs.
131 return ( nDD==0 && nD3D==0 ) ? S_OK : D3DFWERR_NONZEROREFCOUNT;
137 //-----------------------------------------------------------------------------
138 // Name: Initialize()
139 // Desc: Creates the internal objects for the framework
140 //-----------------------------------------------------------------------------
141 HRESULT CD3DFramework::Initialize( HWND hWnd, GUID* pDriverGUID,
142 GUID* pDeviceGUID, DDSURFACEDESC2* pMode,
147 // Check params. A NULL mode is valid for windowed modes only. A NULL
148 // device GUID is legal for apps that only want 2D support.
149 if( NULL==hWnd || ( NULL==pMode && (dwFlags&D3DFW_FULLSCREEN) ) )
152 // Setup state for windowed/fullscreen mode
154 m_bIsFullscreen = ( dwFlags & D3DFW_FULLSCREEN ) ? TRUE : FALSE;
156 // Create the D3D rendering environment (surfaces, device, viewport, etc.)
157 if( FAILED( hr = CreateEnvironment( pDriverGUID, pDeviceGUID, pMode,
162 hr = D3DFWERR_INITIALIZATIONFAILED;
170 //-----------------------------------------------------------------------------
171 // Name: CreateEnvironment()
172 // Desc: Creates the internal objects for the framework
173 //-----------------------------------------------------------------------------
174 HRESULT CD3DFramework::CreateEnvironment( GUID* pDriverGUID, GUID* pDeviceGUID,
175 DDSURFACEDESC2* pMode, DWORD dwFlags )
179 // Create the DDraw object
180 if( FAILED( hr = CreateDirectDraw( pDriverGUID, dwFlags ) ) )
183 // Create the Direct3D object
185 if( FAILED( hr = CreateDirect3D( pDeviceGUID, dwFlags ) ) )
188 // Create the front and back buffers, and attach a clipper
189 if( FAILED( hr = CreateBuffers( pMode, dwFlags ) ) )
192 // If there is no device GUID, then the app only wants 2D, so we're done
193 if( NULL == pDeviceGUID )
196 // Create and attach the zbuffer
197 if( dwFlags & D3DFW_ZBUFFER )
198 if( FAILED( hr = CreateZBuffer() ) )
201 // Query the render buffer for the 3ddevice
202 if( FAILED( hr = Create3DDevice( pDeviceGUID ) ) )
205 // Create and set the viewport
206 if( FAILED( hr = CreateViewport() ) )
215 //-----------------------------------------------------------------------------
216 // Name: CreateDirectDraw()
217 // Desc: Create the DirectDraw interface
218 //-----------------------------------------------------------------------------
219 HRESULT CD3DFramework::CreateDirectDraw( GUID* pDriverGUID, DWORD dwFlags )
221 // Create the DirectDraw interface, and query for the DD4 interface
223 if( FAILED( DirectDrawCreate( pDriverGUID, &pDD, NULL ) ) )
225 DEBUG_MSG( TEXT("Could not create DirectDraw") );
226 return D3DFWERR_NODIRECTDRAW;
229 if( FAILED( pDD->QueryInterface( IID_IDirectDraw4, (VOID**)&m_pDD ) ) )
232 DEBUG_MSG( TEXT("Couldn't query for DirectDraw4") );
233 return D3DFWERR_NODIRECTDRAW;
237 // Set the Windows cooperative level
238 DWORD dwCoopFlags = DDSCL_NORMAL;
239 if( m_bIsFullscreen )
240 dwCoopFlags = DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN;
242 // By defualt, set the flag to allow D3D to optimize floating point calcs
243 if( 0L == ( dwFlags & D3DFW_NO_FPUSETUP ) )
244 dwCoopFlags |= DDSCL_FPUSETUP;
246 if( FAILED( m_pDD->SetCooperativeLevel( m_hWnd, dwCoopFlags ) ) )
248 DEBUG_MSG( TEXT("Couldn't set coop level") );
249 return D3DFWERR_COULDNTSETCOOPLEVEL;
258 //-----------------------------------------------------------------------------
259 // Name: CreateDirect3D()
260 // Desc: Create the Direct3D interface
261 //-----------------------------------------------------------------------------
262 HRESULT CD3DFramework::CreateDirect3D( GUID* pDeviceGUID, DWORD dwFlags )
264 // Query DirectDraw for access to Direct3D
265 if( FAILED( m_pDD->QueryInterface( IID_IDirect3D3, (VOID**)&m_pD3D ) ) )
267 DEBUG_MSG( TEXT("Couldn't query the Direct3D interface") );
268 return D3DFWERR_NODIRECT3D;
271 // Use the FindDevice() method to test if the requested device
272 // exists, and if so, take note of what memory type it takes.
273 D3DFINDDEVICERESULT devResult;
274 D3DFINDDEVICESEARCH devSearch;
275 ZeroMemory( &devResult, sizeof(D3DFINDDEVICERESULT) );
276 ZeroMemory( &devSearch, sizeof(D3DFINDDEVICESEARCH) );
277 devResult.dwSize = sizeof(D3DFINDDEVICERESULT);
278 devSearch.dwSize = sizeof(D3DFINDDEVICESEARCH);
279 devSearch.dwFlags = D3DFDS_GUID;
280 CopyMemory( &devSearch.guid, pDeviceGUID, sizeof(GUID) );
282 if( FAILED( m_pD3D->FindDevice( &devSearch, &devResult ) ) )
284 DEBUG_MSG( TEXT("Couldn't find the specified device") );
285 return D3DFWERR_NODIRECT3D;
288 // Whether device is SW or HW, get the devicedesc, and the defualt memtype
289 if( 0L == devResult.ddHwDesc.dwFlags )
291 m_dwDeviceMemType = DDSCAPS_SYSTEMMEMORY;
292 memcpy( &m_ddDeviceDesc, &devResult.ddSwDesc, sizeof(D3DDEVICEDESC) );
296 m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
297 memcpy( &m_ddDeviceDesc, &devResult.ddHwDesc, sizeof(D3DDEVICEDESC) );
300 // Using the device GUID, let's enumerate a format for our z-buffer, in
301 // case we later decide to create one.
302 ZeroMemory( &m_ddpfZBuffer, sizeof(DDPIXELFORMAT) );
304 if( dwFlags & D3DFW_STENCILBUFFER )
305 m_ddpfZBuffer.dwFlags = DDPF_ZBUFFER | DDPF_STENCILBUFFER;
307 m_ddpfZBuffer.dwFlags = DDPF_ZBUFFER;
309 // Get an appropiate pixel format from enumeration of the formats.
310 m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
311 (VOID*)&m_ddpfZBuffer );
313 if( sizeof(DDPIXELFORMAT) != m_ddpfZBuffer.dwSize )
315 DEBUG_MSG( TEXT("Device doesn't support requested zbuffer format") );
316 return D3DFWERR_NOZBUFFER;
325 //-----------------------------------------------------------------------------
326 // Name: CreateBuffers()
327 // Desc: Creates the primary and (optional) backbuffer for rendering.
328 // Windowed mode and fullscreen mode are handled differently.
329 //-----------------------------------------------------------------------------
330 HRESULT CD3DFramework::CreateBuffers( DDSURFACEDESC2* pddsd, DWORD dwFlags )
334 if( dwFlags & D3DFW_FULLSCREEN )
336 // Get the dimensions of the viewport and screen bounds
337 // Store the rectangle which contains the renderer
338 SetRect( &m_rcViewportRect, 0, 0, pddsd->dwWidth, pddsd->dwHeight );
339 memcpy( &m_rcScreenRect, &m_rcViewportRect, sizeof(RECT) );
340 m_dwRenderWidth = m_rcViewportRect.right;
341 m_dwRenderHeight = m_rcViewportRect.bottom;
343 // Set the display mode to the requested dimensions. Check for
344 // 320x200x8 modes, and set flag to avoid using ModeX
345 DWORD dwModeFlags = 0;
347 if( (320==m_dwRenderWidth) && (200==m_dwRenderHeight) &&
348 (8==pddsd->ddpfPixelFormat.dwRGBBitCount) )
349 dwModeFlags |= DDSDM_STANDARDVGAMODE;
351 if( FAILED( m_pDD->SetDisplayMode( m_dwRenderWidth, m_dwRenderHeight,
352 pddsd->ddpfPixelFormat.dwRGBBitCount,
353 pddsd->dwRefreshRate, dwModeFlags ) ) )
355 DEBUG_MSG( TEXT("Can't set display mode") );
356 return D3DFWERR_BADDISPLAYMODE;
359 // Create the primary surface
361 D3DUtil_InitSurfaceDesc( ddsd, DDSD_CAPS );
362 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
364 // With no backbuffer, the primary becomes the render target
365 if( dwFlags & D3DFW_BACKBUFFER )
367 ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
368 ddsd.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX;
369 ddsd.dwBackBufferCount = 1;
372 if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
374 DEBUG_MSG( TEXT("Error: Can't create primary surface") );
375 if( hr != DDERR_OUTOFVIDEOMEMORY )
376 return D3DFWERR_NOPRIMARY;
377 DEBUG_MSG( TEXT("Error: Out of video memory") );
378 return DDERR_OUTOFVIDEOMEMORY;
381 // Get the backbuffer. For fullscreen mode, the backbuffer was created
382 // along with the primary, but windowed mode still needs to create one.
383 if( dwFlags & D3DFW_BACKBUFFER )
385 // Get a ptr to the back buffer, which will be our render target
387 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
388 if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps,
389 &m_pddsBackBuffer ) ) )
391 DEBUG_MSG( TEXT("Error: Can't get/create the backbuffer") );
392 if( hr != DDERR_OUTOFVIDEOMEMORY )
393 return D3DFWERR_NOBACKBUFFER;
394 DEBUG_MSG( TEXT("Error: Out of video memory") );
395 return DDERR_OUTOFVIDEOMEMORY;
399 else // Set up buffers for windowed rendering
401 // Get the dimensions of the viewport and screen bounds
402 GetClientRect( m_hWnd, &m_rcViewportRect );
403 GetClientRect( m_hWnd, &m_rcScreenRect );
404 ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.left );
405 ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.right );
406 m_dwRenderWidth = m_rcViewportRect.right;
407 m_dwRenderHeight = m_rcViewportRect.bottom;
409 // Create the primary surface
411 D3DUtil_InitSurfaceDesc( ddsd, DDSD_CAPS );
412 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
414 // With no backbuffer, the primary becomes the render target
415 if( 0L == ( dwFlags & D3DFW_BACKBUFFER ) )
416 ddsd.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
418 if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
420 DEBUG_MSG( TEXT("Error: Can't create primary surface") );
421 if( hr != DDERR_OUTOFVIDEOMEMORY )
422 return D3DFWERR_NOPRIMARY;
423 DEBUG_MSG( TEXT("Error: Out of video memory") );
424 return DDERR_OUTOFVIDEOMEMORY;
427 // If in windowed-mode, create a clipper object
428 LPDIRECTDRAWCLIPPER pcClipper;
429 if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
431 DEBUG_MSG( TEXT("Error: Couldn't create clipper") );
432 return D3DFWERR_NOCLIPPER;
435 // Associate the clipper with the window
436 pcClipper->SetHWnd( 0, m_hWnd );
437 m_pddsFrontBuffer->SetClipper( pcClipper );
438 SAFE_RELEASE( pcClipper );
440 // Get the backbuffer. For fullscreen mode, the backbuffer was created
441 // along with the primary, but windowed mode still needs to create one.
442 if( dwFlags & D3DFW_BACKBUFFER )
444 // Create the back buffer (the render target)
445 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
446 ddsd.dwWidth = m_dwRenderWidth;
447 ddsd.dwHeight = m_dwRenderHeight;
448 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
450 if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) )
452 DEBUG_MSG( TEXT("Error: Couldn't create the backbuffer") );
453 if( hr != DDERR_OUTOFVIDEOMEMORY )
454 return D3DFWERR_NOBACKBUFFER;
455 DEBUG_MSG( TEXT("Error: Out of video memory") );
456 return DDERR_OUTOFVIDEOMEMORY;
459 else // For rendering without a backbuffer
461 ClientToScreen( m_hWnd, (POINT*)&m_rcViewportRect.left );
462 ClientToScreen( m_hWnd, (POINT*)&m_rcViewportRect.right );
466 // Set up backbuffer ptr and ref counts
467 if( dwFlags & D3DFW_BACKBUFFER )
468 m_pddsRenderTarget = m_pddsBackBuffer;
470 m_pddsRenderTarget = m_pddsFrontBuffer;
471 m_pddsRenderTarget->AddRef();
479 //-----------------------------------------------------------------------------
480 // Name: CreateZBuffer()
481 // Desc: Internal function called by Create() to make and attach a zbuffer
483 //-----------------------------------------------------------------------------
484 HRESULT CD3DFramework::CreateZBuffer()
488 // Check if the device supports z-bufferless hidden surface removal. If so,
489 // we don't really need a z-buffer
490 DWORD dwRasterCaps = m_ddDeviceDesc.dpcTriCaps.dwRasterCaps;
491 if( dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
494 // Get z-buffer dimensions from the render target
495 // Setup the surface desc for the z-buffer.
497 D3DUtil_InitSurfaceDesc( ddsd, DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS |
499 ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_dwDeviceMemType;
500 ddsd.dwWidth = m_dwRenderWidth;
501 ddsd.dwHeight = m_dwRenderHeight;
502 memcpy( &ddsd.ddpfPixelFormat, &m_ddpfZBuffer, sizeof(DDPIXELFORMAT) );
504 // Create and attach a z-buffer
505 if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsZBuffer, NULL ) ) )
507 DEBUG_MSG( TEXT("Error: Couldn't create a ZBuffer surface") );
508 if( hr != DDERR_OUTOFVIDEOMEMORY )
509 return D3DFWERR_NOZBUFFER;
510 DEBUG_MSG( TEXT("Error: Out of video memory") );
511 return DDERR_OUTOFVIDEOMEMORY;
514 if( FAILED( m_pddsRenderTarget->AddAttachedSurface( m_pddsZBuffer ) ) )
516 DEBUG_MSG( TEXT("Error: Couldn't attach zbuffer to render surface") );
517 return D3DFWERR_NOZBUFFER;
526 //-----------------------------------------------------------------------------
527 // Name: Create3DDevice()
528 // Desc: Creates the 3D device for the render target
529 //-----------------------------------------------------------------------------
530 HRESULT CD3DFramework::Create3DDevice( GUID* pDeviceGUID )
532 // Check that we are NOT in a palettized display. That case will fail,
533 // since the framework doesn't use palettes.
535 ddsd.dwSize = sizeof(DDSURFACEDESC2);
536 m_pDD->GetDisplayMode( &ddsd );
537 if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
538 return D3DFWERR_INVALIDMODE;
541 if( FAILED( m_pD3D->CreateDevice( *pDeviceGUID, m_pddsRenderTarget,
542 &m_pd3dDevice, NULL ) ) )
544 DEBUG_MSG( TEXT("Couldn't create the D3DDevice") );
545 return D3DFWERR_NO3DDEVICE;
554 //-----------------------------------------------------------------------------
555 // Name: CreateViewport()
556 // Desc: Create the D3D viewport used by the renderer.
557 //-----------------------------------------------------------------------------
558 HRESULT CD3DFramework::CreateViewport()
560 // Set up the viewport data parameters
563 D3DUtil_InitViewport( vdData, m_dwRenderWidth, m_dwRenderHeight );
565 // Create the viewport
566 if( FAILED( m_pD3D->CreateViewport( &m_pvViewport, NULL ) ) )
568 DEBUG_MSG( TEXT("Error: Couldn't create a viewport") );
569 return D3DFWERR_NOVIEWPORT;
572 // Associate the viewport with the D3DDEVICE object
573 if( FAILED( hr = m_pd3dDevice->AddViewport( m_pvViewport ) ) )
575 DEBUG_MSG( TEXT("Error: Couldn't add the viewport") );
576 return D3DFWERR_NOVIEWPORT;
579 // Set the parameters to the new viewport
580 if( FAILED( m_pvViewport->SetViewport2( &vdData ) ) )
582 DEBUG_MSG( TEXT("Error: Couldn't set the viewport data") );
583 return D3DFWERR_NOVIEWPORT;
586 // Finally, set the current viewport for the current device
587 if( FAILED( m_pd3dDevice->SetCurrentViewport( m_pvViewport ) ) )
589 DEBUG_MSG( TEXT("Error: Couldn't set current viewport to device") );
590 return D3DFWERR_NOVIEWPORT;
599 //-----------------------------------------------------------------------------
601 // Desc: Show the frame on the primary surface, via a blt or a flip.
602 //-----------------------------------------------------------------------------
603 HRESULT CD3DFramework::ShowFrame()
605 if( NULL == m_pddsFrontBuffer )
606 return D3DFWERR_NOTINITIALIZED;
608 // Check for a backbuffer. If no backbuffer exists, then we have nothing to
609 // do. However, to be consistent let's check for lost surfaces
610 if( NULL == m_pddsBackBuffer )
611 return m_pddsFrontBuffer->IsLost();
613 // If we are in fullscreen mode perform a flip.
614 if( m_bIsFullscreen )
615 return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT );
617 // Else, we are in windowed mode, so perform a blit.
618 return m_pddsFrontBuffer->Blt( &m_rcScreenRect, m_pddsBackBuffer,
619 &m_rcViewportRect, DDBLT_WAIT, NULL );
625 //-----------------------------------------------------------------------------
626 // Name: FlipToGDISurface()
627 // Desc: Puts the GDI surface in front of the primary, so that dialog
628 // boxes and other windows drawing funcs may happen.
629 //-----------------------------------------------------------------------------
630 HRESULT CD3DFramework::FlipToGDISurface( BOOL bDrawFrame )
632 if( m_pDD && m_bIsFullscreen )
634 m_pDD->FlipToGDISurface();
638 DrawMenuBar( m_hWnd );
639 RedrawWindow( m_hWnd, NULL, NULL, RDW_FRAME );
649 //-----------------------------------------------------------------------------
650 // Name: RestoreSurfaces()
651 // Desc: Checks for lost surfaces and restores them if lost. Note: Don't
652 // restore render surface, since it's just a duplicate ptr.
653 //-----------------------------------------------------------------------------
654 HRESULT CD3DFramework::RestoreSurfaces()
656 // Check/restore the primary surface
657 if( m_pddsFrontBuffer )
658 if( m_pddsFrontBuffer->IsLost() )
659 m_pddsFrontBuffer->Restore();
661 // Check/restore the back buffer
662 if( m_pddsBackBuffer )
663 if( m_pddsBackBuffer->IsLost() )
664 m_pddsBackBuffer->Restore();
666 // Check/restore the z-buffer surface
668 if( m_pddsZBuffer->IsLost() )
669 m_pddsZBuffer->Restore();
677 //-----------------------------------------------------------------------------
679 // Desc: Moves the screen rect for windowed renderers
680 //-----------------------------------------------------------------------------
681 VOID CD3DFramework::Move( INT x, INT y )
683 if( FALSE == m_bIsFullscreen )
685 SetRect( &m_rcScreenRect, x, y,
686 x + m_dwRenderWidth, y + m_dwRenderHeight );
688 // If we have no backbuffer, then update viewport rect as well
689 if( NULL == m_pddsBackBuffer )
690 CopyMemory( &m_rcViewportRect, &m_rcScreenRect, sizeof(RECT) );
697 //-----------------------------------------------------------------------------
698 // Name: ChangeRenderTarget()
699 // Desc: Wrapper for the IDirect3DDevice::SetRenderTarget() function, which
700 // adds functionality to handle an attached z-buffer. Note that this
701 // function does NOT alter the current viewport
702 //-----------------------------------------------------------------------------
703 HRESULT CD3DFramework::ChangeRenderTarget( LPDIRECTDRAWSURFACE4 pddsNewTarget )
705 if( NULL == pddsNewTarget )
708 // Get the new render target dimensions
710 D3DUtil_InitSurfaceDesc( ddsd );
711 pddsNewTarget->GetSurfaceDesc( &ddsd );
712 m_dwRenderWidth = ddsd.dwWidth;
713 m_dwRenderHeight = ddsd.dwHeight;
715 // If a z-buffer is attached, delete and recreate it
716 if( NULL != m_pddsZBuffer )
718 // Remove the old z-buffer
719 m_pddsRenderTarget->DeleteAttachedSurface( 0, m_pddsZBuffer );
720 SAFE_RELEASE( m_pddsZBuffer );
722 // Keep track of reference counts
723 SAFE_RELEASE( m_pddsRenderTarget );
724 m_pddsRenderTarget = pddsNewTarget;
725 m_pddsRenderTarget->AddRef();
727 // Create the new z-buffer
728 if( FAILED( CreateZBuffer() ) )
730 DEBUG_MSG( TEXT("ChangeRenderTarget() - zbuffer create failed") );
731 return D3DFWERR_NOZBUFFER;
736 // With no z-buffer, we just do accounting on the reference counts
737 SAFE_RELEASE( m_pddsRenderTarget );
738 m_pddsRenderTarget = pddsNewTarget;
739 m_pddsRenderTarget->AddRef();
742 // Finally, perform the set render target call
743 if( FAILED( m_pd3dDevice->SetRenderTarget( m_pddsRenderTarget, 0 ) ) )
745 return D3DFWERR_NORENDERTARGET;