691 lines
20 KiB
C++
691 lines
20 KiB
C++
![]() |
//-----------------------------------------------------------------------------
|
||
|
// File: WinMain.cpp
|
||
|
//
|
||
|
// Desc: Windows code for Direct3D samples
|
||
|
//
|
||
|
// This code uses the Direct3D sample framework.
|
||
|
//
|
||
|
//
|
||
|
// Copyright (c) 1996-1998 Microsoft Corporation. All rights reserved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "WinMain.h"
|
||
|
#include "D3DFrame.h"
|
||
|
#include "D3DEnum.h"
|
||
|
#include "D3DUtil.h"
|
||
|
#include "resource.h"
|
||
|
|
||
|
#include "scene.h"
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Global variables for using the D3D sample framework class
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CD3DFramework* g_pFramework = NULL;
|
||
|
BOOL g_bActive = FALSE;
|
||
|
BOOL g_bReady = FALSE;
|
||
|
BOOL g_bFrameMoving = TRUE;
|
||
|
BOOL g_bSingleStep = FALSE;
|
||
|
BOOL g_bWindowed = TRUE;
|
||
|
BOOL g_bShowStats = TRUE;
|
||
|
RECT g_rcWindow;
|
||
|
HACCEL g_hAccel;
|
||
|
HWND g_hWnd;
|
||
|
|
||
|
enum APPMSGTYPE { MSG_NONE, MSGERR_APPMUSTEXIT, MSGWARN_SWITCHTOSOFTWARE };
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Local function-prototypes
|
||
|
//-----------------------------------------------------------------------------
|
||
|
INT CALLBACK AboutProc( HWND, UINT, WPARAM, LPARAM );
|
||
|
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
|
||
|
HRESULT Initialize3DEnvironment( HWND );
|
||
|
HRESULT Change3DEnvironment( HWND );
|
||
|
HRESULT Render3DEnvironment();
|
||
|
VOID Cleanup3DEnvironment();
|
||
|
VOID DisplayFrameworkError( HRESULT, APPMSGTYPE );
|
||
|
VOID AppShowStats();
|
||
|
VOID AppOutputText( LPDIRECT3DDEVICE3, DWORD, DWORD, CHAR* );
|
||
|
VOID AppPause( BOOL );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: WinMain()
|
||
|
// Desc: Entry point to the program. Initializes everything, and goes into a
|
||
|
// message-processing loop. Idle time is used to render the scene.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
//INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
|
||
|
extern "C" INT InitMain ()
|
||
|
{
|
||
|
HINSTANCE hInst = GetModuleHandle (NULL);
|
||
|
|
||
|
// Register the window class
|
||
|
WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst,
|
||
|
LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN_ICON)),
|
||
|
LoadCursor(NULL, IDC_ARROW),
|
||
|
(HBRUSH)GetStockObject(WHITE_BRUSH),
|
||
|
MAKEINTRESOURCE(IDR_MENU),
|
||
|
TEXT("Render Window") };
|
||
|
RegisterClass( &wndClass );
|
||
|
|
||
|
// Create our main window
|
||
|
g_hWnd = CreateWindow( TEXT("Render Window"), g_strAppTitle,
|
||
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
|
||
|
CW_USEDEFAULT, 300, 300, 0L, 0L, hInst, 0L );
|
||
|
|
||
|
RECT rect;
|
||
|
if (GetClientRect (g_hWnd, &rect))
|
||
|
{
|
||
|
int cx = 320 + (300 - rect.right);
|
||
|
int cy = 200 + (300 - rect.bottom);
|
||
|
|
||
|
SetWindowPos (g_hWnd, NULL, 0, 0, cx, cy, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);
|
||
|
}
|
||
|
|
||
|
ShowWindow( g_hWnd, SW_SHOWNORMAL );
|
||
|
UpdateWindow( g_hWnd );
|
||
|
|
||
|
// Save the window size/pos for switching modes
|
||
|
GetWindowRect( g_hWnd, &g_rcWindow );
|
||
|
|
||
|
// Load keyboard accelerators
|
||
|
g_hAccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
|
||
|
|
||
|
// Enumerate available D3D devices, passing a callback that allows devices
|
||
|
// to be accepted/rejected based on what capabilities the app requires.
|
||
|
HRESULT hr;
|
||
|
if( FAILED( hr = D3DEnum_EnumerateDevices( App_ConfirmDevice ) ) )
|
||
|
{
|
||
|
DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Check if we could not get a device that renders into a window, which
|
||
|
// means the display must be 16- or 256-color mode. If so, let's bail.
|
||
|
D3DEnum_DriverInfo* pDriverInfo;
|
||
|
D3DEnum_DeviceInfo* pDeviceInfo;
|
||
|
D3DEnum_GetSelectedDriver( &pDriverInfo, &pDeviceInfo );
|
||
|
if( FALSE == pDeviceInfo->bWindowed )
|
||
|
{
|
||
|
Cleanup3DEnvironment();
|
||
|
DisplayFrameworkError( D3DFWERR_INVALIDMODE, MSGERR_APPMUSTEXIT );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Initialize the 3D environment for the app
|
||
|
if( FAILED( hr = Initialize3DEnvironment( g_hWnd ) ) )
|
||
|
{
|
||
|
Cleanup3DEnvironment();
|
||
|
DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
g_bReady = TRUE;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void PumpMessages (void)
|
||
|
{
|
||
|
MSG msg;
|
||
|
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
|
||
|
{
|
||
|
// Exit App ?!?
|
||
|
if (msg.message == WM_QUIT)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!TranslateAccelerator (g_hWnd, g_hAccel, &msg))
|
||
|
{
|
||
|
TranslateMessage (&msg);
|
||
|
DispatchMessage (&msg);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: WndProc()
|
||
|
// Desc: This is the basic Windows-programming function that processes
|
||
|
// Windows messages. We need to handle window movement, painting,
|
||
|
// and destruction.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
LRESULT CALLBACK WndProc( HWND g_hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
switch( uMsg )
|
||
|
{
|
||
|
case WM_PAINT:
|
||
|
if( g_pFramework )
|
||
|
{
|
||
|
// If we are paused, and in fullscreen mode, give the dialogs
|
||
|
// a GDI surface to draw on.
|
||
|
if( !g_bReady && !g_bWindowed)
|
||
|
g_pFramework->FlipToGDISurface( TRUE );
|
||
|
else // Simply repaint the frame's contents
|
||
|
g_pFramework->ShowFrame();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_MOVE:
|
||
|
if( g_bActive && g_bReady && g_bWindowed )
|
||
|
{
|
||
|
GetWindowRect( g_hWnd, &g_rcWindow );
|
||
|
g_pFramework->Move( (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_SIZE:
|
||
|
// Check to see if we are losing our window...
|
||
|
if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
|
||
|
g_bActive = FALSE;
|
||
|
else g_bActive = TRUE;
|
||
|
|
||
|
// A new window size will require a new viewport and backbuffer
|
||
|
// size, so the 3D structures must be changed accordingly.
|
||
|
if( g_bActive && g_bReady && g_bWindowed )
|
||
|
{
|
||
|
g_bReady = FALSE;
|
||
|
GetWindowRect( g_hWnd, &g_rcWindow );
|
||
|
Change3DEnvironment( g_hWnd );
|
||
|
g_bReady = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_GETMINMAXINFO:
|
||
|
((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
|
||
|
((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
|
||
|
break;
|
||
|
|
||
|
case WM_SETCURSOR:
|
||
|
if( g_bActive && g_bReady && (!g_bWindowed) )
|
||
|
{
|
||
|
SetCursor(NULL);
|
||
|
return TRUE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_CLOSE:
|
||
|
DestroyWindow( g_hWnd );
|
||
|
return 0;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
Cleanup3DEnvironment();
|
||
|
PostQuitMessage(0);
|
||
|
return 0L;
|
||
|
|
||
|
case WM_ENTERMENULOOP:
|
||
|
AppPause(TRUE);
|
||
|
break;
|
||
|
|
||
|
case WM_EXITMENULOOP:
|
||
|
AppPause(FALSE);
|
||
|
break;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
{
|
||
|
HMENU hMenu = LoadMenu( 0, MAKEINTRESOURCE(IDR_POPUP) );
|
||
|
TrackPopupMenuEx( GetSubMenu( hMenu, 0 ),
|
||
|
TPM_VERTICAL, LOWORD(lParam),
|
||
|
HIWORD(lParam), g_hWnd, NULL );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
switch( LOWORD(wParam) )
|
||
|
{
|
||
|
case SC_MONITORPOWER:
|
||
|
// Prevent potential crashes when the monitor powers down
|
||
|
return 1;
|
||
|
|
||
|
case IDM_TOGGLESTART:
|
||
|
g_bFrameMoving = !g_bFrameMoving;
|
||
|
break;
|
||
|
|
||
|
case IDM_SINGLESTEP:
|
||
|
g_bSingleStep = TRUE;
|
||
|
break;
|
||
|
|
||
|
case IDM_CHANGEDEVICE:
|
||
|
// Display the driver-selection dialog box.
|
||
|
if( g_bActive && g_bReady )
|
||
|
{
|
||
|
AppPause(TRUE);
|
||
|
if( g_bWindowed )
|
||
|
GetWindowRect( g_hWnd, &g_rcWindow );
|
||
|
|
||
|
HWND hWnd = g_hWnd;
|
||
|
if( IDOK == D3DEnum_UserDlgSelectDriver( hWnd, g_bWindowed ) )
|
||
|
{
|
||
|
D3DEnum_DriverInfo* pDriverInfo;
|
||
|
D3DEnum_DeviceInfo* pDeviceInfo;
|
||
|
D3DEnum_GetSelectedDriver( &pDriverInfo, &pDeviceInfo );
|
||
|
g_bWindowed = pDeviceInfo->bWindowed;
|
||
|
|
||
|
Change3DEnvironment( g_hWnd );
|
||
|
}
|
||
|
AppPause(FALSE);
|
||
|
}
|
||
|
return 0;
|
||
|
|
||
|
case IDM_TOGGLEFULLSCREEN:
|
||
|
// Toggle the fullscreen/window mode
|
||
|
if( g_bActive && g_bReady )
|
||
|
{
|
||
|
g_bReady = FALSE;
|
||
|
if( g_bWindowed )
|
||
|
GetWindowRect( g_hWnd, &g_rcWindow );
|
||
|
g_bWindowed = !g_bWindowed;
|
||
|
Change3DEnvironment( g_hWnd );
|
||
|
g_bReady = TRUE;
|
||
|
}
|
||
|
return 0;
|
||
|
|
||
|
case IDM_HELP:
|
||
|
AppPause(TRUE);
|
||
|
DialogBox( (HINSTANCE)GetWindowLong( g_hWnd, GWL_HINSTANCE ),
|
||
|
MAKEINTRESOURCE(IDD_ABOUT), g_hWnd, (DLGPROC)AboutProc );
|
||
|
AppPause(FALSE);
|
||
|
return 0;
|
||
|
|
||
|
case IDM_EXIT:
|
||
|
// Recieved key/menu command to exit app
|
||
|
SendMessage( g_hWnd, WM_CLOSE, 0, 0 );
|
||
|
return 0;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return DefWindowProc( g_hWnd, uMsg, wParam, lParam );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: AboutProc()
|
||
|
// Desc: Minimal message proc function for the about box
|
||
|
//-----------------------------------------------------------------------------
|
||
|
BOOL CALLBACK AboutProc( HWND g_hWnd, UINT uMsg, WPARAM wParam, LPARAM )
|
||
|
{
|
||
|
if( WM_COMMAND == uMsg )
|
||
|
if( IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam) )
|
||
|
EndDialog (g_hWnd, TRUE);
|
||
|
|
||
|
return ( WM_INITDIALOG == uMsg ) ? TRUE : FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Note: From this point on, the code is DirectX specific support for the app.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: AppInitialize()
|
||
|
// Desc: Initializes the sample framework, then calls the app-specific function
|
||
|
// to initialize device specific objects. This code is structured to
|
||
|
// handled any errors that may occur duing initialization
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT AppInitialize( HWND g_hWnd )
|
||
|
{
|
||
|
D3DEnum_DriverInfo* pDriverInfo;
|
||
|
D3DEnum_DeviceInfo* pDeviceInfo;
|
||
|
DWORD dwFrameworkFlags = 0L;
|
||
|
HRESULT hr;
|
||
|
|
||
|
D3DEnum_GetSelectedDriver( &pDriverInfo, &pDeviceInfo );
|
||
|
|
||
|
dwFrameworkFlags |= (!g_bWindowed ? D3DFW_FULLSCREEN : 0L );
|
||
|
dwFrameworkFlags |= ( g_bAppUseZBuffer ? D3DFW_ZBUFFER : 0L );
|
||
|
dwFrameworkFlags |= ( g_bAppUseBackBuffer ? D3DFW_BACKBUFFER : 0L );
|
||
|
|
||
|
// Initialize the D3D framework
|
||
|
if( SUCCEEDED( hr = g_pFramework->Initialize( g_hWnd, &pDriverInfo->guid,
|
||
|
&pDeviceInfo->guid, &pDeviceInfo->pCurrentMode->ddsd,
|
||
|
dwFrameworkFlags ) ) )
|
||
|
{
|
||
|
// Let the app run its startup code which creates the 3d scene.
|
||
|
if( SUCCEEDED( hr = App_InitDeviceObjects( g_pFramework->GetD3DDevice(),
|
||
|
g_pFramework->GetViewport() ) ) )
|
||
|
return S_OK;
|
||
|
else
|
||
|
{
|
||
|
App_DeleteDeviceObjects( g_pFramework->GetD3DDevice(),
|
||
|
g_pFramework->GetViewport() );
|
||
|
g_pFramework->DestroyObjects();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If we get here, the first initialization passed failed. If that was with a
|
||
|
// hardware device, try again using a software rasterizer instead.
|
||
|
if( pDeviceInfo->bIsHardware )
|
||
|
{
|
||
|
// Try again with a software rasterizer
|
||
|
DisplayFrameworkError( hr, MSGWARN_SWITCHTOSOFTWARE );
|
||
|
D3DEnum_SelectDefaultDriver( D3DENUM_SOFTWAREONLY );
|
||
|
return AppInitialize( g_hWnd );
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: Initialize3DEnvironment()
|
||
|
// Desc: Called when the app window is initially created, this triggers
|
||
|
// creation of the remaining portion (the 3D stuff) of the app.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT Initialize3DEnvironment( HWND g_hWnd )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
// Initialize the app
|
||
|
if( FAILED( hr = App_OneTimeSceneInit( g_hWnd ) ) )
|
||
|
return E_FAIL;
|
||
|
|
||
|
// Create a new CD3DFramework class. This class does all of our D3D
|
||
|
// initialization and manages the common D3D objects.
|
||
|
if( NULL == ( g_pFramework = new CD3DFramework() ) )
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
// Finally, initialize the framework and scene.
|
||
|
return AppInitialize( g_hWnd );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: Change3DEnvironment()
|
||
|
// Desc: Handles driver, device, and/or mode changes for the app.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT Change3DEnvironment( HWND g_hWnd )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
// Release all objects that need to be re-created for the new device
|
||
|
App_DeleteDeviceObjects( g_pFramework->GetD3DDevice(),
|
||
|
g_pFramework->GetViewport() );
|
||
|
|
||
|
// Release the current framework objects (they will be recreated later on)
|
||
|
if( FAILED( hr = g_pFramework->DestroyObjects() ) )
|
||
|
{
|
||
|
DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
|
||
|
DestroyWindow( g_hWnd );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// In case we're coming from a fullscreen mode, restore the window size
|
||
|
if( g_bWindowed )
|
||
|
{
|
||
|
SetWindowPos( g_hWnd, HWND_NOTOPMOST, g_rcWindow.left, g_rcWindow.top,
|
||
|
( g_rcWindow.right - g_rcWindow.left ),
|
||
|
( g_rcWindow.bottom - g_rcWindow.top ), SWP_SHOWWINDOW );
|
||
|
}
|
||
|
|
||
|
// Inform the framework class of the driver change. It will internally
|
||
|
// re-create valid surfaces, a d3ddevice, and a viewport.
|
||
|
if( FAILED( hr = AppInitialize( g_hWnd ) ) )
|
||
|
{
|
||
|
DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
|
||
|
DestroyWindow( g_hWnd );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// Trigger the rendering of a frame and return
|
||
|
g_bSingleStep = TRUE;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
FLOAT g_fTime;
|
||
|
|
||
|
extern "C" HRESULT Win32_start_frame ()
|
||
|
{
|
||
|
// Check the cooperative level before rendering
|
||
|
if( FAILED( g_pFramework->GetDirectDraw()->TestCooperativeLevel() ) )
|
||
|
return S_OK;
|
||
|
|
||
|
// Get the current time
|
||
|
g_fTime = GetTickCount() * 0.001f;
|
||
|
|
||
|
return App_StartFrame( g_pFramework->GetD3DDevice(),
|
||
|
g_pFramework->GetViewport(),
|
||
|
(D3DRECT*)g_pFramework->GetViewportRect() );
|
||
|
}
|
||
|
|
||
|
extern "C" HRESULT Win32_end_frame ()
|
||
|
{
|
||
|
// Show the frame rate, etc.
|
||
|
if( g_bShowStats )
|
||
|
AppShowStats();
|
||
|
|
||
|
return App_EndFrame ();
|
||
|
}
|
||
|
|
||
|
extern "C" HRESULT Win32_flip_screens ()
|
||
|
{
|
||
|
// Show the frame on the primary surface.
|
||
|
if( DDERR_SURFACELOST == g_pFramework->ShowFrame() )
|
||
|
{
|
||
|
g_pFramework->RestoreSurfaces();
|
||
|
App_RestoreSurfaces();
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: Cleanup3DEnvironment()
|
||
|
// Desc: Cleanup scene objects
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID Cleanup3DEnvironment()
|
||
|
{
|
||
|
if( g_pFramework )
|
||
|
{
|
||
|
App_FinalCleanup( g_pFramework->GetD3DDevice(),
|
||
|
g_pFramework->GetViewport() );
|
||
|
|
||
|
SAFE_DELETE( g_pFramework );
|
||
|
}
|
||
|
g_bActive = FALSE;
|
||
|
g_bReady = FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: AppPause()
|
||
|
// Desc: Called in to toggle the pause state of the app. This function
|
||
|
// brings the GDI surface to the front of the display, so drawing
|
||
|
// output like message boxes and menus may be displayed.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID AppPause( BOOL bPause )
|
||
|
{
|
||
|
static DWORD dwAppPausedCount = 0L;
|
||
|
|
||
|
if( bPause && 0 == dwAppPausedCount )
|
||
|
if( g_pFramework )
|
||
|
g_pFramework->FlipToGDISurface( TRUE );
|
||
|
|
||
|
dwAppPausedCount += ( bPause ? +1 : -1 );
|
||
|
|
||
|
g_bReady = (0==dwAppPausedCount);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: AppShowStats()
|
||
|
// Desc: Shows frame rate and dimensions of the rendering device. Note: a
|
||
|
// "real" app wouldn't query the surface dimensions each frame.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID AppShowStats()
|
||
|
{
|
||
|
static FLOAT fFPS = 0.0f;
|
||
|
static FLOAT fLastTime = 0.0f;
|
||
|
static DWORD dwFrames = 0L;
|
||
|
|
||
|
// Keep track of the time lapse and frame count
|
||
|
FLOAT fTime = GetTickCount() * 0.001f; // Get current time in seconds
|
||
|
++dwFrames;
|
||
|
|
||
|
// Update the frame rate once per second
|
||
|
if( fTime - fLastTime > 1.0f )
|
||
|
{
|
||
|
fFPS = dwFrames / (fTime - fLastTime);
|
||
|
fLastTime = fTime;
|
||
|
dwFrames = 0L;
|
||
|
}
|
||
|
|
||
|
// Get dimensions of the render surface
|
||
|
DDSURFACEDESC2 ddsd;
|
||
|
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
|
g_pFramework->GetRenderSurface()->GetSurfaceDesc(&ddsd);
|
||
|
|
||
|
// Setup the text buffer to write out
|
||
|
CHAR buffer[80];
|
||
|
sprintf( buffer, "%7.02f fps (%dx%dx%d)", fFPS, ddsd.dwWidth,
|
||
|
ddsd.dwHeight, ddsd.ddpfPixelFormat.dwRGBBitCount );
|
||
|
AppOutputText( g_pFramework->GetD3DDevice(), 0, 0, buffer );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: AppOutputText()
|
||
|
// Desc: Draws text on the window.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID AppOutputText( LPDIRECT3DDEVICE3 pd3dDevice, DWORD x, DWORD y, CHAR* str )
|
||
|
{
|
||
|
LPDIRECTDRAWSURFACE4 pddsRenderSurface;
|
||
|
if( FAILED( pd3dDevice->GetRenderTarget( &pddsRenderSurface ) ) )
|
||
|
return;
|
||
|
|
||
|
// Get a DC for the surface. Then, write out the buffer
|
||
|
HDC hDC;
|
||
|
if( SUCCEEDED( pddsRenderSurface->GetDC(&hDC) ) )
|
||
|
{
|
||
|
SetTextColor( hDC, RGB(255,255,0) );
|
||
|
SetBkMode( hDC, TRANSPARENT );
|
||
|
ExtTextOut( hDC, x, y, 0, NULL, str, strlen(str), NULL );
|
||
|
|
||
|
pddsRenderSurface->ReleaseDC(hDC);
|
||
|
}
|
||
|
pddsRenderSurface->Release();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: DisplayFrameworkError()
|
||
|
// Desc: Displays error messages in a message box
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID DisplayFrameworkError( HRESULT hr, APPMSGTYPE errType )
|
||
|
{
|
||
|
CHAR strMsg[512];
|
||
|
|
||
|
switch( hr )
|
||
|
{
|
||
|
case D3DENUMERR_NOCOMPATIBLEDEVICES:
|
||
|
strcpy( strMsg, TEXT("Could not find any compatible Direct3D\n"
|
||
|
"devices.") );
|
||
|
break;
|
||
|
case D3DENUMERR_SUGGESTREFRAST:
|
||
|
strcpy( strMsg, TEXT("Could not find any compatible devices.\n\n"
|
||
|
"Try enabling the reference rasterizer using\n"
|
||
|
"EnableRefRast.reg.") );
|
||
|
break;
|
||
|
case D3DENUMERR_ENUMERATIONFAILED:
|
||
|
strcpy( strMsg, TEXT("Enumeration failed. Your system may be in an\n"
|
||
|
"unstable state and need to be rebooted") );
|
||
|
break;
|
||
|
case D3DFWERR_INITIALIZATIONFAILED:
|
||
|
strcpy( strMsg, TEXT("Generic initialization error.\n\nEnable "
|
||
|
"debug output for detailed information.") );
|
||
|
break;
|
||
|
case D3DFWERR_NODIRECTDRAW:
|
||
|
strcpy( strMsg, TEXT("No DirectDraw") );
|
||
|
break;
|
||
|
case D3DFWERR_NODIRECT3D:
|
||
|
strcpy( strMsg, TEXT("No Direct3D") );
|
||
|
break;
|
||
|
case D3DFWERR_INVALIDMODE:
|
||
|
strcpy( strMsg, TEXT("This sample requires a 16-bit (or higher) "
|
||
|
"display mode\nto run in a window.\n\nPlease switch "
|
||
|
"your desktop settings accordingly.") );
|
||
|
break;
|
||
|
case D3DFWERR_COULDNTSETCOOPLEVEL:
|
||
|
strcpy( strMsg, TEXT("Could not set Cooperative Level") );
|
||
|
break;
|
||
|
case D3DFWERR_NO3DDEVICE:
|
||
|
strcpy( strMsg, TEXT("No 3D Device") );
|
||
|
break;
|
||
|
case D3DFWERR_NOZBUFFER:
|
||
|
strcpy( strMsg, TEXT("No ZBuffer") );
|
||
|
break;
|
||
|
case D3DFWERR_NOVIEWPORT:
|
||
|
strcpy( strMsg, TEXT("No Viewport") );
|
||
|
break;
|
||
|
case D3DFWERR_NOPRIMARY:
|
||
|
strcpy( strMsg, TEXT("No primary") );
|
||
|
break;
|
||
|
case D3DFWERR_NOCLIPPER:
|
||
|
strcpy( strMsg, TEXT("No Clipper") );
|
||
|
break;
|
||
|
case D3DFWERR_BADDISPLAYMODE:
|
||
|
strcpy( strMsg, TEXT("Bad display mode") );
|
||
|
break;
|
||
|
case D3DFWERR_NOBACKBUFFER:
|
||
|
strcpy( strMsg, TEXT("No backbuffer") );
|
||
|
break;
|
||
|
case D3DFWERR_NONZEROREFCOUNT:
|
||
|
strcpy( strMsg, TEXT("Nonzerorefcount") );
|
||
|
break;
|
||
|
case D3DFWERR_NORENDERTARGET:
|
||
|
strcpy( strMsg, TEXT("No render target") );
|
||
|
break;
|
||
|
case E_OUTOFMEMORY:
|
||
|
strcpy( strMsg, TEXT("Not enough memory!") );
|
||
|
break;
|
||
|
case DDERR_OUTOFVIDEOMEMORY:
|
||
|
strcpy( strMsg, TEXT("There was insufficient video memory "
|
||
|
"to use the\nhardware device.") );
|
||
|
break;
|
||
|
default:
|
||
|
strcpy( strMsg, TEXT("Generic application error.\n\nEnable "
|
||
|
"debug output for detailed information.") );
|
||
|
}
|
||
|
|
||
|
if( MSGERR_APPMUSTEXIT == errType )
|
||
|
{
|
||
|
strcat( strMsg, TEXT("\n\nThis sample will now exit.") );
|
||
|
MessageBox( NULL, strMsg, g_strAppTitle, MB_ICONERROR|MB_OK );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( MSGWARN_SWITCHTOSOFTWARE == errType )
|
||
|
strcat( strMsg, TEXT("\n\nSwitching to software rasterizer.") );
|
||
|
MessageBox( NULL, strMsg, g_strAppTitle, MB_ICONWARNING|MB_OK );
|
||
|
}
|
||
|
}
|