720 lines
23 KiB
C++
720 lines
23 KiB
C++
//--------------------------------------------------------------------------------------
|
|
// File: D3D9ExSample.cpp
|
|
//
|
|
// Sample showing how to use D3D9Ex advanced features.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//--------------------------------------------------------------------------------------
|
|
#define INITGUID
|
|
#include <windows.h>
|
|
#include <d3d9.h>
|
|
#include <d3dx9.h>
|
|
#include "TxtHelper.h"
|
|
|
|
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p) = NULL; } }
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// structures
|
|
//--------------------------------------------------------------------------------------
|
|
struct CURSORVERTEX
|
|
{
|
|
FLOAT x, y, z, w; // The transformed position for the vertex
|
|
DWORD dwColor; // Color
|
|
};
|
|
#define D3DFVF_CURSORVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
|
|
|
|
struct SCREENVERTEX
|
|
{
|
|
FLOAT x, y, z, w; // The transformed position for the vertex
|
|
FLOAT u, v; // texture coordinate
|
|
};
|
|
#define D3DFVF_SCREENVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1)
|
|
|
|
#define CURSOR_SIZE 60.0f
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Global variables
|
|
//--------------------------------------------------------------------------------------
|
|
HWND g_hWnd = NULL; // Window Handle
|
|
IDirect3D9Ex* g_pD3D9 = NULL; // Direct3D9Ex object
|
|
IDirect3DDevice9Ex* g_pDevRealTime = NULL; // Device for rendering the real-time
|
|
// objects like cursors
|
|
|
|
D3DPRESENT_PARAMETERS g_D3DPresentParameters = {0}; // Current present parameters
|
|
|
|
HANDLE g_hBackgroundThread = NULL; // Background thread
|
|
|
|
IDirect3DVertexBuffer9* g_pCursorVB = NULL; // cursor vertex buffer
|
|
IDirect3DVertexBuffer9* g_pScreenVB = NULL; // screen vertex buffer
|
|
|
|
IDirect3DTexture9* g_pSharedBackgroundTexture = NULL;// Our shared texture
|
|
|
|
ID3DXFont* g_pFont = NULL; // Font for drawing text
|
|
ID3DXSprite* g_pSprite = NULL; // Sprite for batching draw text calls
|
|
|
|
extern UINT g_RTWidth;
|
|
extern UINT g_RTHeight;
|
|
|
|
bool g_bSkipRendering = false;
|
|
int g_cubeCount = 3;
|
|
D3DPRESENTSTATS g_PresentStats;
|
|
float g_fLastFrameTime = 0.0f;
|
|
LARGE_INTEGER g_liLastTimerUpdate = {0};
|
|
LARGE_INTEGER g_liTimerFrequency = {0};
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Function Prototypes
|
|
//--------------------------------------------------------------------------------------
|
|
BOOL InitWindow( HINSTANCE hInstance, int nCmdShow );
|
|
HRESULT CreateD3D9VDevice( IDirect3D9Ex* pD3D, IDirect3DDevice9Ex** ppDev9Ex, D3DPRESENT_PARAMETERS* pD3DPresentParameters, HWND hWnd );
|
|
HRESULT InitD3D();
|
|
HRESULT CreateFont();
|
|
HRESULT CreateSprite();
|
|
void Cleanup();
|
|
HRESULT CreateD3DCursor();
|
|
HRESULT CreateScreenVB( float screenX, float screenY );
|
|
HRESULT UpdateScreenVB( float screenX, float screenY );
|
|
HRESULT CreateSharedTexture();
|
|
void MoveCursor( UINT posX, UINT posY );
|
|
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
|
void Render( IDirect3DDevice9Ex* pDev );
|
|
void RenderText( IDirect3DDevice9Ex* pDev );
|
|
|
|
extern HANDLE CreateBackgroundThread(IDirect3D9Ex* pD3D9);
|
|
extern void KillBackgroundThread();
|
|
extern HANDLE GetSharedTextureHandle();
|
|
extern int IncreaseCubeCount();
|
|
extern int DecreaseCubeCount();
|
|
extern float GetFPS();
|
|
|
|
|
|
int APIENTRY wWinMain( HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPWSTR lpCmdLine,
|
|
int nCmdShow )
|
|
{
|
|
MSG msg = {0};
|
|
msg.wParam = -1;
|
|
|
|
if( !InitWindow( hInstance, nCmdShow ) )
|
|
return 0;
|
|
if( FAILED(InitD3D()) )
|
|
return 1;
|
|
|
|
g_D3DPresentParameters.hDeviceWindow = g_hWnd;
|
|
g_D3DPresentParameters.Windowed = TRUE;
|
|
g_D3DPresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
g_D3DPresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
|
|
|
if( FAILED(CreateD3D9VDevice( g_pD3D9, &g_pDevRealTime, &g_D3DPresentParameters, g_hWnd ) ) )
|
|
return 2;
|
|
if( FAILED(CreateD3DCursor()) )
|
|
return 3;
|
|
if( FAILED( CreateScreenVB( 800, 600 ) ) )
|
|
return 4;
|
|
if( FAILED( CreateFont() ) )
|
|
return 5;
|
|
if( FAILED( CreateSprite() ) )
|
|
return 6;
|
|
|
|
// set the realtime GPU thread priority
|
|
g_pDevRealTime->SetGPUThreadPriority( 7 );
|
|
SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST );
|
|
|
|
// Get Timer Frequency
|
|
QueryPerformanceFrequency( &g_liTimerFrequency );
|
|
QueryPerformanceCounter( &g_liLastTimerUpdate );
|
|
|
|
// Create the background thread
|
|
g_hBackgroundThread = CreateBackgroundThread(g_pD3D9);
|
|
if(!g_hBackgroundThread)
|
|
goto exit;
|
|
|
|
if( FAILED( CreateSharedTexture() ) )
|
|
return 5;
|
|
|
|
// Hide the cursor
|
|
ShowCursor( false );
|
|
|
|
// Main loop
|
|
msg.message = WM_NULL;
|
|
PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE );
|
|
while( WM_QUIT != msg.message )
|
|
{
|
|
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
|
|
{
|
|
TranslateMessage( &msg );
|
|
DispatchMessage( &msg );
|
|
}
|
|
else
|
|
{
|
|
Render(g_pDevRealTime); // Do some rendering
|
|
}
|
|
}
|
|
|
|
exit:
|
|
if(g_hBackgroundThread)
|
|
{
|
|
KillBackgroundThread();
|
|
WaitForSingleObject(g_hBackgroundThread,INFINITE);
|
|
}
|
|
|
|
Cleanup();
|
|
return (int) msg.wParam;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Register class and create window
|
|
//--------------------------------------------------------------------------------------
|
|
BOOL InitWindow( HINSTANCE hInstance, int nCmdShow )
|
|
{
|
|
//
|
|
// Register class
|
|
//
|
|
WNDCLASSEX wcex;
|
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
wcex.style = CS_CLASSDC;
|
|
wcex.lpfnWndProc = WndProc;
|
|
wcex.cbClsExtra = 0;
|
|
wcex.cbWndExtra = 0;
|
|
wcex.hInstance = hInstance;
|
|
wcex.hIcon = 0;
|
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
|
wcex.lpszMenuName = NULL;
|
|
wcex.lpszClassName = L"d3d9vwindowclass";
|
|
wcex.hIconSm = 0;
|
|
|
|
if( !RegisterClassEx(&wcex) )
|
|
return FALSE;
|
|
|
|
//
|
|
// Create window
|
|
//
|
|
RECT rc = { 0, 0, 800, 600 };
|
|
AdjustWindowRectEx( &rc, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_CLIENTEDGE );
|
|
g_hWnd = CreateWindowEx( WS_EX_CLIENTEDGE, L"d3d9vwindowclass", L"Direct3D9Ex Sample", WS_OVERLAPPEDWINDOW,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL,
|
|
hInstance, NULL);
|
|
|
|
if( !g_hWnd )
|
|
return FALSE;
|
|
|
|
ShowWindow( g_hWnd, nCmdShow );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
HRESULT CreateD3D9VDevice( IDirect3D9Ex* pD3D, IDirect3DDevice9Ex** ppDev9Ex, D3DPRESENT_PARAMETERS* pD3DPresentParameters, HWND hWnd )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Create a d3d9ex device
|
|
DWORD dwFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_ENABLE_PRESENTSTATS;
|
|
|
|
if( !hWnd )
|
|
{
|
|
hWnd = g_hWnd;
|
|
dwFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
|
}
|
|
|
|
hr = pD3D->CreateDeviceEx( D3DADAPTER_DEFAULT,
|
|
D3DDEVTYPE_HAL,
|
|
hWnd,
|
|
dwFlags,
|
|
pD3DPresentParameters,
|
|
NULL,
|
|
ppDev9Ex );
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
// Make sure our formats are OK
|
|
D3DCAPS9 Caps;
|
|
ZeroMemory(&Caps,sizeof(D3DCAPS9));
|
|
pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &Caps );
|
|
|
|
// Skip backbuffer formats that don't support alpha blending
|
|
hr = pD3D->CheckDeviceFormat( Caps.AdapterOrdinal, Caps.DeviceType,
|
|
pD3DPresentParameters->BackBufferFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
|
|
D3DRTYPE_TEXTURE, pD3DPresentParameters->BackBufferFormat );
|
|
if(FAILED(hr))
|
|
{
|
|
SAFE_RELEASE( *ppDev9Ex );
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT InitD3D()
|
|
{
|
|
// Create a d3d9 device
|
|
HRESULT hr = Direct3DCreate9Ex( D3D_SDK_VERSION, &g_pD3D9 );
|
|
return hr;
|
|
}
|
|
|
|
HRESULT Reset(IDirect3DDevice9Ex* pDev9Ex)
|
|
{
|
|
// reset the d3d9ex device
|
|
HRESULT hr = pDev9Ex->Reset( &g_D3DPresentParameters);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
return CreateSprite();
|
|
}
|
|
|
|
HRESULT CreateFont()
|
|
{
|
|
if ( FAILED( D3DXCreateFont( g_pDevRealTime, 16, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET,
|
|
OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
|
|
L"Arial", &g_pFont ) ) )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CreateSprite()
|
|
{
|
|
// Create a sprite to help batch calls when drawing many lines of text
|
|
return D3DXCreateSprite( g_pDevRealTime, &g_pSprite );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Clean up the objects we've created
|
|
//--------------------------------------------------------------------------------------
|
|
void Cleanup()
|
|
{
|
|
SAFE_RELEASE(g_pD3D9);
|
|
SAFE_RELEASE(g_pDevRealTime);
|
|
SAFE_RELEASE(g_pCursorVB);
|
|
SAFE_RELEASE(g_pScreenVB);
|
|
SAFE_RELEASE(g_pSharedBackgroundTexture);
|
|
SAFE_RELEASE(g_pFont);
|
|
SAFE_RELEASE(g_pSprite);
|
|
}
|
|
|
|
|
|
HRESULT CreateD3DCursor()
|
|
{
|
|
// create the vb
|
|
if( FAILED( g_pDevRealTime->CreateVertexBuffer( 4*sizeof(CURSORVERTEX),
|
|
D3DUSAGE_DYNAMIC,
|
|
D3DFVF_CURSORVERTEX,
|
|
D3DPOOL_DEFAULT,
|
|
&g_pCursorVB,
|
|
NULL ) ) )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
MoveCursor( 400, 300 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CreateScreenVB( float screenX, float screenY )
|
|
{
|
|
// create the vb
|
|
if( FAILED( g_pDevRealTime->CreateVertexBuffer( 4*sizeof(SCREENVERTEX),
|
|
D3DUSAGE_DYNAMIC,
|
|
D3DFVF_SCREENVERTEX,
|
|
D3DPOOL_DEFAULT,
|
|
&g_pScreenVB,
|
|
NULL ) ) )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
UpdateScreenVB( screenX, screenY);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT UpdateScreenVB( float screenX, float screenY )
|
|
{
|
|
SCREENVERTEX* vertices = NULL;
|
|
if( FAILED( g_pScreenVB->Lock( 0, 4*sizeof(SCREENVERTEX), (void**)&vertices, 0 ) ) )
|
|
return E_FAIL;
|
|
|
|
vertices[0].x = 0;
|
|
vertices[0].y = screenY;
|
|
vertices[0].z = 0.5f;
|
|
vertices[0].w = 1.0f;
|
|
vertices[0].u = 0.0f;
|
|
vertices[0].v = 1.0f;
|
|
|
|
vertices[1].x = 0;
|
|
vertices[1].y = 0;
|
|
vertices[1].z = 0.5f;
|
|
vertices[1].w = 1.0f;
|
|
vertices[1].u = 0.0f;
|
|
vertices[1].v = 0.0f;
|
|
|
|
vertices[2].x = screenX;
|
|
vertices[2].y = screenY;
|
|
vertices[2].z = 0.5f;
|
|
vertices[2].w = 1.0f;
|
|
vertices[2].u = 1.0f;
|
|
vertices[2].v = 1.0f;
|
|
|
|
vertices[3].x = screenX;
|
|
vertices[3].y = 0;
|
|
vertices[3].z = 0.5f;
|
|
vertices[3].w = 1.0f;
|
|
vertices[3].u = 1.0f;
|
|
vertices[3].v = 0.0f;
|
|
|
|
g_pScreenVB->Unlock();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CreateSharedTexture()
|
|
{
|
|
// wait for a handle from the other thread
|
|
HANDLE hHandle = NULL;
|
|
while( !hHandle )
|
|
hHandle = GetSharedTextureHandle();
|
|
|
|
HRESULT hr = g_pDevRealTime->CreateTexture( g_RTWidth,
|
|
g_RTHeight,
|
|
1,
|
|
D3DUSAGE_RENDERTARGET,
|
|
D3DFMT_X8R8G8B8,
|
|
D3DPOOL_DEFAULT,
|
|
&g_pSharedBackgroundTexture,
|
|
&hHandle );
|
|
if( FAILED( hr ) )
|
|
return E_FAIL;
|
|
|
|
return hr;
|
|
}
|
|
|
|
void MoveCursor( UINT posX, UINT posY )
|
|
{
|
|
float x = static_cast<float>(posX);
|
|
float y = static_cast<float>(posY);
|
|
|
|
// Initialize vertices for rendering a quad
|
|
CURSORVERTEX vertices[4];
|
|
|
|
vertices[0].x = x;
|
|
vertices[0].y = y;
|
|
vertices[0].z = 0.5f;
|
|
vertices[0].w = 1.0f;
|
|
|
|
vertices[1].x = x + CURSOR_SIZE;
|
|
vertices[1].y = y + CURSOR_SIZE*0.6f;
|
|
vertices[1].z = 0.5f;
|
|
vertices[1].w = 1.0f;
|
|
|
|
vertices[2].x = x + CURSOR_SIZE*0.6f;
|
|
vertices[2].y = y + CURSOR_SIZE;
|
|
vertices[2].z = 0.5f;
|
|
vertices[2].w = 1.0f;
|
|
|
|
vertices[3].x = x + CURSOR_SIZE;
|
|
vertices[3].y = y + CURSOR_SIZE;
|
|
vertices[3].z = 0.5f;
|
|
vertices[3].w = 1.0f;
|
|
|
|
for(int i=0; i<4; i++)
|
|
vertices[i].dwColor = 0xff0000;
|
|
|
|
VOID* pVertices;
|
|
if( FAILED( g_pCursorVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
|
|
return;
|
|
memcpy( pVertices, vertices, sizeof(vertices) );
|
|
g_pCursorVB->Unlock();
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_PAINT:
|
|
hdc = BeginPaint(hWnd, &ps);
|
|
EndPaint(hWnd, &ps);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case WM_MOUSEMOVE:
|
|
{
|
|
UINT x = LOWORD( lParam );
|
|
UINT y = HIWORD( lParam );
|
|
MoveCursor( x,y );
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_KEYUP:
|
|
switch( wParam )
|
|
{
|
|
case VK_UP:
|
|
g_cubeCount = IncreaseCubeCount();
|
|
break;
|
|
case VK_DOWN:
|
|
g_cubeCount = DecreaseCubeCount();
|
|
break;
|
|
case VK_ESCAPE:
|
|
PostQuitMessage(0);
|
|
break;
|
|
};
|
|
break;
|
|
|
|
case WM_SYSKEYUP:
|
|
if( (wParam == VK_RETURN) && (g_pD3D9 != NULL) && (g_pDevRealTime != NULL) )
|
|
{
|
|
g_D3DPresentParameters.Windowed = !g_D3DPresentParameters.Windowed;
|
|
|
|
DWORD dwStyle;
|
|
DWORD dwExStyle;
|
|
|
|
D3DDISPLAYMODE Mode;
|
|
|
|
g_pD3D9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode);
|
|
|
|
if (g_D3DPresentParameters.Windowed)
|
|
{
|
|
//
|
|
// Default to using the window client area size
|
|
//
|
|
g_D3DPresentParameters.BackBufferWidth = 800;
|
|
g_D3DPresentParameters.BackBufferHeight = 600;
|
|
|
|
//
|
|
// Window styles for D3D windowed mode
|
|
//
|
|
dwStyle = WS_OVERLAPPEDWINDOW;
|
|
dwExStyle = WS_EX_CLIENTEDGE;
|
|
}
|
|
else
|
|
{
|
|
g_D3DPresentParameters.BackBufferWidth=Mode.Width;
|
|
g_D3DPresentParameters.BackBufferHeight=Mode.Height;
|
|
|
|
dwStyle = WS_POPUP;
|
|
dwExStyle = WS_EX_TOPMOST;
|
|
}
|
|
|
|
SetWindowLong( g_hWnd, GWL_STYLE, dwStyle );
|
|
SetWindowLong( g_hWnd, GWL_EXSTYLE, dwExStyle );
|
|
|
|
if (g_D3DPresentParameters.Windowed)
|
|
{
|
|
|
|
RECT rc = { 0, 0, g_D3DPresentParameters.BackBufferWidth, g_D3DPresentParameters.BackBufferHeight };
|
|
AdjustWindowRectEx( &rc, dwStyle, FALSE, dwExStyle);
|
|
|
|
SetWindowPos( g_hWnd, HWND_NOTOPMOST,
|
|
0, 0,
|
|
rc.right - rc.left,
|
|
rc.bottom - rc.top,
|
|
SWP_SHOWWINDOW | SWP_NOMOVE );
|
|
}
|
|
|
|
HRESULT hr;
|
|
|
|
hr = g_pDevRealTime->Reset(&g_D3DPresentParameters);
|
|
|
|
if (SUCCEEDED( hr ))
|
|
{
|
|
hr = UpdateScreenVB(static_cast<float>(g_D3DPresentParameters.BackBufferWidth),
|
|
static_cast<float>(g_D3DPresentParameters.BackBufferHeight));
|
|
}
|
|
|
|
if (FAILED( hr ))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Render( IDirect3DDevice9Ex* pDev )
|
|
{
|
|
// Begin the scene
|
|
if( !g_bSkipRendering && SUCCEEDED( pDev->BeginScene() ) )
|
|
{
|
|
// disable lighting
|
|
pDev->SetRenderState( D3DRS_LIGHTING, FALSE );
|
|
|
|
|
|
//
|
|
// Render the background
|
|
//
|
|
|
|
// set the texture
|
|
pDev->SetTexture( 0, g_pSharedBackgroundTexture );
|
|
|
|
pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
|
|
pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
|
|
// stream sources
|
|
pDev->SetStreamSource( 0, g_pScreenVB, 0, sizeof(SCREENVERTEX) );
|
|
pDev->SetFVF( D3DFVF_SCREENVERTEX );
|
|
|
|
// draw
|
|
pDev->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
|
|
|
|
|
|
//
|
|
// Render the cursor
|
|
//
|
|
|
|
pDev->SetTexture( 0, NULL );
|
|
|
|
// set the texture stage states
|
|
pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
|
|
pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
|
|
|
|
// stream sources
|
|
pDev->SetStreamSource( 0, g_pCursorVB, 0, sizeof(CURSORVERTEX) );
|
|
pDev->SetFVF( D3DFVF_CURSORVERTEX );
|
|
|
|
// draw
|
|
pDev->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
|
|
|
|
// render text
|
|
RenderText( pDev );
|
|
|
|
// End the scene
|
|
pDev->EndScene();
|
|
}
|
|
else if( g_bSkipRendering )
|
|
Sleep(20); //don't hog the entire CPU
|
|
|
|
// Present the backbuffer contents to the display
|
|
HRESULT hr = pDev->Present( NULL, NULL, NULL, NULL );
|
|
|
|
// Handle Occluded, DeviceReset, or Mode Changes
|
|
if( S_PRESENT_OCCLUDED == hr )
|
|
{
|
|
g_bSkipRendering = true;
|
|
}
|
|
else if( D3DERR_DEVICELOST == hr )
|
|
{
|
|
if(FAILED( Reset( pDev ) ) )
|
|
g_bSkipRendering = true;
|
|
}
|
|
else if( S_PRESENT_MODE_CHANGED == hr )
|
|
{
|
|
//
|
|
// Reenumerate modes by calling IDirect3D9::GetAdapterModeCountEx
|
|
//
|
|
D3DDISPLAYMODEFILTER DisplayModeFilter;
|
|
|
|
ZeroMemory(&DisplayModeFilter, sizeof(DisplayModeFilter));
|
|
|
|
DisplayModeFilter.Size = sizeof(DisplayModeFilter);
|
|
DisplayModeFilter.Format = D3DFMT_UNKNOWN;
|
|
DisplayModeFilter.ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE;
|
|
|
|
UINT ModeCount = g_pD3D9->GetAdapterModeCountEx(D3DADAPTER_DEFAULT, &DisplayModeFilter);
|
|
|
|
if(FAILED( Reset( pDev ) ) )
|
|
g_bSkipRendering = true;
|
|
}
|
|
else if( D3DERR_DEVICEHUNG == hr )
|
|
{
|
|
MessageBox( g_hWnd,
|
|
L"This application has caused the graphics adapter to hang, check with the hardware vendor for a new driver.",
|
|
L"Graphics Adapter Hang",
|
|
MB_OK );
|
|
|
|
PostQuitMessage(0);
|
|
g_bSkipRendering = true;
|
|
}
|
|
else
|
|
{
|
|
g_bSkipRendering = false;
|
|
}
|
|
|
|
// Get some presents stats
|
|
IDirect3DSwapChain9* pSwapChain;
|
|
if( SUCCEEDED( pDev->GetSwapChain( 0, &pSwapChain ) ) )
|
|
{
|
|
IDirect3DSwapChain9Ex* pSwapChainEx;
|
|
if( SUCCEEDED( pSwapChain->QueryInterface( IID_IDirect3DSwapChain9Ex, (void**)&pSwapChainEx ) ) )
|
|
{
|
|
hr = pSwapChainEx->GetLastPresentCount( &g_PresentStats.PresentCount );
|
|
if( SUCCEEDED( hr ) )
|
|
hr = pSwapChainEx->GetPresentStats( &g_PresentStats );
|
|
pSwapChainEx->Release();
|
|
}
|
|
pSwapChain->Release();
|
|
}
|
|
|
|
// Get the time
|
|
LARGE_INTEGER liCurrentTime;
|
|
QueryPerformanceCounter( &liCurrentTime );
|
|
g_fLastFrameTime = (float)(liCurrentTime.QuadPart - g_liLastTimerUpdate.QuadPart) / (float)g_liTimerFrequency.QuadPart;
|
|
g_liLastTimerUpdate.QuadPart = liCurrentTime.QuadPart;
|
|
}
|
|
|
|
void RenderText( IDirect3DDevice9Ex* pDev )
|
|
{
|
|
// The helper object simply helps keep track of text position, and color
|
|
// and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
|
|
// If NULL is passed in as the sprite object, then it will work fine however the
|
|
// pFont->DrawText() will not be batched together. Batching calls will improves perf.
|
|
CTextHelper txtHelper( g_pFont, g_pSprite, 15 );
|
|
|
|
// Output statistics
|
|
txtHelper.Begin();
|
|
txtHelper.SetInsertionPos( 2, 0 );
|
|
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
|
|
txtHelper.DrawTextLine( L"This sample demonstrates rendering a cursor indepedently of geometry." );
|
|
txtHelper.DrawTextLine( L"The scene (cubes in this case) is drawn by a D3D9Ex device that runs" );
|
|
txtHelper.DrawTextLine( L"in a lower priority background thread. The image is copied to a shared" );
|
|
txtHelper.DrawTextLine( L"surface. The main application thread contains a D3D9Ex device as well." );
|
|
txtHelper.DrawTextLine( L"This thread runs at a higher priority and composites the shared image" );
|
|
txtHelper.DrawTextLine( L"with a D3D9Ex drawn cursor and text in real time. This allows for" );
|
|
txtHelper.DrawTextLine( L"fluid cursor and text updates even when the scene is too complex to be" );
|
|
txtHelper.DrawTextLine( L"handled in real-time." );
|
|
|
|
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ) );
|
|
txtHelper.DrawTextLine( L"" );
|
|
txtHelper.DrawTextLine( L"Press the UP arrow key to increase the scene complexity." );
|
|
txtHelper.DrawTextLine( L"Press the DOWN arrow key to decrease the scene complexity." );
|
|
txtHelper.DrawTextLine( L"" );
|
|
txtHelper.DrawTextLine( L"Try increasing the Number of Cubes to a very high number. The cubes will" );
|
|
txtHelper.DrawTextLine( L"update slowly, but the cursor will still be responsive." );
|
|
txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
|
|
txtHelper.DrawTextLine( L"" );
|
|
txtHelper.DrawFormattedTextLine( L"Number of Cubes: %d", g_cubeCount*g_cubeCount );
|
|
|
|
// get stats from the background thread
|
|
float FPS = GetFPS();
|
|
txtHelper.SetForegroundColor( D3DXCOLOR( 0.0f, 1.0f, 0.0f, 1.0f ) );
|
|
txtHelper.DrawTextLine( L"" );
|
|
txtHelper.DrawTextLine( L"Background Thread:" );
|
|
txtHelper.DrawFormattedTextLine( L"FPS: %0.2f", FPS );
|
|
txtHelper.DrawTextLine( L"" );
|
|
txtHelper.DrawTextLine( L"Foreground Thread:" );
|
|
txtHelper.DrawFormattedTextLine( L"FPS: %0.2f", 1.0f / g_fLastFrameTime );
|
|
txtHelper.DrawFormattedTextLine( L"Present Count: %d", g_PresentStats.PresentCount );
|
|
txtHelper.DrawFormattedTextLine( L"Present Refresh Count: %d", g_PresentStats.PresentRefreshCount );
|
|
txtHelper.DrawFormattedTextLine( L"Sync Refresh Count: %d", g_PresentStats.SyncRefreshCount );
|
|
|
|
txtHelper.End();
|
|
}
|
|
|
|
|