topical media & game development
hush-src-multi-DLL-RenderEngine.cpp / cpp
//------------------------------------------------------------------------------
// File: RenderEngine.cpp
//
// Desc: DirectShow sample code - Implementation of CMultiVMR9RenderEngine
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
include <stdafx.h>
include <RenderEngine.h>
include <d3dx9.h>
****************************Public*Routine******************************\
CMultiVMR9RenderEngine
constructor
\*************************************************************************
CMultiVMR9RenderEngine::CMultiVMR9RenderEngine(LPUNKNOWN pUnk, HRESULT *phr)
: CUnknown(NAME("MultiVMR9 Render Engine"), pUnk)
, m_hwnd( NULL )
, m_pDevice( NULL)
, m_pUILayer( NULL )
, m_pMixerControl( NULL )
, m_pOwner( NULL )
, m_bInitialized( FALSE )
, m_Timer( NULL )
, m_setFPS( 100000 )
, m_getFPS( 0 )
, m_interframe( 33)
, m_interframeInstant( 0L )
, m_dwFramesDrawn( 0)
, m_dwStart(0)
, m_dwLastRender( 0)
, m_bChangingDevice( FALSE )
{
// make sure timer is at least 2 ms accurate
timeBeginPeriod(2);
}
****************************Public*Routine******************************\
CMultiVMR9RenderEngine
destructor
\*************************************************************************
CMultiVMR9RenderEngine::~CMultiVMR9RenderEngine()
{
HRESULT hr = S_OK;
CAutoLock Lock(&m_ObjectLock);
// here we have to disconnect child IMultiVMR9UILayer and IMultiVMR9MixerControl
if( m_pUILayer )
{
hr = m_pUILayer->SetRenderEngineOwner( NULL);
if( FAILED(hr))
{
::DbgMsg("~CMultiVMR9RenderEngine: failed to disconnect child UILayer, he = 0x%08x", hr);
}
}
if( m_pMixerControl )
{
hr = m_pMixerControl->SetRenderEngineOwner(NULL);
if( FAILED(hr))
{
::DbgMsg("~CMultiVMR9RenderEngine: failed to disconnect child mixer control, he = 0x%08x", hr);
}
}
Clean_();
// call off the timer
timeEndPeriod(2);
}
/////////////////// IUnknown ///////////////////////////////////
****************************Public*Routine******************************\
CreateInstance
\*************************************************************************
CUnknown* CMultiVMR9RenderEngine::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
return new CMultiVMR9RenderEngine(pUnk, phr);
}
****************************Public*Routine******************************\
NonDelegatingQueryInterface
\*************************************************************************
STDMETHODIMP
CMultiVMR9RenderEngine::NonDelegatingQueryInterface(
REFIID riid,
void ** ppv)
{
HRESULT hr = E_NOINTERFACE;
*ppv = NULL;
if (riid == IID_IMultiVMR9RenderEngine)
{
hr = GetInterface((IMultiVMR9RenderEngine *)this, ppv);
}
else
{
hr = CUnknown::NonDelegatingQueryInterface(riid,ppv);
}
return hr;
}
/////////////////// IMultiVMR9RenderEngine ////////////////////////
****************************Public*Routine******************************\
Initialize
Call this method right after IMultiVMR9Wizard object is created to configure
and initialize internal structures as well as D3D environment.
hWnd - handle to valid video window
dwFlags - Configuration flags
lViewWidth - desired width of the view port. If <=0, render engine will use
default backbuffer width
lVieweHeight - desired height of the view port. if <=0, render engine
will use default value of backbuffer height
pMixerControl - customized IMultiVMR9MixerControl, use NULL for the default
pUILayer - customized IMultiVMR9UILayer, use NULL if there is no UI layer
Return error codes: E_INVALIDARG (invalid config flags or hWnd),
VFW_E_WRONG_STATE (method was already called before)
E_FAIL (unexpected error),
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::Initialize(
HWND hWnd,
DWORD dwFlags,
IMultiVMR9MixerControl* pMixerControl,
IMultiVMR9UILayer* pUILayer
)
{
HRESULT hr = S_OK;
if( FALSE == IsWindow( hWnd ))
{
::DbgMsg("CMultiVMR9RenderEngine::Initialize: received invalid window handle");
return E_INVALIDARG;
}
if( m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::Initialize: method was already called");
return VFW_E_WRONG_STATE;
}
CAutoLock Lock(&m_ObjectLock);
try
{
m_hwnd = hWnd;
// TODO: check flags
m_dwCfgFlags = dwFlags;
if( pMixerControl )
{
m_pMixerControl = pMixerControl;
m_pMixerControl->AddRef();
}
else // create default mixer control
{
CHECK_HR(
hr = CoCreateInstance( CLSID_MultiVMR9MixerControl,
NULL, CLSCTX_INPROC_SERVER,
IID_IMultiVMR9MixerControl,
(void**)&m_pMixerControl),
::DbgMsg("CMultiVMR9RenderEngine::Initialize: failed to create default MultiVMR9MixerControl, "\
"hr = 0x%08x", hr));
}
CHECK_HR(
m_pMixerControl->SetRenderEngineOwner( this ),
::DbgMsg("CMultiVMR9RenderEngine::Initialize: failed to advise 'this' owner to the mixer control"));
if( pUILayer )
{
m_pUILayer = pUILayer;
m_pUILayer->AddRef();
CHECK_HR(
m_pUILayer->SetRenderEngineOwner( this ),
::DbgMsg("CMultiVMR9RenderEngine::Initialize: failed to advise 'this' owner to the UI layer"));
}
hr = CreateDevice_();
CHECK_HR(
hr = m_pMixerControl->Initialize( m_pDevice ),
::DbgMsg("CMultiVMR9RenderEngine::Initialize: failed to initialize mixer control, hr = 0x%08x", hr));
if( m_pUILayer )
{
CHECK_HR(
hr = m_pUILayer->Initialize( m_pDevice ),
::DbgMsg("CMultiVMR9RenderEngine::Initialize: failed to initialize UI Layer, hr = 0x%08x", hr));
}
m_bInitialized = TRUE;
}// try
catch( HRESULT hr1 )
{
hr = hr1;
}
return hr;
}
****************************Public*Routine******************************\
Terminate
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::Terminate( void )
{
HRESULT hr = S_OK;
if( m_pMixerControl )
{
hr = m_pMixerControl->SetRenderEngineOwner(NULL);
if( FAILED(hr))
{
::DbgMsg("CMultiVMR9RenderEngine::Terminate: failed to unadvise RenderEngineOwner for mixer control, hr = 0x%08x", hr);
return hr;
}
RELEASE( m_pMixerControl );
}
if( m_pUILayer )
{
hr = m_pUILayer->SetRenderEngineOwner(NULL);
if( FAILED(hr))
{
::DbgMsg("CMultiVMR9RenderEngine::Terminate: failed to unadvise RenderEngineOwner for UI layer, hr = 0x%08x", hr);
return hr;
}
RELEASE( m_pUILayer );
}
return S_OK;
}
****************************Public*Routine******************************\
Render
This method is called from a separate thread asynchronously from VMR calls
First, method checks internal timer, and if it is time to render new scene,
method calls mixer control's methods Compose() and Render(). After that, if
UI layer is present, we also call for its Render() method. We also keep track on
actual FPS rate here
Return error codes: E_INVALIDARG (invalid config flags or hWnd),
VFW_E_WRONG_STATE (method was already called before)
E_FAIL (unexpected error),
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::Render(void)
{
HRESULT hr = S_OK;
HRESULT hrMC = S_OK;
HRESULT hrUI = S_OK;
COLORREF clr = RGB(0,0,0);
D3DCOLOR backgroundColor;
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::Render: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( m_bChangingDevice )
{
hr = ProcessLostDevice();
return hr;
}
DWORD dwCurTime = timeGetTime();
if( 0 == m_dwStart )
{
m_dwStart = timeGetTime();
}
if( dwCurTime - (m_dwStart + m_Timer) < m_interframe )
{
return S_OK; // to early to do anything
}
// time is up: render
CAutoLock Lock(&m_ObjectLock);
m_interframeInstant = dwCurTime - (m_dwStart + m_Timer);
m_Timer = dwCurTime - m_dwStart;
if( !m_pMixerControl )
{
::DbgMsg("CMultiVMR9RenderEngine::Render: FATAL, cannot find IMultiVMR9MixerControl");
return E_UNEXPECTED;
}
hr = m_pMixerControl->GetBackgroundColor( &clr );
if( FAILED(hr))
{
backgroundColor = D3DCOLOR_XRGB( 0x00, 0x00, 0x00);
}
else
{
backgroundColor = D3DCOLOR_XRGB( GetRValue( clr), GetGValue( clr), GetBValue( clr));
}
try
{
hr = m_pMixerControl->Compose( (void*)m_Timer );
if( FAILED(hr))
{
::DbgMsg("CMultiVMR9RenderEngine::Render: failed in IMultiVMR9MixerControl::Compose, hr = 0x%08x", hr);
return hr;
}
if( !m_pDevice )
throw S_OK;
// render the scene
CHECK_HR(
hr = m_pDevice->Clear( 0L, // no rects (clear all)
NULL, // clear entire viewport
D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,// clear render target
backgroundColor,
1.0f, // clear all the depth
0L ), // no stencil
::DbgMsg("CMultiVMR9RenderEngine::Render: failed in IDirect3DDevice9::Clear, hr = 0x%08x", hr));
CHECK_HR(
hr = m_pDevice->BeginScene(),
::DbgMsg("CMultiVMR9RenderEngine::Render: failed in BeginScene(), hr = 0x%08x",hr));
// first, render all the video source by means of mixer control
hrMC = m_pMixerControl->Render( m_pDevice, (void*)m_Timer );
if( m_pUILayer )
{
hrUI = m_pUILayer->Render( m_pDevice );
}
CHECK_HR(
hr = m_pDevice->EndScene(),
::DbgMsg("CMultiVMR9RenderEngine::Render: failed in EndScene(), hr = 0x%08x",hr));
CHECK_HR(
hr = m_pDevice->Present(NULL,NULL,NULL,NULL),
::DbgMsg("CMultiVMR9RenderEngine::Render: failed in IDirect3DDevice9::Present(), hr = 0x%08x",hr));
if( FAILED( hrMC ))
{
::DbgMsg("CMultiVMR9RenderEngine::Render: failed in IMultiVMR9MixerControl::Render, error code 0x%08x", hrMC);
hr = hrMC;
}
if( FAILED( hrUI ))
{
::DbgMsg("CMultiVMR9RenderEngine::Render: failed in IMultiVMR9UILayer::Render, error code 0x%08x", hrUI);
hr = FAILED(hr) ? hrUI : hr;
}
m_dwFramesDrawn++;
if( m_dwFramesDrawn == ULONG_MAX ) // we have been running renderer for sooo long
{
// flush counters
m_dwFramesDrawn = 0;
}
if( m_dwFramesDrawn > 1 )
{
m_interframeAvg = m_interframeAvg *(m_dwFramesDrawn-1) + (m_Timer - m_dwLastRender);
m_interframeAvg /= m_dwFramesDrawn;
}
else
{
m_interframeAvg = m_interframeInstant;
}
} // try
catch( HRESULT hr1 )
{
if( (hr1 == D3DERR_DEVICELOST ||
hr1 == D3DERR_DRIVERINTERNALERROR) && m_pOwner )
{
m_bChangingDevice = TRUE;
hr = ProcessLostDevice();
}
else
{
hr = hr1;
}
}
m_dwLastRender = m_Timer;
return hr;
}
****************************Public*Routine******************************\
ProcessLostDevice
responds to the device loss event
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::ProcessLostDevice()
{
HRESULT hr = S_OK;
// tell all the components that we are lost. so that they would release all the
// allocated video resources
if( m_pMixerControl )
{
hr = m_pMixerControl->BeginDeviceLoss();
}
if( m_pUILayer )
{
hr = m_pUILayer->BeginDeviceLoss();
}
if( m_pOwner )
{
hr = m_pOwner->BeginDeviceLoss();
}
RELEASE( m_pDevice );
hr = CreateDevice_();
if( SUCCEEDED(hr) && m_pDevice )
{
if( m_pMixerControl )
{
hr = m_pMixerControl->EndDeviceLoss( m_pDevice );
}
if( m_pUILayer )
{
hr = m_pUILayer->EndDeviceLoss( m_pDevice );
}
if( m_pOwner )
{
hr = m_pOwner->EndDeviceLoss( m_pDevice );
}
m_bChangingDevice = FALSE;
}
return hr;
}
****************************Public*Routine******************************\
GetUILayer
Call this method to obtain pointer to currently used UI layer.
if there is no UI Layer involved, method returns *ppUILayer = NULL;
Return error codes: E_POINTER (ppUILayer is NULL)
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::GetUILayer(IMultiVMR9UILayer** ppUILayer)
{
HRESULT hr = S_OK;
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::GetUILayer: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( !ppUILayer )
{
return E_POINTER;
}
if( m_pUILayer )
{
*ppUILayer = m_pUILayer;
(*ppUILayer)->AddRef();
}
else
{
*ppUILayer = NULL;
}
return hr;
}
****************************Public*Routine******************************\
SetFrameRate
Call this method to specify desired frame rate, in (frames per sec)x100
Render engine will try to keep desired rate, but does not guarantee it,
use GetFrameRate() to get actual frame rate
Return error codes: E_INVALIDARG (nFramesPerSecBy100 is less than 1 or bigger than 100000)
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::SetFrameRate(int nFramesPerSecBy100)
{
HRESULT hr = S_OK;
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::SetFrameRate: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( nFramesPerSecBy100 <1 ||
nFramesPerSecBy100 >100000 )
{
::DbgMsg("CMultiVMR9RenderEngine::SetFrameRate: desired rate must be between 1 and 100000");
return E_INVALIDARG;
}
CAutoLock Lock(&m_ObjectLock);
m_setFPS = nFramesPerSecBy100;
// update m_interframe which is inverse of FPS
m_interframe = 100000 / m_setFPS;
// we also have to flush counters for actual FPS
m_interframeAvg = m_interframe;
return hr;
}
****************************Public*Routine******************************\
GetFrameRate
Call this method to obtain actual frame rate (instanteneous from the last rendering),
in (frames per sec)x100. Once started, renderer stops only when destroyed
(and if all the subgraphs are idle, it will be drawing last available images),
Return error codes: E_POINTER (pnFramesPerSecBy100 is NULL)
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::GetFrameRate(int* pnFramesPerSecBy100)
{
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::GetFrameRate: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( !pnFramesPerSecBy100 )
{
::DbgMsg("CMultiVMR9RenderEngine::GetFrameRate: received NULL pointer");
return E_POINTER;
}
if( m_interframeInstant )
{
m_getFPS = 100000L / m_interframeInstant;
}
else
{
m_getFPS = 0L;
}
*pnFramesPerSecBy100 = m_getFPS;
return S_OK;
}
****************************Public*Routine******************************\
GetFrameRateAvg
Call this method to obtain actual frame rate, smoothed and averaged in time,
in (frames per sec)x100. Once started, renderer stops only when destroyed
(and if all the subgraphs are idle, it will be drawing last available images),
so we calculate actual frame rate as
InterFrameTime_ms = (InterFrameTime_ms *(FramesDrawn-1) + (time_from_the_last_rendering_ms)) / FramesDrawn;
FrameRateAvg = 100000 / InterFrameTime_ms;
Actual calculations are performed in Render().
Return error codes: E_POINTER (pnFramesPerSecBy100 is NULL)
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::GetFrameRateAvg( int* pnFramesPerSecBy100 )
{
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::GetFrameRateAvg: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( !pnFramesPerSecBy100 )
{
::DbgMsg("CMultiVMR9RenderEngine::GetFrameRateAvg: received NULL pointer");
return E_POINTER;
}
if( m_interframeAvg )
{
*pnFramesPerSecBy100 = 100000L / m_interframeAvg;
}
else
{
*pnFramesPerSecBy100 = 0L;
}
return S_OK;
}
****************************Public*Routine******************************\
GetMixingPrefs
Call this method to obtain flags with which this render engine was initialized
Return error codes: E_POINTER (pdwPrefs is NULL)
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::GetMixingPrefs(DWORD* pdwPrefs)
{
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::GetMixingPrefs: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( !pdwPrefs )
{
::DbgMsg("CMultiVMR9RenderEngine::GetMixingPrefs: received NULL pointer");
return E_POINTER;
}
*pdwPrefs = m_dwCfgFlags;
return S_OK;
}
****************************Public*Routine******************************\
SetWizardOwner
This method is called by IMultiVMR9Wizard when it takes 'this' as a render engine
Return error codes:
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::SetWizardOwner(IMultiVMR9Wizard* pWizard)
{
HRESULT hr = S_OK;
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::SetWizardOwner: object is not initialized");
return VFW_E_WRONG_STATE;
}
CAutoLock Lock(&m_ObjectLock);
RELEASE( m_pOwner );
if( pWizard )
{
m_pOwner = pWizard;
m_pOwner->AddRef();
}
return hr;
}
****************************Public*Routine******************************\
GetWizardOwner
Call this method to obtain pointer to IMultiVMR9Wizard that owns
'this' as a render engine
Return error codes: E_POINTER ( ppWizard is NULL )
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::GetWizardOwner(IMultiVMR9Wizard** ppWizard)
{
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::GetWizardOwner: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( !ppWizard )
{
::DbgMsg("CMultiVMR9RenderEngine::GetWizardOwner: received NULL pointer");
return E_POINTER;
}
if( m_pOwner )
{
*ppWizard = m_pOwner;
(*ppWizard)->AddRef();
}
else
{
*ppWizard = NULL;
}
return S_OK;
}
****************************Public*Routine******************************\
GetMixerControl
Call this method to obtain pointer to IMultiVMR9MixerControl that is used by
'this' render engine. Mixer Control is advised in Initialize() method.
Return error codes: E_POINTER ( ppMixerControl is NULL )
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::GetMixerControl(IMultiVMR9MixerControl** ppMixerControl)
{
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::GetMixerControl: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( !ppMixerControl )
{
::DbgMsg("CMultiVMR9RenderEngine::GetMixerControl: received NULL pointer");
return E_POINTER;
}
if( m_pMixerControl )
{
*ppMixerControl = m_pMixerControl;
(*ppMixerControl)->AddRef();
}
else
{
*ppMixerControl = NULL;
}
return S_OK;
}
****************************Public*Routine******************************\
Get3DDevice
Call this method to obtain Direct3DDevice9 used for rendering.
This device is created by 'Initialize()' method
Return error codes: E_POINTER ( ppDevice is NULL )
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::Get3DDevice(IDirect3DDevice9 ** ppDevice)
{
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::Get3DDevice: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( !ppDevice )
{
::DbgMsg("CMultiVMR9RenderEngine::Get3DDevice: received NULL pointer");
return E_POINTER;
}
if( m_pDevice )
{
*ppDevice = m_pDevice;
(*ppDevice)->AddRef();
}
else
{
*ppDevice = NULL;
}
return S_OK;
}
****************************Public*Routine******************************\
GetVideoWindow
Call this method to obtain handle to the video window.
This handle is sent to 'Initialize()' method
Return error codes: E_POINTER ( phwnd is NULL )
VFW_E_WRONG_STATE (method Initialize() was never called)
\*************************************************************************
STDMETHODIMP CMultiVMR9RenderEngine::GetVideoWindow(HWND *phwnd)
{
if( FALSE == m_bInitialized )
{
::DbgMsg("CMultiVMR9RenderEngine::GetVideoWindow: object is not initialized");
return VFW_E_WRONG_STATE;
}
if( !phwnd )
{
::DbgMsg("CMultiVMR9RenderEngine::GetVideoWindow: received NULL pointer");
return E_POINTER;
}
*phwnd = m_hwnd;
return S_OK;
}
///////////////// Private routine /////////////////////////////////
****************************Private*Routine******************************\
CreateDevice_
creates IDirect3DDevice9
\*************************************************************************
HRESULT CMultiVMR9RenderEngine::CreateDevice_()
{
HRESULT hr = S_OK;
D3DPRESENT_PARAMETERS pp;
IDirect3D9* pD3D9 = NULL;
try
{
// create Direct3D
pD3D9 = Direct3DCreate9(D3D_SDK_VERSION);
CHECK_HR(
pD3D9 ? S_OK : E_FAIL,
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed to create Direct3D9 object"));
// create device
D3DFORMAT D3DFormatAlternatives[] =
{
D3DFMT_X8R8G8B8,
D3DFMT_R5G6B5,
D3DFMT_A8B8G8R8,
D3DFMT_X4R4G4B4,
D3DFMT_A4R4G4B4,
D3DFMT_A1R5G5B5,
D3DFMT_X1R5G5B5,
};
int nD3DFormatAlternatives = sizeof(D3DFormatAlternatives) / sizeof(D3DFORMAT);
// try different alternatives
for( int nFmt = 0; nFmt < nD3DFormatAlternatives; nFmt++)
{
D3DFORMAT fmt = D3DFormatAlternatives[ nFmt ];
ZeroMemory( &pp, sizeof(D3DPRESENT_PARAMETERS));
pp.Windowed = TRUE;
pp.hDeviceWindow = m_hwnd;
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
pp.BackBufferCount = 1;
pp.BackBufferFormat = fmt;
pp.EnableAutoDepthStencil = TRUE;
pp.AutoDepthStencilFormat = D3DFMT_D16;
pp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
pp.PresentationInterval = 0x80000000;
hr = pD3D9->CreateDevice(D3DADAPTER_DEFAULT ,
D3DDEVTYPE_HAL,
m_hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
&pp,
&m_pDevice);
if( SUCCEEDED(hr) && m_pDevice )
break;
}// for
hr = m_pDevice ? S_OK : hr;
CHECK_HR(
hr,
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed to create device, error code 0x%08x", hr));
//maximum ambient light
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_AMBIENT,RGB(255,255,255)),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_AMBIENT...)"));
//lighting disabled
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_LIGHTING,FALSE),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_LIGHTING...)"));
//don't cull backside
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_CULLMODE...)"));
//DISABLE depth buffering
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_FALSE),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_ZENABLE...)"));
// enable dithering
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_DITHERENABLE...)"));
// disable stensil
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_STENCILENABLE...)"));
// manage blending
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_ALPHABLENDENABLE...)"));
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_SRCBLEND...)"));
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_DESTBLEND...)"));
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_ALPHATESTENABLE...)"));
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_ALPHAREF, 0x10),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_ALPHAREF...)"));
CHECK_HR(
m_pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetRenderState(D3DRS_ALPHAFUNC...)"));
// set up sampler
CHECK_HR(
m_pDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetSamplerState(D3DSAMP_ADDRESSU...)"));
CHECK_HR(
m_pDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetSamplerState(D3DSAMP_ADDRESSV...)"));
CHECK_HR(
m_pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetSamplerState(D3DSAMP_MAGFILTER...)"));
CHECK_HR(
m_pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR),
::DbgMsg("CMultiVMR9RenderEngine::CreateDevice_: failed in SetSamplerState(D3DSAMP_MINFILTER...)"));
}// try
catch( HRESULT hr1 )
{
hr = hr1;
}
RELEASE( pD3D9 );
return hr;
}
****************************Private*Routine******************************\
Clean_
clean all the data, release all interfaces
\*************************************************************************
void CMultiVMR9RenderEngine::Clean_()
{
if( m_pOwner ) { m_pOwner->Release(); m_pOwner = NULL; }
if( m_pMixerControl ) { m_pMixerControl->Release(); m_pMixerControl = NULL; }
if( m_pUILayer ){ m_pUILayer->Release(); m_pUILayer = NULL; }
if( m_pDevice ){ m_pDevice->Release(); m_pDevice = NULL; }
// if( m_pRenderTarget ){ m_pRenderTarget->Release(); m_pRenderTarget = NULL;}
}
(C) Æliens
20/2/2008
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.