2916 lines
98 KiB
C++
2916 lines
98 KiB
C++
/*=============================================================================
|
|
D3DSystem.cpp : D3D initialization / system functions.
|
|
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
|
|
|
Revision history:
|
|
* Created by Honich Andrey
|
|
|
|
=============================================================================*/
|
|
|
|
#include "RenderPCH.h"
|
|
#include "DriverD3D9.h"
|
|
#include <dxerr9.h>
|
|
#include "D3DCGVProgram.h"
|
|
#include "D3DCGPShader.h"
|
|
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
|
|
|
|
void CD3D9Renderer::DisplaySplash()
|
|
{
|
|
#ifdef GAME_IS_FARCRY
|
|
HBITMAP hImage = (HBITMAP)LoadImage(GetModuleHandle(0), "fcsplash.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
|
|
#else
|
|
HBITMAP hImage = (HBITMAP)LoadImage(GetModuleHandle(0), "splash.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
|
|
#endif
|
|
|
|
if (hImage != INVALID_HANDLE_VALUE)
|
|
{
|
|
RECT rect;
|
|
HDC hDC = GetDC(m_hWnd);
|
|
HDC hDCBitmap = CreateCompatibleDC(hDC);
|
|
BITMAP bm;
|
|
|
|
GetClientRect(m_hWnd, &rect);
|
|
GetObject(hImage, sizeof(bm), &bm);
|
|
SelectObject(hDCBitmap, hImage);
|
|
|
|
DWORD x = rect.left + (((rect.right-rect.left)-bm.bmWidth) >> 1);
|
|
DWORD y = rect.top + (((rect.bottom-rect.top)-bm.bmHeight) >> 1);
|
|
|
|
BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hDCBitmap, 0, 0, SRCCOPY);
|
|
|
|
DeleteObject(hImage);
|
|
DeleteDC(hDCBitmap);
|
|
}
|
|
}
|
|
|
|
void CD3D9Renderer::UnSetRes()
|
|
{
|
|
m_Features |= RFT_DIRECTACCESSTOVIDEOMEMORY | RFT_SUPPORTZBIAS | RFT_DETAILTEXTURE;
|
|
|
|
m_bActive = FALSE;
|
|
m_bReady = FALSE;
|
|
|
|
if( m_pd3dDevice )
|
|
{
|
|
Cleanup3DEnvironment();
|
|
SAFE_RELEASE(m_pD3D);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: FinalCleanup()
|
|
// Desc: Called before the app exits, this function gives the app the chance
|
|
// to cleanup after itself.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CD3D9Renderer::FinalCleanup()
|
|
{
|
|
UnSetRes();
|
|
DeleteContext(m_hWnd);
|
|
DestroyWindow();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CD3D9Renderer::DestroyWindow(void)
|
|
{
|
|
if (m_hWnd)
|
|
{
|
|
::DestroyWindow(m_hWnd);
|
|
m_hWnd = NULL;
|
|
}
|
|
}
|
|
|
|
void CD3D9Renderer::RestoreGamma(void)
|
|
{
|
|
if (!(GetFeatures() & RFT_HWGAMMA))
|
|
return;
|
|
|
|
if (CV_r_nohwgamma)
|
|
return;
|
|
|
|
m_fLastGamma = 1.0f;
|
|
m_fLastBrightness = 0.5f;
|
|
m_fLastContrast = 0.5f;
|
|
|
|
HDC dc;
|
|
|
|
//iLog->Log("...RestoreGamma");
|
|
|
|
struct
|
|
{
|
|
ushort red[256];
|
|
ushort green[256];
|
|
ushort blue[256];
|
|
} Ramp;
|
|
|
|
for(int i=0; i<256; i++)
|
|
{
|
|
Ramp.red[i] = Ramp.green[i] = Ramp.blue[i] = i << 8;
|
|
}
|
|
|
|
m_hWndDesktop = GetDesktopWindow();
|
|
|
|
dc = GetDC(m_hWndDesktop);
|
|
SetDeviceGammaRamp(dc, &Ramp);
|
|
ReleaseDC(m_hWndDesktop, dc);
|
|
}
|
|
|
|
void CD3D9Renderer::SetDeviceGamma(ushort *r, ushort *g, ushort *b)
|
|
{
|
|
ushort gamma[3][256];
|
|
int i;
|
|
|
|
if (!(GetFeatures() & RFT_HWGAMMA))
|
|
return;
|
|
|
|
if (CV_r_nohwgamma)
|
|
return;
|
|
|
|
m_hWndDesktop = GetDesktopWindow();
|
|
|
|
HDC dc = GetDC(m_hWndDesktop);
|
|
|
|
if (!dc)
|
|
return;
|
|
|
|
for (i=0; i<256; i++)
|
|
{
|
|
gamma[0][i] = r[i];
|
|
gamma[1][i] = g[i];
|
|
gamma[2][i] = b[i];
|
|
}
|
|
//iLog->Log("...SetDeviceGamma");
|
|
SetDeviceGammaRamp(dc, gamma);
|
|
ReleaseDC(m_hWndDesktop, dc);
|
|
}
|
|
|
|
void CD3D9Renderer::SetGamma(float fGamma, float fBrightness, float fContrast, bool bForce)
|
|
{
|
|
int i;
|
|
|
|
fGamma = CLAMP(fGamma, 0.1f, 3.0f);
|
|
if (!bForce && m_fLastGamma == fGamma && m_fLastBrightness == fBrightness && m_fLastContrast == fContrast)
|
|
return;
|
|
|
|
//int n;
|
|
for ( i=0; i<256; i++ )
|
|
{
|
|
m_GammaTable[i] = CLAMP((int)((fContrast+0.5f)*cry_powf((float)i/255.f,1.0f/fGamma)*65535.f + (fBrightness-0.5f)*32768.f - fContrast*32768.f + 16384.f), 0, 65535);
|
|
}
|
|
|
|
m_fLastGamma = fGamma;
|
|
m_fLastBrightness = fBrightness;
|
|
m_fLastContrast = fContrast;
|
|
|
|
//iLog->Log("...SetGamma %.3f", fGamma);
|
|
|
|
SetDeviceGamma(m_GammaTable, m_GammaTable, m_GammaTable);
|
|
}
|
|
|
|
bool CD3D9Renderer::SetGammaDelta(const float fGamma)
|
|
{
|
|
m_fDeltaGamma = fGamma;
|
|
SetGamma(CV_r_gamma + fGamma, CV_r_brightness, CV_r_contrast, false);
|
|
return true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InvalidateDeviceObjects()
|
|
// Desc: Called when the device-dependent objects are about to be lost.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CD3D9Renderer::InvalidateDeviceObjects()
|
|
{
|
|
int i = 0;
|
|
int j;
|
|
HRESULT hr;
|
|
|
|
//iLog->Log("...InvalidateDeviceObjects");
|
|
|
|
m_nFrameReset++;
|
|
SAFE_RELEASE(m_pVB2D);
|
|
SAFE_RELEASE(m_pIB);
|
|
SAFE_RELEASE(m_pQuery);
|
|
for (j=0; j<3; j++)
|
|
{
|
|
for (i=0; i<4; i++)
|
|
{
|
|
SAFE_RELEASE(m_pVB3DAr[j][i]);
|
|
}
|
|
m_pVB3D[j] = NULL;
|
|
}
|
|
SAFE_RELEASE(m_pSphere);
|
|
|
|
EF_Invalidate();
|
|
|
|
// Unload vertex/index buffers
|
|
CLeafBuffer *pLB = CLeafBuffer::m_RootGlobal.m_NextGlobal;
|
|
//iLog->Log("Start Unload");
|
|
while (pLB != &CLeafBuffer::m_RootGlobal)
|
|
{
|
|
CLeafBuffer *Next = pLB->m_NextGlobal;
|
|
if (pLB->m_bDynamic)
|
|
{
|
|
//if (pLB->m_sSource)
|
|
// iLog->Log("Unload '%s' LB", pLB->m_sSource);
|
|
pLB->Unload();
|
|
}
|
|
pLB = Next;
|
|
}
|
|
//iLog->Log("End Unload\n\n");
|
|
|
|
CRendElement *pRE = CRendElement::m_RootGlobal.m_NextGlobal;
|
|
while (pRE != &CRendElement::m_RootGlobal)
|
|
{
|
|
pRE->mfReset();
|
|
pRE = pRE->m_NextGlobal;
|
|
}
|
|
|
|
for (i=0; i<96; i++)
|
|
{
|
|
CCGVProgram_D3D::m_CurParams[i][0] = -99999.9f;
|
|
CCGVProgram_D3D::m_CurParams[i][1] = -99999.9f;
|
|
CCGVProgram_D3D::m_CurParams[i][2] = -99999.9f;
|
|
CCGVProgram_D3D::m_CurParams[i][3] = -99999.9f;
|
|
}
|
|
for (i=0; i<32; i++)
|
|
{
|
|
CCGPShader_D3D::m_CurParams[i][0] = -99999.9f;
|
|
CCGPShader_D3D::m_CurParams[i][1] = -99999.9f;
|
|
CCGPShader_D3D::m_CurParams[i][2] = -99999.9f;
|
|
CCGPShader_D3D::m_CurParams[i][3] = -99999.9f;
|
|
}
|
|
if (m_TexMan)
|
|
{
|
|
for (i=0; i<gRenDev->m_TexMan->m_Textures.Num(); i++)
|
|
{
|
|
STexPicD3D *tp = (STexPicD3D *)gRenDev->m_TexMan->m_Textures[i];
|
|
if (!tp || !tp->m_RefTex.m_VidTex || tp->m_Bind == TX_FIRSTBIND)
|
|
continue;
|
|
IDirect3DTexture9 *pID3DTexture = NULL;
|
|
IDirect3DCubeTexture9 *pID3DCubeTexture = NULL;
|
|
LPDIRECT3DSURFACE9 pSurf = NULL;
|
|
D3DSURFACE_DESC Desc;
|
|
if (tp->m_eTT == eTT_Cubemap || tp->m_eTT == eTT_AutoCubemap)
|
|
{
|
|
pID3DCubeTexture = (IDirect3DCubeTexture9*)tp->m_RefTex.m_VidTex;
|
|
hr = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)0, 0, &pSurf);
|
|
}
|
|
else
|
|
if (tp->m_eTT == eTT_Base || tp->m_eTT == eTT_Bumpmap || tp->m_eTT == eTT_Rectangle || tp->m_eTT == eTT_DSDTBump)
|
|
{
|
|
pID3DTexture = (IDirect3DTexture9*)tp->m_RefTex.m_VidTex;
|
|
hr = pID3DTexture->GetSurfaceLevel(0, &pSurf);
|
|
}
|
|
if (!pSurf)
|
|
continue;
|
|
hr = pSurf->GetDesc(&Desc);
|
|
SAFE_RELEASE(pSurf);
|
|
if (Desc.Pool != D3DPOOL_DEFAULT)
|
|
continue;
|
|
|
|
tp->m_Flags2 |= FT2_NEEDRESTORED;
|
|
SAFE_RELEASE(pID3DTexture);
|
|
SAFE_RELEASE(pID3DCubeTexture);
|
|
tp->m_RefTex.m_VidTex = NULL;
|
|
}
|
|
for (i=0; i<MAX_ENVLIGHTCUBEMAPS; i++)
|
|
{
|
|
SEnvTexture *cur = &gRenDev->m_TexMan->m_EnvLCMaps[i];
|
|
for (j=0; j<6; j++)
|
|
{
|
|
if (cur->m_RenderTargets[j])
|
|
{
|
|
IDirect3DSurface9* pSurface = (IDirect3DSurface9* )cur->m_RenderTargets[j];
|
|
cur->m_RenderTargets[j] = NULL;
|
|
pSurface->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SAFE_RELEASE (m_pTempZBuffer);
|
|
SAFE_RELEASE (m_pZBuffer);
|
|
SAFE_RELEASE (m_pBackBuffer);
|
|
m_pCurBackBuffer = NULL;
|
|
m_pCurZBuffer = NULL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CD3D9Renderer::RestoreDeviceObjects()
|
|
{
|
|
HRESULT hr;
|
|
int i, j;
|
|
|
|
//InitTexFillers();
|
|
//Flush();
|
|
|
|
//iLog->Log("...RestoreDeviceObjects");
|
|
|
|
for (i=0; i<MAX_TMU; i++)
|
|
{
|
|
m_RP.m_TexStages[i].Flush();
|
|
}
|
|
|
|
SAFE_RELEASE (m_pTempZBuffer);
|
|
SAFE_RELEASE(m_pZBuffer);
|
|
SAFE_RELEASE(m_pBackBuffer);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//if( m_FSAA == 2 )
|
|
//{
|
|
// hr = m_pd3dDevice->CreateDepthStencilSurface( m_width, m_height, m_d3dpp.AutoDepthStencilFormat, ConvertFSAASamplesToType( m_FSAA_samples ), m_FSAA_quality, TRUE, &m_pZBuffer, 0 );
|
|
// if( SUCCEEDED( hr ) )
|
|
// {
|
|
// hr = m_pd3dDevice->SetDepthStencilSurface( m_pZBuffer );
|
|
// //iLog->Log( "HDR-FSAA: Created multi-sampled Z-Buffer for current FSAA settings (samples = %d / quality = %d).", m_FSAA_samples, m_FSAA_quality );
|
|
// }
|
|
// //else
|
|
// // iLog->Log( "HDR-FSAA: Multi-sampled Z-Buffer creation failed render target creation failed!" );
|
|
//}
|
|
//else
|
|
// m_pd3dDevice->GetDepthStencilSurface( &m_pZBuffer );
|
|
|
|
// m_pZBuffer->GetDesc( &m_d3dsdZBuffer );
|
|
// m_pd3dDevice->CreateDepthStencilSurface(m_d3dsdZBuffer.Width, m_d3dsdZBuffer.Height, m_d3dsdZBuffer.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &m_pTempZBuffer, NULL);
|
|
// m_pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer );
|
|
// m_pBackBuffer->GetDesc(&m_d3dsdBackBuffer);
|
|
// m_pCurBackBuffer = m_pBackBuffer;
|
|
// m_pCurZBuffer = m_pZBuffer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// new approach to re-use original non-aa z buffer for temp. render tasks
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
if( m_FSAA == 2 )
|
|
{
|
|
hr = m_pd3dDevice->CreateDepthStencilSurface( m_width, m_height, m_d3dpp.AutoDepthStencilFormat, ConvertFSAASamplesToType( m_FSAA_samples ), m_FSAA_quality, TRUE, &m_pZBuffer, 0 );
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
//iLog->Log( "HDR-FSAA: Created multi-sampled Z-Buffer for current FSAA settings (samples = %d / quality = %d).", m_FSAA_samples, m_FSAA_quality );
|
|
hr = m_pd3dDevice->GetDepthStencilSurface( &m_pTempZBuffer ); // re-use current non multi-sampled z buffer for temporary rendering tasks
|
|
hr = m_pd3dDevice->SetDepthStencilSurface( m_pZBuffer );
|
|
m_pZBuffer->GetDesc( &m_d3dsdZBuffer );
|
|
}
|
|
else
|
|
{
|
|
//iLog->Log( "HDR-FSAA: Multi-sampled Z-Buffer creation failed render target creation failed! Resorting back to r_FSAA 0!" );
|
|
m_FSAA = 0;
|
|
CV_r_fsaa = 0;
|
|
}
|
|
}
|
|
|
|
if( m_FSAA != 2 )
|
|
{
|
|
m_pd3dDevice->GetDepthStencilSurface( &m_pZBuffer );
|
|
m_pZBuffer->GetDesc( &m_d3dsdZBuffer );
|
|
m_pd3dDevice->CreateDepthStencilSurface(m_d3dsdZBuffer.Width, m_d3dsdZBuffer.Height, m_d3dsdZBuffer.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &m_pTempZBuffer, NULL);
|
|
}
|
|
|
|
m_pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer );
|
|
m_pBackBuffer->GetDesc(&m_d3dsdBackBuffer);
|
|
m_pCurBackBuffer = m_pBackBuffer;
|
|
m_pCurZBuffer = m_pZBuffer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
SAFE_RELEASE(m_pVB2D);
|
|
SAFE_RELEASE(m_pIB);
|
|
SAFE_RELEASE(m_pQuery);
|
|
for (j=0; j<3; j++)
|
|
{
|
|
for (i=0; i<4; i++)
|
|
{
|
|
SAFE_RELEASE(m_pVB3DAr[j][i]);
|
|
}
|
|
m_pVB3D[j] = NULL;
|
|
}
|
|
SAFE_RELEASE(m_pSphere);
|
|
|
|
m_nVertsDMesh2D = 400;
|
|
m_nIndsDMesh = CV_d3d9_rb_tris*3;
|
|
m_nIOffsDMesh = m_nIndsDMesh;
|
|
m_nOffsDMesh2D = m_nVertsDMesh2D;
|
|
hr = m_pd3dDevice->CreateVertexBuffer(m_nVertsDMesh2D*sizeof(struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, D3DPOOL_DEFAULT, &m_pVB2D, NULL);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
hr = m_pd3dDevice->CreateIndexBuffer(m_nIndsDMesh*sizeof(short), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pIB, NULL);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &m_pQuery);
|
|
if(hr != D3DERR_NOTAVAILABLE )
|
|
{
|
|
assert(m_pQuery);
|
|
m_pQuery->Issue(D3DISSUE_END);
|
|
}
|
|
|
|
for (j=0; j<3; j++)
|
|
{
|
|
int nVertSize;
|
|
int fvf;
|
|
switch (j)
|
|
{
|
|
case 0:
|
|
default:
|
|
m_nVertsDMesh3D[j] = MAX_DYNVB3D_VERTS;
|
|
nVertSize = sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F);
|
|
fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
|
|
break;
|
|
case 1:
|
|
m_nVertsDMesh3D[j] = 16384;
|
|
nVertSize = sizeof(struct_VERTEX_FORMAT_P3F_TEX2F);
|
|
fvf = D3DFVF_XYZ | D3DFVF_TEX1;
|
|
break;
|
|
case 2:
|
|
m_nVertsDMesh3D[j] = 16384;
|
|
nVertSize = sizeof(SPipTangents);
|
|
fvf = 0;
|
|
break;
|
|
}
|
|
m_nOffsDMesh3D[j] = m_nVertsDMesh3D[j];
|
|
for (i=0; i<4; i++)
|
|
{
|
|
hr = m_pd3dDevice->CreateVertexBuffer(m_nVertsDMesh3D[j]*nVertSize, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, fvf, D3DPOOL_DEFAULT, &m_pVB3DAr[j][i], NULL);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
m_pVB3D[j] = m_pVB3DAr[j][0];
|
|
}
|
|
hr = D3DXCreateSphere(m_pd3dDevice, 1, 16, 16, &m_pSphere, NULL);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
memset(&m_Material, 0, sizeof(m_Material));
|
|
for (i=0; i<16; i++)
|
|
{
|
|
D3DLIGHT9 *l = &m_Lights[i];
|
|
memset(l, 0, sizeof(D3DLIGHT9));
|
|
l->Ambient.r = 0.0f;
|
|
l->Ambient.g = 0.0f;
|
|
l->Ambient.b = 0.0f;
|
|
l->Ambient.a = 0.0f;
|
|
l->Type = D3DLIGHT_DIRECTIONAL;
|
|
l->Attenuation0 = 1.0f;
|
|
}
|
|
|
|
EF_Restore();
|
|
|
|
for (i=0; i<gRenDev->m_TexMan->m_Textures.Num(); i++)
|
|
{
|
|
STexPicD3D *tp = (STexPicD3D *)gRenDev->m_TexMan->m_Textures[i];
|
|
if (!tp || tp->m_Bind == TX_FIRSTBIND)
|
|
continue;
|
|
IDirect3DTexture9 *pID3DTexture = NULL;
|
|
IDirect3DCubeTexture9 *pID3DCubeTexture = NULL;
|
|
if (!(tp->m_Flags2 & FT2_NEEDRESTORED))
|
|
continue;
|
|
|
|
int D3DUsage = 0;
|
|
if (tp->m_Flags2 & FT2_RENDERTARGET)
|
|
D3DUsage |= D3DUSAGE_RENDERTARGET;
|
|
if (tp->m_DstFormat == D3DFMT_D24S8 || tp->m_DstFormat == D3DFMT_D16)
|
|
{
|
|
D3DUsage |= D3DUSAGE_DEPTHSTENCIL;
|
|
D3DUsage &= ~D3DUSAGE_RENDERTARGET;
|
|
}
|
|
if (tp->m_Flags & FT_DYNAMIC)
|
|
D3DUsage |= D3DUSAGE_DYNAMIC;
|
|
if (tp->m_eTT == eTT_Cubemap)
|
|
{
|
|
hr = m_pd3dDevice->CreateCubeTexture(tp->m_Width, 1, D3DUsage, (D3DFORMAT)tp->m_DstFormat, D3DPOOL_DEFAULT, &pID3DCubeTexture, NULL);
|
|
tp->m_RefTex.m_VidTex = pID3DCubeTexture;
|
|
|
|
for (int i=0; i<6; i++)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PDIRECT3DSURFACE9 pSurface = NULL;
|
|
hr = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pSurface);
|
|
if (SUCCEEDED(hr))
|
|
m_pd3dDevice->ColorFill(pSurface, NULL, D3DCOLOR_ARGB(0, 0, 0, 0));
|
|
SAFE_RELEASE(pSurface);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = m_pd3dDevice->CreateTexture(tp->m_Width, tp->m_Height, 1, D3DUsage, (D3DFORMAT)tp->m_DstFormat, D3DPOOL_DEFAULT, &pID3DTexture, NULL);
|
|
tp->m_RefTex.m_VidTex = pID3DTexture;
|
|
|
|
if (D3DUsage & D3DUSAGE_RENDERTARGET)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PDIRECT3DSURFACE9 pSurface = NULL;
|
|
hr = pID3DTexture->GetSurfaceLevel(0, &pSurface);
|
|
if (SUCCEEDED(hr))
|
|
m_pd3dDevice->ColorFill(pSurface, NULL, D3DCOLOR_ARGB(0, 0, 0, 0));
|
|
SAFE_RELEASE(pSurface);
|
|
}
|
|
}
|
|
}
|
|
m_bDeviceLost = false;
|
|
|
|
// Restore onlyVideo buffers
|
|
CLeafBuffer *pLB = CLeafBuffer::m_RootGlobal.m_NextGlobal;
|
|
while (pLB != &CLeafBuffer::m_RootGlobal)
|
|
{
|
|
CLeafBuffer *Next = pLB->m_NextGlobal;
|
|
if (pLB->m_bDynamic)
|
|
{
|
|
if (pLB->m_bOnlyVideoBuffer)
|
|
{
|
|
pLB->CreateVidVertices(pLB->m_SecVertCount, pLB->m_nVertexFormat);
|
|
}
|
|
}
|
|
pLB = Next;
|
|
}
|
|
|
|
m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );
|
|
// ATI instancing
|
|
if (m_bDeviceSupportsInstancing == 2)
|
|
{
|
|
// Notify the driver that instancing support is expected
|
|
D3DFORMAT instanceSupport = (D3DFORMAT)MAKEFOURCC('I', 'N', 'S', 'T');
|
|
m_pd3dDevice->SetRenderState(D3DRS_POINTSIZE, instanceSupport);
|
|
}
|
|
m_pLastVDeclaration = NULL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
void CD3D9Renderer::RefreshResources(int nFlags)
|
|
{
|
|
}
|
|
|
|
|
|
void CD3D9Renderer::ShutDown(bool bReInit)
|
|
{
|
|
m_cEF.mfShutdown();
|
|
if (bReInit)
|
|
FreeResources(FRR_SHADERS | FRR_TEXTURES | FRR_REINITHW);
|
|
else
|
|
FreeResources(FRR_ALL);
|
|
EF_PipelineShutdown();
|
|
|
|
if (CV_r_printmemoryleaks)
|
|
{
|
|
FILE *fp = fxopen("LeafBufferLeaks.txt", "w");
|
|
if (fp)
|
|
{
|
|
CLeafBuffer *pLB = CLeafBuffer::m_RootGlobal.m_NextGlobal;
|
|
while (pLB != &CLeafBuffer::m_RootGlobal)
|
|
{
|
|
CLeafBuffer *Next = pLB->m_NextGlobal;
|
|
float fSize = pLB->Size(0)/1024.0f/1024.0f;
|
|
fprintf(fp, "*** LB %s: %0.3fMb\n", pLB->m_sSource, fSize);
|
|
iLog->Log("WARNING: LB Leak %s: %0.3fMb", pLB->m_sSource, fSize);
|
|
//DeleteLeafBuffer(pLB);
|
|
pLB = Next;
|
|
}
|
|
|
|
CRendElement *pRE = CRendElement::m_RootGlobal.m_NextGlobal;
|
|
while (pRE != &CRendElement::m_RootGlobal)
|
|
{
|
|
CRendElement *Next = pRE->m_NextGlobal;
|
|
float fSize = pRE->Size()/1024.0f/1024.0f;
|
|
fprintf(fp, "*** RE %s: %0.3fMb\n", pRE->mfTypeString(), fSize);
|
|
iLog->Log("WARNING: RE Leak %s: %0.3fMb", pRE->mfTypeString(), fSize);
|
|
//SAFE_RELEASE(pRE);
|
|
pRE = Next;
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
#ifndef WIN64
|
|
// NOTE: AMD64 port: find the 64-bit CG runtime
|
|
if (m_CGContext)
|
|
{
|
|
cgDestroyContext(m_CGContext);
|
|
cgD3D9SetDevice(NULL);
|
|
m_CGContext = NULL;
|
|
}
|
|
#endif
|
|
FinalCleanup();
|
|
CName::mfExitSubsystem();
|
|
|
|
if (m_hLibHandle3DC)
|
|
{
|
|
::FreeLibrary((HINSTANCE)m_hLibHandle3DC);
|
|
m_hLibHandle3DC = NULL;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Clear globals.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (!bReInit)
|
|
{
|
|
iLog = NULL;
|
|
iConsole = NULL;
|
|
iTimer = NULL;
|
|
iSystem = NULL;
|
|
pIPhysicalWorld = NULL;
|
|
}
|
|
|
|
STexPic::m_Root.m_Next = &STexPic::m_Root;
|
|
STexPic::m_Root.m_Prev = &STexPic::m_Root;
|
|
|
|
CLeafBuffer::m_Root.m_Next = &CLeafBuffer::m_Root;
|
|
CLeafBuffer::m_Root.m_Prev = &CLeafBuffer::m_Root;
|
|
CLeafBuffer::m_RootGlobal.m_NextGlobal = &CLeafBuffer::m_RootGlobal;
|
|
CLeafBuffer::m_RootGlobal.m_PrevGlobal = &CLeafBuffer::m_RootGlobal;
|
|
}
|
|
|
|
bool CD3D9Renderer::SetWindow(int width, int height, bool fullscreen, WIN_HWND hWnd)
|
|
{
|
|
HWND temp = GetDesktopWindow();
|
|
RECT trect;
|
|
|
|
GetWindowRect(temp, &trect);
|
|
|
|
m_deskwidth =trect.right-trect.left;
|
|
m_deskheight=trect.bottom-trect.top;
|
|
|
|
DWORD style, exstyle;
|
|
int x, y, wdt, hgt;
|
|
|
|
if (width < 640)
|
|
width = 640;
|
|
if (height < 480)
|
|
height = 480;
|
|
|
|
m_dwWindowStyle = WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_OVERLAPPED;
|
|
|
|
if (fullscreen)
|
|
{
|
|
#ifdef _DEBUG
|
|
exstyle = 0;
|
|
#else
|
|
exstyle = WS_EX_TOPMOST;
|
|
#endif
|
|
style = WS_POPUP | WS_VISIBLE;
|
|
}
|
|
else
|
|
{
|
|
exstyle = WS_EX_APPWINDOW;
|
|
style = m_dwWindowStyle;
|
|
}
|
|
|
|
x = (GetSystemMetrics(SM_CXFULLSCREEN)-width)/2;
|
|
y = (GetSystemMetrics(SM_CYFULLSCREEN)-height)/2;
|
|
wdt = GetSystemMetrics(SM_CXDLGFRAME)*2 + width;
|
|
hgt = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXDLGFRAME)*2 + height;
|
|
|
|
if (!hWnd)
|
|
{
|
|
m_hWnd = CreateWindowEx(exstyle,
|
|
"CryENGINE",
|
|
m_WinTitle,
|
|
style,
|
|
x,
|
|
y,
|
|
wdt,
|
|
hgt,
|
|
NULL,
|
|
NULL,
|
|
m_hInst,
|
|
NULL);
|
|
}
|
|
else
|
|
m_hWnd = (HWND)hWnd;
|
|
|
|
if (!m_hWnd)
|
|
iConsole->Exit("Couldn't create window\n");
|
|
|
|
if (!hWnd)
|
|
{
|
|
if (fullscreen)
|
|
{
|
|
// Hide the cursor
|
|
SetCursor(NULL);
|
|
ShowCursor(FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifdef USE_3DC
|
|
#include "../Common/3Dc/CompressorLib.h"
|
|
void (*DeleteDataATI)(void *pData);
|
|
COMPRESSOR_ERROR (*CompressTextureATI)(DWORD width,
|
|
DWORD height,
|
|
UNCOMPRESSED_FORMAT sourceFormat,
|
|
COMPRESSED_FORMAT destinationFormat,
|
|
void *inputData,
|
|
void **dataOut,
|
|
DWORD *outDataSize);
|
|
#endif
|
|
|
|
WIN_HWND CD3D9Renderer::Init(int x,int y,int width,int height,unsigned int cbpp, int zbpp, int sbits, bool fullscreen,WIN_HINSTANCE hinst, WIN_HWND Glhwnd, WIN_HDC Glhdc, WIN_HGLRC hGLrc, bool bReInit)
|
|
{
|
|
if (m_IsDedicated)
|
|
{
|
|
m_MaxTextureSize = 256;
|
|
return 0;
|
|
}
|
|
if (!iSystem || !iLog)
|
|
return 0;
|
|
|
|
/*float *f = (float *)0x402a92c0;
|
|
FILE *fp = fopen("fl.txt", "w");
|
|
for (int i=0; i<4; i++)
|
|
{
|
|
fprintf(fp, "{\n");
|
|
for (int j=0; j<6; j++)
|
|
{
|
|
fprintf(fp, " {%ff, %ff, %ff, %ff},\n", f[0], f[1], f[2], f[3]);
|
|
f += 4;
|
|
}
|
|
fprintf(fp, "}\n");
|
|
}
|
|
fclose(fp);*/
|
|
|
|
bool b = false;
|
|
|
|
m_CVWidth = iConsole->GetCVar("r_Width");
|
|
m_CVHeight = iConsole->GetCVar("r_Height");
|
|
m_CVFullScreen = iConsole->GetCVar("r_FullScreen");
|
|
m_CVColorBits = iConsole->GetCVar("r_ColorBits");
|
|
|
|
iLog->Log ( "Direct3D9 driver is creating...\n");
|
|
iLog->Log ( "\nCrytek Direct3D9 driver version %4.2f (%s <%s>).\n", VERSION_D3D, __DATE__, __TIME__);
|
|
|
|
//strcpy(m_WinTitle, "- Far Cry -");
|
|
#ifdef GAME_IS_FARCRY
|
|
sprintf(m_WinTitle,"- Far Cry - %s (%s)",__DATE__, __TIME__);
|
|
#else
|
|
sprintf(m_WinTitle,"- CryEngine - %s (%s)",__DATE__, __TIME__);
|
|
#endif
|
|
m_hInst = (HINSTANCE)hinst;
|
|
|
|
if (Glhwnd)
|
|
m_bEditor = true;
|
|
|
|
#ifdef USE_3DC
|
|
m_hLibHandle3DC = ::LoadLibrary("CompressATI.dll");
|
|
if (!m_hLibHandle3DC)
|
|
m_hLibHandle3DC = ::LoadLibrary("CompressATI2.dll");
|
|
if (m_hLibHandle3DC)
|
|
{
|
|
CompressTextureATI = (FnCompressTextureATI)GetProcAddress((HINSTANCE)m_hLibHandle3DC, "CompressTextureATI");
|
|
DeleteDataATI = (FnDeleteDataATI)GetProcAddress((HINSTANCE)m_hLibHandle3DC, "DeleteDataATI");
|
|
}
|
|
#endif
|
|
|
|
// Save the new dimensions
|
|
CRenderer::m_width = width;
|
|
CRenderer::m_height = height;
|
|
CRenderer::m_cbpp = cbpp;
|
|
CRenderer::m_zbpp = zbpp;
|
|
CRenderer::m_sbpp = sbits;
|
|
m_bFullScreen = fullscreen;
|
|
while (true)
|
|
{
|
|
if (!SetWindow(width, height, fullscreen, Glhwnd))
|
|
{
|
|
ShutDown();
|
|
return 0;
|
|
}
|
|
|
|
if (SetRes())
|
|
break;
|
|
ShutDown(true);
|
|
if (b)
|
|
return 0;
|
|
m_bFullScreen ? m_bFullScreen = 0 : m_bFullScreen = 1;
|
|
b = 1;
|
|
}
|
|
|
|
D3DAdapterInfo *pAI = m_D3DSettings.PAdapterInfo();
|
|
D3DADAPTER_IDENTIFIER9 *ai = &pAI->AdapterIdentifier;
|
|
D3DDeviceInfo *di = m_D3DSettings.PDeviceInfo();
|
|
|
|
iLog->Log(" ****** D3D9 CryRender Stats ******");
|
|
iLog->Log(" Driver description: %s", ai->Description);
|
|
iLog->Log(" Full stats: %s", m_strDeviceStats);
|
|
iLog->Log(" Hardware acceleration: %s", (di->DevType == D3DDEVTYPE_HAL) ? "Yes" : "No");
|
|
//iLog->Log(" Full screen only: %s\n", (di->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) ? "No" : "Yes");
|
|
if (CV_r_fsaa && (GetFeatures() & RFT_SUPPORTFSAA))
|
|
{
|
|
TArray<SAAFormat> Formats;
|
|
int nNum = GetAAFormat(Formats, false);
|
|
iLog->Log(" Full scene AA: Enabled: %s (%d Quality)\n", Formats[nNum].szDescr, Formats[nNum].nQuality);
|
|
GetAAFormat(Formats, true);
|
|
}
|
|
else
|
|
iLog->Log(" Full scene AA: Disabled\n");
|
|
iLog->Log(" Projective EMBM: %s\n", (GetFeatures() & RFT_HW_ENVBUMPPROJECTED) ? "Enabled" : "Disabled");
|
|
iLog->Log(" Detail textures: %s\n", (GetFeatures() & RFT_DETAILTEXTURE) ? "Enabled" : "Disabled");
|
|
iLog->Log(" Z Buffer Locking: %s\n", (m_Features & RFT_ZLOCKABLE) ? "Enabled" : "Disabled");
|
|
iLog->Log(" Multitexturing: %s (%d textures)\n", (m_Features & RFT_MULTITEXTURE) ? "Supported" : "Not supported", di->Caps.MaxSimultaneousTextures);
|
|
iLog->Log(" Use bumpmapping : %s\n", (m_Features & RFT_BUMP) ? "Enabled (DOT3)" : "Disabled");
|
|
iLog->Log(" Use paletted textures : %s\n", (m_Features & RFT_PALTEXTURE) ? "Enabled" : "Disabled");
|
|
iLog->Log(" Current Resolution: %dx%dx%d %s\n", CRenderer::m_width, CRenderer::m_height, CRenderer::m_cbpp, m_bFullScreen ? "Full Screen" : "Windowed");
|
|
iLog->Log(" Maximum Resolution: %dx%d\n", pAI->m_MaxWidth, pAI->m_MaxHeight);
|
|
iLog->Log(" Maximum Texture size: %dx%d (Max Aspect: %d)\n", di->Caps.MaxTextureWidth, di->Caps.MaxTextureHeight, di->Caps.MaxTextureAspectRatio);
|
|
iLog->Log(" Texture filtering type: %s\n", CV_d3d9_texturefilter->GetString());
|
|
iLog->Log(" HDR Rendering: %s\n", m_nHDRType == 1 ? "FP16" : m_nHDRType == 2 ? "MRT" : "Disabled");
|
|
iLog->Log(" MRT Rendering: %s\n", (m_bDeviceSupportsMRT) ? "Enabled" : "Disabled");
|
|
iLog->Log(" Occlusion queries: %s\n", (m_Features & RFT_OCCLUSIONTEST) ? "Supported" : "Not supported");
|
|
iLog->Log(" Geometry instancing: %s\n", (m_bDeviceSupportsInstancing) ? "Supported" : "Not supported");
|
|
iLog->Log(" NormalMaps compression: %s\n", m_bDeviceSupportsComprNormalmaps==1 ? "3Dc" : m_bDeviceSupportsComprNormalmaps==2 ? "V8U8" : m_bDeviceSupportsComprNormalmaps==3 ? "CxV8U8" : "Not supported");
|
|
iLog->Log(" Gamma control: %s\n", (m_Features & RFT_HWGAMMA) ? "Hardware" : "Software");
|
|
iLog->Log(" Vertex Shaders version %d.%d\n", D3DSHADER_VERSION_MAJOR(di->Caps.VertexShaderVersion), D3DSHADER_VERSION_MINOR(di->Caps.VertexShaderVersion));
|
|
iLog->Log(" Pixel Shaders version %d.%d\n", D3DSHADER_VERSION_MAJOR(di->Caps.PixelShaderVersion), D3DSHADER_VERSION_MINOR(di->Caps.PixelShaderVersion));
|
|
int nGPU = m_Features & RFT_HW_MASK;
|
|
if (nGPU == RFT_HW_NV4X)
|
|
iLog->Log(" Use Hardware Shaders for NV4x GPU\n");
|
|
else
|
|
if (nGPU == RFT_HW_GFFX)
|
|
iLog->Log(" Use Hardware Shaders for NV3x GPU\n");
|
|
else
|
|
if (nGPU == RFT_HW_GF2)
|
|
iLog->Log(" Use Hardware Shaders for NV1x GPU\n");
|
|
else
|
|
if (nGPU == RFT_HW_GF3)
|
|
iLog->Log(" Use Hardware Shaders for NV2x GPU\n");
|
|
else
|
|
if (nGPU == RFT_HW_RADEON)
|
|
{
|
|
if (m_bDeviceSupports_PS2X)
|
|
iLog->Log(" Use Hardware Shaders for ATI R420 GPU\n");
|
|
else
|
|
iLog->Log(" Use Hardware Shaders for ATI R300 GPU\n");
|
|
}
|
|
else
|
|
iLog->Log(" Hardware Shaders are not supported\n");
|
|
if (D3DSHADER_VERSION_MAJOR(di->Caps.PixelShaderVersion) >= 3)
|
|
{
|
|
if (CV_r_shadowtype == 0)
|
|
m_Features |= RFT_SHADOWMAP_SELFSHADOW;
|
|
m_Features |= RFT_HW_PS30 | RFT_HW_PS20;
|
|
m_bDeviceSupports_PS30 = true;
|
|
m_bDeviceSupports_PS2X = false;
|
|
}
|
|
else
|
|
if (D3DSHADER_VERSION_MAJOR(di->Caps.PixelShaderVersion) >= 2)
|
|
{
|
|
if (CV_r_shadowtype == 0)
|
|
m_Features |= RFT_SHADOWMAP_SELFSHADOW;
|
|
m_Features |= RFT_HW_PS20;
|
|
}
|
|
#ifndef USE_HDR
|
|
m_Features &= ~RFT_HW_HDR;
|
|
#endif
|
|
|
|
// Disable per-pixel lighting if pixel-shaders aren't supported
|
|
if (!(m_Features & (RFT_HW_PS20 | RFT_HW_TS | RFT_HW_RC)))
|
|
{
|
|
if (CV_r_Quality_BumpMapping)
|
|
_SetVar("r_Quality_BumpMapping", 0);
|
|
if (CV_r_checkSunVis >= 2)
|
|
_SetVar("r_checkSunVis", 1);
|
|
}
|
|
|
|
// Allow pixel shaders 2.0 lighting on Radeon only cards with PS.2.0 support
|
|
if (CV_r_Quality_BumpMapping == 3)
|
|
{
|
|
if (!(m_Features & RFT_HW_PS20) || (nGPU == RFT_HW_GFFX && !CV_d3d9_nv30_ps20))
|
|
_SetVar("r_Quality_BumpMapping", 2);
|
|
}
|
|
|
|
// Shaders remapping for non-PS20 hardware
|
|
if (!(m_Features & RFT_HW_PS20) || (nGPU == RFT_HW_GFFX && !CV_d3d9_nv30_ps20))
|
|
{
|
|
_SetVar("r_NoPS20", 1);
|
|
if (CV_r_shadowblur == 3)
|
|
_SetVar("r_ShadowBlur", 2);
|
|
}
|
|
|
|
// Disable trees per-pixel lighting from medium and low spec settings
|
|
if (CV_r_Quality_BumpMapping < 2)
|
|
_SetVar("r_Vegetation_PerpixelLight", 0);
|
|
|
|
// Allow offset bump-mapping and parametric shaders system for very high spec settings only
|
|
if (CV_r_Quality_BumpMapping < 3)
|
|
{
|
|
if (CV_r_usehwshaders == 2)
|
|
_SetVar("r_UseHWShaders", 1);
|
|
if (CV_r_offsetbump)
|
|
_SetVar("r_OffsetBump", 0);
|
|
m_bDeviceSupports_PS2X = false;
|
|
m_bDeviceSupports_PS30 = false;
|
|
}
|
|
|
|
if (!m_bDeviceSupports_PS2X && CV_r_sm2xpath)
|
|
_SetVar("r_SM2XPATH", 0);
|
|
if (!CV_r_sm2xpath)
|
|
_SetVar("r_NoPS2X", 1);
|
|
m_nEnabled_PS2X = CV_r_nops2x ? 0 : 1;
|
|
m_NoPS2X = CV_r_nops2x;
|
|
m_sm2xpath = CV_r_sm2xpath;
|
|
|
|
if (!m_bDeviceSupports_PS30 && CV_r_sm30path)
|
|
_SetVar("r_SM30PATH", 0);
|
|
if (!CV_r_sm30path)
|
|
_SetVar("r_NoPS30", 1);
|
|
m_nEnabled_PS30 = CV_r_nops30 ? 0 : 1;
|
|
m_NoPS30 = CV_r_nops30;
|
|
m_sm30path = CV_r_sm30path;
|
|
|
|
if (m_bDeviceSupportsComprNormalmaps == 0)
|
|
_SetVar("r_TexNormalMapCompressed", 0);
|
|
|
|
if ((m_sm30path || m_sm2xpath) && m_bDeviceSupportsInstancing)
|
|
_SetVar("r_GeomInstancing", 1);
|
|
|
|
if (m_nHDRType == 2)
|
|
{
|
|
// HDRFake mode works only on NV40
|
|
_SetVar("r_HDRFake", 0);
|
|
}
|
|
|
|
// DO NOT Use VB Pools with fixed pipeline (some driver bug)
|
|
if (nGPU == RFT_HW_GF2 || CV_r_Quality_BumpMapping==0 || !(m_d3dCaps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET))
|
|
{
|
|
_SetVar("d3d9_VBPools", 0);
|
|
}
|
|
|
|
char *str;
|
|
if (nGPU == RFT_HW_GF2)
|
|
str = "Not using pixel shaders";
|
|
else
|
|
if (CV_r_nops20)
|
|
str = "Replace PS.2.0 to PS.1.1";
|
|
else
|
|
if (CV_r_Quality_BumpMapping == 3)
|
|
{
|
|
if (m_bDeviceSupports_PS30)
|
|
str = "PS.3.0, PS.2.0 and PS.1.1";
|
|
else
|
|
if (m_bDeviceSupports_PS2X)
|
|
{
|
|
if (nGPU == RFT_HW_GFFX)
|
|
str = "PS.2.A, PS.2.0 and PS.1.1";
|
|
else
|
|
str = "PS.2.B, PS.2.0 and PS.1.1";
|
|
}
|
|
else
|
|
str = "PS.2.0 and PS.1.1";
|
|
}
|
|
else
|
|
str ="PS1.1 only";
|
|
iLog->Log(" Pixel shaders usage: %s\n", str);
|
|
|
|
if (nGPU == RFT_HW_GF2)
|
|
str = "Not using vertex shaders";
|
|
else
|
|
if (CV_r_nops20)
|
|
str = "Replace VS.2.0 to VS.1.1";
|
|
else
|
|
if (CV_r_Quality_BumpMapping == 3)
|
|
{
|
|
if (D3DSHADER_VERSION_MAJOR(di->Caps.VertexShaderVersion) >= 3)
|
|
str = "VS.3.0, VS.2.0 and VS.1.1";
|
|
else
|
|
str = "VS.2.0 and VS.1.1";
|
|
}
|
|
else
|
|
str ="VS1.1 only";
|
|
iLog->Log(" Vertex shaders usage: %s\n", str);
|
|
iLog->Log(" Shadow maps type: %s\n", (m_Features & RFT_DEPTHMAPS) ? "Depth maps" : (m_Features & RFT_SHADOWMAP_SELFSHADOW) ? "Mixed Depth/2D maps" : "2D shadow maps");
|
|
iLog->Log(" Stencil shadows type: %s\n", m_d3dCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED ? "Two sided" : "Single sided");
|
|
iLog->Log(" Lighting quality: %s\n", CV_r_Quality_BumpMapping==0 ? "Low" : CV_r_Quality_BumpMapping==1 ? "Medium" : CV_r_Quality_BumpMapping==2 ? "High" : "Highest");
|
|
iLog->Log(" *****************************************\n\n");
|
|
|
|
iLog->Log("Init Shaders\n");
|
|
|
|
m_numtmus = di->Caps.MaxSimultaneousTextures;
|
|
|
|
#ifndef WIN64
|
|
// NOTE: AMD64 port: find the 64-bit CG runtime
|
|
if (!m_CGContext)
|
|
{
|
|
m_CGContext = cgCreateContext();
|
|
assert(m_CGContext);
|
|
cgD3D9SetDevice(mfGetD3DDevice());
|
|
#ifdef _DEBUG
|
|
cgD3D9EnableDebugTracing(true);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
gRenDev->m_cEF.mfInit();
|
|
EF_Init();
|
|
//ChangeResolution(1024, 768, 32, 75, false);
|
|
|
|
m_bInitialized = true;
|
|
|
|
// Cry_memcheck();
|
|
|
|
// Success, return the window handle
|
|
return (m_hWnd);
|
|
}
|
|
|
|
const char *CD3D9Renderer::D3DError( HRESULT h )
|
|
{
|
|
const TCHAR* strHRESULT;
|
|
strHRESULT = DXGetErrorString9(h);
|
|
return strHRESULT;
|
|
}
|
|
|
|
bool CD3D9Renderer::Error(char *Msg, HRESULT h)
|
|
{
|
|
const char *str = D3DError(h);
|
|
iLog->Log("Error: %s (%s)", Msg, str);
|
|
|
|
//UnSetRes();
|
|
|
|
//if (Msg)
|
|
// iConsole->Exit("%s (%s)\n", Msg, str);
|
|
//else
|
|
// iConsole->Exit("(%s)\n", str);
|
|
|
|
return false;
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: FindBestWindowedMode()
|
|
// Desc: Sets up m_D3DSettings with best available windowed mode, subject to
|
|
// the bRequireHAL and bRequireREF constraints. Returns false if no such
|
|
// mode can be found.
|
|
//-----------------------------------------------------------------------------
|
|
bool CD3D9Renderer::FindBestWindowedMode( bool bRequireHAL, bool bRequireREF )
|
|
{
|
|
// Get display mode of primary adapter (which is assumed to be where the window
|
|
// will appear)
|
|
D3DDISPLAYMODE primaryDesktopDisplayMode;
|
|
m_pD3D->GetAdapterDisplayMode(0, &primaryDesktopDisplayMode);
|
|
|
|
D3DAdapterInfo* pBestAdapterInfo = NULL;
|
|
D3DDeviceInfo* pBestDeviceInfo = NULL;
|
|
D3DDeviceCombo* pBestDeviceCombo = NULL;
|
|
|
|
for(int iai=0; iai<m_D3DEnum.m_pAdapterInfoList->Num(); iai++)
|
|
{
|
|
D3DAdapterInfo* pAdapterInfo = m_D3DEnum.m_pAdapterInfoList->Get(iai);
|
|
for(int idi=0; idi<pAdapterInfo->pDeviceInfoList->Num(); idi++)
|
|
{
|
|
D3DDeviceInfo* pDeviceInfo = pAdapterInfo->pDeviceInfoList->Get(idi);
|
|
if (bRequireHAL && pDeviceInfo->DevType != D3DDEVTYPE_HAL)
|
|
continue;
|
|
if (bRequireREF && pDeviceInfo->DevType != D3DDEVTYPE_REF)
|
|
continue;
|
|
for(int idc=0; idc<pDeviceInfo->pDeviceComboList->Num(); idc++)
|
|
{
|
|
D3DDeviceCombo* pDeviceCombo = pDeviceInfo->pDeviceComboList->Get(idc);
|
|
bool bAdapterMatchesBB = (pDeviceCombo->BackBufferFormat == pDeviceCombo->AdapterFormat);
|
|
if (!pDeviceCombo->IsWindowed)
|
|
continue;
|
|
if (pDeviceCombo->AdapterFormat != primaryDesktopDisplayMode.Format)
|
|
continue;
|
|
// If we haven't found a compatible DeviceCombo yet, or if this set
|
|
// is better (because it's a HAL, and/or because formats match better),
|
|
// save it
|
|
if( pBestDeviceCombo == NULL || pBestDeviceCombo->DevType != D3DDEVTYPE_HAL && pDeviceCombo->DevType == D3DDEVTYPE_HAL || pDeviceCombo->DevType == D3DDEVTYPE_HAL && bAdapterMatchesBB)
|
|
{
|
|
pBestAdapterInfo = pAdapterInfo;
|
|
pBestDeviceInfo = pDeviceInfo;
|
|
pBestDeviceCombo = pDeviceCombo;
|
|
if( pDeviceCombo->DevType == D3DDEVTYPE_HAL && bAdapterMatchesBB )
|
|
{
|
|
// This windowed device combo looks great -- take it
|
|
goto EndWindowedDeviceComboSearch;
|
|
}
|
|
// Otherwise keep looking for a better windowed device combo
|
|
}
|
|
}
|
|
}
|
|
}
|
|
EndWindowedDeviceComboSearch:
|
|
if (pBestDeviceCombo == NULL )
|
|
return false;
|
|
|
|
m_D3DSettings.pWindowed_AdapterInfo = pBestAdapterInfo;
|
|
m_D3DSettings.pWindowed_DeviceInfo = pBestDeviceInfo;
|
|
m_D3DSettings.pWindowed_DeviceCombo = pBestDeviceCombo;
|
|
m_D3DSettings.IsWindowed = true;
|
|
m_D3DSettings.Windowed_DisplayMode = primaryDesktopDisplayMode;
|
|
m_D3DSettings.Windowed_Width = m_rcWindowClient.right - m_rcWindowClient.left;
|
|
m_D3DSettings.Windowed_Height = m_rcWindowClient.bottom - m_rcWindowClient.top;
|
|
if (m_D3DEnum.AppUsesDepthBuffer)
|
|
m_D3DSettings.Windowed_DepthStencilBufferFormat = pBestDeviceCombo->pDepthStencilFormatList->Get(0);
|
|
m_D3DSettings.Windowed_MultisampleType = pBestDeviceCombo->pMultiSampleTypeList->Get(0);
|
|
m_D3DSettings.Windowed_MultisampleQuality = 0;
|
|
m_D3DSettings.Windowed_VertexProcessingType = pBestDeviceCombo->pVertexProcessingTypeList->Get(0);
|
|
m_D3DSettings.Windowed_PresentInterval = pBestDeviceCombo->pPresentIntervalList->Get(0);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: FindBestFullscreenMode()
|
|
// Desc: Sets up m_D3DSettings with best available fullscreen mode, subject to
|
|
// the bRequireHAL and bRequireREF constraints. Returns false if no such
|
|
// mode can be found.
|
|
//-----------------------------------------------------------------------------
|
|
bool CD3D9Renderer::FindBestFullscreenMode( bool bRequireHAL, bool bRequireREF )
|
|
{
|
|
// For fullscreen, default to first HAL DeviceCombo that supports the current desktop
|
|
// display mode, or any display mode if HAL is not compatible with the desktop mode, or
|
|
// non-HAL if no HAL is available
|
|
D3DDISPLAYMODE adapterDesktopDisplayMode;
|
|
D3DDISPLAYMODE bestAdapterDesktopDisplayMode;
|
|
D3DDISPLAYMODE bestDisplayMode;
|
|
bestAdapterDesktopDisplayMode.Width = 0;
|
|
bestAdapterDesktopDisplayMode.Height = 0;
|
|
bestAdapterDesktopDisplayMode.Format = D3DFMT_UNKNOWN;
|
|
bestAdapterDesktopDisplayMode.RefreshRate = 0;
|
|
|
|
D3DAdapterInfo* pBestAdapterInfo = NULL;
|
|
D3DDeviceInfo* pBestDeviceInfo = NULL;
|
|
D3DDeviceCombo* pBestDeviceCombo = NULL;
|
|
|
|
for(int iai=0; iai<m_D3DEnum.m_pAdapterInfoList->Num(); iai++)
|
|
{
|
|
D3DAdapterInfo* pAdapterInfo = m_D3DEnum.m_pAdapterInfoList->Get(iai);
|
|
m_pD3D->GetAdapterDisplayMode( pAdapterInfo->AdapterOrdinal, &adapterDesktopDisplayMode );
|
|
for(int idi=0; idi<pAdapterInfo->pDeviceInfoList->Num(); idi++)
|
|
{
|
|
D3DDeviceInfo* pDeviceInfo = pAdapterInfo->pDeviceInfoList->Get(idi);
|
|
if (bRequireHAL && pDeviceInfo->DevType != D3DDEVTYPE_HAL)
|
|
continue;
|
|
if (bRequireREF && pDeviceInfo->DevType != D3DDEVTYPE_REF)
|
|
continue;
|
|
for(int idc=0; idc<pDeviceInfo->pDeviceComboList->Num(); idc++)
|
|
{
|
|
D3DDeviceCombo* pDeviceCombo = pDeviceInfo->pDeviceComboList->Get(idc);
|
|
bool bAdapterMatchesBB = (pDeviceCombo->BackBufferFormat == pDeviceCombo->AdapterFormat);
|
|
bool bAdapterMatchesDesktop = (pDeviceCombo->AdapterFormat == adapterDesktopDisplayMode.Format);
|
|
if (pDeviceCombo->IsWindowed)
|
|
continue;
|
|
// If we haven't found a compatible set yet, or if this set
|
|
// is better (because it's a HAL, and/or because formats match better),
|
|
// save it
|
|
if (pBestDeviceCombo == NULL ||
|
|
(pBestDeviceCombo->DevType != D3DDEVTYPE_HAL && pDeviceInfo->DevType == D3DDEVTYPE_HAL) ||
|
|
(pDeviceCombo->DevType == D3DDEVTYPE_HAL && pBestDeviceCombo->AdapterFormat != adapterDesktopDisplayMode.Format && bAdapterMatchesDesktop) ||
|
|
pDeviceCombo->DevType == D3DDEVTYPE_HAL && bAdapterMatchesDesktop && bAdapterMatchesBB )
|
|
{
|
|
bestAdapterDesktopDisplayMode = adapterDesktopDisplayMode;
|
|
pBestAdapterInfo = pAdapterInfo;
|
|
pBestDeviceInfo = pDeviceInfo;
|
|
pBestDeviceCombo = pDeviceCombo;
|
|
if (pDeviceInfo->DevType == D3DDEVTYPE_HAL && bAdapterMatchesDesktop && bAdapterMatchesBB)
|
|
{
|
|
// This fullscreen device combo looks great -- take it
|
|
goto EndFullscreenDeviceComboSearch;
|
|
}
|
|
// Otherwise keep looking for a better fullscreen device combo
|
|
}
|
|
}
|
|
}
|
|
}
|
|
EndFullscreenDeviceComboSearch:
|
|
if (pBestDeviceCombo == NULL)
|
|
return false;
|
|
|
|
// Need to find a display mode on the best adapter that uses pBestDeviceCombo->AdapterFormat
|
|
// and is as close to bestAdapterDesktopDisplayMode's res as possible
|
|
bestDisplayMode.Width = 0;
|
|
bestDisplayMode.Height = 0;
|
|
bestDisplayMode.Format = D3DFMT_UNKNOWN;
|
|
bestDisplayMode.RefreshRate = 0;
|
|
for(int idm=0; idm<pBestAdapterInfo->pDisplayModeList->Num(); idm++)
|
|
{
|
|
D3DDISPLAYMODE* pdm = &pBestAdapterInfo->pDisplayModeList->Get(idm);
|
|
if( pdm->Format != pBestDeviceCombo->AdapterFormat )
|
|
continue;
|
|
if( pdm->Width == bestAdapterDesktopDisplayMode.Width && pdm->Height == bestAdapterDesktopDisplayMode.Height && pdm->RefreshRate == bestAdapterDesktopDisplayMode.RefreshRate )
|
|
{
|
|
// found a perfect match, so stop
|
|
bestDisplayMode = *pdm;
|
|
break;
|
|
}
|
|
else
|
|
if( pdm->Width == bestAdapterDesktopDisplayMode.Width && pdm->Height == bestAdapterDesktopDisplayMode.Height && pdm->RefreshRate > bestDisplayMode.RefreshRate )
|
|
{
|
|
// refresh rate doesn't match, but width/height match, so keep this
|
|
// and keep looking
|
|
bestDisplayMode = *pdm;
|
|
}
|
|
else if( pdm->Width == bestAdapterDesktopDisplayMode.Width )
|
|
{
|
|
// width matches, so keep this and keep looking
|
|
bestDisplayMode = *pdm;
|
|
}
|
|
else
|
|
if( bestDisplayMode.Width == 0 )
|
|
{
|
|
// we don't have anything better yet, so keep this and keep looking
|
|
bestDisplayMode = *pdm;
|
|
}
|
|
}
|
|
|
|
m_D3DSettings.pFullscreen_AdapterInfo = pBestAdapterInfo;
|
|
m_D3DSettings.pFullscreen_DeviceInfo = pBestDeviceInfo;
|
|
m_D3DSettings.pFullscreen_DeviceCombo = pBestDeviceCombo;
|
|
m_D3DSettings.IsWindowed = false;
|
|
m_D3DSettings.Fullscreen_DisplayMode = bestDisplayMode;
|
|
if (m_D3DEnum.AppUsesDepthBuffer)
|
|
m_D3DSettings.Fullscreen_DepthStencilBufferFormat = pBestDeviceCombo->pDepthStencilFormatList->Get(0);
|
|
m_D3DSettings.Fullscreen_MultisampleType = pBestDeviceCombo->pMultiSampleTypeList->Get(0);
|
|
m_D3DSettings.Fullscreen_MultisampleQuality = 0;
|
|
m_D3DSettings.Fullscreen_VertexProcessingType = pBestDeviceCombo->pVertexProcessingTypeList->Get(0);
|
|
m_D3DSettings.Fullscreen_PresentInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ChooseInitialD3DSettings()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CD3D9Renderer::ChooseInitialD3DSettings()
|
|
{
|
|
bool bFoundFullscreen = FindBestFullscreenMode( false, false );
|
|
bool bFoundWindowed = FindBestWindowedMode( false, false );
|
|
|
|
if( m_bFullScreen && bFoundFullscreen )
|
|
m_D3DSettings.IsWindowed = false;
|
|
if( !bFoundWindowed && bFoundFullscreen )
|
|
m_D3DSettings.IsWindowed = false;
|
|
|
|
if( !bFoundFullscreen && !bFoundWindowed )
|
|
return D3DAPPERR_NOCOMPATIBLEDEVICES;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CD3D9Renderer::ConfirmDevice()
|
|
// Desc: Called during device intialization, this code checks the device
|
|
// for some minimum set of capabilities
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CD3D9Renderer::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior, D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ConfirmDeviceHelper()
|
|
// Desc: Static function used by D3DEnumeration
|
|
//-----------------------------------------------------------------------------
|
|
bool CD3D9Renderer::ConfirmDeviceHelper(D3DCAPS9* pCaps, VertexProcessingType vertexProcessingType, D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat)
|
|
{
|
|
DWORD dwBehavior;
|
|
|
|
if (vertexProcessingType == SOFTWARE_VP)
|
|
dwBehavior = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
|
else
|
|
if (vertexProcessingType == MIXED_VP)
|
|
dwBehavior = D3DCREATE_MIXED_VERTEXPROCESSING;
|
|
else
|
|
if (vertexProcessingType == HARDWARE_VP)
|
|
dwBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING;
|
|
else
|
|
if (vertexProcessingType == PURE_HARDWARE_VP)
|
|
dwBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
|
|
else
|
|
dwBehavior = 0; // TODO: throw exception
|
|
|
|
return SUCCEEDED(gcpRendD3D->ConfirmDevice(pCaps, dwBehavior, adapterFormat, backBufferFormat));
|
|
}
|
|
|
|
static char *sD3DFMT( D3DFORMAT fmt )
|
|
{
|
|
switch( fmt )
|
|
{
|
|
case D3DFMT_R8G8B8:
|
|
return "D3DFMT_R8G8B8";
|
|
case D3DFMT_A8R8G8B8:
|
|
return "D3DFMT_A8R8G8B8";
|
|
case D3DFMT_X8R8G8B8:
|
|
return "D3DFMT_X8R8G8B8";
|
|
case D3DFMT_R5G6B5:
|
|
return "D3DFMT_R5G6B5";
|
|
case D3DFMT_X1R5G5B5:
|
|
return "D3DFMT_X1R5G5B5";
|
|
case D3DFMT_A1R5G5B5:
|
|
return "D3DFMT_A1R5G5B5";
|
|
case D3DFMT_A4R4G4B4:
|
|
return "D3DFMT_A4R4G4B4";
|
|
case D3DFMT_R3G3B2:
|
|
return "D3DFMT_R3G3B2";
|
|
case D3DFMT_A8R3G3B2:
|
|
return "D3DFMT_A8R3G3B2";
|
|
case D3DFMT_X4R4G4B4:
|
|
return "D3DFMT_X4R4G4B4";
|
|
case D3DFMT_A2B10G10R10:
|
|
return "D3DFMT_A2B10G10R10";
|
|
case D3DFMT_A2R10G10B10:
|
|
return "D3DFMT_A2R10G10B10";
|
|
|
|
case D3DFMT_D24S8:
|
|
return "D3DFMT_D24S8";
|
|
case D3DFMT_D24X8:
|
|
return "D3DFMT_D24X8";
|
|
case D3DFMT_D16:
|
|
return "D3DFMT_D16";
|
|
case D3DFMT_D24X4S4:
|
|
return "D3DFMT_D24X4S4";
|
|
case D3DFMT_D32:
|
|
return "D3DFMT_D32";
|
|
case D3DFMT_D16_LOCKABLE:
|
|
return "D3DFMT_D16_LOCKABLE";
|
|
case D3DFMT_D15S1:
|
|
return "D3DFMT_D15S1";
|
|
case D3DFMT_D32F_LOCKABLE:
|
|
return "D3DFMT_D32F_LOCKABLE";
|
|
case D3DFMT_D24FS8:
|
|
return "D3DFMT_D24FS8";
|
|
default:
|
|
return "Unknown";
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Initialize3DEnvironment()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CD3D9Renderer::Initialize3DEnvironment()
|
|
{
|
|
HRESULT hr;
|
|
|
|
D3DAdapterInfo* pAdapterInfo = m_D3DSettings.PAdapterInfo();
|
|
D3DDeviceInfo* pDeviceInfo = m_D3DSettings.PDeviceInfo();
|
|
D3DDISPLAYMODE ModeInfo = m_D3DSettings.DisplayMode();
|
|
|
|
SetRendParms(&ModeInfo, pDeviceInfo);
|
|
|
|
// Prepare window for possible windowed/fullscreen change
|
|
AdjustWindowForChange();
|
|
|
|
// Set up the presentation parameters
|
|
BuildPresentParamsFromSettings();
|
|
|
|
if( pDeviceInfo->Caps.PrimitiveMiscCaps & D3DPMISCCAPS_NULLREFERENCE )
|
|
{
|
|
// Warn user about null ref device that can't render anything
|
|
iLog->Log("ERROR: Chosed NULL Ref Device that can't render anything");
|
|
return E_FAIL;
|
|
}
|
|
|
|
DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE;
|
|
if (CV_d3d9_forcesoftware)
|
|
behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
|
else
|
|
{
|
|
if (m_D3DSettings.GetVertexProcessingType() == SOFTWARE_VP)
|
|
behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
|
else
|
|
if (m_D3DSettings.GetVertexProcessingType() == MIXED_VP)
|
|
behaviorFlags |= D3DCREATE_MIXED_VERTEXPROCESSING;
|
|
else
|
|
if (m_D3DSettings.GetVertexProcessingType() == HARDWARE_VP)
|
|
behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
|
|
else
|
|
if (m_D3DSettings.GetVertexProcessingType() == PURE_HARDWARE_VP)
|
|
behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
|
|
}
|
|
|
|
// Create the device
|
|
iLog->Log("Creating D3D device (Adapter format: %s, BackBuffer format: %s, Depth format: %s)", sD3DFMT(m_D3DSettings.AdapterFormat()), sD3DFMT(m_d3dpp.BackBufferFormat), sD3DFMT(m_d3dpp.AutoDepthStencilFormat));
|
|
if (!CV_d3d9_nvperfhud)
|
|
hr = m_pD3D->CreateDevice(m_D3DSettings.AdapterOrdinal(), pDeviceInfo->DevType, (HWND)m_CurrContext->m_hWnd, behaviorFlags, &m_d3dpp, &m_pd3dDevice);
|
|
else
|
|
hr = m_pD3D->CreateDevice(m_pD3D->GetAdapterCount()-1, D3DDEVTYPE_REF, (HWND)m_CurrContext->m_hWnd, behaviorFlags & ~(D3DCREATE_PUREDEVICE), &m_d3dpp, &m_pd3dDevice);
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
// If we cannot use Queries Back Buffer should be lockable
|
|
if (!(m_d3dpp.Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER))
|
|
{
|
|
hr = m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, NULL);
|
|
if(hr != D3DERR_NOTAVAILABLE)
|
|
hr = m_pd3dDevice->CreateQuery (D3DQUERYTYPE_OCCLUSION, NULL);
|
|
if(hr == D3DERR_NOTAVAILABLE)
|
|
{
|
|
SAFE_RELEASE(m_pd3dDevice);
|
|
Sleep(1000);
|
|
m_d3dpp.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
|
|
|
|
// Create the device
|
|
hr = m_pD3D->CreateDevice(m_D3DSettings.AdapterOrdinal(), pDeviceInfo->DevType, (HWND)m_CurrContext->m_hWnd, behaviorFlags, &m_d3dpp, &m_pd3dDevice);
|
|
if (FAILED(hr))
|
|
{
|
|
SAFE_RELEASE(m_pd3dDevice);
|
|
Sleep(1000);
|
|
m_d3dpp.Flags &= ~D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
|
|
hr = m_pD3D->CreateDevice(m_D3DSettings.AdapterOrdinal(), pDeviceInfo->DevType, (HWND)m_CurrContext->m_hWnd, behaviorFlags, &m_d3dpp, &m_pd3dDevice);
|
|
}
|
|
}
|
|
}
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
// When moving from fullscreen to windowed mode, it is important to
|
|
// adjust the window size after recreating the device rather than
|
|
// beforehand to ensure that you get the window size you want. For
|
|
// example, when switching from 640x480 fullscreen to windowed with
|
|
// a 1000x600 window on a 1024x768 desktop, it is impossible to set
|
|
// the window size to 1000x600 until after the display mode has
|
|
// changed to 1024x768, because windows cannot be larger than the
|
|
// desktop.
|
|
ShowWindow(m_hWnd, SW_SHOW);
|
|
UpdateWindow(m_hWnd);
|
|
|
|
SetForegroundWindow(m_hWnd);
|
|
SetFocus(m_hWnd);
|
|
|
|
if(!m_bFullScreen )
|
|
{
|
|
SetWindowPos(m_hWnd, HWND_NOTOPMOST, m_rcWindowBounds.left, m_rcWindowBounds.top, (m_rcWindowBounds.right-m_rcWindowBounds.left), (m_rcWindowBounds.bottom - m_rcWindowBounds.top), SWP_SHOWWINDOW);
|
|
}
|
|
ChangeLog();
|
|
DisplaySplash();
|
|
|
|
// Store device Caps
|
|
m_pd3dDevice->GetDeviceCaps(&m_d3dCaps);
|
|
m_dwCreateFlags = behaviorFlags;
|
|
|
|
// Store device description
|
|
if(pDeviceInfo->DevType == D3DDEVTYPE_REF)
|
|
lstrcpy(m_strDeviceStats, TEXT("REF"));
|
|
else
|
|
if(pDeviceInfo->DevType == D3DDEVTYPE_HAL)
|
|
lstrcpy(m_strDeviceStats, TEXT("HAL"));
|
|
else
|
|
if(pDeviceInfo->DevType == D3DDEVTYPE_SW)
|
|
lstrcpy( m_strDeviceStats, TEXT("SW") );
|
|
|
|
if(behaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING && behaviorFlags & D3DCREATE_PUREDEVICE)
|
|
{
|
|
if(pDeviceInfo->DevType == D3DDEVTYPE_HAL)
|
|
lstrcat( m_strDeviceStats, TEXT(" (pure hw vp)") );
|
|
else
|
|
lstrcat( m_strDeviceStats, TEXT(" (simulated pure hw vp)") );
|
|
}
|
|
else
|
|
if(behaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING)
|
|
{
|
|
if(pDeviceInfo->DevType == D3DDEVTYPE_HAL)
|
|
lstrcat( m_strDeviceStats, TEXT(" (hw vp)") );
|
|
else
|
|
lstrcat( m_strDeviceStats, TEXT(" (simulated hw vp)") );
|
|
}
|
|
else
|
|
if(behaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING)
|
|
{
|
|
if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
|
|
lstrcat( m_strDeviceStats, TEXT(" (mixed vp)") );
|
|
else
|
|
lstrcat( m_strDeviceStats, TEXT(" (simulated mixed vp)") );
|
|
}
|
|
else
|
|
if(behaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
|
|
{
|
|
lstrcat( m_strDeviceStats, TEXT(" (sw vp)") );
|
|
}
|
|
|
|
if(pDeviceInfo->DevType == D3DDEVTYPE_HAL)
|
|
{
|
|
// Be sure not to overflow m_strDeviceStats when appending the adapter
|
|
// description, since it can be long. Note that the adapter description
|
|
// is initially CHAR and must be converted to TCHAR.
|
|
lstrcat( m_strDeviceStats, TEXT(": ") );
|
|
const int cchDesc = sizeof(pAdapterInfo->AdapterIdentifier.Description);
|
|
TCHAR szDescription[cchDesc];
|
|
strncpy(szDescription, pAdapterInfo->AdapterIdentifier.Description, cchDesc);
|
|
int maxAppend = sizeof(m_strDeviceStats) / sizeof(TCHAR) - lstrlen( m_strDeviceStats ) - 1;
|
|
strncat(m_strDeviceStats, szDescription, maxAppend);
|
|
}
|
|
|
|
// Store render target surface desc
|
|
CD3D9TexMan *pTM = (CD3D9TexMan *)m_TexMan;
|
|
m_Features |= RFT_ZLOCKABLE;
|
|
|
|
m_pd3dDevice->GetDepthStencilSurface( &m_pZBuffer );
|
|
m_pZBuffer->GetDesc( &m_d3dsdZBuffer );
|
|
m_pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer );
|
|
m_pBackBuffer->GetDesc(&m_d3dsdBackBuffer);
|
|
|
|
// Initialize the app's device-dependent objects
|
|
hr = InitDeviceObjects();
|
|
if( FAILED(hr) )
|
|
{
|
|
DeleteDeviceObjects();
|
|
}
|
|
else
|
|
{
|
|
m_bDeviceObjectsInited = true;
|
|
hr = RestoreDeviceObjects();
|
|
if( FAILED(hr) )
|
|
{
|
|
InvalidateDeviceObjects();
|
|
}
|
|
else
|
|
{
|
|
m_bDeviceObjectsRestored = true;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
// Cleanup before we try again
|
|
Cleanup3DEnvironment();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
struct SMultiSample
|
|
{
|
|
D3DMULTISAMPLE_TYPE Type;
|
|
DWORD Quality;
|
|
};
|
|
|
|
int __cdecl MS_Cmp(const void* v1, const void* v2)
|
|
{
|
|
SMultiSample *pMS0 = (SMultiSample *)v1;
|
|
SMultiSample *pMS1 = (SMultiSample *)v2;
|
|
|
|
if (pMS0->Type < pMS1->Type)
|
|
return -1;
|
|
if (pMS0->Type > pMS1->Type)
|
|
return 1;
|
|
|
|
if (pMS0->Quality < pMS1->Quality)
|
|
return -1;
|
|
if (pMS0->Quality > pMS1->Quality)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//! Return all supported by video card video AA formats
|
|
int CD3D9Renderer::EnumAAFormats(TArray<SAAFormat>& Formats, bool bReset)
|
|
{
|
|
int i;
|
|
if (bReset)
|
|
{
|
|
Formats.Free();
|
|
return 0;
|
|
}
|
|
SAAFormat DF;
|
|
|
|
D3DAdapterInfo *pAI = m_D3DSettings.PAdapterInfo();
|
|
D3DDeviceCombo *pDev = m_D3DSettings.PDeviceCombo();
|
|
TArray <SMultiSample> MSList;
|
|
int nNONMaskable = 0;
|
|
int nMaskable = 0;
|
|
int nQuality = 0;
|
|
for (i=0; i<pDev->pMultiSampleTypeList->Num(); i++)
|
|
{
|
|
if (pDev->pMultiSampleTypeList->Get(i) == D3DMULTISAMPLE_NONE)
|
|
continue;
|
|
SMultiSample MS;
|
|
MS.Type = pDev->pMultiSampleTypeList->Get(i);
|
|
if (MS.Type == D3DMULTISAMPLE_NONMASKABLE)
|
|
nNONMaskable++;
|
|
else
|
|
nMaskable++;
|
|
for (DWORD j=0; j<pDev->pMultiSampleQualityList->Get(i); j++)
|
|
{
|
|
MS.Quality = j;
|
|
MSList.AddElem(MS);
|
|
if (MS.Type == D3DMULTISAMPLE_NONMASKABLE)
|
|
nQuality++;
|
|
}
|
|
}
|
|
qsort(&MSList[0], MSList.Num(), sizeof(MSList[0]), MS_Cmp);
|
|
DF.nAPIType = D3DMULTISAMPLE_NONMASKABLE;
|
|
DF.nQuality = 0;
|
|
DF.nSamples = 1;
|
|
char str[64];
|
|
for (i=0; i<MSList.Num(); i++)
|
|
{
|
|
if (MSList[i].Type == D3DMULTISAMPLE_NONMASKABLE)
|
|
{
|
|
if (nMaskable)
|
|
continue;
|
|
DF.nAPIType = D3DMULTISAMPLE_NONMASKABLE;
|
|
DF.nQuality = MSList[i].Quality;
|
|
DF.nSamples = 1;
|
|
if (pAI->AdapterIdentifier.VendorId == 4318 && nNONMaskable == 1 && nQuality == 4)
|
|
{
|
|
switch (DF.nQuality)
|
|
{
|
|
case 0:
|
|
strcpy(DF.szDescr, "2x");
|
|
break;
|
|
case 1:
|
|
strcpy(DF.szDescr, "Quincunx");
|
|
break;
|
|
case 2:
|
|
strcpy(DF.szDescr, "4x");
|
|
break;
|
|
case 3:
|
|
strcpy(DF.szDescr, "4xS");
|
|
break;
|
|
default:
|
|
sprintf(str, "AA Quality lev. %d", DF.nQuality);
|
|
strcpy(DF.szDescr, str);
|
|
break;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprintf(str, "AA Quality lev. %d", MSList[i].Quality);
|
|
strcpy(DF.szDescr, str);
|
|
}
|
|
Formats.AddElem(DF);
|
|
}
|
|
else
|
|
{
|
|
DF.nAPIType = MSList[i].Type;
|
|
DF.nQuality = MSList[i].Quality;
|
|
DF.nSamples = MSList[i].Type;
|
|
sprintf(str, "%dx Samples", MSList[i].Type);
|
|
strcpy(DF.szDescr, str);
|
|
Formats.AddElem(DF);
|
|
}
|
|
}
|
|
return Formats.Num();
|
|
}
|
|
|
|
int CD3D9Renderer::GetAAFormat(TArray<SAAFormat>& Formats, bool bReset)
|
|
{
|
|
int nNums = EnumAAFormats(Formats, bReset);
|
|
if (bReset)
|
|
return nNums;
|
|
int i;
|
|
|
|
if (!CV_r_fsaa)
|
|
return -1;
|
|
for (i=0; i<Formats.Num(); i++)
|
|
{
|
|
if (CV_r_fsaa_samples == Formats[i].nSamples && CV_r_fsaa_quality == Formats[i].nQuality)
|
|
return i;
|
|
}
|
|
ICVar *pVar = iConsole->GetCVar("r_FSAA_samples");
|
|
if (pVar)
|
|
pVar->Set(Formats[0].nSamples);
|
|
pVar = iConsole->GetCVar("r_FSAA_quality");
|
|
if (pVar)
|
|
pVar->Set(Formats[0].nQuality);
|
|
return 0;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: BuildPresentParamsFromSettings()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void CD3D9Renderer::BuildPresentParamsFromSettings()
|
|
{
|
|
m_d3dpp.Windowed = m_D3DSettings.IsWindowed;
|
|
m_d3dpp.BackBufferCount = CV_d3d9_triplebuffering ? 2 : 1;
|
|
m_d3dpp.MultiSampleType = m_D3DSettings.MultisampleType();
|
|
m_d3dpp.MultiSampleQuality = m_D3DSettings.MultisampleQuality();
|
|
m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
m_d3dpp.EnableAutoDepthStencil = m_D3DEnum.AppUsesDepthBuffer;
|
|
m_d3dpp.hDeviceWindow = m_hWnd;
|
|
if( m_D3DEnum.AppUsesDepthBuffer )
|
|
{
|
|
if (CV_d3d9_forcesoftware)
|
|
m_d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
|
|
else
|
|
m_d3dpp.Flags = 0;
|
|
m_d3dpp.AutoDepthStencilFormat = m_D3DSettings.DepthStencilBufferFormat();
|
|
}
|
|
else
|
|
{
|
|
m_d3dpp.Flags = 0;
|
|
}
|
|
|
|
if(!m_bFullScreen)
|
|
{
|
|
if (m_bEditor)
|
|
{
|
|
m_d3dpp.BackBufferWidth = m_deskwidth;
|
|
m_d3dpp.BackBufferHeight = m_deskheight;
|
|
}
|
|
else
|
|
{
|
|
m_d3dpp.BackBufferWidth = m_width;
|
|
m_d3dpp.BackBufferHeight = m_height;
|
|
}
|
|
|
|
m_d3dpp.BackBufferFormat = m_D3DSettings.PDeviceCombo()->BackBufferFormat;
|
|
m_d3dpp.FullScreen_RefreshRateInHz = 0;
|
|
m_d3dpp.PresentationInterval = m_D3DSettings.PresentInterval();
|
|
}
|
|
else
|
|
{
|
|
m_d3dpp.BackBufferWidth = m_D3DSettings.DisplayMode().Width;
|
|
m_d3dpp.BackBufferHeight = m_D3DSettings.DisplayMode().Height;
|
|
m_d3dpp.BackBufferFormat = m_D3DSettings.PDeviceCombo()->BackBufferFormat;
|
|
m_d3dpp.FullScreen_RefreshRateInHz = m_D3DSettings.Fullscreen_DisplayMode.RefreshRate;
|
|
m_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //m_D3DSettings.PresentInterval();
|
|
}
|
|
if (CV_r_fsaa)
|
|
{
|
|
TArray<SAAFormat> Formats;
|
|
int nNum = GetAAFormat(Formats, false);
|
|
D3DMULTISAMPLE_TYPE nType = (D3DMULTISAMPLE_TYPE)Formats[nNum].nAPIType;
|
|
DWORD nQualityLevel = 0;
|
|
HRESULT hr = m_pD3D->CheckDeviceMultiSampleType(m_D3DSettings.AdapterOrdinal(), m_D3DSettings.DevType(), m_d3dpp.BackBufferFormat, m_d3dpp.Windowed, nType, &nQualityLevel);
|
|
|
|
if (!FAILED(hr) && nQualityLevel >= (DWORD)Formats[nNum].nQuality)
|
|
{
|
|
HRESULT hr = m_pD3D->CheckDeviceMultiSampleType(m_D3DSettings.AdapterOrdinal(), m_D3DSettings.DevType(), m_d3dpp.AutoDepthStencilFormat, m_d3dpp.Windowed, nType, &nQualityLevel);
|
|
if (!FAILED(hr) && nQualityLevel >= (DWORD)Formats[nNum].nQuality)
|
|
{
|
|
if( CV_r_fsaa == 1 )
|
|
{
|
|
m_d3dpp.MultiSampleType = nType;
|
|
m_d3dpp.MultiSampleQuality = Formats[nNum].nQuality;
|
|
m_Features |= RFT_SUPPORTFSAA;
|
|
}
|
|
else
|
|
{
|
|
// Use special mode to enable FSAA in HDR which requires the d3d device to be setup w/o a FSAA backbuffer!
|
|
m_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
|
m_d3dpp.MultiSampleQuality = 0;
|
|
}
|
|
}
|
|
}
|
|
m_FSAA = CV_r_fsaa;
|
|
m_FSAA_samples = Formats[nNum].nSamples;
|
|
m_FSAA_quality = Formats[nNum].nQuality;
|
|
GetAAFormat(Formats, true);
|
|
}
|
|
else
|
|
{
|
|
m_FSAA = 0;
|
|
m_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
|
m_d3dpp.MultiSampleQuality = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Cleanup3DEnvironment()
|
|
// Desc: Cleanup scene objects
|
|
//-----------------------------------------------------------------------------
|
|
void CD3D9Renderer::Cleanup3DEnvironment()
|
|
{
|
|
if( m_pd3dDevice != NULL )
|
|
{
|
|
if( m_bDeviceObjectsRestored )
|
|
{
|
|
m_bDeviceObjectsRestored = false;
|
|
InvalidateDeviceObjects();
|
|
}
|
|
if( m_bDeviceObjectsInited )
|
|
{
|
|
m_bDeviceObjectsInited = false;
|
|
DeleteDeviceObjects();
|
|
}
|
|
RestoreGamma();
|
|
|
|
if( m_pd3dDevice->Release() > 0 )
|
|
{
|
|
iLog->Log("ERROR: CD3D9Renderer::Cleanup3DEnvironment: Non zero reference counter after release of D3D Device");
|
|
while( m_pd3dDevice->Release() ) {}
|
|
}
|
|
m_pd3dDevice = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Reset3DEnvironment()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CD3D9Renderer::Reset3DEnvironment()
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Release all vidmem objects
|
|
if( m_bDeviceObjectsRestored )
|
|
{
|
|
m_bDeviceObjectsRestored = false;
|
|
InvalidateDeviceObjects();
|
|
}
|
|
|
|
/*for (int i=0; i<gDVB.Num(); i++)
|
|
{
|
|
SDynVB *vb = &gDVB[i];
|
|
if (vb->m_pRes->GetType() == D3DRTYPE_INDEXBUFFER)
|
|
{
|
|
D3DINDEXBUFFER_DESC desc;
|
|
IDirect3DIndexBuffer9 *pIB = (IDirect3DIndexBuffer9 *)vb->m_pRes;
|
|
pIB->GetDesc(&desc);
|
|
assert(desc.Pool != D3DPOOL_DEFAULT);
|
|
}
|
|
else
|
|
if (vb->m_pRes->GetType() == D3DRTYPE_VERTEXBUFFER)
|
|
{
|
|
D3DVERTEXBUFFER_DESC desc;
|
|
IDirect3DVertexBuffer9 *pIB = (IDirect3DVertexBuffer9 *)vb->m_pRes;
|
|
pIB->GetDesc(&desc);
|
|
assert(desc.Pool != D3DPOOL_DEFAULT);
|
|
}
|
|
else
|
|
assert(0);
|
|
}*/
|
|
|
|
// Reset the device
|
|
if( FAILED( hr = m_pd3dDevice->Reset( &m_d3dpp ) ) )
|
|
return hr;
|
|
|
|
// Initialize the app's device-dependent objects
|
|
hr = RestoreDeviceObjects();
|
|
if( FAILED(hr) )
|
|
{
|
|
InvalidateDeviceObjects();
|
|
return hr;
|
|
}
|
|
|
|
m_bDeviceObjectsRestored = true;
|
|
m_bTemporaryDisabledSFX = false;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
bool CD3D9Renderer::ChooseDevice(void)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Save window properties
|
|
GetWindowRect( m_hWnd, &m_rcWindowBounds );
|
|
GetClientRect( m_hWnd, &m_rcWindowClient );
|
|
|
|
if(FAILED(hr = ChooseInitialD3DSettings()))
|
|
return Error("Couldn't find any suitable device", hr);
|
|
|
|
char drv[64];
|
|
strcpy(drv, CV_d3d9_device->GetString());
|
|
|
|
int numAdap = -1;
|
|
bool bAuto = false;
|
|
if (!strnicmp(drv, "auto", 4))
|
|
bAuto = true;
|
|
else
|
|
if (!strnicmp(drv, "primary", 7))
|
|
numAdap = 0;
|
|
else
|
|
if (!strnicmp(drv, "3dfx", 4) || !strnicmp(drv, "second", 6) || !strnicmp(drv, "Voodoo", 6))
|
|
numAdap = 1;
|
|
else
|
|
if (drv[0] && isdigit(drv[0]))
|
|
numAdap = atol(drv);
|
|
else
|
|
{
|
|
iLog->Log ( "Unknown device name '%s' (use AutoDetect)\n", drv);
|
|
iLog->Log ( "Only 'Auto', 'Primary', '3dfx' or digital device ID are supported\n");
|
|
bAuto = true;
|
|
}
|
|
if (numAdap < 0)
|
|
numAdap = 0;
|
|
|
|
int nDev = -1;
|
|
bool bAllowSoft = false;
|
|
while (true)
|
|
{
|
|
if (bAuto)
|
|
{
|
|
for(int a=0; a<m_D3DEnum.m_pAdapterInfoList->Num(); a++)
|
|
{
|
|
if ((nDev=FindSuitableDevice(a, bAllowSoft)) >= 0)
|
|
{
|
|
numAdap = a;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nDev = FindSuitableDevice(numAdap, bAllowSoft);
|
|
}
|
|
|
|
if (nDev < 0)
|
|
{
|
|
if (!bAllowSoft)
|
|
{
|
|
if (CV_d3d9_allowsoftware)
|
|
{
|
|
bAllowSoft = true;
|
|
continue;
|
|
}
|
|
}
|
|
return Error("Can't find any suitable D3D device\n", 0);
|
|
}
|
|
break;
|
|
}
|
|
// The focus window can be a specified to be a different window than the
|
|
// device window. If not, use the device window as the focus window.
|
|
if( m_CurrContext == NULL )
|
|
CreateContext(m_hWnd);
|
|
return true;
|
|
}
|
|
|
|
bool CD3D9Renderer::SetRes(void)
|
|
{
|
|
UnSetRes();
|
|
|
|
HRESULT hr;
|
|
|
|
// Create the Direct3D object
|
|
m_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
|
|
if( m_pD3D == NULL )
|
|
return Error("DirectX9 not installed", 0);
|
|
|
|
m_D3DEnum.SetD3D(m_pD3D);
|
|
m_D3DEnum.ConfirmDeviceCallback = ConfirmDeviceHelper;
|
|
|
|
// Build a list of Direct3D adapters, modes and devices. The
|
|
// ConfirmDevice() callback is used to confirm that only devices that
|
|
// meet the app's requirements are considered.
|
|
if(FAILED(hr = m_D3DEnum.Enumerate()))
|
|
{
|
|
if (hr == D3DAPPERR_NOWINDOWABLEDEVICES)
|
|
{
|
|
if (!m_bFullScreen)
|
|
return Error("Couldn't build list of D3D devices", hr);
|
|
}
|
|
else
|
|
return Error("Couldn't build list of D3D devices", hr);
|
|
}
|
|
|
|
ChooseDevice();
|
|
|
|
// Initialize the 3D environment for the app
|
|
if( FAILED( hr = Initialize3DEnvironment() ) )
|
|
return Error("Couldn't initialize 3D environment", hr);
|
|
|
|
if (FAILED (hr = D3DXCreateMatrixStack(0, &m_matView)))
|
|
return false;
|
|
if (FAILED (hr = D3DXCreateMatrixStack(0, &m_matProj)))
|
|
return false;
|
|
D3DXMatrixIdentity(&m_TexMatrix[0]);
|
|
D3DXMatrixIdentity(&m_TexMatrix[1]);
|
|
D3DXMatrixIdentity(&m_TexMatrix[2]);
|
|
D3DXMatrixIdentity(&m_TexMatrix[3]);
|
|
|
|
RestoreDeviceObjects();
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CD3D9Renderer::mfAdjustWindowForChange()
|
|
// Desc: Prepare the window for a possible change between windowed mode and
|
|
// fullscreen mode. This function is virtual and thus can be overridden
|
|
// to provide different behavior, such as switching to an entirely
|
|
// different window for fullscreen mode (as in the MFC sample apps).
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CD3D9Renderer::AdjustWindowForChange()
|
|
{
|
|
if (m_bEditor)
|
|
return S_OK;
|
|
if( !m_bFullScreen )
|
|
{
|
|
// Set windowed-mode style
|
|
SetWindowLong( m_hWnd, GWL_STYLE, m_dwWindowStyle );
|
|
}
|
|
else
|
|
{
|
|
// Set fullscreen-mode style
|
|
SetWindowLong( m_hWnd, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CD3D9Renderer::InitDeviceObjects()
|
|
{
|
|
int i;
|
|
|
|
// Gamma correction support
|
|
if (m_d3dCaps.Caps2 & D3DCAPS2_FULLSCREENGAMMA)
|
|
m_Features |= RFT_HWGAMMA;
|
|
if (m_d3dCaps.Caps2 & D3DCAPS2_CANCALIBRATEGAMMA)
|
|
m_bGammaCalibrate = true;
|
|
else
|
|
m_bGammaCalibrate = false;
|
|
|
|
// Device Id's
|
|
D3DAdapterInfo *pAI = m_D3DSettings.PAdapterInfo();
|
|
D3DADAPTER_IDENTIFIER9 *ai = &pAI->AdapterIdentifier;
|
|
iLog->Log ( "D3D Adapter: Driver name: %s\n", ai->Driver);
|
|
iLog->Log ( "D3D Adapter: Driver description: %s\n", ai->Description);
|
|
iLog->Log ( "D3D Adapter: Driver version: %d.%02d.%02d.%04d\n", HIWORD( ai->DriverVersion.u.HighPart ), LOWORD( ai->DriverVersion.u.HighPart ), HIWORD(ai->DriverVersion.u.LowPart), LOWORD(ai->DriverVersion.u.LowPart));
|
|
// Unique driver/device identifier:
|
|
GUID *pGUID = &ai->DeviceIdentifier;
|
|
iLog->Log ( "D3D Adapter: Driver GUID: %08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X\n", pGUID->Data1, pGUID->Data2, pGUID->Data3, pGUID->Data4[0], pGUID->Data4[1], pGUID->Data4[2], pGUID->Data4[3], pGUID->Data4[4], pGUID->Data4[5], pGUID->Data4[6], pGUID->Data4[7] );
|
|
iLog->Log ( "D3D Adapter: VendorId = %i\n", ai->VendorId);
|
|
iLog->Log ( "D3D Adapter: DeviceId = %i\n", ai->DeviceId);
|
|
iLog->Log ( "D3D Adapter: SubSysId = %i\n", ai->SubSysId);
|
|
iLog->Log ( "D3D Adapter: Revision = %i\n", ai->Revision);
|
|
|
|
// Hardware-specific initialization and workarounds for driver bugs.
|
|
{
|
|
bool ConstrainAspect = 1;
|
|
if( CV_d3d9_nodeviceid )
|
|
{
|
|
iLog->Log ("D3D Detected: -nodeviceid specified, 3D device identification skipped\n");
|
|
}
|
|
else
|
|
if( ai->VendorId==4098 )
|
|
{
|
|
m_Features &= ~RFT_HW_MASK;
|
|
m_Features |= RFT_HW_RADEON;
|
|
iLog->Log ("D3D Detected: ATI video card\n");
|
|
if( ai->DeviceId==18242 )
|
|
{
|
|
iLog->Log ("D3D Detected: ATI Rage Pro\n");
|
|
}
|
|
else
|
|
if( ai->DeviceId==21062 )
|
|
{
|
|
iLog->Log ("D3D Detected: ATI Rage 128\n");
|
|
}
|
|
else
|
|
if( ai->DeviceId==20812 )
|
|
{
|
|
iLog->Log ("D3D Detected: ATI Radeon 8500\n");
|
|
}
|
|
else
|
|
if( ai->DeviceId==20036 )
|
|
{
|
|
iLog->Log ("D3D Detected: ATI Radeon 9700\n");
|
|
}
|
|
else
|
|
if( ai->DeviceId==0x4a49 )
|
|
{
|
|
iLog->Log ("D3D Detected: ATI Radeon X800 Pro\n");
|
|
}
|
|
if( ai->DeviceId==0x4a49 || ai->DeviceId==0x4a4a || ai->DeviceId==0x4a4b || ai->DeviceId==0x4a4c || ai->DeviceId==0x4a50 || ai->DeviceId==0x4a69 || ai->DeviceId==0x4a6a || ai->DeviceId==0x4a6b || ai->DeviceId==0x4a6c || ai->DeviceId==0x4a70 ||
|
|
ai->DeviceId==0x5b60 || ai->DeviceId==0x5b70 || ai->DeviceId==0x3e50 || ai->DeviceId==0x3e70 || ai->DeviceId==0x5549 || ai->DeviceId==0x5569 || ai->DeviceId==0x554b || ai->DeviceId==0x556b)
|
|
{
|
|
// Workaround for R42x to avoid terrain flickering
|
|
_SetVar("d3d9_VBPools", 0);
|
|
}
|
|
}
|
|
else
|
|
if( ai->VendorId==4634 )
|
|
{
|
|
iLog->Log ("D3D Detected: 3dfx video card\n");
|
|
if( ai->DeviceId==1 )
|
|
{
|
|
iLog->Log ("D3D Detected: 3dfx Voodoo\n");
|
|
}
|
|
else
|
|
if( ai->DeviceId==2 )
|
|
{
|
|
iLog->Log ("D3D Detected: 3dfx Voodoo2\n");
|
|
}
|
|
else
|
|
if( ai->DeviceId==3 )
|
|
{
|
|
iLog->Log ("D3D Detected: 3dfx Voodoo Banshee\n");
|
|
}
|
|
else
|
|
if( ai->DeviceId==5 )
|
|
{
|
|
iLog->Log ("D3D Detected: 3dfx Voodoo3\n");
|
|
}
|
|
}
|
|
else
|
|
if( ai->VendorId==32902 )
|
|
{
|
|
iLog->Log ("D3D Detected: Intel video card\n");
|
|
if( ai->DeviceId==30720 )
|
|
{
|
|
iLog->Log ("D3D Detected: Intel i740\n");
|
|
}
|
|
if( ai->DeviceId==7121 )
|
|
{
|
|
iLog->Log ("D3D Detected: Intel 810L\n");
|
|
}
|
|
if( ai->DeviceId==7123 )
|
|
{
|
|
iLog->Log ("D3D Detected: Intel 810 DC100\n");
|
|
}
|
|
if( ai->DeviceId==7125 )
|
|
{
|
|
iLog->Log ("D3D Detected: Intel 810E\n");
|
|
}
|
|
}
|
|
else
|
|
if( ai->VendorId==4818 )
|
|
{
|
|
iLog->Log ("D3D Detected: NVidia Riva video card\n");
|
|
if( ai->DeviceId==0x18 || ai->DeviceId==0x19 )
|
|
iLog->Log ("D3D Detected: Riva 128\n");
|
|
else
|
|
iLog->Log ("D3D Detected: Riva unknown\n");
|
|
}
|
|
else
|
|
if( ai->VendorId==4318 )
|
|
{
|
|
m_Features |= RFT_FOGVP;
|
|
iLog->Log ("D3D Detected: NVidia video card\n");
|
|
if( ai->DeviceId==0x20 )
|
|
{
|
|
iLog->Log ("D3D Detected: Riva TNT\n");
|
|
ConstrainAspect = 0;
|
|
}
|
|
if( ai->DeviceId==0x28 )
|
|
{
|
|
iLog->Log ("D3D Detected: Riva TNT2/TNT2 Pro\n");
|
|
ConstrainAspect = 0;
|
|
}
|
|
if( ai->DeviceId==0x29 )
|
|
{
|
|
iLog->Log ("D3D Detected: Riva TNT2 Ultra\n");
|
|
ConstrainAspect = 0;
|
|
}
|
|
if( ai->DeviceId==0x2c)
|
|
{
|
|
iLog->Log ("D3D Detected: Vanta/Vanta LT\n");
|
|
ConstrainAspect = 0;
|
|
}
|
|
if( ai->DeviceId==0x2d)
|
|
{
|
|
iLog->Log ("D3D Detected: Riva TNT2 Model 64/Model 64 Pro\n");
|
|
ConstrainAspect = 0;
|
|
}
|
|
if( ai->DeviceId==0x40 )
|
|
{
|
|
iLog->Log ("D3D Detected: Riva TNT2\n");
|
|
ConstrainAspect = 0;
|
|
}
|
|
if( ai->DeviceId==0xa0)
|
|
{
|
|
iLog->Log ("D3D Detected: Aladdin TNT2\n");
|
|
ConstrainAspect = 0;
|
|
}
|
|
if (ai->DeviceId == 0x100)
|
|
iLog->Log ("D3D Detected: GeForce 256 SDR\n");
|
|
if (ai->DeviceId == 0x101)
|
|
iLog->Log ("D3D Detected: GeForce 256 DDR\n");
|
|
if (ai->DeviceId == 0x103)
|
|
iLog->Log ("D3D Detected: Quadro\n");
|
|
if (ai->DeviceId == 0x110)
|
|
iLog->Log ("D3D Detected: GeForce2 MX/MX 400\n");
|
|
if (ai->DeviceId == 0x111)
|
|
iLog->Log ("D3D Detected: GeForce2 MX 100/200\n");
|
|
if (ai->DeviceId == 0x112)
|
|
iLog->Log ("D3D Detected: GeForce2 Go\n");
|
|
if (ai->DeviceId == 0x113)
|
|
iLog->Log ("D3D Detected: Quadro2 MXR/EX/Go\n");
|
|
if (ai->DeviceId == 0x150)
|
|
iLog->Log ("D3D Detected: GeForce2 GTS/GeForce2 Pro\n");
|
|
if (ai->DeviceId == 0x151)
|
|
iLog->Log ("D3D Detected: GeForce2 Ti\n");
|
|
if (ai->DeviceId == 0x152)
|
|
iLog->Log ("D3D Detected: GeForce2 Ultra\n");
|
|
if (ai->DeviceId == 0x153)
|
|
iLog->Log ("D3D Detected: Quadro2 Pro\n");
|
|
if (ai->DeviceId == 0x170)
|
|
iLog->Log ("D3D Detected: GeForce4 MX 460\n");
|
|
if (ai->DeviceId == 0x171)
|
|
iLog->Log ("D3D Detected: GeForce4 MX 440\n");
|
|
if (ai->DeviceId == 0x172)
|
|
iLog->Log ("D3D Detected: GeForce4 MX 420\n");
|
|
if (ai->DeviceId == 0x173)
|
|
iLog->Log ("D3D Detected: GeForce4 MX 440-SE\n");
|
|
if (ai->DeviceId == 0x174)
|
|
iLog->Log ("D3D Detected: GeForce4 440 Go\n");
|
|
if (ai->DeviceId == 0x175)
|
|
iLog->Log ("D3D Detected: GeForce4 420 Go\n");
|
|
if (ai->DeviceId == 0x176)
|
|
iLog->Log ("D3D Detected: GeForce4 420 Go 32M\n");
|
|
if (ai->DeviceId == 0x177)
|
|
iLog->Log ("D3D Detected: GeForce4 460 Go\n");
|
|
if (ai->DeviceId == 0x178)
|
|
iLog->Log ("D3D Detected: Quadro4 500 XGL\n");
|
|
if (ai->DeviceId == 0x179)
|
|
iLog->Log ("D3D Detected: GeForce4 440 Go 64M\n");
|
|
if (ai->DeviceId == 0x17a)
|
|
iLog->Log ("D3D Detected: Quadro4 200 NVS\n");
|
|
if (ai->DeviceId == 0x17c)
|
|
iLog->Log ("D3D Detected: Quadro4 500 GoGL\n");
|
|
if (ai->DeviceId == 0x17d)
|
|
iLog->Log ("D3D Detected: GeForce4 410 Go 16M\n");
|
|
if (ai->DeviceId == 0x181)
|
|
iLog->Log ("D3D Detected: GeForce4 MX 440 with AGP8X\n");
|
|
if (ai->DeviceId == 0x182)
|
|
iLog->Log ("D3D Detected: GeForce4 MX 440-SE with AGP8X\n");
|
|
if (ai->DeviceId == 0x183)
|
|
iLog->Log ("D3D Detected: GeForce4 MX 420 with AGP8X\n");
|
|
if (ai->DeviceId == 0x186)
|
|
iLog->Log ("D3D Detected: GeForce4 448 Go\n");
|
|
if (ai->DeviceId == 0x187)
|
|
iLog->Log ("D3D Detected: GeForce4 488 Go\n");
|
|
if (ai->DeviceId == 0x188)
|
|
iLog->Log ("D3D Detected: Quadro4 580 XGL\n");
|
|
if (ai->DeviceId == 0x18a)
|
|
iLog->Log ("D3D Detected: Quadro NVS with AGP8X\n");
|
|
if (ai->DeviceId == 0x18b)
|
|
iLog->Log ("D3D Detected: Quadro4 380 XGL\n");
|
|
if (ai->DeviceId == 0x1a0)
|
|
iLog->Log ("D3D Detected: GeForce2 Integrated GPU\n");
|
|
if (ai->DeviceId == 0x1f0)
|
|
iLog->Log ("D3D Detected: GeForce4 MX Integrated GPU\n");
|
|
|
|
if (ai->DeviceId == 0x200)
|
|
iLog->Log ("D3D Detected: GeForce3\n");
|
|
if (ai->DeviceId == 0x201)
|
|
iLog->Log ("D3D Detected: GeForce3 Ti 200\n");
|
|
if (ai->DeviceId == 0x202)
|
|
iLog->Log ("D3D Detected: GeForce3 Ti 500\n");
|
|
if (ai->DeviceId == 0x203)
|
|
iLog->Log ("D3D Detected: Quadro DCC\n");
|
|
if (ai->DeviceId == 0x250)
|
|
iLog->Log ("D3D Detected: GeForce4 Ti 4600\n");
|
|
if (ai->DeviceId == 0x251)
|
|
iLog->Log ("D3D Detected: GeForce4 Ti 4400\n");
|
|
if (ai->DeviceId == 0x251)
|
|
iLog->Log ("D3D Detected: NV25\n");
|
|
if (ai->DeviceId == 0x253)
|
|
iLog->Log ("D3D Detected: GeForce4 Ti 4200\n");
|
|
if (ai->DeviceId == 0x258)
|
|
iLog->Log ("D3D Detected: Quadro4 900 XGL\n");
|
|
if (ai->DeviceId == 0x259)
|
|
iLog->Log ("D3D Detected: Quadro4 750 XGL\n");
|
|
if (ai->DeviceId == 0x25b)
|
|
iLog->Log ("D3D Detected: Quadro4 700 XGL\n");
|
|
if (ai->DeviceId == 0x280)
|
|
iLog->Log ("D3D Detected: GeForce4 TI4800\n");
|
|
if (ai->DeviceId == 0x281)
|
|
iLog->Log ("D3D Detected: GeForce4 TI4200 with AGP8X\n");
|
|
if (ai->DeviceId == 0x282)
|
|
iLog->Log ("D3D Detected: GeForce4 TI4800 SE\n");
|
|
if (ai->DeviceId == 0x286)
|
|
iLog->Log ("D3D Detected: GeForce4 4200 Go\n");
|
|
if (ai->DeviceId == 0x288)
|
|
iLog->Log ("D3D Detected: Quadro4 980 XGL\n");
|
|
if (ai->DeviceId == 0x289)
|
|
iLog->Log ("D3D Detected: Quadro4 780 XGL\n");
|
|
if (ai->DeviceId == 0x28c)
|
|
iLog->Log ("D3D Detected: Quadro4 700 GoGL\n");
|
|
|
|
if (ai->DeviceId == 0x300)
|
|
iLog->Log ("D3D Detected: GeForce FX 5800\n");
|
|
if (ai->DeviceId == 0x301)
|
|
iLog->Log ("D3D Detected: GeForce FX 5800 Ultra\n");
|
|
if (ai->DeviceId == 0x302)
|
|
iLog->Log ("D3D Detected: GeForce FX 5800\n");
|
|
if (ai->DeviceId == 0x308)
|
|
iLog->Log ("D3D Detected: QuadroFX 2000\n");
|
|
if (ai->DeviceId == 0x309)
|
|
iLog->Log ("D3D Detected: QuadroFX 1000\n");
|
|
if (ai->DeviceId == 0x30a)
|
|
iLog->Log ("D3D Detected: ICE FX 2000\n");
|
|
if (ai->DeviceId == 0x311)
|
|
iLog->Log ("D3D Detected: GeForce FX 5600 Ultra\n");
|
|
if (ai->DeviceId == 0x312)
|
|
iLog->Log ("D3D Detected: GeForce FX 5600\n");
|
|
if (ai->DeviceId == 0x313)
|
|
iLog->Log ("D3D Detected: NV31\n");
|
|
if (ai->DeviceId == 0x314)
|
|
iLog->Log ("D3D Detected: GeForce FX 5600SE\n");
|
|
if (ai->DeviceId == 0x316)
|
|
iLog->Log ("D3D Detected: NV31M\n");
|
|
if (ai->DeviceId == 0x317)
|
|
iLog->Log ("D3D Detected: NV31M Pro\n");
|
|
if (ai->DeviceId == 0x31a)
|
|
iLog->Log ("D3D Detected: GeForce FX Go5600\n");
|
|
if (ai->DeviceId == 0x31b)
|
|
iLog->Log ("D3D Detected: GeForce FX Go5650\n");
|
|
if (ai->DeviceId == 0x31c)
|
|
iLog->Log ("D3D Detected: Quadro FX Go700\n");
|
|
if (ai->DeviceId == 0x31d)
|
|
iLog->Log ("D3D Detected: NV31GLM\n");
|
|
if (ai->DeviceId == 0x31e)
|
|
iLog->Log ("D3D Detected: NV31GLM Pro\n");
|
|
if (ai->DeviceId == 0x31f)
|
|
iLog->Log ("D3D Detected: NV31GLM Pro\n");
|
|
if (ai->DeviceId == 0x321)
|
|
iLog->Log ("D3D Detected: GeForce FX 5200 Ultra\n");
|
|
if (ai->DeviceId == 0x322)
|
|
iLog->Log ("D3D Detected: GeForce FX 5200\n");
|
|
if (ai->DeviceId == 0x323)
|
|
iLog->Log ("D3D Detected: GeForce FX 5200SE\n");
|
|
if (ai->DeviceId == 0x324)
|
|
iLog->Log ("D3D Detected: GeForce FX Go5200\n");
|
|
if (ai->DeviceId == 0x325)
|
|
iLog->Log ("D3D Detected: GeForce FX Go5250\n");
|
|
if (ai->DeviceId == 0x328)
|
|
iLog->Log ("D3D Detected: GeForce FX Go5200 32M/64M\n");
|
|
if (ai->DeviceId == 0x32a)
|
|
iLog->Log ("D3D Detected: NV34GL\n");
|
|
if (ai->DeviceId == 0x32b)
|
|
iLog->Log ("D3D Detected: Quadro FX 500\n");
|
|
if (ai->DeviceId == 0x32d)
|
|
iLog->Log ("D3D Detected: GeForce FX Go5100\n");
|
|
if (ai->DeviceId == 0x32f)
|
|
iLog->Log ("D3D Detected: NV34GL\n");
|
|
if (ai->DeviceId == 0x330)
|
|
iLog->Log ("D3D Detected: GeForce FX 5900 Ultra\n");
|
|
if (ai->DeviceId == 0x331)
|
|
iLog->Log ("D3D Detected: GeForce FX 5900\n");
|
|
if (ai->DeviceId == 0x332)
|
|
iLog->Log ("D3D Detected: NV35\n");
|
|
|
|
if (ai->DeviceId <= 0x40 && ai->DeviceId <= 0x4f)
|
|
iLog->Log ("D3D Detected: NV4X\n");
|
|
}
|
|
else
|
|
if( ai->VendorId==4818 )
|
|
{
|
|
iLog->Log ("D3D Detected: NVidia video card\n");
|
|
if( ai->DeviceId==0x18 || ai->DeviceId==0x19)
|
|
{
|
|
iLog->Log ("D3D Detected: Riva 128\n");
|
|
ConstrainAspect = 0;
|
|
}
|
|
}
|
|
else
|
|
if( ai->VendorId==4139 )
|
|
{
|
|
iLog->Log ("D3D Detected: Matrox video card\n");
|
|
if( ai->DeviceId==1313 )
|
|
iLog->Log ("D3D Detected: Matrox G200\n");
|
|
else
|
|
if( ai->DeviceId==1317 )
|
|
iLog->Log ("D3D Detected: Matrox G400\n");
|
|
//G400 lies about texture stages, last one is for bump only
|
|
}
|
|
else
|
|
if( ai->VendorId==0x18ca )
|
|
{
|
|
m_Features &= ~RFT_HW_MASK;
|
|
m_Features |= RFT_HW_RADEON;
|
|
iLog->Log ("D3D Detected: XGI video card\n");
|
|
if( ai->DeviceId==0x40 )
|
|
iLog->Log ("D3D Detected: XGI Volary V8 DUO Ultra\n");
|
|
else
|
|
iLog->Log ("D3D Detected: XGI Unknown\n");
|
|
//G400 lies about texture stages, last one is for bump only
|
|
}
|
|
else
|
|
{
|
|
iLog->Log ("D3D Detected: Generic 3D accelerator\n");
|
|
// Hack for NVidia DualView
|
|
if (!strnicmp(ai->Description, "NVIDIA", 6))
|
|
m_Features |= RFT_FOGVP;
|
|
}
|
|
}
|
|
|
|
if (m_d3dCaps.PS20Caps.NumInstructionSlots >= 256 && (D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) >= 2))
|
|
m_bDeviceSupports_PS2X = true;
|
|
|
|
// Set viewport.
|
|
SetViewport(0,0,CRenderer::m_width, CRenderer::m_height);
|
|
|
|
// Check multitexture caps.
|
|
iLog->Log ( "D3D Driver: MaxTextureBlendStages = %i\n", m_d3dCaps.MaxTextureBlendStages);
|
|
iLog->Log ( "D3D Driver: MaxSimultaneousTextures = %i\n", m_d3dCaps.MaxSimultaneousTextures);
|
|
if( m_d3dCaps.MaxSimultaneousTextures>=2 )
|
|
m_Features |= RFT_MULTITEXTURE;
|
|
|
|
// Handle the texture formats we need.
|
|
{
|
|
// Zero them all.
|
|
mFormatA8.Init(); // A
|
|
mFormatA8L8.Init(); // A8L8
|
|
mFormat8888.Init(); // BGRA
|
|
mFormat4444.Init(); // BGRA
|
|
mFormat0565.Init(); // BGR
|
|
mFormat0555.Init(); // BGR
|
|
mFormat1555.Init(); // BGRA
|
|
mFormatV8U8.Init(); // Bump
|
|
mFormatCxV8U8.Init(); // Bump
|
|
mFormatU5V5L6.Init(); // Bump
|
|
mFormat3Dc.Init(); // 3Dc
|
|
mFormatDXT1.Init(); // DXT1
|
|
mFormatDXT3.Init(); // DXT3
|
|
mFormatDXT5.Init(); // DXT5
|
|
mFormatPal8.Init(); // Paletted8
|
|
mFormatDepth24.Init(); // Depth teture
|
|
mFormatDepth16.Init(); // Depth teture
|
|
|
|
// Find the needed texture formats.
|
|
{
|
|
mFirstPixelFormat = NULL;
|
|
if(m_TextureBits >= 24)
|
|
{
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8)))
|
|
RecognizePixelFormat(mFormat8888, D3DFMT_A8R8G8B8, 32, "8888");
|
|
}
|
|
if( !mFirstPixelFormat )
|
|
{
|
|
m_TextureBits = 16;
|
|
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_A1R5G5B5)))
|
|
RecognizePixelFormat(mFormat1555, D3DFMT_A1R5G5B5, 16, "1555");
|
|
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_A4R4G4B4)))
|
|
RecognizePixelFormat(mFormat4444, D3DFMT_A4R4G4B4, 16, "4444");
|
|
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_R5G6B5)))
|
|
RecognizePixelFormat(mFormat0565, D3DFMT_R5G6B5, 16, "0565");
|
|
else
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_X1R5G5B5)))
|
|
RecognizePixelFormat(mFormat0555, D3DFMT_X1R5G5B5, 16, "0555");
|
|
}
|
|
// Alpha formats
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_A8)))
|
|
RecognizePixelFormat(mFormatA8, D3DFMT_A8, 8, "Alpha8");
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)))
|
|
RecognizePixelFormat(mFormatA8L8, D3DFMT_A8L8, 16, "Alpha8Lum8");
|
|
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_V16U16)))
|
|
RecognizePixelFormat(mFormatU16V16, D3DFMT_V16U16, 32, "V16U16");
|
|
|
|
// Depth formats
|
|
if (CV_d3d9_forcesoftware)
|
|
m_Features |= RFT_DEPTHMAPS;
|
|
else
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_D24S8)))
|
|
{
|
|
m_Features |= RFT_DEPTHMAPS;
|
|
RecognizePixelFormat(mFormatDepth24, D3DFMT_D24S8, 8, "Depth24");
|
|
}
|
|
else
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_D16)))
|
|
{
|
|
m_Features |= RFT_DEPTHMAPS;
|
|
RecognizePixelFormat(mFormatDepth16, D3DFMT_D16, 8, "Depth16");
|
|
}
|
|
//// REMOVED DRIVER HACK -- Carsten
|
|
// // Workaround for NVidia drivers less than 61.00
|
|
// // Depth maps are working extremely bad on rel5X drivers
|
|
// if (LOWORD(ai->DriverVersion.u.LowPart) < 6100)
|
|
// {
|
|
// ICVar *pVar = iConsole->GetCVar("d3d9_NoDepthMaps");
|
|
// if (pVar)
|
|
// pVar->Set(1);
|
|
// }
|
|
if (CV_r_shadowtype == 1 || CV_d3d9_nodepthmaps)
|
|
m_Features &= ~RFT_DEPTHMAPS;
|
|
|
|
// Bump formats
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_V8U8)))
|
|
{
|
|
RecognizePixelFormat(mFormatV8U8, D3DFMT_V8U8, 16, "BumpV8U8");
|
|
m_bDeviceSupportsComprNormalmaps = 2;
|
|
}
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_CxV8U8)))
|
|
{
|
|
RecognizePixelFormat(mFormatCxV8U8, D3DFMT_CxV8U8, 16, "BumpCxV8U8");
|
|
//m_bDeviceSupportsComprNormalmaps = 3;
|
|
}
|
|
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_Q8W8V8U8)))
|
|
RecognizePixelFormat(mFormatQ8W8U8V8, D3DFMT_Q8W8V8U8, 32, "BumpQ8W8U8V8");
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8)))
|
|
RecognizePixelFormat(mFormatX8L8U8V8, D3DFMT_X8L8V8U8, 32, "BumpX8L8U8V8");
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_L6V5U5)))
|
|
RecognizePixelFormat(mFormatU5V5L6, D3DFMT_L6V5U5, 16, "BumpU5V5L6");
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, (D3DFORMAT)(MAKEFOURCC('A', 'T', 'I', '2')))))
|
|
{
|
|
RecognizePixelFormat(mFormat3Dc, (D3DFORMAT)(MAKEFOURCC('A', 'T', 'I', '2')), 16, "3Dc");
|
|
m_bDeviceSupportsComprNormalmaps = 1;
|
|
}
|
|
|
|
// Paletted formats
|
|
if (CV_d3d9_palettedtextures)
|
|
{
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_P8)))
|
|
{
|
|
RecognizePixelFormat(mFormatPal8, D3DFMT_P8, 8, "Paletted8");
|
|
m_Features |= RFT_PALTEXTURE;
|
|
}
|
|
}
|
|
|
|
// Compressed formats
|
|
if (CV_d3d9_compressedtextures)
|
|
{
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)))
|
|
{
|
|
RecognizePixelFormat(mFormatDXT1, D3DFMT_DXT1, 8, "DXT1");
|
|
m_Features |= RFT_COMPRESSTEXTURE;
|
|
}
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)))
|
|
{
|
|
RecognizePixelFormat(mFormatDXT3, D3DFMT_DXT3, 8, "DXT3");
|
|
m_Features |= RFT_COMPRESSTEXTURE;
|
|
}
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)))
|
|
{
|
|
RecognizePixelFormat(mFormatDXT5, D3DFMT_DXT5, 8, "DXT5");
|
|
m_Features |= RFT_COMPRESSTEXTURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Verify mipmapping supported.
|
|
if (!(m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP))
|
|
{
|
|
iLog->Log ("D3D Driver: Mipmapping not available with this driver\n");
|
|
//m_Features |= RFT_NOMIPS;
|
|
}
|
|
else
|
|
{
|
|
if( m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR )
|
|
iLog->Log ("D3D Driver: Supports trilinear texture filtering\n");
|
|
}
|
|
|
|
if (!(m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_NOPROJECTEDBUMPENV))
|
|
{
|
|
iLog->Log ("D3D Driver: Allowed projected textures with Env. bump mapping\n");
|
|
m_Features |= RFT_HW_ENVBUMPPROJECTED;
|
|
}
|
|
else
|
|
iLog->Log ("D3D Driver: projected textures with Env. bump mapping not allowed\n");
|
|
|
|
if( m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE )
|
|
{
|
|
iLog->Log ("D3D Driver: Supports alpha palettes\n");
|
|
m_bAllowAlphaPalettes = true;
|
|
}
|
|
if( m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
|
|
{
|
|
m_d3dCaps.MaxTextureAspectRatio = 1;
|
|
iLog->Log ("D3D Driver: Requires square textures\n");
|
|
}
|
|
else
|
|
if( !m_d3dCaps.MaxTextureAspectRatio )
|
|
m_d3dCaps.MaxTextureAspectRatio = max(1,max(m_d3dCaps.MaxTextureWidth,m_d3dCaps.MaxTextureHeight));
|
|
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE )
|
|
iLog->Log ("D3D Driver: Supports range-based fog\n");
|
|
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_WFOG )
|
|
iLog->Log ("D3D Driver: Supports eye-relative fog\n");
|
|
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY )
|
|
iLog->Log ("D3D Driver: Supports anisotropic filtering\n");
|
|
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS )
|
|
iLog->Log ("D3D Driver: Supports LOD biasing\n");
|
|
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_DEPTHBIAS )
|
|
iLog->Log ("D3D Driver: Supports Z biasing\n");
|
|
else
|
|
m_Features &= ~RFT_SUPPORTZBIAS;
|
|
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
|
|
iLog->Log ("D3D Driver: Device can perform hidden-surface removal (HSR)\n");
|
|
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST )
|
|
iLog->Log ("D3D Driver: Supports scissor test\n");
|
|
if (m_d3dCaps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET)
|
|
iLog->Log ("D3D Driver: Supports stream offset\n");
|
|
|
|
if( !(m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_POW2) )
|
|
iLog->Log ("D3D Driver: Supports non-power-of-2 textures\n");
|
|
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_ADDSIGNED2X )
|
|
iLog->Log ("D3D Driver: Supports D3DTOP_ADDSIGNED2X TextureOp\n");
|
|
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP )
|
|
iLog->Log ("D3D Driver: Supports D3DTOP_BUMPENVMAP TextureOp\n");
|
|
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAPLUMINANCE )
|
|
iLog->Log ("D3D Driver: Supports D3DTOP_BUMPENVMAPLUMINANCE TextureOp\n");
|
|
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3 )
|
|
iLog->Log ("D3D Driver: Supports D3DTOP_DOTPRODUCT3 TextureOp\n");
|
|
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR )
|
|
iLog->Log ("D3D Driver: Supports D3DTOP_MODULATEALPHA_ADDCOLOR TextureOp\n");
|
|
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA )
|
|
iLog->Log ("D3D Driver: Supports D3DTOP_MODULATECOLOR_ADDALPHA TextureOp\n");
|
|
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_ADD )
|
|
iLog->Log ("D3D Driver: Supports D3DTOP_ADD TextureOp\n");
|
|
|
|
m_MaxAnisotropyLevel = 1;
|
|
m_AnisotropyLevel = 1;
|
|
// Check the device for supported filtering methods
|
|
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY )
|
|
{
|
|
m_MaxAnisotropyLevel = m_AnisotropyLevel = m_d3dCaps.MaxAnisotropy;
|
|
iLog->Log ("D3D Driver: Supports MaxAnisotropy level %d\n", m_AnisotropyLevel);
|
|
m_Features |= RFT_ALLOWANISOTROPIC;
|
|
}
|
|
if( m_d3dCaps.StencilCaps & (D3DSTENCILCAPS_KEEP|D3DSTENCILCAPS_INCR|D3DSTENCILCAPS_DECR) )
|
|
{
|
|
iLog->Log ("D3D Driver: Supports Stencil shadows\n");
|
|
if( m_d3dCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED)
|
|
iLog->Log ("D3D Driver: Supports Two-Sided stencil\n");
|
|
}
|
|
else
|
|
CRenderer::m_sbpp = 0;
|
|
|
|
iLog->Log ("D3D Driver: Textures (%ix%i)-(%ix%i), Max aspect %i\n", mMinTextureWidth, mMinTextureHeight, m_d3dCaps.MaxTextureWidth, m_d3dCaps.MaxTextureHeight, m_d3dCaps.MaxTextureAspectRatio );
|
|
|
|
// Depth buffering.
|
|
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
|
|
/*if ( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_WBUFFER )
|
|
{
|
|
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_USEW );
|
|
m_bUseWBuffer = true;
|
|
iLog->Log ("D3D Driver: Supports w-buffering\n");
|
|
}
|
|
else*/
|
|
m_bUseWBuffer = false;
|
|
|
|
m_Features &= ~RFT_BUMP;
|
|
if( CV_d3d9_usebumpmap && (GetFeatures() & RFT_MULTITEXTURE))
|
|
{
|
|
if ((m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) && (m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP))
|
|
m_Features |= RFT_BUMP;
|
|
}
|
|
|
|
// Init render states.
|
|
{
|
|
m_pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
|
m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
|
|
m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
|
|
m_pd3dDevice->SetRenderState( D3DRS_COLORVERTEX, TRUE );
|
|
D3DSetCull(eCULL_None);
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 127 );
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATER );
|
|
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_DEPTHBIAS )
|
|
m_pd3dDevice->SetRenderState( D3DRS_DEPTHBIAS, 0 );
|
|
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
|
|
m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
|
|
m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE);
|
|
m_pd3dDevice->SetRenderState( D3DRS_FOGCOLOR, 0 );
|
|
m_pd3dDevice->SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_NONE );
|
|
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
|
|
m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE);
|
|
m_pd3dDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
|
|
m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, FALSE );
|
|
m_pd3dDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE );
|
|
//m_pd3dDevice->SetBackBufferScale(1.0f, 1.0f);
|
|
m_pd3dDevice->SetPixelShader( NULL );
|
|
m_pd3dDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );
|
|
m_pd3dDevice->SetRenderState( D3DRS_POINTSCALEENABLE, FALSE );
|
|
m_pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, FALSE );
|
|
m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );
|
|
m_FS.m_bEnable = false;
|
|
|
|
// Set default stencil states
|
|
m_CurStencilState = 0;
|
|
m_CurStencMask = 0xffffffff;
|
|
m_CurStencRef = 0;
|
|
m_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
|
if (m_d3dCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED)
|
|
{
|
|
m_pd3dDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP);
|
|
m_pd3dDevice->SetRenderState(D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP);
|
|
m_pd3dDevice->SetRenderState(D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP);
|
|
m_pd3dDevice->SetRenderState(D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS);
|
|
}
|
|
m_pd3dDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);
|
|
m_pd3dDevice->SetRenderState(D3DRS_STENCILREF, 0);
|
|
|
|
m_pd3dDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
|
|
m_pd3dDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
|
|
m_pd3dDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
|
|
m_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
|
|
}
|
|
|
|
msCurState = GS_DEPTHWRITE | GS_NODEPTHTEST;
|
|
for (i=0; i<MAX_TMU; i++)
|
|
{
|
|
m_eCurColorOp[i] = eCO_DISABLE;
|
|
m_eCurColorArg[i] = 255;
|
|
m_eCurAlphaArg[i] = 255;
|
|
}
|
|
|
|
// Init texture stage state.
|
|
{
|
|
//FLOAT LodBias=-0.5;
|
|
//m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)&LodBias );
|
|
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP );
|
|
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP );
|
|
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
|
|
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
|
|
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
|
|
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
|
|
m_RP.m_TexStages[0].MinFilter = D3DTEXF_LINEAR;
|
|
m_RP.m_TexStages[0].MagFilter = D3DTEXF_LINEAR;
|
|
m_RP.m_TexStages[0].nMipFilter = D3DTEXF_LINEAR;
|
|
m_RP.m_TexStages[0].TCIndex = 0;
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
|
|
|
{
|
|
if( GetFeatures() & RFT_MULTITEXTURE )
|
|
{
|
|
for( i=1; i<(int)m_d3dCaps.MaxSimultaneousTextures; i++ )
|
|
{
|
|
m_TexMan->m_CurStage = i;
|
|
|
|
// Set stage i state.
|
|
m_pd3dDevice->SetSamplerState( i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP );
|
|
m_pd3dDevice->SetSamplerState( i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP );
|
|
EF_SetColorOp(eCO_DISABLE, eCO_DISABLE, DEF_TEXARG1, DEF_TEXARG1);
|
|
m_pd3dDevice->SetSamplerState( i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
|
|
m_pd3dDevice->SetSamplerState( i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
|
|
m_pd3dDevice->SetSamplerState( i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
|
|
m_pd3dDevice->SetTextureStageState( i, D3DTSS_TEXCOORDINDEX, i );
|
|
m_RP.m_TexStages[i].MinFilter = D3DTEXF_LINEAR;
|
|
m_RP.m_TexStages[i].MagFilter = D3DTEXF_LINEAR;
|
|
m_RP.m_TexStages[i].nMipFilter = D3DTEXF_LINEAR;
|
|
m_RP.m_TexStages[0].TCIndex = i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check to see if device supports visibility query
|
|
if (!CV_d3d9_occlusion_query || D3DERR_NOTAVAILABLE == m_pd3dDevice->CreateQuery (D3DQUERYTYPE_OCCLUSION, NULL))
|
|
m_Features &= ~RFT_OCCLUSIONTEST;
|
|
else
|
|
m_Features |= RFT_OCCLUSIONTEST;
|
|
|
|
m_TexMan->m_CurStage = 0;
|
|
m_TexMan->SetFilter(CV_d3d9_texturefilter->GetString());
|
|
|
|
// For safety, lots of drivers don't handle tiny texture sizes too tell.
|
|
mMinTextureWidth = 8;
|
|
mMinTextureHeight = 8;
|
|
m_MaxTextureMemory = m_pd3dDevice->GetAvailableTextureMem();
|
|
if (CRenderer::CV_r_texturesstreampoolsize <= 0)
|
|
CRenderer::CV_r_texturesstreampoolsize = (int)(m_MaxTextureMemory/1024.0f/1024.0f*0.75f);
|
|
|
|
m_MaxTextureSize = min(m_d3dCaps.MaxTextureHeight, m_d3dCaps.MaxTextureWidth); //min(wdt, hgt);
|
|
|
|
m_Features &= ~RFT_DEPTHMAPS;
|
|
if (m_d3dCaps.MaxSimultaneousTextures <= 2)
|
|
{
|
|
m_Features &= ~RFT_HW_MASK;
|
|
m_Features |= RFT_HW_GF2;
|
|
}
|
|
else
|
|
{
|
|
if (m_d3dCaps.MaxSimultaneousTextures == 4 && D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) == 1)
|
|
{
|
|
m_Features &= ~RFT_HW_MASK;
|
|
m_Features |= RFT_HW_GF3;
|
|
if (ai->VendorId==4318 && !CV_d3d9_nodepthmaps)
|
|
m_Features |= RFT_DEPTHMAPS;
|
|
}
|
|
else
|
|
if( ai->VendorId==4318 )
|
|
{
|
|
if (m_d3dCaps.MaxSimultaneousTextures >= 8 && (D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) >= 3 || (D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) >= 2 && D3DSHADER_VERSION_MINOR(m_d3dCaps.PixelShaderVersion) >= 1)))
|
|
{
|
|
m_Features &= ~RFT_HW_MASK;
|
|
m_Features |= RFT_HW_NV4X;
|
|
}
|
|
else
|
|
if (m_d3dCaps.MaxSimultaneousTextures >= 8 && D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) >= 2)
|
|
{
|
|
m_Features &= ~RFT_HW_MASK;
|
|
m_Features |= RFT_HW_GFFX;
|
|
}
|
|
else
|
|
{
|
|
m_Features &= ~RFT_HW_MASK;
|
|
m_Features |= RFT_HW_GF3;
|
|
}
|
|
if (!CV_d3d9_nodepthmaps)
|
|
m_Features |= RFT_DEPTHMAPS;
|
|
if (m_bDeviceSupportsComprNormalmaps == 1)
|
|
{
|
|
iLog->Log ("Warning: Disabled 3DC for NVidia card\n");
|
|
if (mFormatV8U8.BitsPerPixel)
|
|
m_bDeviceSupportsComprNormalmaps = 2;
|
|
}
|
|
}
|
|
else
|
|
if (m_d3dCaps.MaxSimultaneousTextures >= 8 && D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) >= 2)
|
|
{
|
|
m_Features &= ~RFT_HW_MASK;
|
|
m_Features |= RFT_HW_RADEON;
|
|
}
|
|
else
|
|
if (!(m_Features & RFT_HW_MASK))
|
|
m_Features |= RFT_HW_GF3;
|
|
}
|
|
if (m_d3dCaps.MaxSimultaneousTextures >= 4 && D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) >= 1)
|
|
m_Features |= RFT_HW_TS | RFT_HW_VS;
|
|
|
|
m_bDeviceSupportsInstancing = (D3DSHADER_VERSION_MAJOR(m_d3dCaps.VertexShaderVersion) >= 3);
|
|
if (!m_bDeviceSupportsInstancing)
|
|
{
|
|
D3DFORMAT instanceSupport = (D3DFORMAT)MAKEFOURCC('I', 'N', 'S', 'T');
|
|
if(SUCCEEDED(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, instanceSupport)))
|
|
{
|
|
m_bDeviceSupportsInstancing = 2;
|
|
// Notify the driver that instancing support is expected
|
|
m_pd3dDevice->SetRenderState(D3DRS_POINTSIZE, instanceSupport);
|
|
}
|
|
}
|
|
m_bDeviceSupportsMRT = (m_d3dCaps.NumSimultaneousRTs>=4) && SUCCEEDED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_G16R16F));
|
|
|
|
//// REMOVED DRIVER HACK -- Carsten
|
|
//// Workaround for NVidia drivers less than 66.00
|
|
// // Don't use MRT on old drivers
|
|
// if (LOWORD(ai->DriverVersion.u.LowPart) < 6600)
|
|
// {
|
|
// m_bDeviceSupportsMRT = 0;
|
|
// }
|
|
|
|
m_bDeviceSupportsFP16Filter = true;
|
|
if(FAILED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)))
|
|
m_bDeviceSupportsFP16Filter = false;
|
|
if(FAILED(m_pD3D->CheckDeviceFormat(pAI->AdapterOrdinal, m_d3dCaps.DeviceType, m_D3DSettings.AdapterFormat(), D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_G16R16F)))
|
|
m_bDeviceSupportsFP16Filter = false;
|
|
|
|
int nHDRSupported = 1;
|
|
{
|
|
// Check support for HDR rendering
|
|
D3DDeviceCombo *pDev = m_D3DSettings.PDeviceCombo();
|
|
m_HDR_FloatFormat_Scalar = D3DFMT_R16F;
|
|
if (CV_r_Quality_BumpMapping < 3)
|
|
nHDRSupported = 0;
|
|
else
|
|
if(FAILED(m_pD3D->CheckDeviceFormat(pDev->AdapterOrdinal, pDev->DevType, pDev->AdapterFormat, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)))
|
|
nHDRSupported = 0;
|
|
else
|
|
if(FAILED(m_pD3D->CheckDeviceFormat(pDev->AdapterOrdinal, pDev->DevType, pDev->AdapterFormat, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_SURFACE, D3DFMT_A16B16G16R16F)))
|
|
nHDRSupported = 0;
|
|
else
|
|
if(FAILED(m_pD3D->CheckDeviceFormat(pDev->AdapterOrdinal, pDev->DevType, pDev->AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R16F)))
|
|
{
|
|
m_HDR_FloatFormat_Scalar = D3DFMT_R32F;
|
|
if(FAILED(m_pD3D->CheckDeviceFormat(pDev->AdapterOrdinal, pDev->DevType, pDev->AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R32F)))
|
|
nHDRSupported = 0;
|
|
}
|
|
if (D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) < 2)
|
|
nHDRSupported = 0;
|
|
}
|
|
if (!nHDRSupported && m_d3dCaps.NumSimultaneousRTs>=2 && (m_d3dCaps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING) &&
|
|
D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) >= 2 &&
|
|
CV_r_Quality_BumpMapping >= 3)
|
|
nHDRSupported = 2;
|
|
if (nHDRSupported == 2 || CV_r_Quality_BumpMapping < 3)
|
|
nHDRSupported = 0;
|
|
if (!nHDRSupported)
|
|
{
|
|
#ifdef USE_HDR
|
|
_SetVar("r_HDRRendering", 0);
|
|
#endif
|
|
m_Features &= ~RFT_HW_HDR;
|
|
}
|
|
else
|
|
m_Features |= RFT_HW_HDR;
|
|
m_nHDRType = nHDRSupported;
|
|
|
|
float fColor[4];
|
|
fColor[0] = fColor[1] = fColor[2] = fColor[3] = 0;
|
|
EF_ClearBuffers(true, false, fColor);
|
|
|
|
m_pd3dDevice->BeginScene();
|
|
m_SceneRecurseCount++;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CD3D9Renderer::RecognizePixelFormat(SPixFormat& Dest, D3DFORMAT FromD3D, INT InBitsPerPixel, const TCHAR* InDesc)
|
|
{
|
|
Dest.Init();
|
|
Dest.Format = FromD3D;
|
|
Dest.MaxWidth = m_d3dCaps.MaxTextureWidth;
|
|
Dest.MaxHeight = m_d3dCaps.MaxTextureHeight;
|
|
Dest.Desc = InDesc;
|
|
Dest.BitsPerPixel = InBitsPerPixel;
|
|
Dest.Next = mFirstPixelFormat;
|
|
mFirstPixelFormat = &Dest;
|
|
|
|
iLog->Log(" Using '%s' pixel texture format\n", InDesc);
|
|
}
|
|
|