This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/ww3d2/dx8wrapper.cpp

3342 lines
No EOL
102 KiB
C++

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/dx8wrapper.cpp $*
* *
* Original Author:: Jani Penttinen *
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 3/12/02 4:27p $*
* *
* $Revision:: 170 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* DX8Wrapper::_Update_Texture -- Copies a texture from system memory to video memory *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//#define CREATE_DX8_MULTI_THREADED
//#define CREATE_DX8_FPU_PRESERVE
#define WW3D_DEVTYPE D3DDEVTYPE_HAL
#include "dx8wrapper.h"
#include "dx8fvf.h"
#include "dx8vertexbuffer.h"
#include "dx8indexbuffer.h"
#include "dx8renderer.h"
#include "ww3d.h"
#include "camera.h"
#include "wwstring.h"
#include "matrix4.h"
#include "vertmaterial.h"
#include "rddesc.h"
#include "lightenvironment.h"
#include "statistics.h"
#include "registry.h"
#include "boxrobj.h"
#include "pointgr.h"
#include "render2d.h"
#include "sortingrenderer.h"
#include "shattersystem.h"
#include "light.h"
#include "assetmgr.h"
#include "textureloader.h"
#include "missingtexture.h"
#include "thread.h"
#include <stdio.h>
#include <D3dx8core.h>
#include "pot.h"
#include "wwprofile.h"
#include "ffactory.h"
#include "dx8caps.h"
#include "formconv.h"
#include "dx8texman.h"
#include "bound.h"
const int DEFAULT_RESOLUTION_WIDTH = 800;
const int DEFAULT_RESOLUTION_HEIGHT = 600;
const int DEFAULT_BIT_DEPTH = 32;
const int DEFAULT_TEXTURE_BIT_DEPTH = 16;
/***********************************************************************************
**
** DX8Wrapper Static Variables
**
***********************************************************************************/
static HWND _Hwnd = NULL;
bool DX8Wrapper::IsInitted = false;
bool DX8Wrapper::_EnableTriangleDraw = true;
int DX8Wrapper::CurRenderDevice = -1;
int DX8Wrapper::ResolutionWidth = DEFAULT_RESOLUTION_WIDTH;
int DX8Wrapper::ResolutionHeight = DEFAULT_RESOLUTION_HEIGHT;
int DX8Wrapper::BitDepth = DEFAULT_BIT_DEPTH;
int DX8Wrapper::TextureBitDepth = DEFAULT_TEXTURE_BIT_DEPTH;
bool DX8Wrapper::IsWindowed = false;
D3DMATRIX DX8Wrapper::old_world;
D3DMATRIX DX8Wrapper::old_view;
D3DMATRIX DX8Wrapper::old_prj;
bool DX8Wrapper::world_identity;
unsigned DX8Wrapper::RenderStates[256];
unsigned DX8Wrapper::TextureStageStates[MAX_TEXTURE_STAGES][32];
IDirect3DBaseTexture8 * DX8Wrapper::Textures[MAX_TEXTURE_STAGES];
RenderStateStruct DX8Wrapper::render_state;
unsigned DX8Wrapper::render_state_changed;
bool DX8Wrapper::FogEnable = false;
D3DCOLOR DX8Wrapper::FogColor = 0;
IDirect3D8 * DX8Wrapper::D3DInterface = NULL;
IDirect3DDevice8 * DX8Wrapper::D3DDevice = NULL;
IDirect3DSurface8 * DX8Wrapper::CurrentRenderTarget = NULL;
IDirect3DSurface8 * DX8Wrapper::DefaultRenderTarget = NULL;
IDirect3DSurface8 * DX8Wrapper::DefaultDepthBuffer = NULL;
bool DX8Wrapper::IsRenderToTexture = false;
unsigned DX8Wrapper::matrix_changes = 0;
unsigned DX8Wrapper::material_changes = 0;
unsigned DX8Wrapper::vertex_buffer_changes = 0;
unsigned DX8Wrapper::index_buffer_changes = 0;
unsigned DX8Wrapper::light_changes = 0;
unsigned DX8Wrapper::texture_changes = 0;
unsigned DX8Wrapper::render_state_changes = 0;
unsigned DX8Wrapper::texture_stage_state_changes = 0;
unsigned DX8Wrapper::_MainThreadID = 0;
bool DX8Wrapper::CurrentDX8LightEnables[4];
bool DX8Wrapper::IsDeviceLost;
int DX8Wrapper::ZBias;
float DX8Wrapper::ZNear;
float DX8Wrapper::ZFar;
Matrix4 DX8Wrapper::ProjectionMatrix;
DX8Caps* DX8Wrapper::CurrentCaps;
D3DADAPTER_IDENTIFIER8 DX8Wrapper::CurrentAdapterIdentifier;
unsigned long DX8Wrapper::FrameCount = 0;
bool _DX8SingleThreaded = false;
unsigned number_of_DX8_calls = 0;
static unsigned last_frame_matrix_changes = 0;
static unsigned last_frame_material_changes = 0;
static unsigned last_frame_vertex_buffer_changes = 0;
static unsigned last_frame_index_buffer_changes = 0;
static unsigned last_frame_light_changes = 0;
static unsigned last_frame_texture_changes = 0;
static unsigned last_frame_render_state_changes = 0;
static unsigned last_frame_texture_stage_state_changes = 0;
static unsigned last_frame_number_of_DX8_calls = 0;
static D3DDISPLAYMODE DesktopMode;
static D3DPRESENT_PARAMETERS _PresentParameters;
static DynamicVectorClass<StringClass> _RenderDeviceNameTable;
static DynamicVectorClass<StringClass> _RenderDeviceShortNameTable;
static DynamicVectorClass<RenderDeviceDescClass> _RenderDeviceDescriptionTable;
typedef IDirect3D8* (WINAPI *Direct3DCreate8Type) (UINT SDKVersion);
Direct3DCreate8Type Direct3DCreate8Ptr = NULL;
HINSTANCE D3D8Lib = NULL;
/***********************************************************************************
**
** DX8Wrapper Implementation
**
***********************************************************************************/
void Log_DX8_ErrorCode(unsigned res)
{
char tmp[256]="";
HRESULT new_res=D3DXGetErrorStringA(
res,
tmp,
sizeof(tmp));
if (new_res==D3D_OK) {
WWDEBUG_SAY((tmp));
}
WWASSERT(0);
}
void Non_Fatal_Log_DX8_ErrorCode(unsigned res,const char * file,int line)
{
char tmp[256]="";
HRESULT new_res=D3DXGetErrorStringA(
res,
tmp,
sizeof(tmp));
if (new_res==D3D_OK) {
WWDEBUG_SAY(("DX8 Error: %s, File: %s, Line: %d\r\n",tmp,file,line));
}
}
bool DX8Wrapper::Init(void * hwnd, bool lite)
{
WWASSERT(!IsInitted);
/*
** Initialize all variables!
*/
_Hwnd = (HWND)hwnd;
_MainThreadID=ThreadClass::_Get_Current_Thread_ID();
WWDEBUG_SAY(("DX8Wrapper main thread: 0x%x\n",_MainThreadID));
CurRenderDevice = -1;
ResolutionWidth = DEFAULT_RESOLUTION_WIDTH;
ResolutionHeight = DEFAULT_RESOLUTION_HEIGHT;
// Initialize Render2DClass Screen Resolution
Render2DClass::Set_Screen_Resolution( RectClass( 0, 0, ResolutionWidth, ResolutionHeight ) );
BitDepth = DEFAULT_BIT_DEPTH;
IsWindowed = false;
for (int light=0;light<4;++light) CurrentDX8LightEnables[light]=false;
::ZeroMemory(&old_world, sizeof(D3DMATRIX));
::ZeroMemory(&old_view, sizeof(D3DMATRIX));
::ZeroMemory(&old_prj, sizeof(D3DMATRIX));
//old_vertex_shader; TODO
//old_sr_shader;
//current_shader;
//world_identity;
//CurrentFogColor;
D3DInterface = NULL;
D3DDevice = NULL;
WWDEBUG_SAY(("Reset DX8Wrapper statistics\n"));
Reset_Statistics();
Invalidate_Cached_Render_States();
if (!lite) {
D3D8Lib = LoadLibrary("D3D8.DLL");
if (D3D8Lib == NULL) return false;
Direct3DCreate8Ptr = (Direct3DCreate8Type) GetProcAddress(D3D8Lib, "Direct3DCreate8");
if (Direct3DCreate8Ptr) {
/*
** Create the D3D interface object
*/
WWDEBUG_SAY(("Create Direct3D8\n"));
D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
if (D3DInterface == NULL) {
return(false);
}
IsInitted = true;
/*
** Enumerate the available devices
*/
WWDEBUG_SAY(("Enumerate devices\n"));
Enumerate_Devices();
WWDEBUG_SAY(("DX8Wrapper Init completed\n"));
}
}
return(true);
}
void DX8Wrapper::Shutdown(void)
{
if (D3DDevice) {
Set_Render_Target ((IDirect3DSurface8 *)NULL);
// If in full screen, reset device to windowed mode before releasing it. This is an attempt to
// fix some random bugs and crashes on some devices.
#if (0)
if (!IsWindowed) {
IsWindowed=true;
ResolutionWidth=DEFAULT_RESOLUTION_WIDTH;
ResolutionHeight=DEFAULT_RESOLUTION_HEIGHT;
_PresentParameters.BackBufferWidth = ResolutionWidth;
_PresentParameters.BackBufferHeight = ResolutionHeight;
_PresentParameters.BackBufferCount = 1;
_PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
_PresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
_PresentParameters.Windowed = IsWindowed;
_PresentParameters.EnableAutoDepthStencil = FALSE;
_PresentParameters.Flags=0;
_PresentParameters.BackBufferFormat = DesktopMode.Format;
Reset_Device();
}
#endif //(0)
Release_Device();
}
if (D3DInterface) {
D3DInterface->Release();
D3DInterface=NULL;
}
for (int i = 0; i < MAX_TEXTURE_STAGES; i++) {
if (Textures[i]) {
Textures[i]->Release();
Textures[i] = NULL;
}
}
_RenderDeviceNameTable.Delete_All();
_RenderDeviceShortNameTable.Delete_All();
_RenderDeviceDescriptionTable.Delete_All();
if (D3D8Lib) {
FreeLibrary(D3D8Lib);
D3D8Lib = NULL;
}
IsInitted = false;
}
void DX8Wrapper::Do_Onetime_Device_Dependent_Inits(void)
{
/*
** Set Global render states (some of which depend on caps)
*/
Compute_Caps(D3DFormat_To_WW3DFormat(_PresentParameters.BackBufferFormat));
/*
** Initalize any other subsystems inside of WW3D
*/
MissingTexture::_Init();
TextureClass::_Init_Filters((TextureClass::TextureFilterMode)WW3D::Get_Texture_Filter());
TheDX8MeshRenderer.Init();
BoxRenderObjClass::Init();
VertexMaterialClass::Init();
PointGroupClass::_Init(); // This needs the VertexMaterialClass to be initted
ShatterSystem::Init();
TextureLoader::Init();
Set_Default_Global_Render_States();
}
inline DWORD F2DW(float f) { return *((unsigned*)&f); }
void DX8Wrapper::Set_Default_Global_Render_States(void)
{
DX8_THREAD_ASSERT();
const D3DCAPS8 &caps = Get_Current_Caps()->Get_DX8_Caps();
Set_DX8_Render_State(D3DRS_RANGEFOGENABLE, (caps.RasterCaps & D3DPRASTERCAPS_FOGRANGE) ? TRUE : FALSE);
Set_DX8_Render_State(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
Set_DX8_Render_State(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
Set_DX8_Render_State(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
Set_DX8_Render_State(D3DRS_COLORVERTEX, TRUE);
Set_DX8_Render_State(D3DRS_ZBIAS,0);
Set_DX8_Texture_Stage_State(1, D3DTSS_BUMPENVLSCALE, F2DW(1.0f));
Set_DX8_Texture_Stage_State(1, D3DTSS_BUMPENVLOFFSET, F2DW(0.0f));
Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT00,F2DW(1.0f));
Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT01,F2DW(0.0f));
Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT10,F2DW(0.0f));
Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT11,F2DW(1.0f));
// Set_DX8_Render_State(D3DRS_CULLMODE, D3DCULL_CW);
// Set dither mode here?
}
void DX8Wrapper::Invalidate_Cached_Render_States(void)
{
int a;
for (a=0;a<sizeof(RenderStates)/sizeof(unsigned);++a) {
RenderStates[a]=0x12345678;
}
for (a=0;a<MAX_TEXTURE_STAGES;++a) {
for (int b=0; b<32;b++) {
TextureStageStates[a][b]=0x12345678;
}
Textures[a]=NULL;
}
ShaderClass::Invalidate();
}
void DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns(void)
{
/*
** Shutdown ww3d systems
*/
if (render_state.vertex_buffer) render_state.vertex_buffer->Release_Engine_Ref();
REF_PTR_RELEASE(render_state.vertex_buffer);
if (render_state.index_buffer) render_state.index_buffer->Release_Engine_Ref();
REF_PTR_RELEASE(render_state.index_buffer);
REF_PTR_RELEASE(render_state.material);
for (unsigned i=0;i<MAX_TEXTURE_STAGES;++i) REF_PTR_RELEASE(render_state.Textures[i]);
TextureLoader::Deinit();
SortingRendererClass::Deinit();
DynamicVBAccessClass::_Deinit();
DynamicIBAccessClass::_Deinit();
ShatterSystem::Shutdown();
PointGroupClass::_Shutdown();
VertexMaterialClass::Shutdown();
BoxRenderObjClass::Shutdown();
TheDX8MeshRenderer.Shutdown();
MissingTexture::_Deinit();
if (CurrentCaps) {
delete CurrentCaps;
CurrentCaps=NULL;
}
}
bool DX8Wrapper::Create_Device(void)
{
WWASSERT(D3DDevice == NULL); // for now, once you've created a device, you're stuck with it!
D3DCAPS8 caps;
if (FAILED( D3DInterface->GetDeviceCaps(
CurRenderDevice,
WW3D_DEVTYPE,
&caps))) {
return false;
}
::ZeroMemory(&CurrentAdapterIdentifier, sizeof(D3DADAPTER_IDENTIFIER8));
if (FAILED( D3DInterface->GetAdapterIdentifier(CurRenderDevice,D3DENUM_NO_WHQL_LEVEL,&CurrentAdapterIdentifier))) {
return false;
}
unsigned vertex_processing_type=D3DCREATE_SOFTWARE_VERTEXPROCESSING;
if (caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
vertex_processing_type=D3DCREATE_MIXED_VERTEXPROCESSING;
}
#ifdef CREATE_DX8_MULTI_THREADED
vertex_processing_type|=D3DCREATE_MULTITHREADED;
_DX8SingleThreaded=false;
#else
_DX8SingleThreaded=true;
#endif
#ifdef CREATE_DX8_FPU_PRESERVE
vertex_processing_type|=D3DCREATE_FPU_PRESERVE;
#endif
// JANI HACK! Some objects flicker on ATI Radeons. This can be fixed by locking the back buffer before flipping.
// For this to work the back buffers need to be created as lockable!
DX8Caps dx8_caps(
D3DInterface,
caps,
D3DFormat_To_WW3DFormat(_PresentParameters.BackBufferFormat),
CurrentAdapterIdentifier);
if (dx8_caps.Get_Vendor()==DX8Caps::VENDOR_ATI) {
_PresentParameters.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
}
HRESULT hr = D3DInterface->CreateDevice(
CurRenderDevice,
WW3D_DEVTYPE,
_Hwnd,
vertex_processing_type,
&_PresentParameters,
&D3DDevice );
if (FAILED(hr)) {
// The device selection may fail because the device lied that it supports 32 bit zbuffer with 16 bit
// display. This happens at least on Voodoo2.
if ((_PresentParameters.BackBufferFormat==D3DFMT_R5G6B5 ||
_PresentParameters.BackBufferFormat==D3DFMT_X1R5G5B5 ||
_PresentParameters.BackBufferFormat==D3DFMT_A1R5G5B5) &&
(_PresentParameters.AutoDepthStencilFormat==D3DFMT_D32 ||
_PresentParameters.AutoDepthStencilFormat==D3DFMT_D24S8 ||
_PresentParameters.AutoDepthStencilFormat==D3DFMT_D24X8)) {
_PresentParameters.AutoDepthStencilFormat=D3DFMT_D16;
hr = D3DInterface->CreateDevice(
CurRenderDevice,
WW3D_DEVTYPE,
_Hwnd,
vertex_processing_type,
&_PresentParameters,
&D3DDevice );
if (FAILED(hr)) {
return false;
}
}
}
/*
** Initialize all subsystems
*/
Do_Onetime_Device_Dependent_Inits();
return true;
}
bool DX8Wrapper::Reset_Device(void)
{
WWDEBUG_SAY(("Resetting device.\n"));
DX8_THREAD_ASSERT();
if ((IsInitted) && (D3DDevice != NULL)) {
// Release all non-MANAGED stuff
WW3D::_Invalidate_Textures();
Set_Vertex_Buffer (NULL);
Set_Index_Buffer (NULL, 0);
DynamicVBAccessClass::_Deinit();
DynamicIBAccessClass::_Deinit();
DX8TextureManagerClass::Release_Textures();
// Reset frame count to reflect the flipping chain being reset by Reset()
FrameCount = 0;
DX8CALL(Reset(&_PresentParameters));
DX8TextureManagerClass::Recreate_Textures();
Invalidate_Cached_Render_States();
Set_Default_Global_Render_States();
WWDEBUG_SAY(("Device reset completed\n"));
return true;
}
WWDEBUG_SAY(("Device reset failed\n"));
return false;
}
void DX8Wrapper::Release_Device(void)
{
if (D3DDevice) {
/*
** Release the current vertex and index buffers
*/
if (render_state.vertex_buffer) render_state.vertex_buffer->Release_Engine_Ref();
REF_PTR_RELEASE(render_state.vertex_buffer);
if (render_state.index_buffer) render_state.index_buffer->Release_Engine_Ref();
REF_PTR_RELEASE(render_state.index_buffer);
/*
** Shutdown all subsystems
*/
Do_Onetime_Device_Dependent_Shutdowns();
/*
** Release the device
*/
D3DDevice->Release();
D3DDevice=NULL;
}
}
void DX8Wrapper::Enumerate_Devices()
{
DX8_Assert();
int adapter_count = D3DInterface->GetAdapterCount();
for (int adapter_index=0; adapter_index<adapter_count; adapter_index++) {
D3DADAPTER_IDENTIFIER8 id;
::ZeroMemory(&id, sizeof(D3DADAPTER_IDENTIFIER8));
HRESULT res = D3DInterface->GetAdapterIdentifier(adapter_index,D3DENUM_NO_WHQL_LEVEL,&id);
if (res == D3D_OK) {
/*
** Set up the render device description
** TODO: Fill in more fields of the render device description? (need some lookup tables)
*/
RenderDeviceDescClass desc;
desc.set_device_name(id.Description);
desc.set_driver_name(id.Driver);
char buf[64];
sprintf(buf,"%d.%d.%d.%d", //"%04x.%04x.%04x.%04x",
HIWORD(id.DriverVersion.HighPart),
LOWORD(id.DriverVersion.HighPart),
HIWORD(id.DriverVersion.LowPart),
LOWORD(id.DriverVersion.LowPart));
desc.set_driver_version(buf);
D3DInterface->GetDeviceCaps(adapter_index,WW3D_DEVTYPE,&desc.Caps);
D3DInterface->GetAdapterIdentifier(adapter_index,D3DENUM_NO_WHQL_LEVEL,&desc.AdapterIdentifier);
DX8Caps dx8caps(D3DInterface,desc.Caps,WW3D_FORMAT_UNKNOWN,desc.AdapterIdentifier);
/*
** Enumerate the resolutions
*/
desc.reset_resolution_list();
int mode_count = D3DInterface->GetAdapterModeCount(adapter_index);
for (int mode_index=0; mode_index<mode_count; mode_index++) {
D3DDISPLAYMODE d3dmode;
::ZeroMemory(&d3dmode, sizeof(D3DDISPLAYMODE));
HRESULT res = D3DInterface->EnumAdapterModes(adapter_index,mode_index,&d3dmode);
if (res == D3D_OK) {
int bits = 0;
switch (d3dmode.Format)
{
case D3DFMT_R8G8B8:
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8: bits = 32; break;
case D3DFMT_R5G6B5:
case D3DFMT_X1R5G5B5: bits = 16; break;
}
// Some cards fail in certain modes, DX8Caps keeps list of those.
if (!dx8caps.Is_Valid_Display_Format(d3dmode.Width,d3dmode.Height,D3DFormat_To_WW3DFormat(d3dmode.Format))) {
bits=0;
}
/*
** If we recognize the format, add it to the list
** TODO: should we handle more formats? will any cards report more than 24 or 16 bit?
*/
if (bits != 0) {
desc.add_resolution(d3dmode.Width,d3dmode.Height,bits);
}
}
}
// IML: If the device has one or more valid resolutions add it to the device list.
// NOTE: Testing has shown that there are drivers with zero resolutions.
if (desc.Enumerate_Resolutions().Count() > 0) {
/*
** Set up the device name
*/
StringClass device_name(id.Description,true);
_RenderDeviceNameTable.Add(device_name);
_RenderDeviceShortNameTable.Add(device_name); // for now, just add the same name to the "pretty name table"
/*
** Add the render device to our table
*/
_RenderDeviceDescriptionTable.Add(desc);
}
}
}
}
bool DX8Wrapper::Set_Any_Render_Device(void)
{
// Then fullscreen
for (int dev_number = 0; dev_number < _RenderDeviceNameTable.Count(); dev_number++) {
if (Set_Render_Device(dev_number,-1,-1,-1,0,false)) {
return true;
}
}
// Try windowed first
for (dev_number = 0; dev_number < _RenderDeviceNameTable.Count(); dev_number++) {
if (Set_Render_Device(dev_number,-1,-1,-1,1,false)) {
return true;
}
}
return false;
}
bool DX8Wrapper::Set_Render_Device
(
const char * dev_name,
int width,
int height,
int bits,
int windowed,
bool resize_window
)
{
for ( int dev_number = 0; dev_number < _RenderDeviceNameTable.Count(); dev_number++) {
if ( strcmp( dev_name, _RenderDeviceNameTable[dev_number]) == 0) {
return Set_Render_Device( dev_number, width, height, bits, windowed, resize_window );
}
if ( strcmp( dev_name, _RenderDeviceShortNameTable[dev_number]) == 0) {
return Set_Render_Device( dev_number, width, height, bits, windowed, resize_window );
}
}
return false;
}
bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int windowed, bool resize_window)
{
WWASSERT(IsInitted);
WWASSERT(dev >= -1);
WWASSERT(dev < _RenderDeviceNameTable.Count());
/*
** If user has never selected a render device, start out with device 0
*/
if ((CurRenderDevice == -1) && (dev == -1)) {
CurRenderDevice = 0;
} else if (dev != -1) {
CurRenderDevice = dev;
}
/*
** If user doesn't want to change res, set the res variables to match the
** current resolution
*/
if (width != -1) ResolutionWidth = width;
if (height != -1) ResolutionHeight = height;
// Initialize Render2DClass Screen Resolution
Render2DClass::Set_Screen_Resolution( RectClass( 0, 0, ResolutionWidth, ResolutionHeight ) );
if (bits != -1) BitDepth = bits;
if (windowed != -1) IsWindowed = (windowed != 0);
WWDEBUG_SAY(("Attempting Set_Render_Device: name: %s, width: %d, height: %d, windowed: %d\r\n",
_RenderDeviceNameTable[CurRenderDevice],ResolutionWidth,ResolutionHeight,(IsWindowed ? 1 : 0)));
WWASSERT(D3DDevice == NULL);
/*
** Initialize values for D3DPRESENT_PARAMETERS members.
*/
::ZeroMemory(&_PresentParameters, sizeof(D3DPRESENT_PARAMETERS));
_PresentParameters.BackBufferWidth = ResolutionWidth;
_PresentParameters.BackBufferHeight = ResolutionHeight;
_PresentParameters.BackBufferCount = IsWindowed ? 1 : 2;
_PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
_PresentParameters.SwapEffect = IsWindowed ? D3DSWAPEFFECT_DISCARD : D3DSWAPEFFECT_FLIP; // Shouldn't this be D3DSWAPEFFECT_FLIP?
_PresentParameters.hDeviceWindow = _Hwnd;
_PresentParameters.Windowed = IsWindowed;
_PresentParameters.EnableAutoDepthStencil = TRUE; // Driver will attempt to match Z-buffer depth
_PresentParameters.Flags=0; // We're not going to lock the backbuffer
_PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
_PresentParameters.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
/*
** Set up the buffer formats. Several issues here:
** - if in windowed mode, the backbuffer must use the current display format.
** - the depth buffer must use
*/
::ZeroMemory(&DesktopMode, sizeof(D3DDISPLAYMODE));
D3DInterface->GetAdapterDisplayMode( CurRenderDevice, &DesktopMode );
_PresentParameters.BackBufferFormat = DesktopMode.Format;
if (IsWindowed) {
WWDEBUG_SAY(("Initializing windowed mode\r\n"));
// 10/23/01 - Denzil - DX window initialization
/*
** Enforce a required set of window styles and size if the main window
** IS NOT A CHILD WINDOW. :)
*/
if ((::GetWindowLong(_Hwnd, GWL_STYLE) & WS_CHILD) == 0) {
::SetWindowLong(_Hwnd, GWL_STYLE, WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX|WS_CLIPCHILDREN);
// Always resize the window to the desired resolution in windowed mode.
resize_window = true;
}
// End Denzil - DX window initialzaion
// In windowed mode, define the bitdepth from desktop mode (as it can't be changed)
switch (_PresentParameters.BackBufferFormat) {
case D3DFMT_X8R8G8B8:
case D3DFMT_A8R8G8B8:
case D3DFMT_R8G8B8: BitDepth=32; break;
case D3DFMT_A4R4G4B4:
case D3DFMT_A1R5G5B5:
case D3DFMT_R5G6B5: BitDepth=16; break;
case D3DFMT_L8:
case D3DFMT_A8:
case D3DFMT_P8: BitDepth=8; break;
default:
// Unknown backbuffer format probably means the device can't do windowed
return false;
}
WWDEBUG_SAY(("Using buffer format: %d\r\n",_PresentParameters.BackBufferFormat));
/*
** Find an appropriate Z buffer
*/
if (!Find_Z_Mode(_PresentParameters.BackBufferFormat,_PresentParameters.BackBufferFormat,&_PresentParameters.AutoDepthStencilFormat))
{
// If opening 32 bit mode failed, try 16 bit, even if the desktop happens to be 32 bit
if (BitDepth==32) {
WWDEBUG_SAY(("Failed to find a 32 bit mode, trying 16 bit\r\n"));
BitDepth=16;
_PresentParameters.BackBufferFormat=D3DFMT_R5G6B5;
if (!Find_Z_Mode(_PresentParameters.BackBufferFormat,_PresentParameters.BackBufferFormat,&_PresentParameters.AutoDepthStencilFormat)) {
_PresentParameters.AutoDepthStencilFormat=D3DFMT_UNKNOWN;
}
}
else {
_PresentParameters.AutoDepthStencilFormat=D3DFMT_UNKNOWN;
}
}
} else {
// 10/23/01 - Denzil - DX Window initialization
// For fullscreen set the window style to WS_POPUP (Recommended in DX docs)
SetWindowLong(_Hwnd, GWL_STYLE, WS_POPUP);
// Set fullscreen window position to top left and resize to cover entire display.
// Recommended in DX docs to prevent other windows on the desktop from attempting
// to repaint. This also prevents the OS from spending time calculating invalid
// rects for windows that will never been seen.
SetWindowPos(_Hwnd, HWND_TOPMOST, 0, 0,
GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
SWP_SHOWWINDOW|SWP_NOCOPYBITS);
// We already resized the window
resize_window = false;
// End Denzil - DX window initialization
WWDEBUG_SAY(("Initializing full-screen mode\r\n"));
/*
** Try to find a mode that matches the user's desired bit-depth.
*/
Find_Color_And_Z_Mode(ResolutionWidth,ResolutionHeight,BitDepth,
&_PresentParameters.BackBufferFormat,&_PresentParameters.AutoDepthStencilFormat);
}
#ifdef _WINDOWS
// PWG 4/13/2000 - changed so that if you say to resize the window it resizes
// regardless of whether its windowed or not as OpenGL resizes its self around
// the caption and edges of the window type you provide, so its important to
// push the client area to be the size you really want.
// if ( resize_window && windowed ) {
if (resize_window) {
// Get the current dimensions of the 'render area' of the window
RECT rect = { 0 };
::GetClientRect (_Hwnd, &rect);
#if(0) // Denzil - DX Window initialization
// Is the window the correct size for this resolution?
if ((rect.right-rect.left) != ResolutionWidth ||
(rect.bottom-rect.top) != ResolutionHeight) {
// Calculate what the main window's bounding rectangle should be to
// accomodate this resolution
rect.left = 0;
rect.top = 0;
rect.right = ResolutionWidth;
rect.bottom = ResolutionHeight;
DWORD dwstyle = ::GetWindowLong (_Hwnd, GWL_STYLE);
AdjustWindowRect (&rect, dwstyle, FALSE);
// Resize the window to fit this resolution
::SetWindowPos (_Hwnd,
NULL,
0,
0,
rect.right-rect.left,
rect.bottom-rect.top,
SWP_NOZORDER | SWP_NOMOVE);
}
#else
// Adjust the main window's client area to accomodate the resolution
DWORD dwstyle = ::GetWindowLong(_Hwnd, GWL_STYLE);
DWORD dwexstyle = ::GetWindowLong(_Hwnd, GWL_EXSTYLE);
rect.right = ResolutionWidth;
rect.bottom = ResolutionHeight;
::AdjustWindowRectEx(&rect, dwstyle, (::GetMenu(_Hwnd) != NULL), dwexstyle);
::SetWindowPos(_Hwnd, HWND_TOP, 0, 0,
(rect.right - rect.left), (rect.bottom - rect.top),
SWP_SHOWWINDOW|SWP_NOCOPYBITS);
#endif
}
#endif
/*
** Time to actually create the device.
*/
if (_PresentParameters.AutoDepthStencilFormat==D3DFMT_UNKNOWN) {
if (BitDepth==32) {
_PresentParameters.AutoDepthStencilFormat=D3DFMT_D32;
}
else {
_PresentParameters.AutoDepthStencilFormat=D3DFMT_D16;
}
}
return Create_Device();
}
bool DX8Wrapper::Set_Next_Render_Device(void)
{
int new_dev = (CurRenderDevice + 1) % _RenderDeviceNameTable.Count();
return Set_Render_Device(new_dev);
}
bool DX8Wrapper::Toggle_Windowed(void)
{
#ifdef WW3D_DX8
// State OK?
assert (IsInitted);
if (IsInitted) {
// Get information about the current render device's resolutions
const RenderDeviceDescClass &render_device = Get_Render_Device_Desc ();
const DynamicVectorClass<ResolutionDescClass> &resolutions = render_device.Enumerate_Resolutions ();
// Loop through all the resolutions supported by the current device.
// If we aren't currently running under one of these resolutions,
// then we should probably to the closest resolution before
// toggling the windowed state.
int curr_res = -1;
for (int res = 0;
(res < resolutions.Count ()) && (curr_res == -1);
res ++) {
// Is this the resolution we are looking for?
if ((resolutions[res].Width == ResolutionWidth) &&
(resolutions[res].Height == ResolutionHeight) &&
(resolutions[res].BitDepth == BitDepth)) {
curr_res = res;
}
}
if (curr_res == -1) {
// We don't match any of the standard resolutions,
// so set the first resolution and toggle the windowed state.
return Set_Device_Resolution (resolutions[0].Width,
resolutions[0].Height,
resolutions[0].BitDepth,
!IsWindowed, true);
} else {
// Toggle the windowed state
return Set_Device_Resolution (-1, -1, -1, !IsWindowed, true);
}
}
#endif //WW3D_DX8
return false;
}
void DX8Wrapper::Set_Swap_Interval(int swap)
{
switch (swap) {
case 0: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; break;
case 1: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE ; break;
case 2: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_TWO; break;
case 3: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_THREE; break;
default: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE ; break;
}
Reset_Device();
}
int DX8Wrapper::Get_Swap_Interval(void)
{
return _PresentParameters.FullScreen_PresentationInterval;
}
int DX8Wrapper::Get_Render_Device_Count(void)
{
return _RenderDeviceNameTable.Count();
}
int DX8Wrapper::Get_Render_Device(void)
{
assert(IsInitted);
return CurRenderDevice;
}
const RenderDeviceDescClass & DX8Wrapper::Get_Render_Device_Desc(int deviceidx)
{
WWASSERT(IsInitted);
if ((deviceidx == -1) && (CurRenderDevice == -1)) {
CurRenderDevice = 0;
}
// if the device index is -1 then we want the current device
if (deviceidx == -1) {
WWASSERT(CurRenderDevice >= 0);
WWASSERT(CurRenderDevice < _RenderDeviceNameTable.Count());
return _RenderDeviceDescriptionTable[CurRenderDevice];
}
// We can only ask for multiple device information if the devices
// have been detected.
WWASSERT(deviceidx >= 0);
WWASSERT(deviceidx < _RenderDeviceNameTable.Count());
return _RenderDeviceDescriptionTable[deviceidx];
}
const char * DX8Wrapper::Get_Render_Device_Name(int device_index)
{
device_index = device_index % _RenderDeviceShortNameTable.Count();
return _RenderDeviceShortNameTable[device_index];
}
bool DX8Wrapper::Set_Device_Resolution(int width,int height,int bits,int windowed, bool resize_window)
{
if (D3DDevice != NULL) {
if (width != -1) {
_PresentParameters.BackBufferWidth = ResolutionWidth = width;
}
if (height != -1) {
_PresentParameters.BackBufferHeight = ResolutionHeight = height;
}
#pragma message("TODO: support changing windowed status and changing the bit depth")
return Reset_Device();
} else {
return false;
}
}
void DX8Wrapper::Get_Device_Resolution(int & set_w,int & set_h,int & set_bits,bool & set_windowed)
{
WWASSERT(IsInitted);
set_w = ResolutionWidth;
set_h = ResolutionHeight;
set_bits = BitDepth;
set_windowed = IsWindowed;
return ;
}
void DX8Wrapper::Get_Render_Target_Resolution(int & set_w,int & set_h,int & set_bits,bool & set_windowed)
{
WWASSERT(IsInitted);
if (CurrentRenderTarget != NULL) {
D3DSURFACE_DESC info;
CurrentRenderTarget->GetDesc (&info);
set_w = info.Width;
set_h = info.Height;
set_bits = BitDepth; // should we get the actual bit depth of the target?
set_windowed = IsWindowed; // this doesn't really make sense for render targets (shouldn't matter)...
} else {
Get_Device_Resolution (set_w, set_h, set_bits, set_windowed);
}
return ;
}
bool DX8Wrapper::Registry_Save_Render_Device( const char * sub_key )
{
int width, height, depth;
bool windowed;
Get_Device_Resolution(width, height, depth, windowed);
return Registry_Save_Render_Device(sub_key, CurRenderDevice, ResolutionWidth, ResolutionHeight, BitDepth, IsWindowed, TextureBitDepth);
}
bool DX8Wrapper::Registry_Save_Render_Device( const char *sub_key, int device, int width, int height, int depth, bool windowed, int texture_depth)
{
RegistryClass * registry = new RegistryClass( sub_key );
WWASSERT( registry );
if ( !registry->Is_Valid() ) {
delete registry;
WWDEBUG_SAY(( "Error getting Registry\n" ));
return false;
}
registry->Set_String( VALUE_NAME_RENDER_DEVICE_NAME,
_RenderDeviceShortNameTable[device] );
registry->Set_Int( VALUE_NAME_RENDER_DEVICE_WIDTH, width );
registry->Set_Int( VALUE_NAME_RENDER_DEVICE_HEIGHT, height );
registry->Set_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, depth );
registry->Set_Int( VALUE_NAME_RENDER_DEVICE_WINDOWED, windowed );
registry->Set_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, texture_depth );
delete registry;
return true;
}
bool DX8Wrapper::Registry_Load_Render_Device( const char * sub_key, bool resize_window )
{
char name[ 200 ];
int width,height,depth,windowed;
if ( Registry_Load_Render_Device( sub_key,
name,
sizeof(name),
width,
height,
depth,
windowed,
TextureBitDepth) &&
(*name != 0))
{
WWDEBUG_SAY(( "Device %s (%d X %d) %d bit windowed:%d\n", name,width,height,depth,windowed));
if (TextureBitDepth==16 || TextureBitDepth==32) {
// WWDEBUG_SAY(( "Texture depth %d\n", TextureBitDepth));
} else {
WWDEBUG_SAY(( "Invalid texture depth %d, switching to 16 bits\n", TextureBitDepth));
TextureBitDepth=16;
}
// _RenderDeviceDescriptionTable.
if ( Set_Render_Device( name, width,height,depth,windowed, resize_window ) != true) {
if (depth==16) depth=32;
else depth=16;
if ( Set_Render_Device( name, width,height,depth,windowed, resize_window ) == true) {
return true;
}
if (depth==16) depth=32;
else depth=16;
// we'll test resolutions down, so if start is 640, increase to begin with...
if (width==640) {
width=1024;
height=768;
}
while (true) {
if (width>2048) {
width=2048;
height=1536;
}
else if (width>1920) {
width=1920;
height=1440;
}
else if (width>1600) {
width=1600;
height=1200;
}
else if (width>1280) {
width=1280;
height=1024;
}
else if (width>1024) {
width=1024;
height=768;
}
else if (width>800) {
width=800;
height=600;
}
else if (width!=640) {
width=640;
height=480;
}
else {
return Set_Any_Render_Device();
}
for (int i=0;i<2;++i) {
if ( Set_Render_Device( name, width,height,depth,windowed, resize_window ) == true) {
return true;
}
if (depth==16) depth=32;
else depth=16;
}
}
}
return true;
}
WWDEBUG_SAY(( "Error getting Registry\n" ));
return Set_Any_Render_Device();
}
bool DX8Wrapper::Registry_Load_Render_Device( const char * sub_key, char *device, int device_len, int &width, int &height, int &depth, int &windowed, int &texture_depth)
{
RegistryClass registry( sub_key );
if ( registry.Is_Valid() ) {
registry.Get_String( VALUE_NAME_RENDER_DEVICE_NAME,
device, device_len);
width = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_WIDTH, -1 );
height = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_HEIGHT, -1 );
depth = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, -1 );
windowed = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_WINDOWED, -1 );
texture_depth = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, -1 );
return true;
}
*device=0;
width=-1;
height=-1;
depth=-1;
windowed=-1;
texture_depth=-1;
return false;
}
bool DX8Wrapper::Find_Color_And_Z_Mode(int resx,int resy,int bitdepth,D3DFORMAT * set_colorbuffer,D3DFORMAT * set_zmode)
{
static D3DFORMAT _formats16[] =
{
D3DFMT_R5G6B5,
D3DFMT_X1R5G5B5,
D3DFMT_A1R5G5B5
};
static D3DFORMAT _formats32[] =
{
D3DFMT_A8R8G8B8,
D3DFMT_X8R8G8B8,
D3DFMT_R8G8B8,
};
/*
** Select the table that we're going to use to search for a valid backbuffer format
*/
D3DFORMAT * format_table = NULL;
int format_count = 0;
if (BitDepth == 16) {
format_table = _formats16;
format_count = sizeof(_formats16) / sizeof(D3DFORMAT);
} else {
format_table = _formats32;
format_count = sizeof(_formats32) / sizeof(D3DFORMAT);
}
/*
** now search for a valid format
*/
bool found = false;
unsigned int mode = 0;
for (int format_index=0; format_index < format_count; format_index++) {
found |= Find_Color_Mode(format_table[format_index],resx,resy,&mode);
if (found) break;
}
if (!found) {
return false;
} else {
*set_colorbuffer = format_table[format_index];
}
/*
** We found a backbuffer format, now find a zbuffer format
*/
return Find_Z_Mode(*set_colorbuffer,*set_colorbuffer, set_zmode);
};
// find the resolution mode with at least resx,resy with the highest supported
// refresh rate
bool DX8Wrapper::Find_Color_Mode(D3DFORMAT colorbuffer, int resx, int resy, UINT *mode)
{
UINT i,j,modemax;
UINT rx,ry;
D3DDISPLAYMODE dmode;
::ZeroMemory(&dmode, sizeof(D3DDISPLAYMODE));
rx=(unsigned int) resx;
ry=(unsigned int) resy;
bool found=false;
modemax=D3DInterface->GetAdapterModeCount(D3DADAPTER_DEFAULT);
i=0;
while (i<modemax && !found)
{
D3DInterface->EnumAdapterModes(D3DADAPTER_DEFAULT, i, &dmode);
if (dmode.Width==rx && dmode.Height==ry && dmode.Format==colorbuffer) {
WWDEBUG_SAY(("Found valid color mode. Width = %d Height = %d Format = %d\r\n",dmode.Width,dmode.Height,dmode.Format));
found=true;
}
i++;
}
i--; // this is the first valid mode
// no match
if (!found) {
WWDEBUG_SAY(("Failed to find a valid color mode\r\n"));
return false;
}
// go to the highest refresh rate in this mode
bool stillok=true;
j=i;
while (j<modemax && stillok)
{
D3DInterface->EnumAdapterModes(D3DADAPTER_DEFAULT, j, &dmode);
if (dmode.Width==rx && dmode.Height==ry && dmode.Format==colorbuffer)
stillok=true; else stillok=false;
j++;
}
if (stillok==false) *mode=j-2;
else *mode=i;
return true;
}
// Helper function to find a Z buffer mode for the colorbuffer
// Will look for greatest Z precision
bool DX8Wrapper::Find_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT *zmode)
{
if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D32))
{
*zmode=D3DFMT_D32;
WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D32\r\n"));
return true;
}
if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D24S8))
{
*zmode=D3DFMT_D24S8;
WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D24S8\r\n"));
return true;
}
if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D24X8))
{
*zmode=D3DFMT_D24X8;
WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D24X8\r\n"));
return true;
}
if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D24X4S4))
{
*zmode=D3DFMT_D24X4S4;
WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D24X4S4\r\n"));
return true;
}
if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D16))
{
*zmode=D3DFMT_D16;
WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D16\r\n"));
return true;
}
if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D15S1))
{
*zmode=D3DFMT_D15S1;
WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D15S1\r\n"));
return true;
}
// can't find a match
WWDEBUG_SAY(("Failed to find a valid zbuffer mode\r\n"));
return false;
}
bool DX8Wrapper::Test_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT zmode)
{
// See if we have this mode first
if (FAILED(D3DInterface->CheckDeviceFormat(D3DADAPTER_DEFAULT,WW3D_DEVTYPE,
colorbuffer,D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE,zmode)))
{
WWDEBUG_SAY(("CheckDeviceFormat failed. Colorbuffer format = %d Zbufferformat = %d\r\n",colorbuffer,zmode));
return false;
}
// Then see if it matches the color buffer
if(FAILED(D3DInterface->CheckDepthStencilMatch(D3DADAPTER_DEFAULT, WW3D_DEVTYPE,
colorbuffer,backbuffer,zmode)))
{
WWDEBUG_SAY(("CheckDepthStencilMatch failed. Colorbuffer format = %d Backbuffer format = %d Zbufferformat = %d\r\n",colorbuffer,backbuffer,zmode));
return false;
}
return true;
}
void DX8Wrapper::Reset_Statistics()
{
matrix_changes = 0;
material_changes = 0;
vertex_buffer_changes = 0;
index_buffer_changes = 0;
light_changes = 0;
texture_changes = 0;
render_state_changes =0;
texture_stage_state_changes =0;
number_of_DX8_calls = 0;
last_frame_matrix_changes = 0;
last_frame_material_changes = 0;
last_frame_vertex_buffer_changes = 0;
last_frame_index_buffer_changes = 0;
last_frame_light_changes = 0;
last_frame_texture_changes = 0;
last_frame_render_state_changes = 0;
last_frame_texture_stage_state_changes = 0;
last_frame_number_of_DX8_calls = 0;
}
void DX8Wrapper::Begin_Statistics()
{
matrix_changes=0;
material_changes=0;
vertex_buffer_changes=0;
index_buffer_changes=0;
light_changes=0;
texture_changes = 0;
render_state_changes =0;
texture_stage_state_changes =0;
number_of_DX8_calls=0;
}
void DX8Wrapper::End_Statistics()
{
last_frame_matrix_changes=matrix_changes;
last_frame_material_changes=material_changes;
last_frame_vertex_buffer_changes=vertex_buffer_changes;
last_frame_index_buffer_changes=index_buffer_changes;
last_frame_light_changes=light_changes;
last_frame_texture_changes = texture_changes;
last_frame_render_state_changes = render_state_changes;
last_frame_texture_stage_state_changes = texture_stage_state_changes;
last_frame_number_of_DX8_calls=number_of_DX8_calls;
}
unsigned DX8Wrapper::Get_Last_Frame_Matrix_Changes() { return last_frame_matrix_changes; }
unsigned DX8Wrapper::Get_Last_Frame_Material_Changes() { return last_frame_material_changes; }
unsigned DX8Wrapper::Get_Last_Frame_Vertex_Buffer_Changes() { return last_frame_vertex_buffer_changes; }
unsigned DX8Wrapper::Get_Last_Frame_Index_Buffer_Changes() { return last_frame_index_buffer_changes; }
unsigned DX8Wrapper::Get_Last_Frame_Light_Changes() { return last_frame_light_changes; }
unsigned DX8Wrapper::Get_Last_Frame_Texture_Changes() { return last_frame_texture_changes; }
unsigned DX8Wrapper::Get_Last_Frame_Render_State_Changes() { return last_frame_render_state_changes; }
unsigned DX8Wrapper::Get_Last_Frame_Texture_Stage_State_Changes() { return last_frame_texture_stage_state_changes; }
unsigned DX8Wrapper::Get_Last_Frame_DX8_Calls() { return last_frame_number_of_DX8_calls; }
unsigned long DX8Wrapper::Get_FrameCount(void) {return FrameCount;}
void DX8_Assert()
{
WWASSERT(DX8Wrapper::_Get_D3D8());
DX8_THREAD_ASSERT();
}
void DX8Wrapper::Begin_Scene(void)
{
DX8_THREAD_ASSERT();
DX8CALL(BeginScene());
}
void DX8Wrapper::End_Scene(bool flip_frames)
{
DX8_THREAD_ASSERT();
DX8CALL(EndScene());
if (flip_frames) {
// JANI HACK! Some objects flicker on ATI Radeons. This can be fixed by locking the back buffer before flipping.
// Remember that for this to work the back buffers need to have been create as lockable!
if (Get_Current_Caps()->Get_Vendor()==DX8Caps::VENDOR_ATI) {
IDirect3DSurface8 * bb;
DX8CALL(GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&bb));
D3DLOCKED_RECT rect;
HRESULT res=bb->LockRect(
&rect,
NULL,
D3DLOCK_READONLY);
if (res==D3D_OK) {
bb->UnlockRect();
bb->Release();
}
}
DX8_Assert();
HRESULT hr;
{
WWPROFILE("DX8Device::Present()");
hr=_Get_D3D_Device8()->Present(NULL, NULL, NULL, NULL);
}
number_of_DX8_calls++;
if (SUCCEEDED(hr)) {
IsDeviceLost=false;
FrameCount++;
}
else {
IsDeviceLost=true;
}
// If the device was lost we need to check for cooperative level and possibly reset the device
if (hr==D3DERR_DEVICELOST) {
hr=_Get_D3D_Device8()->TestCooperativeLevel();
if (hr==D3DERR_DEVICENOTRESET) {
Reset_Device();
}
else {
// Sleep it not active
ThreadClass::Sleep_Ms(200);
}
}
else {
DX8_ErrorCode(hr);
}
}
// Each frame, release all of the buffers and textures.
Set_Vertex_Buffer(NULL);
Set_Index_Buffer(NULL,0);
for (unsigned i=0;i<MAX_TEXTURE_STAGES;++i) Set_Texture(i,NULL);
Set_Material(NULL);
}
void DX8Wrapper::Flip_To_Primary(void)
{
// If we are fullscreen and the current frame is odd then we need
// to force a page flip to ensure that the first buffer in the flipping
// chain is the one visible.
if (!IsWindowed) {
DX8_Assert();
int numBuffers = (_PresentParameters.BackBufferCount + 1);
int visibleBuffer = (FrameCount % numBuffers);
int flipCount = ((numBuffers - visibleBuffer) % numBuffers);
int resetAttempts = 0;
while ((flipCount > 0) && (resetAttempts < 3)) {
HRESULT hr = _Get_D3D_Device8()->TestCooperativeLevel();
if (FAILED(hr)) {
WWDEBUG_SAY(("TestCooperativeLevel Failed!\n"));
if (D3DERR_DEVICELOST == hr) {
IsDeviceLost=true;
WWDEBUG_SAY(("DEVICELOST: Cannot flip to primary.\n"));
return;
}
IsDeviceLost=false;
if (D3DERR_DEVICENOTRESET == hr) {
WWDEBUG_SAY(("DEVICENOTRESET\n"));
Reset_Device();
resetAttempts++;
}
} else {
WWDEBUG_SAY(("Flipping: %ld\n", FrameCount));
hr = _Get_D3D_Device8()->Present(NULL, NULL, NULL, NULL);
if (SUCCEEDED(hr)) {
IsDeviceLost=false;
FrameCount++;
WWDEBUG_SAY(("Flip to primary succeeded %ld\n", FrameCount));
}
else {
IsDeviceLost=true;
}
}
--flipCount;
}
}
}
void DX8Wrapper::Clear(bool clear_color, bool clear_z_stencil, const Vector3 &color, float z, unsigned int stencil)
{
DX8_THREAD_ASSERT();
// If we try to clear a stencil buffer which is not there, the entire call will fail
bool has_stencil = ( _PresentParameters.AutoDepthStencilFormat == D3DFMT_D15S1 ||
_PresentParameters.AutoDepthStencilFormat == D3DFMT_D24S8 ||
_PresentParameters.AutoDepthStencilFormat == D3DFMT_D24X4S4);
DWORD flags = 0;
if (clear_color) flags |= D3DCLEAR_TARGET;
if (clear_z_stencil) flags |= D3DCLEAR_ZBUFFER;
if (clear_z_stencil && has_stencil) flags |= D3DCLEAR_STENCIL;
if (flags)
{
DX8CALL(Clear(0, NULL, flags, Convert_Color(color,0.0f), z, stencil));
}
}
void DX8Wrapper::Set_Viewport(CONST D3DVIEWPORT8* pViewport)
{
DX8_THREAD_ASSERT();
DX8CALL(SetViewport(pViewport));
}
// ----------------------------------------------------------------------------
//
// Set vertex buffer. A reference to previous vertex buffer is released and
// this one is assigned the current vertex buffer. The DX8 vertex buffer will
// actually be set in Apply() which is called by Draw_Indexed_Triangles().
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Set_Vertex_Buffer(const VertexBufferClass* vb)
{
render_state.vba_offset=0;
render_state.vba_count=0;
if (render_state.vertex_buffer) {
render_state.vertex_buffer->Release_Engine_Ref();
}
REF_PTR_SET(render_state.vertex_buffer,const_cast<VertexBufferClass*>(vb));
if (vb) {
vb->Add_Engine_Ref();
render_state.vertex_buffer_type=vb->Type();
}
else {
render_state.index_buffer_type=BUFFER_TYPE_INVALID;
}
render_state_changed|=VERTEX_BUFFER_CHANGED;
}
// ----------------------------------------------------------------------------
//
// Set index buffer. A reference to previous index buffer is released and
// this one is assigned the current index buffer. The DX8 index buffer will
// actually be set in Apply() which is called by Draw_Indexed_Triangles().
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Set_Index_Buffer(const IndexBufferClass* ib,unsigned short index_base_offset)
{
render_state.iba_offset=0;
if (render_state.index_buffer) {
render_state.index_buffer->Release_Engine_Ref();
}
REF_PTR_SET(render_state.index_buffer,const_cast<IndexBufferClass*>(ib));
render_state.index_base_offset=index_base_offset;
if (ib) {
ib->Add_Engine_Ref();
render_state.index_buffer_type=ib->Type();
}
else {
render_state.index_buffer_type=BUFFER_TYPE_INVALID;
}
render_state_changed|=INDEX_BUFFER_CHANGED;
}
// ----------------------------------------------------------------------------
//
// Set vertex buffer using dynamic access object.
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Set_Vertex_Buffer(const DynamicVBAccessClass& vba_)
{
if (render_state.vertex_buffer) render_state.vertex_buffer->Release_Engine_Ref();
DynamicVBAccessClass& vba=const_cast<DynamicVBAccessClass&>(vba_);
render_state.vertex_buffer_type=vba.Get_Type();
render_state.vba_offset=vba.VertexBufferOffset;
render_state.vba_count=vba.Get_Vertex_Count();
REF_PTR_SET(render_state.vertex_buffer,vba.VertexBuffer);
render_state.vertex_buffer->Add_Engine_Ref();
render_state_changed|=VERTEX_BUFFER_CHANGED;
render_state_changed|=INDEX_BUFFER_CHANGED; // vba_offset changes so index buffer needs to be reset as well.
}
// ----------------------------------------------------------------------------
//
// Set index buffer using dynamic access object.
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Set_Index_Buffer(const DynamicIBAccessClass& iba_,unsigned short index_base_offset)
{
if (render_state.index_buffer) render_state.index_buffer->Release_Engine_Ref();
DynamicIBAccessClass& iba=const_cast<DynamicIBAccessClass&>(iba_);
render_state.index_base_offset=index_base_offset;
render_state.index_buffer_type=iba.Get_Type();
render_state.iba_offset=iba.IndexBufferOffset;
REF_PTR_SET(render_state.index_buffer,iba.IndexBuffer);
render_state.index_buffer->Add_Engine_Ref();
render_state_changed|=INDEX_BUFFER_CHANGED;
}
// ----------------------------------------------------------------------------
//
// Private function for the special case of rendering polygons from sorting
// index and vertex buffers.
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Draw_Sorting_IB_VB(
unsigned primitive_type,
unsigned short start_index,
unsigned short polygon_count,
unsigned short min_vertex_index,
unsigned short vertex_count)
{
WWASSERT(render_state.vertex_buffer_type==BUFFER_TYPE_SORTING || render_state.vertex_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING);
WWASSERT(render_state.index_buffer_type==BUFFER_TYPE_SORTING || render_state.index_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING);
// Fill dynamic vertex buffer with sorting vertex buffer vertices
DynamicVBAccessClass dyn_vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,vertex_count);
{
DynamicVBAccessClass::WriteLockClass lock(&dyn_vb_access);
VertexFormatXYZNDUV2* src = static_cast<SortingVertexBufferClass*>(render_state.vertex_buffer)->VertexBuffer;
VertexFormatXYZNDUV2* dest= lock.Get_Formatted_Vertex_Array();
src += render_state.vba_offset + render_state.index_base_offset + min_vertex_index;
unsigned size = dyn_vb_access.FVF_Info().Get_FVF_Size()*vertex_count/sizeof(unsigned);
unsigned *dest_u =(unsigned*) dest;
unsigned *src_u = (unsigned*) src;
for (unsigned i=0;i<size;++i) {
*dest_u++=*src_u++;
}
}
DX8CALL(SetStreamSource(
0,
static_cast<DX8VertexBufferClass*>(dyn_vb_access.VertexBuffer)->Get_DX8_Vertex_Buffer(),
dyn_vb_access.FVF_Info().Get_FVF_Size()));
DX8CALL(SetVertexShader(dyn_vb_access.FVF_Info().Get_FVF()));
DX8_RECORD_VERTEX_BUFFER_CHANGE();
unsigned index_count=0;
switch (primitive_type) {
case D3DPT_TRIANGLELIST: index_count=polygon_count*3; break;
case D3DPT_TRIANGLESTRIP: index_count=polygon_count+2; break;
case D3DPT_TRIANGLEFAN: index_count=polygon_count+2; break;
default: WWASSERT(0); break; // Unsupported primitive type
}
// Fill dynamic index buffer with sorting index buffer vertices
DynamicIBAccessClass dyn_ib_access(BUFFER_TYPE_DYNAMIC_DX8,index_count);
{
DynamicIBAccessClass::WriteLockClass lock(&dyn_ib_access);
unsigned short* dest=lock.Get_Index_Array();
unsigned short* src=NULL;
src=static_cast<SortingIndexBufferClass*>(render_state.index_buffer)->index_buffer;
src+=render_state.iba_offset+start_index;
for (unsigned short i=0;i<index_count;++i) {
unsigned short index=*src++;
index-=min_vertex_index;
WWASSERT(index<vertex_count);
*dest++=index;
}
}
DX8CALL(SetIndices(
static_cast<DX8IndexBufferClass*>(dyn_ib_access.IndexBuffer)->Get_DX8_Index_Buffer(),
dyn_vb_access.VertexBufferOffset));
DX8_RECORD_INDEX_BUFFER_CHANGE();
DX8CALL(DrawIndexedPrimitive(
D3DPT_TRIANGLELIST,
0, // start vertex
vertex_count,
dyn_ib_access.IndexBufferOffset,
polygon_count));
DX8_RECORD_RENDER(polygon_count,vertex_count,render_state.shader);
}
// ----------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Draw(
unsigned primitive_type,
unsigned short start_index,
unsigned short polygon_count,
unsigned short min_vertex_index,
unsigned short vertex_count)
{
DX8_THREAD_ASSERT();
SNAPSHOT_SAY(("DX8 - draw\n"));
Apply_Render_State_Changes();
// Debug feature to disable triangle drawing...
if (!_Is_Triangle_Draw_Enabled()) return;
#ifdef MESH_RENDER_SNAPSHOT_ENABLED
if (WW3D::Is_Snapshot_Activated()) {
unsigned long passes=0;
SNAPSHOT_SAY(("ValidateDevice: "));
HRESULT res=D3DDevice->ValidateDevice(&passes);
switch (res) {
case D3D_OK:
SNAPSHOT_SAY(("OK\n"));
break;
case D3DERR_CONFLICTINGTEXTUREFILTER:
SNAPSHOT_SAY(("D3DERR_CONFLICTINGTEXTUREFILTER\n"));
break;
case D3DERR_CONFLICTINGTEXTUREPALETTE:
SNAPSHOT_SAY(("D3DERR_CONFLICTINGTEXTUREPALETTE\n"));
break;
case D3DERR_DEVICELOST:
SNAPSHOT_SAY(("D3DERR_DEVICELOST\n"));
break;
case D3DERR_TOOMANYOPERATIONS:
SNAPSHOT_SAY(("D3DERR_TOOMANYOPERATIONS\n"));
break;
case D3DERR_UNSUPPORTEDALPHAARG:
SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDALPHAARG\n"));
break;
case D3DERR_UNSUPPORTEDALPHAOPERATION:
SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDALPHAOPERATION\n"));
break;
case D3DERR_UNSUPPORTEDCOLORARG:
SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDCOLORARG\n"));
break;
case D3DERR_UNSUPPORTEDCOLOROPERATION:
SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDCOLOROPERATION\n"));
break;
case D3DERR_UNSUPPORTEDFACTORVALUE:
SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDFACTORVALUE\n"));
break;
case D3DERR_UNSUPPORTEDTEXTUREFILTER:
SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDTEXTUREFILTER\n"));
break;
case D3DERR_WRONGTEXTUREFORMAT:
SNAPSHOT_SAY(("D3DERR_WRONGTEXTUREFORMAT\n"));
break;
default:
SNAPSHOT_SAY(("UNKNOWN Error\n"));
break;
}
}
#endif // MESH_RENDER_SHAPSHOT_ENABLED
SNAPSHOT_SAY(("DX8 - draw %d polygons (%d vertices)\n",polygon_count,vertex_count));
if (vertex_count<3) {
min_vertex_index=0;
switch (render_state.vertex_buffer_type) {
case BUFFER_TYPE_DX8:
case BUFFER_TYPE_SORTING:
vertex_count=render_state.vertex_buffer->Get_Vertex_Count()-render_state.index_base_offset-render_state.vba_offset-min_vertex_index;
break;
case BUFFER_TYPE_DYNAMIC_DX8:
case BUFFER_TYPE_DYNAMIC_SORTING:
vertex_count=render_state.vba_count;
break;
}
}
switch (render_state.vertex_buffer_type) {
case BUFFER_TYPE_DX8:
case BUFFER_TYPE_DYNAMIC_DX8:
switch (render_state.index_buffer_type) {
case BUFFER_TYPE_DX8:
case BUFFER_TYPE_DYNAMIC_DX8:
{
DX8_RECORD_RENDER(polygon_count,vertex_count,render_state.shader);
DX8CALL(DrawIndexedPrimitive(
(D3DPRIMITIVETYPE)primitive_type,
min_vertex_index,
vertex_count,
start_index+render_state.iba_offset,
polygon_count));
}
break;
case BUFFER_TYPE_SORTING:
case BUFFER_TYPE_DYNAMIC_SORTING:
WWASSERT_PRINT(0,"VB and IB must of same type (sorting or dx8)");
break;
case BUFFER_TYPE_INVALID:
WWASSERT(0);
break;
}
break;
case BUFFER_TYPE_SORTING:
case BUFFER_TYPE_DYNAMIC_SORTING:
switch (render_state.index_buffer_type) {
case BUFFER_TYPE_DX8:
case BUFFER_TYPE_DYNAMIC_DX8:
WWASSERT_PRINT(0,"VB and IB must of same type (sorting or dx8)");
break;
case BUFFER_TYPE_SORTING:
case BUFFER_TYPE_DYNAMIC_SORTING:
Draw_Sorting_IB_VB(primitive_type,start_index,polygon_count,min_vertex_index,vertex_count);
break;
case BUFFER_TYPE_INVALID:
WWASSERT(0);
break;
}
break;
case BUFFER_TYPE_INVALID:
WWASSERT(0);
break;
}
}
// ----------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Draw_Triangles(
unsigned buffer_type,
unsigned short start_index,
unsigned short polygon_count,
unsigned short min_vertex_index,
unsigned short vertex_count)
{
if (buffer_type==BUFFER_TYPE_SORTING || buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) {
SortingRendererClass::Insert_Triangles(start_index,polygon_count,min_vertex_index,vertex_count);
}
else {
Draw(D3DPT_TRIANGLELIST,start_index,polygon_count,min_vertex_index,vertex_count);
}
}
// ----------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Draw_Triangles(
unsigned short start_index,
unsigned short polygon_count,
unsigned short min_vertex_index,
unsigned short vertex_count)
{
Draw(D3DPT_TRIANGLELIST,start_index,polygon_count,min_vertex_index,vertex_count);
}
// ----------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Draw_Strip(
unsigned short start_index,
unsigned short polygon_count,
unsigned short min_vertex_index,
unsigned short vertex_count)
{
Draw(D3DPT_TRIANGLESTRIP,start_index,polygon_count,min_vertex_index,vertex_count);
}
// ----------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Apply_Render_State_Changes()
{
if (!render_state_changed) return;
if (render_state_changed&SHADER_CHANGED) {
SNAPSHOT_SAY(("DX8 - apply shader\n"));
render_state.shader.Apply();
}
unsigned mask=TEXTURE0_CHANGED;
for (unsigned i=0;i<MAX_TEXTURE_STAGES;++i,mask<<=1) {
if (render_state_changed&mask) {
SNAPSHOT_SAY(("DX8 - apply texture %d (%s)\n",i,render_state.Textures[i] ? render_state.Textures[i]->Get_Full_Path() : "NULL"));
if (render_state.Textures[i]) render_state.Textures[i]->Apply(i);
else TextureClass::Apply_Null(i);
}
else {
SNAPSHOT_SAY(("DX8 - texture %d not changed (%s)\n",i,render_state.Textures[i] ? render_state.Textures[i]->Get_Full_Path() : "NULL"));
}
}
if (render_state_changed&MATERIAL_CHANGED) {
SNAPSHOT_SAY(("DX8 - apply material\n"));
VertexMaterialClass* material=const_cast<VertexMaterialClass*>(render_state.material);
if (material) {
material->Apply();
}
else VertexMaterialClass::Apply_Null();
}
if (render_state_changed&LIGHTS_CHANGED)
{
unsigned mask=LIGHT0_CHANGED;
for (unsigned index=0;index<4;++index,mask<<=1) {
if (render_state_changed&mask) {
SNAPSHOT_SAY(("DX8 - apply light %d\n",index));
if (render_state.LightEnable[index]) {
Set_DX8_Light(index,&render_state.Lights[index]);
}
else {
Set_DX8_Light(index,NULL);
}
}
}
}
if (render_state_changed&WORLD_CHANGED) {
SNAPSHOT_SAY(("DX8 - apply world matrix\n"));
_Set_DX8_Transform(D3DTS_WORLD,render_state.world);
}
if (render_state_changed&VIEW_CHANGED) {
SNAPSHOT_SAY(("DX8 - apply view matrix\n"));
_Set_DX8_Transform(D3DTS_VIEW,render_state.view);
}
if (render_state_changed&VERTEX_BUFFER_CHANGED) {
SNAPSHOT_SAY(("DX8 - apply vb change\n"));
if (render_state.vertex_buffer) {
switch (render_state.vertex_buffer_type) {//->Type()) {
case BUFFER_TYPE_DX8:
case BUFFER_TYPE_DYNAMIC_DX8:
DX8CALL(SetStreamSource(
0,
static_cast<DX8VertexBufferClass*>(render_state.vertex_buffer)->Get_DX8_Vertex_Buffer(),
render_state.vertex_buffer->FVF_Info().Get_FVF_Size()));
DX8_RECORD_VERTEX_BUFFER_CHANGE();
DX8CALL(SetVertexShader(render_state.vertex_buffer->FVF_Info().Get_FVF()));
break;
case BUFFER_TYPE_SORTING:
case BUFFER_TYPE_DYNAMIC_SORTING:
break;
default:
WWASSERT(0);
}
} else {
DX8CALL(SetStreamSource(0,NULL,0));
DX8_RECORD_VERTEX_BUFFER_CHANGE();
}
}
if (render_state_changed&INDEX_BUFFER_CHANGED) {
SNAPSHOT_SAY(("DX8 - apply ib change\n"));
if (render_state.index_buffer) {
switch (render_state.index_buffer_type) {//->Type()) {
case BUFFER_TYPE_DX8:
case BUFFER_TYPE_DYNAMIC_DX8:
DX8CALL(SetIndices(
static_cast<DX8IndexBufferClass*>(render_state.index_buffer)->Get_DX8_Index_Buffer(),
render_state.index_base_offset+render_state.vba_offset));
DX8_RECORD_INDEX_BUFFER_CHANGE();
break;
case BUFFER_TYPE_SORTING:
case BUFFER_TYPE_DYNAMIC_SORTING:
break;
default:
WWASSERT(0);
}
}
else {
DX8CALL(SetIndices(
NULL,
0));
DX8_RECORD_INDEX_BUFFER_CHANGE();
}
}
render_state_changed&=((unsigned)WORLD_IDENTITY|(unsigned)VIEW_IDENTITY);
}
IDirect3DTexture8 * DX8Wrapper::_Create_DX8_Texture(
unsigned int width,
unsigned int height,
WW3DFormat format,
TextureClass::MipCountType mip_level_count,
D3DPOOL pool,
bool rendertarget)
{
DX8_THREAD_ASSERT();
DX8_Assert();
IDirect3DTexture8 *texture = NULL;
// Paletted textures not supported!
WWASSERT(format!=D3DFMT_P8);
// NOTE: If 'format' is not supported as a texture format, this function will find the closest
// format that is supported and use that instead.
// Render target may return NOTAVAILABLE, in
// which case we return NULL.
if (rendertarget) {
unsigned ret=D3DXCreateTexture(
DX8Wrapper::_Get_D3D_Device8(),
width,
height,
mip_level_count,
D3DUSAGE_RENDERTARGET,
WW3DFormat_To_D3DFormat(format),
pool,
&texture);
if (ret==D3DERR_NOTAVAILABLE) {
Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
return NULL;
}
// If ran out of texture ram, try invalidating some textures and mesh cache.
if (ret==D3DERR_OUTOFVIDEOMEMORY) {
WWDEBUG_SAY(("Error: Out of memory while creating render target. Trying to release assets...\n"));
// Free all textures that haven't been used in the last 5 seconds
TextureClass::Invalidate_Old_Unused_Textures(5000);
// Invalidate the mesh cache
WW3D::_Invalidate_Mesh_Cache();
ret=D3DXCreateTexture(
DX8Wrapper::_Get_D3D_Device8(),
width,
height,
mip_level_count,
D3DUSAGE_RENDERTARGET,
WW3DFormat_To_D3DFormat(format),
pool,
&texture);
if (SUCCEEDED(ret)) {
WWDEBUG_SAY(("...Render target creation succesful.\n"));
}
else {
WWDEBUG_SAY(("...Render target creation failed.\n"));
}
if (ret==D3DERR_OUTOFVIDEOMEMORY) {
Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
return NULL;
}
}
DX8_ErrorCode(ret);
// Just return the texture, no reduction
// allowed for render targets.
return texture;
}
// We should never run out of video memory when allocating a non-rendertarget texture.
// However, it seems to happen sometimes when there are a lot of textures in memory and so
// if it happens we'll release assets and try again (anything is better than crashing).
unsigned ret=D3DXCreateTexture(
DX8Wrapper::_Get_D3D_Device8(),
width,
height,
mip_level_count,
0,
WW3DFormat_To_D3DFormat(format),
pool,
&texture);
// If ran out of texture ram, try invalidating some textures and mesh cache.
if (ret==D3DERR_OUTOFVIDEOMEMORY) {
WWDEBUG_SAY(("Error: Out of memory while creating texture. Trying to release assets...\n"));
// Free all textures that haven't been used in the last 5 seconds
TextureClass::Invalidate_Old_Unused_Textures(5000);
// Invalidate the mesh cache
WW3D::_Invalidate_Mesh_Cache();
ret=D3DXCreateTexture(
DX8Wrapper::_Get_D3D_Device8(),
width,
height,
mip_level_count,
0,
WW3DFormat_To_D3DFormat(format),
pool,
&texture);
if (SUCCEEDED(ret)) {
WWDEBUG_SAY(("...Texture creation succesful.\n"));
}
else {
StringClass format_name(0,true);
Get_WW3D_Format_Name(format, format_name);
WWDEBUG_SAY(("...Texture creation failed. (%d x %d, format: %s, mips: %d\n",width,height,format_name,mip_level_count));
}
}
DX8_ErrorCode(ret);
return texture;
}
IDirect3DTexture8 * DX8Wrapper::_Create_DX8_Texture(
const char *filename,
TextureClass::MipCountType mip_level_count)
{
DX8_THREAD_ASSERT();
DX8_Assert();
IDirect3DTexture8 *texture = NULL;
// NOTE: If the original image format is not supported as a texture format, it will
// automatically be converted to an appropriate format.
// NOTE: It is possible to get the size and format of the original image file from this
// function as well, so if we later want to second-guess D3DX's format conversion decisions
// we can do so after this function is called..
unsigned result = D3DXCreateTextureFromFileExA(
_Get_D3D_Device8(),
filename,
D3DX_DEFAULT,
D3DX_DEFAULT,
mip_level_count,//create_mipmaps ? 0 : 1,
0,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_FILTER_BOX,
D3DX_FILTER_BOX,
0,
NULL,
NULL,
&texture);
if (result != D3D_OK) {
return MissingTexture::_Get_Missing_Texture();
}
// Make sure texture wasn't paletted!
D3DSURFACE_DESC desc;
texture->GetLevelDesc(0,&desc);
if (desc.Format==D3DFMT_P8) {
texture->Release();
return MissingTexture::_Get_Missing_Texture();
}
return texture;
}
IDirect3DTexture8 * DX8Wrapper::_Create_DX8_Texture(
IDirect3DSurface8 *surface,
TextureClass::MipCountType mip_level_count)
{
DX8_THREAD_ASSERT();
DX8_Assert();
IDirect3DTexture8 *texture = NULL;
D3DSURFACE_DESC surface_desc;
::ZeroMemory(&surface_desc, sizeof(D3DSURFACE_DESC));
surface->GetDesc(&surface_desc);
// This function will create a texture with a different (but similar) format if the surface is
// not in a supported texture format.
WW3DFormat format=D3DFormat_To_WW3DFormat(surface_desc.Format);
texture = _Create_DX8_Texture(surface_desc.Width, surface_desc.Height, format, mip_level_count);
// Copy the surface to the texture
IDirect3DSurface8 *tex_surface = NULL;
texture->GetSurfaceLevel(0, &tex_surface);
DX8_ErrorCode(D3DXLoadSurfaceFromSurface(tex_surface, NULL, NULL, surface, NULL, NULL, D3DX_FILTER_BOX, 0));
tex_surface->Release();
// Create mipmaps if needed
if (mip_level_count!=TextureClass::MIP_LEVELS_1) {
DX8_ErrorCode(D3DXFilterTexture(texture, NULL, 0, D3DX_FILTER_BOX));
}
return texture;
}
IDirect3DSurface8 * DX8Wrapper::_Create_DX8_Surface(unsigned int width, unsigned int height, WW3DFormat format)
{
DX8_THREAD_ASSERT();
DX8_Assert();
IDirect3DSurface8 *surface = NULL;
// Paletted surfaces not supported!
WWASSERT(format!=D3DFMT_P8);
DX8CALL(CreateImageSurface(width, height, WW3DFormat_To_D3DFormat(format), &surface));
return surface;
}
IDirect3DSurface8 * DX8Wrapper::_Create_DX8_Surface(const char *filename_)
{
DX8_THREAD_ASSERT();
DX8_Assert();
// Note: Since there is no "D3DXCreateSurfaceFromFile" and no "GetSurfaceInfoFromFile" (the
// latter is supposed to be added to D3DX in a future version), we create a texture from the
// file (w/o mipmaps), check that its surface is equal to the original file data (which it
// will not be if the file is not in a texture-supported format or size). If so, copy its
// surface (we might be able to just get its surface and add a ref to it but I'm not sure so
// I'm not going to risk it) and release the texture. If not, create a surface according to
// the file data and use D3DXLoadSurfaceFromFile. This is a horrible hack, but it saves us
// having to write file loaders. Will fix this when D3DX provides us with the right functions.
// Create a surface the size of the file image data
IDirect3DSurface8 *surface = NULL;
{
file_auto_ptr myfile(_TheFileFactory,filename_);
// If file not found, create a surface with missing texture in it
if (!myfile->Is_Available()) {
return MissingTexture::_Create_Missing_Surface();
}
}
StringClass filename_string(filename_,true);
surface=TextureLoader::Load_Surface_Immediate(
filename_string,
WW3D_FORMAT_UNKNOWN,
true);
return surface;
}
/***********************************************************************************************
* DX8Wrapper::_Update_Texture -- Copies a texture from system memory to video memory *
* *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 4/26/2001 hy : Created. *
*=============================================================================================*/
void DX8Wrapper::_Update_Texture(TextureClass *system, TextureClass *video)
{
WWASSERT(system);
WWASSERT(video);
WWASSERT(system->Pool==TextureClass::POOL_SYSTEMMEM);
WWASSERT(video->Pool==TextureClass::POOL_DEFAULT);
DX8CALL(UpdateTexture(system->D3DTexture,video->D3DTexture));
}
void DX8Wrapper::Compute_Caps(WW3DFormat display_format)
{
DX8_THREAD_ASSERT();
DX8_Assert();
delete CurrentCaps;
CurrentCaps=new DX8Caps(_Get_D3D8(),D3DDevice,display_format,Get_Current_Adapter_Identifier());
}
void DX8Wrapper::Set_Light(unsigned index,const LightClass &light)
{
D3DLIGHT8 dlight;
Vector3 temp;
memset(&dlight,0,sizeof(D3DLIGHT8));
switch (light.Get_Type())
{
case LightClass::POINT:
{
dlight.Type=D3DLIGHT_POINT;
}
break;
case LightClass::DIRECTIONAL:
{
dlight.Type=D3DLIGHT_DIRECTIONAL;
}
break;
case LightClass::SPOT:
{
dlight.Type=D3DLIGHT_SPOT;
}
break;
}
light.Get_Diffuse(&temp);
temp*=light.Get_Intensity();
dlight.Diffuse.r=temp.X;
dlight.Diffuse.g=temp.Y;
dlight.Diffuse.b=temp.Z;
dlight.Diffuse.a=1.0f;
light.Get_Specular(&temp);
temp*=light.Get_Intensity();
dlight.Specular.r=temp.X;
dlight.Specular.g=temp.Y;
dlight.Specular.b=temp.Z;
dlight.Specular.a=1.0f;
light.Get_Ambient(&temp);
temp*=light.Get_Intensity();
dlight.Ambient.r=temp.X;
dlight.Ambient.g=temp.Y;
dlight.Ambient.b=temp.Z;
dlight.Ambient.a=1.0f;
temp=light.Get_Position();
dlight.Position=*(D3DVECTOR*) &temp;
light.Get_Spot_Direction(temp);
dlight.Direction=*(D3DVECTOR*) &temp;
dlight.Range=light.Get_Attenuation_Range();
dlight.Falloff=light.Get_Spot_Exponent();
dlight.Theta=light.Get_Spot_Angle();
dlight.Phi=light.Get_Spot_Angle();
// Inverse linear light 1/(1+D)
double a,b;
light.Get_Far_Attenuation_Range(a,b);
dlight.Attenuation0=1.0f;
if (fabs(a-b)<1e-5)
// if the attenuation range is too small assume uniform with cutoff
dlight.Attenuation1=0.0f;
else
// this will cause the light to drop to half intensity at the first far attenuation
dlight.Attenuation1=(float) 1.0/a;
dlight.Attenuation2=0.0f;
Set_Light(index,&dlight);
}
// ----------------------------------------------------------------------------
//
// Set the light environment. This is a lighting model which used up to four
// directional lights to produce the lighting.
//
// ----------------------------------------------------------------------------
void DX8Wrapper::Set_Light_Environment(LightEnvironmentClass* light_env)
{
if (light_env) {
int light_count = light_env->Get_Light_Count();
Set_DX8_Render_State(D3DRS_AMBIENT,Convert_Color(light_env->Get_Equivalent_Ambient(),0.0f));
D3DLIGHT8 light;
::ZeroMemory(&light, sizeof(D3DLIGHT8));
light.Type=D3DLIGHT_DIRECTIONAL;
for (int l=0;l<light_count;++l) {
(Vector3&)light.Diffuse=light_env->Get_Light_Diffuse(l);
Vector3 dir=-light_env->Get_Light_Direction(l);
light.Direction=(const D3DVECTOR&)(dir);
Set_Light(l,&light);
}
for (;l<4;++l) {
Set_Light(l,NULL);
}
}
/* else {
for (int l=0;l<4;++l) {
Set_Light(l,NULL);
}
}
*/
}
IDirect3DSurface8 * DX8Wrapper::_Get_DX8_Front_Buffer()
{
DX8_THREAD_ASSERT();
D3DDISPLAYMODE mode;
DX8CALL(GetDisplayMode(&mode));
IDirect3DSurface8 * fb=NULL;
DX8CALL(CreateImageSurface(mode.Width,mode.Height,D3DFMT_A8R8G8B8,&fb));
DX8CALL(GetFrontBuffer(fb));
return fb;
}
SurfaceClass * DX8Wrapper::_Get_DX8_Back_Buffer(unsigned int num)
{
DX8_THREAD_ASSERT();
IDirect3DSurface8 * bb;
SurfaceClass *surf=NULL;
DX8CALL(GetBackBuffer(num,D3DBACKBUFFER_TYPE_MONO,&bb));
if (bb)
{
surf=NEW_REF(SurfaceClass,(bb));
bb->Release();
}
return surf;
}
TextureClass *
DX8Wrapper::Create_Render_Target (int width, int height, WW3DFormat format)
{
DX8_THREAD_ASSERT();
DX8_Assert();
number_of_DX8_calls++;
// Use the current display format if format isn't specified
if (format==WW3D_FORMAT_UNKNOWN) {
D3DDISPLAYMODE mode;
DX8CALL(GetDisplayMode(&mode));
format=D3DFormat_To_WW3DFormat(mode.Format);
}
// If render target format isn't supported return NULL
if (!Get_Current_Caps()->Support_Render_To_Texture_Format(format)) {
WWDEBUG_SAY(("DX8Wrapper - Render target format is not supported\r\n"));
return NULL;
}
//
// Note: We're going to force the width and height to be powers of two and equal
//
const D3DCAPS8& dx8caps=Get_Current_Caps()->Get_DX8_Caps();
float poweroftwosize = width;
if (height > 0 && height < width) {
poweroftwosize = height;
}
poweroftwosize = ::Find_POT (poweroftwosize);
if (poweroftwosize>dx8caps.MaxTextureWidth) {
poweroftwosize=dx8caps.MaxTextureWidth;
}
if (poweroftwosize>dx8caps.MaxTextureHeight) {
poweroftwosize=dx8caps.MaxTextureHeight;
}
width = height = poweroftwosize;
//
// Attempt to create the render target
//
TextureClass * tex = NEW_REF(TextureClass,(width,height,format,TextureClass::MIP_LEVELS_1,TextureClass::POOL_DEFAULT,true));
// 3dfx drivers are lying in the CheckDeviceFormat call and claiming
// that they support render targets!
if (tex->Peek_DX8_Texture() == NULL) {
WWDEBUG_SAY(("DX8Wrapper - Render target creation failed!\r\n"));
REF_PTR_RELEASE(tex);
}
return tex;
}
void
DX8Wrapper::Set_Render_Target (TextureClass * texture)
{
WWASSERT(texture != NULL);
IDirect3DSurface8 * d3d_surf = texture->Get_D3D_Surface_Level();
WWASSERT(d3d_surf != NULL);
Set_Render_Target(d3d_surf);
d3d_surf->Release();
IsRenderToTexture = true;
}
void
DX8Wrapper::Set_Render_Target(IDirect3DSwapChain8 *swap_chain)
{
DX8_THREAD_ASSERT();
WWASSERT (swap_chain != NULL);
//
// Get the back buffer for the swap chain
//
LPDIRECT3DSURFACE8 render_target = NULL;
swap_chain->GetBackBuffer (0, D3DBACKBUFFER_TYPE_MONO, &render_target);
//
// Set this back buffer as the render targer
//
Set_Render_Target (render_target, true);
//
// Release our hold on the back buffer
//
if (render_target != NULL) {
render_target->Release ();
render_target = NULL;
}
IsRenderToTexture = false;
return ;
}
void
DX8Wrapper::Set_Render_Target(IDirect3DSurface8 *render_target, bool use_default_depth_buffer)
{
DX8_THREAD_ASSERT();
DX8_Assert();
//
// Should we restore the default render target set a new one?
//
if (render_target == NULL || render_target == DefaultRenderTarget) {
// If there is currently a custom render target, default must NOT be NULL.
if (CurrentRenderTarget) {
WWASSERT(DefaultRenderTarget!=NULL);
}
//
// Restore the default render target
//
if (DefaultRenderTarget != NULL) {
DX8CALL(SetRenderTarget (DefaultRenderTarget, DefaultDepthBuffer));
DefaultRenderTarget->Release ();
DefaultRenderTarget = NULL;
if (DefaultDepthBuffer) {
DefaultDepthBuffer->Release ();
DefaultDepthBuffer = NULL;
}
}
//
// Release our hold on the "current" render target
//
if (CurrentRenderTarget != NULL) {
CurrentRenderTarget->Release ();
CurrentRenderTarget = NULL;
}
} else if (render_target != CurrentRenderTarget) {
WWASSERT(DefaultRenderTarget==NULL);
//
// We'll need the depth buffer later...
//
if (DefaultDepthBuffer == NULL) {
// IDirect3DSurface8 *depth_buffer = NULL;
DX8CALL(GetDepthStencilSurface (&DefaultDepthBuffer));
}
//
// Get a pointer to the default render target (if necessary)
//
if (DefaultRenderTarget == NULL) {
DX8CALL(GetRenderTarget (&DefaultRenderTarget));
}
//
// Release our hold on the old "current" render target
//
if (CurrentRenderTarget != NULL) {
CurrentRenderTarget->Release ();
CurrentRenderTarget = NULL;
}
//
// Keep a copy of the current render target (for housekeeping)
//
CurrentRenderTarget = render_target;
WWASSERT (CurrentRenderTarget != NULL);
if (CurrentRenderTarget != NULL) {
CurrentRenderTarget->AddRef ();
//
// Switch render targets
//
if (use_default_depth_buffer) {
DX8CALL(SetRenderTarget (CurrentRenderTarget, DefaultDepthBuffer));
} else {
DX8CALL(SetRenderTarget (CurrentRenderTarget, NULL));
}
}
}
//
// Free our hold on the depth buffer
//
// if (depth_buffer != NULL) {
// depth_buffer->Release ();
// depth_buffer = NULL;
// }
IsRenderToTexture = false;
return ;
}
IDirect3DSwapChain8 *
DX8Wrapper::Create_Additional_Swap_Chain (HWND render_window)
{
DX8_Assert();
//
// Configure the presentation parameters for a windowed render target
//
D3DPRESENT_PARAMETERS params = { 0 };
params.BackBufferFormat = _PresentParameters.BackBufferFormat;
params.BackBufferCount = 1;
params.MultiSampleType = D3DMULTISAMPLE_NONE;
params.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
params.hDeviceWindow = render_window;
params.Windowed = TRUE;
params.EnableAutoDepthStencil = TRUE;
params.AutoDepthStencilFormat = _PresentParameters.AutoDepthStencilFormat;
params.Flags = 0;
params.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
params.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
//
// Create the swap chain
//
IDirect3DSwapChain8 *swap_chain = NULL;
DX8CALL(CreateAdditionalSwapChain(&params, &swap_chain));
return swap_chain;
}
void DX8Wrapper::Flush_DX8_Resource_Manager(unsigned int bytes)
{
DX8_Assert();
DX8CALL(ResourceManagerDiscardBytes(bytes));
}
unsigned int DX8Wrapper::Get_Free_Texture_RAM()
{
DX8_Assert();
number_of_DX8_calls++;
return DX8Wrapper::_Get_D3D_Device8()->GetAvailableTextureMem();
}
// Converts a linear gamma ramp to one that is controlled by:
// Gamma - controls the curvature of the middle of the curve
// Bright - controls the minimum value of the curve
// Contrast - controls the difference between the maximum and the minimum of the curve
void DX8Wrapper::Set_Gamma(float gamma,float bright,float contrast,bool calibrate,bool uselimit)
{
gamma=Bound(gamma,0.6f,6.0f);
bright=Bound(bright,-0.5f,0.5f);
contrast=Bound(contrast,0.5f,2.0f);
float oo_gamma=1.0f/gamma;
DX8_Assert();
number_of_DX8_calls++;
DWORD flag=(calibrate?D3DSGR_CALIBRATE:D3DSGR_NO_CALIBRATION);
D3DGAMMARAMP ramp;
float limit;
// IML: I'm not really sure what the intent of the 'limit' variable is. It does not produce useful results for my purposes.
if (uselimit) {
limit=(contrast-1)/2*contrast;
} else {
limit = 0.0f;
}
// HY - arrived at this equation after much trial and error.
for (int i=0; i<256; i++) {
float in,out;
in=i/256.0f;
float x=in-limit;
x=Bound(x,0.0f,1.0f);
x=powf(x,oo_gamma);
out=contrast*x+bright;
out=Bound(out,0.0f,1.0f);
ramp.red[i]=(WORD) (out*65535);
ramp.green[i]=(WORD) (out*65535);
ramp.blue[i]=(WORD) (out*65535);
}
if (Get_Current_Caps()->Support_Gamma()) {
DX8Wrapper::_Get_D3D_Device8()->SetGammaRamp(flag,&ramp);
} else {
HWND hwnd = GetDesktopWindow();
HDC hdc = GetDC(hwnd);
if (hdc)
{
SetDeviceGammaRamp (hdc, &ramp);
ReleaseDC (hwnd, hdc);
}
}
}
const char* DX8Wrapper::Get_DX8_Render_State_Name(D3DRENDERSTATETYPE state)
{
switch (state) {
case D3DRS_ZENABLE : return "D3DRS_ZENABLE";
case D3DRS_FILLMODE : return "D3DRS_FILLMODE";
case D3DRS_SHADEMODE : return "D3DRS_SHADEMODE";
case D3DRS_LINEPATTERN : return "D3DRS_LINEPATTERN";
case D3DRS_ZWRITEENABLE : return "D3DRS_ZWRITEENABLE";
case D3DRS_ALPHATESTENABLE : return "D3DRS_ALPHATESTENABLE";
case D3DRS_LASTPIXEL : return "D3DRS_LASTPIXEL";
case D3DRS_SRCBLEND : return "D3DRS_SRCBLEND";
case D3DRS_DESTBLEND : return "D3DRS_DESTBLEND";
case D3DRS_CULLMODE : return "D3DRS_CULLMODE";
case D3DRS_ZFUNC : return "D3DRS_ZFUNC";
case D3DRS_ALPHAREF : return "D3DRS_ALPHAREF";
case D3DRS_ALPHAFUNC : return "D3DRS_ALPHAFUNC";
case D3DRS_DITHERENABLE : return "D3DRS_DITHERENABLE";
case D3DRS_ALPHABLENDENABLE : return "D3DRS_ALPHABLENDENABLE";
case D3DRS_FOGENABLE : return "D3DRS_FOGENABLE";
case D3DRS_SPECULARENABLE : return "D3DRS_SPECULARENABLE";
case D3DRS_ZVISIBLE : return "D3DRS_ZVISIBLE";
case D3DRS_FOGCOLOR : return "D3DRS_FOGCOLOR";
case D3DRS_FOGTABLEMODE : return "D3DRS_FOGTABLEMODE";
case D3DRS_FOGSTART : return "D3DRS_FOGSTART";
case D3DRS_FOGEND : return "D3DRS_FOGEND";
case D3DRS_FOGDENSITY : return "D3DRS_FOGDENSITY";
case D3DRS_EDGEANTIALIAS : return "D3DRS_EDGEANTIALIAS";
case D3DRS_ZBIAS : return "D3DRS_ZBIAS";
case D3DRS_RANGEFOGENABLE : return "D3DRS_RANGEFOGENABLE";
case D3DRS_STENCILENABLE : return "D3DRS_STENCILENABLE";
case D3DRS_STENCILFAIL : return "D3DRS_STENCILFAIL";
case D3DRS_STENCILZFAIL : return "D3DRS_STENCILZFAIL";
case D3DRS_STENCILPASS : return "D3DRS_STENCILPASS";
case D3DRS_STENCILFUNC : return "D3DRS_STENCILFUNC";
case D3DRS_STENCILREF : return "D3DRS_STENCILREF";
case D3DRS_STENCILMASK : return "D3DRS_STENCILMASK";
case D3DRS_STENCILWRITEMASK : return "D3DRS_STENCILWRITEMASK";
case D3DRS_TEXTUREFACTOR : return "D3DRS_TEXTUREFACTOR";
case D3DRS_WRAP0 : return "D3DRS_WRAP0";
case D3DRS_WRAP1 : return "D3DRS_WRAP1";
case D3DRS_WRAP2 : return "D3DRS_WRAP2";
case D3DRS_WRAP3 : return "D3DRS_WRAP3";
case D3DRS_WRAP4 : return "D3DRS_WRAP4";
case D3DRS_WRAP5 : return "D3DRS_WRAP5";
case D3DRS_WRAP6 : return "D3DRS_WRAP6";
case D3DRS_WRAP7 : return "D3DRS_WRAP7";
case D3DRS_CLIPPING : return "D3DRS_CLIPPING";
case D3DRS_LIGHTING : return "D3DRS_LIGHTING";
case D3DRS_AMBIENT : return "D3DRS_AMBIENT";
case D3DRS_FOGVERTEXMODE : return "D3DRS_FOGVERTEXMODE";
case D3DRS_COLORVERTEX : return "D3DRS_COLORVERTEX";
case D3DRS_LOCALVIEWER : return "D3DRS_LOCALVIEWER";
case D3DRS_NORMALIZENORMALS : return "D3DRS_NORMALIZENORMALS";
case D3DRS_DIFFUSEMATERIALSOURCE : return "D3DRS_DIFFUSEMATERIALSOURCE";
case D3DRS_SPECULARMATERIALSOURCE : return "D3DRS_SPECULARMATERIALSOURCE";
case D3DRS_AMBIENTMATERIALSOURCE : return "D3DRS_AMBIENTMATERIALSOURCE";
case D3DRS_EMISSIVEMATERIALSOURCE : return "D3DRS_EMISSIVEMATERIALSOURCE";
case D3DRS_VERTEXBLEND : return "D3DRS_VERTEXBLEND";
case D3DRS_CLIPPLANEENABLE : return "D3DRS_CLIPPLANEENABLE";
case D3DRS_SOFTWAREVERTEXPROCESSING : return "D3DRS_SOFTWAREVERTEXPROCESSING";
case D3DRS_POINTSIZE : return "D3DRS_POINTSIZE";
case D3DRS_POINTSIZE_MIN : return "D3DRS_POINTSIZE_MIN";
case D3DRS_POINTSPRITEENABLE : return "D3DRS_POINTSPRITEENABLE";
case D3DRS_POINTSCALEENABLE : return "D3DRS_POINTSCALEENABLE";
case D3DRS_POINTSCALE_A : return "D3DRS_POINTSCALE_A";
case D3DRS_POINTSCALE_B : return "D3DRS_POINTSCALE_B";
case D3DRS_POINTSCALE_C : return "D3DRS_POINTSCALE_C";
case D3DRS_MULTISAMPLEANTIALIAS : return "D3DRS_MULTISAMPLEANTIALIAS";
case D3DRS_MULTISAMPLEMASK : return "D3DRS_MULTISAMPLEMASK";
case D3DRS_PATCHEDGESTYLE : return "D3DRS_PATCHEDGESTYLE";
case D3DRS_PATCHSEGMENTS : return "D3DRS_PATCHSEGMENTS";
case D3DRS_DEBUGMONITORTOKEN : return "D3DRS_DEBUGMONITORTOKEN";
case D3DRS_POINTSIZE_MAX : return "D3DRS_POINTSIZE_MAX";
case D3DRS_INDEXEDVERTEXBLENDENABLE : return "D3DRS_INDEXEDVERTEXBLENDENABLE";
case D3DRS_COLORWRITEENABLE : return "D3DRS_COLORWRITEENABLE";
case D3DRS_TWEENFACTOR : return "D3DRS_TWEENFACTOR";
case D3DRS_BLENDOP : return "D3DRS_BLENDOP";
// case D3DRS_POSITIONORDER : return "D3DRS_POSITIONORDER";
// case D3DRS_NORMALORDER : return "D3DRS_NORMALORDER";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Texture_Stage_State_Name(D3DTEXTURESTAGESTATETYPE state)
{
switch (state) {
case D3DTSS_COLOROP : return "D3DTSS_COLOROP";
case D3DTSS_COLORARG1 : return "D3DTSS_COLORARG1";
case D3DTSS_COLORARG2 : return "D3DTSS_COLORARG2";
case D3DTSS_ALPHAOP : return "D3DTSS_ALPHAOP";
case D3DTSS_ALPHAARG1 : return "D3DTSS_ALPHAARG1";
case D3DTSS_ALPHAARG2 : return "D3DTSS_ALPHAARG2";
case D3DTSS_BUMPENVMAT00 : return "D3DTSS_BUMPENVMAT00";
case D3DTSS_BUMPENVMAT01 : return "D3DTSS_BUMPENVMAT01";
case D3DTSS_BUMPENVMAT10 : return "D3DTSS_BUMPENVMAT10";
case D3DTSS_BUMPENVMAT11 : return "D3DTSS_BUMPENVMAT11";
case D3DTSS_TEXCOORDINDEX : return "D3DTSS_TEXCOORDINDEX";
case D3DTSS_ADDRESSU : return "D3DTSS_ADDRESSU";
case D3DTSS_ADDRESSV : return "D3DTSS_ADDRESSV";
case D3DTSS_BORDERCOLOR : return "D3DTSS_BORDERCOLOR";
case D3DTSS_MAGFILTER : return "D3DTSS_MAGFILTER";
case D3DTSS_MINFILTER : return "D3DTSS_MINFILTER";
case D3DTSS_MIPFILTER : return "D3DTSS_MIPFILTER";
case D3DTSS_MIPMAPLODBIAS : return "D3DTSS_MIPMAPLODBIAS";
case D3DTSS_MAXMIPLEVEL : return "D3DTSS_MAXMIPLEVEL";
case D3DTSS_MAXANISOTROPY : return "D3DTSS_MAXANISOTROPY";
case D3DTSS_BUMPENVLSCALE : return "D3DTSS_BUMPENVLSCALE";
case D3DTSS_BUMPENVLOFFSET : return "D3DTSS_BUMPENVLOFFSET";
case D3DTSS_TEXTURETRANSFORMFLAGS : return "D3DTSS_TEXTURETRANSFORMFLAGS";
case D3DTSS_ADDRESSW : return "D3DTSS_ADDRESSW";
case D3DTSS_COLORARG0 : return "D3DTSS_COLORARG0";
case D3DTSS_ALPHAARG0 : return "D3DTSS_ALPHAARG0";
case D3DTSS_RESULTARG : return "D3DTSS_RESULTARG";
default : return "UNKNOWN";
}
}
void DX8Wrapper::Get_DX8_Render_State_Value_Name(StringClass& name, D3DRENDERSTATETYPE state, unsigned value)
{
switch (state) {
case D3DRS_ZENABLE:
name=Get_DX8_ZBuffer_Type_Name(value);
break;
case D3DRS_FILLMODE:
name=Get_DX8_Fill_Mode_Name(value);
break;
case D3DRS_SHADEMODE:
name=Get_DX8_Shade_Mode_Name(value);
break;
case D3DRS_LINEPATTERN:
case D3DRS_FOGCOLOR:
case D3DRS_ALPHAREF:
case D3DRS_STENCILMASK:
case D3DRS_STENCILWRITEMASK:
case D3DRS_TEXTUREFACTOR:
case D3DRS_AMBIENT:
case D3DRS_CLIPPLANEENABLE:
case D3DRS_MULTISAMPLEMASK:
name.Format("0x%x",value);
break;
case D3DRS_ZWRITEENABLE:
case D3DRS_ALPHATESTENABLE:
case D3DRS_LASTPIXEL:
case D3DRS_DITHERENABLE:
case D3DRS_ALPHABLENDENABLE:
case D3DRS_FOGENABLE:
case D3DRS_SPECULARENABLE:
case D3DRS_STENCILENABLE:
case D3DRS_RANGEFOGENABLE:
case D3DRS_EDGEANTIALIAS:
case D3DRS_CLIPPING:
case D3DRS_LIGHTING:
case D3DRS_COLORVERTEX:
case D3DRS_LOCALVIEWER:
case D3DRS_NORMALIZENORMALS:
case D3DRS_SOFTWAREVERTEXPROCESSING:
case D3DRS_POINTSPRITEENABLE:
case D3DRS_POINTSCALEENABLE:
case D3DRS_MULTISAMPLEANTIALIAS:
case D3DRS_INDEXEDVERTEXBLENDENABLE:
name=value ? "TRUE" : "FALSE";
break;
case D3DRS_SRCBLEND:
case D3DRS_DESTBLEND:
name=Get_DX8_Blend_Name(value);
break;
case D3DRS_CULLMODE:
name=Get_DX8_Cull_Mode_Name(value);
break;
case D3DRS_ZFUNC:
case D3DRS_ALPHAFUNC:
case D3DRS_STENCILFUNC:
name=Get_DX8_Cmp_Func_Name(value);
break;
case D3DRS_ZVISIBLE:
name="NOTSUPPORTED";
break;
case D3DRS_FOGTABLEMODE:
case D3DRS_FOGVERTEXMODE:
name=Get_DX8_Fog_Mode_Name(value);
break;
case D3DRS_FOGSTART:
case D3DRS_FOGEND:
case D3DRS_FOGDENSITY:
case D3DRS_POINTSIZE:
case D3DRS_POINTSIZE_MIN:
case D3DRS_POINTSCALE_A:
case D3DRS_POINTSCALE_B:
case D3DRS_POINTSCALE_C:
case D3DRS_PATCHSEGMENTS:
case D3DRS_POINTSIZE_MAX:
case D3DRS_TWEENFACTOR:
name.Format("%f",*(float*)&value);
break;
case D3DRS_ZBIAS:
case D3DRS_STENCILREF:
name.Format("%d",value);
break;
case D3DRS_STENCILFAIL:
case D3DRS_STENCILZFAIL:
case D3DRS_STENCILPASS:
name=Get_DX8_Stencil_Op_Name(value);
break;
case D3DRS_WRAP0:
case D3DRS_WRAP1:
case D3DRS_WRAP2:
case D3DRS_WRAP3:
case D3DRS_WRAP4:
case D3DRS_WRAP5:
case D3DRS_WRAP6:
case D3DRS_WRAP7:
name="0";
if (value&D3DWRAP_U) name+="|D3DWRAP_U";
if (value&D3DWRAP_V) name+="|D3DWRAP_V";
if (value&D3DWRAP_W) name+="|D3DWRAP_W";
break;
case D3DRS_DIFFUSEMATERIALSOURCE:
case D3DRS_SPECULARMATERIALSOURCE:
case D3DRS_AMBIENTMATERIALSOURCE:
case D3DRS_EMISSIVEMATERIALSOURCE:
name=Get_DX8_Material_Source_Name(value);
break;
case D3DRS_VERTEXBLEND:
name=Get_DX8_Vertex_Blend_Flag_Name(value);
break;
case D3DRS_PATCHEDGESTYLE:
name=Get_DX8_Patch_Edge_Style_Name(value);
break;
case D3DRS_DEBUGMONITORTOKEN:
name=Get_DX8_Debug_Monitor_Token_Name(value);
break;
case D3DRS_COLORWRITEENABLE:
name="0";
if (value&D3DCOLORWRITEENABLE_RED) name+="|D3DCOLORWRITEENABLE_RED";
if (value&D3DCOLORWRITEENABLE_GREEN) name+="|D3DCOLORWRITEENABLE_GREEN";
if (value&D3DCOLORWRITEENABLE_BLUE) name+="|D3DCOLORWRITEENABLE_BLUE";
if (value&D3DCOLORWRITEENABLE_ALPHA) name+="|D3DCOLORWRITEENABLE_ALPHA";
break;
case D3DRS_BLENDOP:
name=Get_DX8_Blend_Op_Name(value);
break;
default:
name.Format("UNKNOWN (%d)",value);
break;
}
}
void DX8Wrapper::Get_DX8_Texture_Stage_State_Value_Name(StringClass& name, D3DTEXTURESTAGESTATETYPE state, unsigned value)
{
switch (state) {
case D3DTSS_COLOROP:
case D3DTSS_ALPHAOP:
name=Get_DX8_Texture_Op_Name(value);
break;
case D3DTSS_COLORARG0:
case D3DTSS_COLORARG1:
case D3DTSS_COLORARG2:
case D3DTSS_ALPHAARG0:
case D3DTSS_ALPHAARG1:
case D3DTSS_ALPHAARG2:
case D3DTSS_RESULTARG:
name=Get_DX8_Texture_Arg_Name(value);
break;
case D3DTSS_ADDRESSU:
case D3DTSS_ADDRESSV:
case D3DTSS_ADDRESSW:
name=Get_DX8_Texture_Address_Name(value);
break;
case D3DTSS_MAGFILTER:
case D3DTSS_MINFILTER:
case D3DTSS_MIPFILTER:
name=Get_DX8_Texture_Filter_Name(value);
break;
case D3DTSS_TEXTURETRANSFORMFLAGS:
name=Get_DX8_Texture_Transform_Flag_Name(value);
// Floating point values
case D3DTSS_MIPMAPLODBIAS:
case D3DTSS_BUMPENVMAT00:
case D3DTSS_BUMPENVMAT01:
case D3DTSS_BUMPENVMAT10:
case D3DTSS_BUMPENVMAT11:
case D3DTSS_BUMPENVLSCALE:
case D3DTSS_BUMPENVLOFFSET:
name.Format("%f",*(float*)&value);
break;
case D3DTSS_TEXCOORDINDEX:
if ((value&0xffff0000)==D3DTSS_TCI_CAMERASPACENORMAL) {
name.Format("D3DTSS_TCI_CAMERASPACENORMAL|%d",value&0xffff);
}
else if ((value&0xffff0000)==D3DTSS_TCI_CAMERASPACEPOSITION) {
name.Format("D3DTSS_TCI_CAMERASPACEPOSITION|%d",value&0xffff);
}
else if ((value&0xffff0000)==D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR) {
name.Format("D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR|%d",value&0xffff);
}
else {
name.Format("%d",value);
}
break;
// Integer value
case D3DTSS_MAXMIPLEVEL:
case D3DTSS_MAXANISOTROPY:
name.Format("%d",value);
break;
// Hex values
case D3DTSS_BORDERCOLOR:
name.Format("0x%x",value);
break;
default:
name.Format("UNKNOWN (%d)",value);
break;
}
}
const char* DX8Wrapper::Get_DX8_Texture_Op_Name(unsigned value)
{
switch (value) {
case D3DTOP_DISABLE : return "D3DTOP_DISABLE";
case D3DTOP_SELECTARG1 : return "D3DTOP_SELECTARG1";
case D3DTOP_SELECTARG2 : return "D3DTOP_SELECTARG2";
case D3DTOP_MODULATE : return "D3DTOP_MODULATE";
case D3DTOP_MODULATE2X : return "D3DTOP_MODULATE2X";
case D3DTOP_MODULATE4X : return "D3DTOP_MODULATE4X";
case D3DTOP_ADD : return "D3DTOP_ADD";
case D3DTOP_ADDSIGNED : return "D3DTOP_ADDSIGNED";
case D3DTOP_ADDSIGNED2X : return "D3DTOP_ADDSIGNED2X";
case D3DTOP_SUBTRACT : return "D3DTOP_SUBTRACT";
case D3DTOP_ADDSMOOTH : return "D3DTOP_ADDSMOOTH";
case D3DTOP_BLENDDIFFUSEALPHA : return "D3DTOP_BLENDDIFFUSEALPHA";
case D3DTOP_BLENDTEXTUREALPHA : return "D3DTOP_BLENDTEXTUREALPHA";
case D3DTOP_BLENDFACTORALPHA : return "D3DTOP_BLENDFACTORALPHA";
case D3DTOP_BLENDTEXTUREALPHAPM : return "D3DTOP_BLENDTEXTUREALPHAPM";
case D3DTOP_BLENDCURRENTALPHA : return "D3DTOP_BLENDCURRENTALPHA";
case D3DTOP_PREMODULATE : return "D3DTOP_PREMODULATE";
case D3DTOP_MODULATEALPHA_ADDCOLOR : return "D3DTOP_MODULATEALPHA_ADDCOLOR";
case D3DTOP_MODULATECOLOR_ADDALPHA : return "D3DTOP_MODULATECOLOR_ADDALPHA";
case D3DTOP_MODULATEINVALPHA_ADDCOLOR : return "D3DTOP_MODULATEINVALPHA_ADDCOLOR";
case D3DTOP_MODULATEINVCOLOR_ADDALPHA : return "D3DTOP_MODULATEINVCOLOR_ADDALPHA";
case D3DTOP_BUMPENVMAP : return "D3DTOP_BUMPENVMAP";
case D3DTOP_BUMPENVMAPLUMINANCE : return "D3DTOP_BUMPENVMAPLUMINANCE";
case D3DTOP_DOTPRODUCT3 : return "D3DTOP_DOTPRODUCT3";
case D3DTOP_MULTIPLYADD : return "D3DTOP_MULTIPLYADD";
case D3DTOP_LERP : return "D3DTOP_LERP";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Texture_Arg_Name(unsigned value)
{
switch (value) {
case D3DTA_CURRENT : return "D3DTA_CURRENT";
case D3DTA_DIFFUSE : return "D3DTA_DIFFUSE";
case D3DTA_SELECTMASK : return "D3DTA_SELECTMASK";
case D3DTA_SPECULAR : return "D3DTA_SPECULAR";
case D3DTA_TEMP : return "D3DTA_TEMP";
case D3DTA_TEXTURE : return "D3DTA_TEXTURE";
case D3DTA_TFACTOR : return "D3DTA_TFACTOR";
case D3DTA_ALPHAREPLICATE : return "D3DTA_ALPHAREPLICATE";
case D3DTA_COMPLEMENT : return "D3DTA_COMPLEMENT";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Texture_Filter_Name(unsigned value)
{
switch (value) {
case D3DTEXF_NONE : return "D3DTEXF_NONE";
case D3DTEXF_POINT : return "D3DTEXF_POINT";
case D3DTEXF_LINEAR : return "D3DTEXF_LINEAR";
case D3DTEXF_ANISOTROPIC : return "D3DTEXF_ANISOTROPIC";
case D3DTEXF_FLATCUBIC : return "D3DTEXF_FLATCUBIC";
case D3DTEXF_GAUSSIANCUBIC : return "D3DTEXF_GAUSSIANCUBIC";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Texture_Address_Name(unsigned value)
{
switch (value) {
case D3DTADDRESS_WRAP : return "D3DTADDRESS_WRAP";
case D3DTADDRESS_MIRROR : return "D3DTADDRESS_MIRROR";
case D3DTADDRESS_CLAMP : return "D3DTADDRESS_CLAMP";
case D3DTADDRESS_BORDER : return "D3DTADDRESS_BORDER";
case D3DTADDRESS_MIRRORONCE: return "D3DTADDRESS_MIRRORONCE";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Texture_Transform_Flag_Name(unsigned value)
{
switch (value) {
case D3DTTFF_DISABLE : return "D3DTTFF_DISABLE";
case D3DTTFF_COUNT1 : return "D3DTTFF_COUNT1";
case D3DTTFF_COUNT2 : return "D3DTTFF_COUNT2";
case D3DTTFF_COUNT3 : return "D3DTTFF_COUNT3";
case D3DTTFF_COUNT4 : return "D3DTTFF_COUNT4";
case D3DTTFF_PROJECTED : return "D3DTTFF_PROJECTED";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_ZBuffer_Type_Name(unsigned value)
{
switch (value) {
case D3DZB_FALSE : return "D3DZB_FALSE";
case D3DZB_TRUE : return "D3DZB_TRUE";
case D3DZB_USEW : return "D3DZB_USEW";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Fill_Mode_Name(unsigned value)
{
switch (value) {
case D3DFILL_POINT : return "D3DFILL_POINT";
case D3DFILL_WIREFRAME : return "D3DFILL_WIREFRAME";
case D3DFILL_SOLID : return "D3DFILL_SOLID";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Shade_Mode_Name(unsigned value)
{
switch (value) {
case D3DSHADE_FLAT : return "D3DSHADE_FLAT";
case D3DSHADE_GOURAUD : return "D3DSHADE_GOURAUD";
case D3DSHADE_PHONG : return "D3DSHADE_PHONG";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Blend_Name(unsigned value)
{
switch (value) {
case D3DBLEND_ZERO : return "D3DBLEND_ZERO";
case D3DBLEND_ONE : return "D3DBLEND_ONE";
case D3DBLEND_SRCCOLOR : return "D3DBLEND_SRCCOLOR";
case D3DBLEND_INVSRCCOLOR : return "D3DBLEND_INVSRCCOLOR";
case D3DBLEND_SRCALPHA : return "D3DBLEND_SRCALPHA";
case D3DBLEND_INVSRCALPHA : return "D3DBLEND_INVSRCALPHA";
case D3DBLEND_DESTALPHA : return "D3DBLEND_DESTALPHA";
case D3DBLEND_INVDESTALPHA : return "D3DBLEND_INVDESTALPHA";
case D3DBLEND_DESTCOLOR : return "D3DBLEND_DESTCOLOR";
case D3DBLEND_INVDESTCOLOR : return "D3DBLEND_INVDESTCOLOR";
case D3DBLEND_SRCALPHASAT : return "D3DBLEND_SRCALPHASAT";
case D3DBLEND_BOTHSRCALPHA : return "D3DBLEND_BOTHSRCALPHA";
case D3DBLEND_BOTHINVSRCALPHA : return "D3DBLEND_BOTHINVSRCALPHA";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Cull_Mode_Name(unsigned value)
{
switch (value) {
case D3DCULL_NONE : return "D3DCULL_NONE";
case D3DCULL_CW : return "D3DCULL_CW";
case D3DCULL_CCW : return "D3DCULL_CCW";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Cmp_Func_Name(unsigned value)
{
switch (value) {
case D3DCMP_NEVER : return "D3DCMP_NEVER";
case D3DCMP_LESS : return "D3DCMP_LESS";
case D3DCMP_EQUAL : return "D3DCMP_EQUAL";
case D3DCMP_LESSEQUAL : return "D3DCMP_LESSEQUAL";
case D3DCMP_GREATER : return "D3DCMP_GREATER";
case D3DCMP_NOTEQUAL : return "D3DCMP_NOTEQUAL";
case D3DCMP_GREATEREQUAL : return "D3DCMP_GREATEREQUAL";
case D3DCMP_ALWAYS : return "D3DCMP_ALWAYS";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Fog_Mode_Name(unsigned value)
{
switch (value) {
case D3DFOG_NONE : return "D3DFOG_NONE";
case D3DFOG_EXP : return "D3DFOG_EXP";
case D3DFOG_EXP2 : return "D3DFOG_EXP2";
case D3DFOG_LINEAR : return "D3DFOG_LINEAR";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Stencil_Op_Name(unsigned value)
{
switch (value) {
case D3DSTENCILOP_KEEP : return "D3DSTENCILOP_KEEP";
case D3DSTENCILOP_ZERO : return "D3DSTENCILOP_ZERO";
case D3DSTENCILOP_REPLACE : return "D3DSTENCILOP_REPLACE";
case D3DSTENCILOP_INCRSAT : return "D3DSTENCILOP_INCRSAT";
case D3DSTENCILOP_DECRSAT : return "D3DSTENCILOP_DECRSAT";
case D3DSTENCILOP_INVERT : return "D3DSTENCILOP_INVERT";
case D3DSTENCILOP_INCR : return "D3DSTENCILOP_INCR";
case D3DSTENCILOP_DECR : return "D3DSTENCILOP_DECR";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Material_Source_Name(unsigned value)
{
switch (value) {
case D3DMCS_MATERIAL : return "D3DMCS_MATERIAL";
case D3DMCS_COLOR1 : return "D3DMCS_COLOR1";
case D3DMCS_COLOR2 : return "D3DMCS_COLOR2";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Vertex_Blend_Flag_Name(unsigned value)
{
switch (value) {
case D3DVBF_DISABLE : return "D3DVBF_DISABLE";
case D3DVBF_1WEIGHTS : return "D3DVBF_1WEIGHTS";
case D3DVBF_2WEIGHTS : return "D3DVBF_2WEIGHTS";
case D3DVBF_3WEIGHTS : return "D3DVBF_3WEIGHTS";
case D3DVBF_TWEENING : return "D3DVBF_TWEENING";
case D3DVBF_0WEIGHTS : return "D3DVBF_0WEIGHTS";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Patch_Edge_Style_Name(unsigned value)
{
switch (value) {
case D3DPATCHEDGE_DISCRETE : return "D3DPATCHEDGE_DISCRETE";
case D3DPATCHEDGE_CONTINUOUS:return "D3DPATCHEDGE_CONTINUOUS";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Debug_Monitor_Token_Name(unsigned value)
{
switch (value) {
case D3DDMT_ENABLE : return "D3DDMT_ENABLE";
case D3DDMT_DISABLE : return "D3DDMT_DISABLE";
default : return "UNKNOWN";
}
}
const char* DX8Wrapper::Get_DX8_Blend_Op_Name(unsigned value)
{
switch (value) {
case D3DBLENDOP_ADD : return "D3DBLENDOP_ADD";
case D3DBLENDOP_SUBTRACT : return "D3DBLENDOP_SUBTRACT";
case D3DBLENDOP_REVSUBTRACT: return "D3DBLENDOP_REVSUBTRACT";
case D3DBLENDOP_MIN : return "D3DBLENDOP_MIN";
case D3DBLENDOP_MAX : return "D3DBLENDOP_MAX";
default : return "UNKNOWN";
}
}