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/Tools/WWConfig/PerformanceConfigDialog.cpp

1204 lines
36 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/>.
*/
// PerformanceConfigDialog.cpp : implementation file
//
#include "stdafx.h"
#include "wwconfig.h"
#include "performanceconfigdialog.h"
#include "registry.h"
#include "ww3d.h"
#include "pscene.h"
#include "rendobj.h"
#include "phys.h"
#include "videoconfigdialog.h"
#include "dx8caps.h"
#include "cpudetect.h"
#include "formconv.h"
#include "dx8wrapper.h"
#include "locale_api.h"
#include "wwconfig_ids.h"
#include "..\..\combat\specialbuilds.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static bool CanDoMultiPass=true;
/////////////////////////////////////////////////////////////////////////////
// Structures and typedefs
/////////////////////////////////////////////////////////////////////////////
typedef struct _PERFORMANCE_SETTING
{
int ctrl_id;
int value;
} PERFORMANCE_SETTING;
/////////////////////////////////////////////////////////////////////////////
// Constants
/////////////////////////////////////////////////////////////////////////////
const int MAX_PERFORMANCE_LEVELS = 4;
const int MAX_EXPERT_OPTIONS = 8;
PERFORMANCE_SETTING _PerformanceLevels[MAX_PERFORMANCE_LEVELS][MAX_EXPERT_OPTIONS] =
{
//
// Low detail
//
{
{IDC_CHAR_SHADOWS_SLIDER, 0},
{IDC_TEXTURE_DETAIL_SLIDER, 0},
{IDC_PARTICLE_DETAIL_SLIDER, 0},
{IDC_SURFACE_DETAIL_SLIDER, 0},
{IDC_GEOMETRY_DETAIL_SLIDER, 0},
{IDC_TEXTURE_FILTER_COMBO, TextureClass::TEXTURE_FILTER_BILINEAR},
{IDC_LIGHTING_MODE_COMBO, WW3D::PRELIT_MODE_VERTEX},
{IDC_TERRAIN_SHADOW_CHECK, 0}
},
{
{IDC_CHAR_SHADOWS_SLIDER, 1},
{IDC_TEXTURE_DETAIL_SLIDER, 1},
{IDC_PARTICLE_DETAIL_SLIDER, 0},
{IDC_SURFACE_DETAIL_SLIDER, 0},
{IDC_GEOMETRY_DETAIL_SLIDER, 0},
{IDC_TEXTURE_FILTER_COMBO, TextureClass::TEXTURE_FILTER_BILINEAR},
{IDC_LIGHTING_MODE_COMBO, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE},
{IDC_TERRAIN_SHADOW_CHECK, 0}
},
{
{IDC_CHAR_SHADOWS_SLIDER, 2},
{IDC_TEXTURE_DETAIL_SLIDER, 2},
{IDC_PARTICLE_DETAIL_SLIDER, 1},
{IDC_SURFACE_DETAIL_SLIDER, 1},
{IDC_GEOMETRY_DETAIL_SLIDER, 1},
{IDC_TEXTURE_FILTER_COMBO, TextureClass::TEXTURE_FILTER_TRILINEAR},
{IDC_LIGHTING_MODE_COMBO, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE},
{IDC_TERRAIN_SHADOW_CHECK, 1}
},
//
// High detail
//
{
{IDC_CHAR_SHADOWS_SLIDER, 3},
{IDC_TEXTURE_DETAIL_SLIDER, 2},
{IDC_PARTICLE_DETAIL_SLIDER, 2},
{IDC_SURFACE_DETAIL_SLIDER, 2},
{IDC_GEOMETRY_DETAIL_SLIDER, 2},
{IDC_TEXTURE_FILTER_COMBO, TextureClass::TEXTURE_FILTER_TRILINEAR},
{IDC_LIGHTING_MODE_COMBO, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE},
{IDC_TERRAIN_SHADOW_CHECK, 1}
},
};
/////////////////////////////////////////////////////////////////////////////
// Registry Values
/////////////////////////////////////////////////////////////////////////////
/*
#ifdef MULTIPLAYERDEMO
const char *KEY_NAME_SETTINGS = "Software\\Westwood\\RenegadeMPDemo\\System Settings";
const char *KEY_NAME_OPTIONS = "Software\\Westwood\\RenegadeMPDemo\\Options";
#else
const char *KEY_NAME_SETTINGS = "Software\\Westwood\\Renegade\\System Settings";
const char *KEY_NAME_OPTIONS = "Software\\Westwood\\Renegade\\Options";
#endif // MULTIPLAYERDEMO
*/
#if defined(FREEDEDICATEDSERVER)
const char *KEY_NAME_SETTINGS = "Software\\Westwood\\RenegadeFDS\\System Settings";
const char *KEY_NAME_OPTIONS = "Software\\Westwood\\RenegadeFDS\\Options";
#elif defined(MULTIPLAYERDEMO)
const char *KEY_NAME_SETTINGS = "Software\\Westwood\\RenegadeMPDemo\\System Settings";
const char *KEY_NAME_OPTIONS = "Software\\Westwood\\RenegadeMPDemo\\Options";
#elif defined(BETACLIENT)
const char *KEY_NAME_SETTINGS = "Software\\Westwood\\RenegadeBeta\\System Settings";
const char *KEY_NAME_OPTIONS = "Software\\Westwood\\RenegadeBeta\\Options";
#else
const char *KEY_NAME_SETTINGS = "Software\\Westwood\\Renegade\\System Settings";
const char *KEY_NAME_OPTIONS = "Software\\Westwood\\Renegade\\Options";
#endif
const char *VALUE_NAME_DYN_LOD = "Dynamic_LOD_Budget";
const char *VALUE_NAME_STATIC_LOD = "Static_LOD_Budget";
const char *VALUE_NAME_DYN_SHADOWS = "Dynamic_Projectors";
const char *VALUE_NAME_TEXTURE_FILTER = "Texture_Filter_Mode";
const char *VALUE_NAME_PRELIT_MODE = "Prelit_Mode";
const char *VALUE_NAME_SHADOW_MODE = "Shadow_Mode";
const char *VALUE_NAME_STATIC_SHADOWS = "Static_Projectors";
const char *VALUE_NAME_TEXTURE_RES = "Texture_Resolution";
const char *VALUE_NAME_SURFACE_EFFECT = "Surface_Effect_Detail";
const char *VALUE_NAME_PARTICLE_DETAIL = "Particle_Detail";
/////////////////////////////////////////////////////////////////////////////
//
// PerformanceConfigDialogClass
//
/////////////////////////////////////////////////////////////////////////////
PerformanceConfigDialogClass::PerformanceConfigDialogClass(CWnd* pParent /*=NULL*/)
: CDialog (PerformanceConfigDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(PerformanceConfigDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
CDialog::Create (PerformanceConfigDialogClass::IDD, pParent);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::DoDataExchange (CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(PerformanceConfigDialogClass)
DDX_Control(pDX, IDC_GEOMETRY_DETAIL_SLIDER, m_GeometrySlider);
DDX_Control(pDX, IDC_CHAR_SHADOWS_SLIDER, m_CharShadowsSlider);
DDX_Control(pDX, IDC_TEXTURE_DETAIL_SLIDER, m_TextureDetailSlider);
DDX_Control(pDX, IDC_SURFACE_DETAIL_SLIDER, m_SurfaceEffectsSlider);
DDX_Control(pDX, IDC_PERFORMANCE_SLIDER, m_PerformanceSlider);
DDX_Control(pDX, IDC_PARTICLE_DETAIL_SLIDER, m_ParticleSlider);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(PerformanceConfigDialogClass, CDialog)
//{{AFX_MSG_MAP(PerformanceConfigDialogClass)
ON_BN_CLICKED(IDC_EXPERT_CHECK, OnExpertCheck)
ON_WM_HSCROLL()
ON_BN_CLICKED(IDC_AUTO_CONFIG_BUTTON, OnGraphicsAutoSetup)
ON_WM_SHOWWINDOW()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
// Modified: 12/06/2001 by MML - Retrieving strings from Locomoto file.
//
/////////////////////////////////////////////////////////////////////////////
BOOL
PerformanceConfigDialogClass::OnInitDialog (void)
{
char string [_MAX_PATH];
CDialog::OnInitDialog ();
//
// Set all the static strings for this dialog.
//
SetDlgItemText( IDC_DETAIL, Locale_GetString( IDS_DETAIL, string ));
SetDlgItemText( IDC_LOW_DESC, Locale_GetString( IDS_LOW_DESC, string ));
SetDlgItemText( IDC_HIGH_DESC, Locale_GetString( IDS_HIGH_DESC, string ));
SetDlgItemText( IDC_EXPERT_CHECK, Locale_GetString( IDS_EXPERT_MODE, string ));
SetDlgItemText( IDC_EXPERT_SETTINGS, Locale_GetString( IDS_EXPERT_SETTINGS, string ));
SetDlgItemText( IDC_AUTO_CONFIG_BUTTON, Locale_GetString( IDS_AUTOCONFIG, string ));
SetDlgItemText( IDC_GEOMETRY_DETAIL, Locale_GetString( IDS_GEOMETRY_DETAIL, string ));
SetDlgItemText( IDC_CHARACTER_SHADOWS, Locale_GetString( IDS_CHARACTER_SHADOWS, string ));
SetDlgItemText( IDC_TEXTURE_DETAIL, Locale_GetString( IDS_TEXTURE_DETAIL, string ));
SetDlgItemText( IDC_PARTICLE_DETAIL, Locale_GetString( IDS_PARTICLE_DETAIL, string ));
SetDlgItemText( IDC_SURFACE_EFFECT_DETAIL, Locale_GetString( IDS_SURFACE_EFFECT_DETAIL, string ));
Locale_GetString( IDS_LOW, string );
SetDlgItemText( IDC_LOW1, string );
SetDlgItemText( IDC_LOW2, string );
SetDlgItemText( IDC_LOW3, string );
SetDlgItemText( IDC_LOW4, string );
SetDlgItemText( IDC_LOW5, string );
Locale_GetString( IDS_HIGH, string );
SetDlgItemText( IDC_HIGH1, string );
SetDlgItemText( IDC_HIGH2, string );
SetDlgItemText( IDC_HIGH3, string );
SetDlgItemText( IDC_HIGH4, string );
SetDlgItemText( IDC_HIGH5, string );
SetDlgItemText( IDC_LIGHTING_MODE, Locale_GetString( IDS_LIGHTING_MODE, string ));
SetDlgItemText( IDC_TEXTURE_FILTER, Locale_GetString( IDS_TEXTURE_FILTER, string ));
SetDlgItemText( IDC_TERRAIN_SHADOW_CHECK, Locale_GetString( IDS_TERRAIN_SHADOWS, string ));
//
// Configure the dialog controls
//
Setup_Controls ();
Load_Values ();
// Determine_Performance_Setting ();
//
// Set the visibility of the expert windows controls
//
Build_Expert_Window_List ();
Display_Expert_Settings (false);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// Build_Expert_Window_List
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::Build_Expert_Window_List (void)
{
ExpertWindowList.Delete_All ();
//
// Find the y-position of the expert mode checkbox
//
CRect rect;
::GetWindowRect (::GetDlgItem (m_hWnd, IDC_EXPERT_CHECK), &rect);
float y_pos = rect.top;
//
// Loop over all the child windows of the dialog
//
for ( HWND child_wnd = ::GetWindow (m_hWnd, GW_CHILD);
child_wnd != NULL;
child_wnd = ::GetWindow (child_wnd, GW_HWNDNEXT))
{
//
// If this child window is below the expert checkbox then its
// part of the expert settings
//
::GetWindowRect (child_wnd, &rect);
if (rect.top > y_pos) {
ExpertWindowList.Add (child_wnd);
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Display_Expert_Settings
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::Display_Expert_Settings (bool onoff)
{
//
// Loop over all the expert settings windows and either
// show or hide them...
//
for (int index = 0; index < ExpertWindowList.Count (); index ++) {
::ShowWindow (ExpertWindowList[index], onoff ? SW_SHOW : SW_HIDE);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnExpertCheck
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::OnExpertCheck (void)
{
bool enabled = bool(SendDlgItemMessage (IDC_EXPERT_CHECK, BM_GETCHECK) == 1);
Display_Expert_Settings (enabled);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Setup_Controls
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::Setup_Controls (void)
{
//
// Configure the main performance slider
//
m_PerformanceSlider.SetRange (0, MAX_PERFORMANCE_LEVELS - 1);
//
// Configure the individual detail-setting sliders
//
m_CharShadowsSlider.SetRange (0, 3);
m_GeometrySlider.SetRange (0, 2);
m_TextureDetailSlider.SetRange (0, 2);
m_SurfaceEffectsSlider.SetRange (0, 2);
m_ParticleSlider.SetRange (0, 2);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Load_Values
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::Load_Values (void)
{
//
// Attempt to open the registry key
//
RegistryClass registry (KEY_NAME_SETTINGS);
if (registry.Is_Valid ()) {
//
// Read the values from the registry
//
int dynamic_lod = registry.Get_Int (VALUE_NAME_DYN_LOD, 3000);
int static_lod = registry.Get_Int (VALUE_NAME_STATIC_LOD, 3000);
int dynamic_shadows = registry.Get_Int (VALUE_NAME_DYN_SHADOWS, 1);
int static_shadows = registry.Get_Int (VALUE_NAME_STATIC_SHADOWS, 1);
int prelit_mode = registry.Get_Int (VALUE_NAME_PRELIT_MODE, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE);
int texture_filter = registry.Get_Int (VALUE_NAME_TEXTURE_FILTER, TextureClass::TEXTURE_FILTER_BILINEAR);
int shadow_mode = registry.Get_Int (VALUE_NAME_SHADOW_MODE, PhysicsSceneClass::SHADOW_MODE_BLOBS_PLUS);
int texture_red = registry.Get_Int (VALUE_NAME_TEXTURE_RES, 0);
int surface_effect = registry.Get_Int (VALUE_NAME_SURFACE_EFFECT, 1);
int particle_detail = registry.Get_Int (VALUE_NAME_PARTICLE_DETAIL, 1);
//
// Set the slider's positions to reflect the loaded values
//
m_CharShadowsSlider.SetPos (min (shadow_mode, 3));
m_TextureDetailSlider.SetPos (max (2 - texture_red, 0));
m_SurfaceEffectsSlider.SetPos (surface_effect);
m_ParticleSlider.SetPos (particle_detail);
//
// Choose a setting for the geometry slider based on
// the dynamic and static LOD budgets
//
if (dynamic_lod < 1000 && static_lod < 1000) {
m_GeometrySlider.SetPos (0);
} else if (dynamic_lod <= 5000 && static_lod <= 5000) {
m_GeometrySlider.SetPos (1);
} else {
m_GeometrySlider.SetPos (2);
}
//
// Check the checkbox controls (if necessary)
//
SendDlgItemMessage (IDC_TERRAIN_SHADOW_CHECK, BM_SETCHECK, (WPARAM)(static_shadows != 0));
//
// Select the correct setting from the lighting mode combo box
//
SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_SETCURSEL, prelit_mode);
//
// Select the correct setting from the texture filtering mode combo box
//
SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_SETCURSEL, texture_filter);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Determine_Performance_Setting
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::Determine_Performance_Setting (void)
{
float option_levels[MAX_EXPERT_OPTIONS] = { 0 };
int count_per_option[MAX_EXPERT_OPTIONS] = { 0 };
//
// Get the current values of each setting
//
DynamicVectorClass<int> option_values;
Get_Settings (option_values);
//
// Find out which level each option is currently set at
//
for (int level = MAX_PERFORMANCE_LEVELS - 1; level >= 0; level --) {
for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) {
//
// If the values match, then record the current level for this option
//
if (option_values[index] == _PerformanceLevels[level][index].value) {
option_levels[index] += level;
count_per_option[index] ++;
}
}
}
//
// Add up all the levels
//
float level_sum = 0;
for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) {
level_sum += (option_levels[index] / count_per_option[index]);
}
//
// Take the average rating
//
float level_rating = level_sum / MAX_EXPERT_OPTIONS;
//
// Set the slider's position
//
m_PerformanceSlider.SetPos (min (int(level_rating + 0.5F), MAX_EXPERT_OPTIONS - 1));
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Settings
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::Get_Settings (DynamicVectorClass<int> &settings)
{
//
// Determine what the value of each control is
//
for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) {
//
// Determine what the value of this control is
//
int curr_value = 0;
int ctrl_id = _PerformanceLevels[0][index].ctrl_id;
switch (ctrl_id) {
//
// Read any of the slider positions
//
case IDC_GEOMETRY_DETAIL_SLIDER:
case IDC_CHAR_SHADOWS_SLIDER:
case IDC_TEXTURE_DETAIL_SLIDER:
case IDC_PARTICLE_DETAIL_SLIDER:
case IDC_SURFACE_DETAIL_SLIDER:
curr_value = SendDlgItemMessage (ctrl_id, TBM_GETPOS);
break;
//
// Read the values from the checkbox
//
case IDC_TERRAIN_SHADOW_CHECK:
curr_value = SendDlgItemMessage (ctrl_id, BM_GETCHECK);
break;
//
// Read a value from a combo box.
//
case IDC_LIGHTING_MODE_COMBO:
case IDC_TEXTURE_FILTER_COMBO:
curr_value = SendDlgItemMessage (ctrl_id, CB_GETCURSEL);
break;
}
//
// Add this value to the list
//
settings.Add (curr_value);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Expert_Controls
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::Update_Expert_Controls (int level)
{
for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) {
//
// Determine which control we are updating
//
int ctrl_id = _PerformanceLevels[level][index].ctrl_id;
switch (ctrl_id) {
//
// Update any of the sliders via the same mechanism
//
case IDC_GEOMETRY_DETAIL_SLIDER:
case IDC_CHAR_SHADOWS_SLIDER:
case IDC_TEXTURE_DETAIL_SLIDER:
case IDC_PARTICLE_DETAIL_SLIDER:
case IDC_SURFACE_DETAIL_SLIDER:
SendDlgItemMessage (ctrl_id, TBM_SETPOS, TRUE, _PerformanceLevels[level][index].value);
break;
//
// Update any of the check boxes via the same mechanism
//
case IDC_TERRAIN_SHADOW_CHECK:
SendDlgItemMessage (ctrl_id, BM_SETCHECK, _PerformanceLevels[level][index].value);
break;
//
// Update any of the combo boxes.
//
case IDC_LIGHTING_MODE_COMBO:
case IDC_TEXTURE_FILTER_COMBO:
SendDlgItemMessage (ctrl_id, CB_SETCURSEL, _PerformanceLevels[level][index].value);
break;
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnHScroll
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::OnHScroll
(
UINT nSBCode,
UINT nPos,
CScrollBar * pScrollBar
)
{
int ctrl_id = ::GetWindowLong (pScrollBar->m_hWnd, GWL_ID);
//
// If this is the overall performance slider, then
// update the expert controls to reflect the new setting
//
if (ctrl_id == IDC_PERFORMANCE_SLIDER) {
int new_level = m_PerformanceSlider.GetPos ();
Update_Expert_Controls (new_level);
}
CDialog::OnHScroll (nSBCode, nPos, pScrollBar);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Apply_Changes
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::Apply_Changes (void)
{
//
// Attempt to open the registry key
//
RegistryClass registry (KEY_NAME_SETTINGS);
if (registry.Is_Valid ()) {
//
// Get the current settings from the dialog
//
int geometry_detail = m_GeometrySlider.GetPos ();
int shadow_mode = m_CharShadowsSlider.GetPos ();
int texture_red = m_TextureDetailSlider.GetPos ();
int surface_effect = m_SurfaceEffectsSlider.GetPos ();
int particle_detail = m_ParticleSlider.GetPos ();
int static_shadows = SendDlgItemMessage (IDC_TERRAIN_SHADOW_CHECK, BM_GETCHECK);
int prelit_mode = SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_GETCURSEL);
// If card can't do multi-pass, value 1 means multi-texture (multi-pass selection is missing from the combo box)
if (!CanDoMultiPass) {
if (prelit_mode==1) prelit_mode=WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE;
}
int texture_filter = SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_GETCURSEL);
//
// Determine a good LOD budget to use
//
int lod_budget = 0;
if (geometry_detail == 0) {
lod_budget = 0;
} else if (geometry_detail == 1) {
lod_budget = 5000;
} else if (geometry_detail == 2) {
lod_budget = 10000;
}
//
// Store the values in the registry
//
registry.Set_Int (VALUE_NAME_DYN_LOD, lod_budget);
registry.Set_Int (VALUE_NAME_STATIC_LOD, lod_budget);
registry.Set_Int (VALUE_NAME_DYN_SHADOWS, (shadow_mode != PhysicsSceneClass::SHADOW_MODE_NONE));
registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, static_shadows);
registry.Set_Int (VALUE_NAME_PRELIT_MODE, prelit_mode);
registry.Set_Int (VALUE_NAME_TEXTURE_FILTER, texture_filter);
registry.Set_Int (VALUE_NAME_SHADOW_MODE, shadow_mode);
registry.Set_Int (VALUE_NAME_TEXTURE_RES, max (2 - texture_red, 0));
registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, surface_effect);
registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, particle_detail);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// WindowProc
//
/////////////////////////////////////////////////////////////////////////////
LRESULT
PerformanceConfigDialogClass::WindowProc
(
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
if (message == (WM_USER + 101)) {
Apply_Changes ();
}
return CDialog::WindowProc(message, wParam, lParam);
}
/*
//If really low texture memory such as 4 Mb (if possible to detect) set level 2
- If multtexturing available, default to multitextured lighting, otherwise multi pass
- If a low end card, default to vertex solve
- Default to 640x480, 800x600 or 1024x768 depending on video card
- Default to 32 bit display on HW T&L cards, 16 bit otherwise
- Default to fullscreen (do we even support windowed mode in the release?)
- The same for particle detail
*/
void AutoConfigSettings();
void PerformanceConfigDialogClass::OnGraphicsAutoSetup()
{
// TODO: Add your control notification handler code here
AutoConfigSettings();
Load_Values();
// Apply_Changes();
};
/*
registry.Set_Int (VALUE_NAME_DYN_LOD, lod_budget);
registry.Set_Int (VALUE_NAME_STATIC_LOD, lod_budget);
registry.Set_Int (VALUE_NAME_DYN_SHADOWS, (shadow_mode != PhysicsSceneClass::SHADOW_MODE_NONE));
registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, static_shadows);
registry.Set_Int (VALUE_NAME_PRELIT_MODE, prelit_mode);
registry.Set_Int (VALUE_NAME_SHADOW_MODE, shadow_mode);
registry.Set_Int (VALUE_NAME_TEXTURE_RES, max (2 - texture_red, 0));
registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, surface_effect);
registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, particle_detail);
*/
void AutoConfigSettings()
{
//
// Attempt to open the registry key
//
RegistryClass registry (KEY_NAME_SETTINGS);
if (!registry.Is_Valid()) return;
// Access registry key "Render"
RegistryClass render_registry(RENEGADE_SUB_KEY_NAME_RENDER);
if ( !render_registry.Is_Valid() ) {
return;
}
IDirect3D8* d3d=NULL;
D3DCAPS8 tmp_caps;
const D3DCAPS8* d3dcaps=NULL;
D3DADAPTER_IDENTIFIER8 adapter_id;
D3DFORMAT display_format;
VideoConfigDialogClass* video=VideoConfigDialogClass::Get_Instance();
if (video) {
WW3D::Set_Texture_Bitdepth(16);
render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, 16 );
d3d=DX8Wrapper::_Get_D3D8();
d3d->AddRef();
d3dcaps=&video->Get_Current_Caps();
adapter_id=video->Get_Current_Adapter_Identifier();
if (video->Get_Current_Bit_Depth()==32) {
display_format=D3DFMT_X8R8G8B8;
}
else {
display_format=D3DFMT_R5G6B5;
}
}
else {
// Init D3D
Init_D3D_To_WW3_Conversion();
d3d=Direct3DCreate8(D3D_SDK_VERSION); // TODO: handle failure cases...
if (!d3d) {
return;
}
// Select device. If there is already a device selected in the registry, use it.
int current_adapter_index=D3DADAPTER_DEFAULT;
//
// Load the render device settings from the registry
//
char device_name[256] = { 0 };
render_registry.Get_String( VALUE_NAME_RENDER_DEVICE_NAME, device_name, sizeof(device_name));
int adapter_count = d3d->GetAdapterCount();
for (int adapter_index=0; adapter_index<adapter_count; adapter_index++) {
D3DADAPTER_IDENTIFIER8 id;
::ZeroMemory(&id, sizeof(D3DADAPTER_IDENTIFIER8));
HRESULT res = d3d->GetAdapterIdentifier(adapter_index,D3DENUM_NO_WHQL_LEVEL,&id);
// If device ok, check if it matches the currently set adapter name
if (res == D3D_OK) {
StringClass name(id.Description,true);
if (name==device_name) {
current_adapter_index=adapter_index;
break;
}
}
}
if (FAILED(d3d->GetDeviceCaps(
current_adapter_index,
D3DDEVTYPE_HAL,
&tmp_caps))) {
d3d->Release();
return;
}
::ZeroMemory(&adapter_id, sizeof(D3DADAPTER_IDENTIFIER8));
if (FAILED( d3d->GetAdapterIdentifier(
current_adapter_index,
D3DENUM_NO_WHQL_LEVEL,
&adapter_id))) {
d3d->Release();
return;
}
// Store device name in registry
render_registry.Set_String( VALUE_NAME_RENDER_DEVICE_NAME, adapter_id.Description);
// Set resolution to 800 x 600 x 16
render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_WIDTH, 800 );
render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_HEIGHT, 600 );
render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, 16 );
render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_WINDOWED, 0 );
render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, 16 );
d3dcaps=&tmp_caps;
display_format=D3DFMT_R5G6B5;
// Test if the card if new enough to do 32 bit...
DX8Caps tmp_caps(d3d,*d3dcaps,WW3D_FORMAT_UNKNOWN,adapter_id);
switch (tmp_caps.Get_Vendor()) {
default:
break;
case DX8Caps::VENDOR_NVIDIA:
switch (tmp_caps.Get_Device()) {
default:
display_format=D3DFMT_X8R8G8B8;
render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, 32 );
break;
case DX8Caps::DEVICE_NVIDIA_TNT2_ALADDIN:
case DX8Caps::DEVICE_NVIDIA_TNT2:
case DX8Caps::DEVICE_NVIDIA_TNT2_ULTRA:
case DX8Caps::DEVICE_NVIDIA_TNT2_VANTA:
case DX8Caps::DEVICE_NVIDIA_TNT2_M64:
case DX8Caps::DEVICE_NVIDIA_TNT:
case DX8Caps::DEVICE_NVIDIA_RIVA_128:
case DX8Caps::DEVICE_NVIDIA_TNT_VANTA:
case DX8Caps::DEVICE_NVIDIA_NV1:
break;
}
break;
case DX8Caps::VENDOR_ATI:
switch (tmp_caps.Get_Device()) {
case DX8Caps::DEVICE_ATI_RAGE_II:
case DX8Caps::DEVICE_ATI_RAGE_II_PLUS:
case DX8Caps::DEVICE_ATI_RAGE_IIC_PCI:
case DX8Caps::DEVICE_ATI_RAGE_IIC_AGP:
case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY:
case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M3:
case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M4:
case DX8Caps::DEVICE_ATI_RAGE_128_PRO_ULTRA:
case DX8Caps::DEVICE_ATI_RAGE_128_4X:
case DX8Caps::DEVICE_ATI_RAGE_128_PRO_GL:
case DX8Caps::DEVICE_ATI_RAGE_128_PRO_VR:
case DX8Caps::DEVICE_ATI_RAGE_128_GL:
case DX8Caps::DEVICE_ATI_RAGE_128_VR:
case DX8Caps::DEVICE_ATI_RAGE_PRO:
case DX8Caps::DEVICE_ATI_RAGE_PRO_MOBILITY:
break;
default:
display_format=D3DFMT_X8R8G8B8;
render_registry.Set_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, 32 );
break;
}
break;
}
}
DX8Caps caps(d3d,*d3dcaps,D3DFormat_To_WW3DFormat(display_format),adapter_id);
CanDoMultiPass=caps.Can_Do_Multi_Pass();
bool high_end_processor=CPUDetectClass::Has_SSE_Instruction_Set();
if (CPUDetectClass::Get_Processor_Manufacturer()==CPUDetectClass::MANUFACTURER_AMD &&
CPUDetectClass::Get_AMD_Processor()>=CPUDetectClass::AMD_PROCESSOR_ATHLON_025) {
high_end_processor=true;
}
// If no texture compression, default to texture resolution 1
if (caps.Support_DXTC()) {
registry.Set_Int (VALUE_NAME_TEXTURE_RES, 0);
}
else {
registry.Set_Int (VALUE_NAME_TEXTURE_RES, 1);
}
// High geometry detail on T&L cards, medium on fast processors and low on slow ones
if (caps.Support_TnL()) {
registry.Set_Int (VALUE_NAME_DYN_LOD, 10000);
registry.Set_Int (VALUE_NAME_STATIC_LOD, 10000);
}
else {
// If T&L hardware present, set to medium or low. Set to medium if high end cpu.
// TODO: Set to medium if Athlon detected.
if (high_end_processor) {
registry.Set_Int (VALUE_NAME_DYN_LOD, 5000);
registry.Set_Int (VALUE_NAME_STATIC_LOD, 5000);
}
else {
registry.Set_Int (VALUE_NAME_DYN_LOD, 0);
registry.Set_Int (VALUE_NAME_STATIC_LOD, 0);
}
}
// Set high shadow detail if render to texture is supported AND HWTL available
// Set medium shadow detail if render to texture is supported but no HWTL
// Set low shadow detail if no render to texture is available
if (caps.Support_Render_To_Texture_Format(D3DFormat_To_WW3DFormat(display_format))) {
if (caps.Support_TnL()) {
registry.Set_Int (VALUE_NAME_SHADOW_MODE, 3);
registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, 1);
}
else {
registry.Set_Int (VALUE_NAME_SHADOW_MODE, 2);
registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, 0);
}
}
else {
registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, 0);
// Set to medium if high end cpu detected.
// TODO: Set to medium if Athlon detected.
if (high_end_processor) {
registry.Set_Int (VALUE_NAME_SHADOW_MODE, 1);
}
else {
registry.Set_Int (VALUE_NAME_SHADOW_MODE, 0);
}
}
// If a low end system turn surface effects off
if (caps.Support_TnL()) {
registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, 2);
}
else {
// Set to medium if high end cpu detected.
// TODO: Set to medium if Athlon detected.
if (high_end_processor) {
registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, 1);
}
else {
registry.Set_Int (VALUE_NAME_SURFACE_EFFECT, 0);
}
}
// If HWTL and high end cpu, use highest particle detail
if (caps.Support_TnL() && high_end_processor) {
registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, 2);
}
// If one or the other, use medium particle detail
else if (caps.Support_TnL() || high_end_processor) {
registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, 1);
}
else {
registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, 0);
}
// If the system has less than 100 Megs (64 or 96 most likely) of RAM, select vertex solve to
// save memory.
// If card can't do multi pass (which is the case if we've seen z-fighting problems when multi-passing)
// select vertex solve.
if (!caps.Can_Do_Multi_Pass() || CPUDetectClass::Get_Total_Physical_Memory()<100*1024*1024) {
registry.Set_Int (VALUE_NAME_PRELIT_MODE, 0);
}
// Otherwise select multitexturing if card can do it, or multipass...
else {
if (caps.Get_Max_Textures_Per_Pass()>=2) {
registry.Set_Int (VALUE_NAME_PRELIT_MODE, 2);
}
else {
registry.Set_Int (VALUE_NAME_PRELIT_MODE, 1);
}
}
RegistryClass registry_options (KEY_NAME_OPTIONS);
if (!registry_options.Is_Valid()) return;
// The uv bias setting for most of the cards
// (PowerVR Kyro and Kyro II and ATI Rage Pro need different UV bias and the rest of the cards.)
registry_options.Set_Int( "ScreenUVBias", 1 );
switch (caps.Get_Vendor()) {
default:
registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,0); // Most cards default to bilinear filtering
break;
case DX8Caps::VENDOR_NVIDIA:
switch (caps.Get_Device()) {
case DX8Caps::DEVICE_NVIDIA_TNT2_ALADDIN:
case DX8Caps::DEVICE_NVIDIA_TNT2:
case DX8Caps::DEVICE_NVIDIA_TNT2_ULTRA:
case DX8Caps::DEVICE_NVIDIA_TNT2_VANTA:
case DX8Caps::DEVICE_NVIDIA_TNT2_M64:
case DX8Caps::DEVICE_NVIDIA_TNT:
case DX8Caps::DEVICE_NVIDIA_RIVA_128:
case DX8Caps::DEVICE_NVIDIA_TNT_VANTA:
case DX8Caps::DEVICE_NVIDIA_NV1:
registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,0);
break;
default:
registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,1); // New NVidia cards default to trilinear
}
break;
case DX8Caps::VENDOR_ATI:
switch (caps.Get_Device()) {
case DX8Caps::DEVICE_ATI_RAGE_II:
case DX8Caps::DEVICE_ATI_RAGE_II_PLUS:
case DX8Caps::DEVICE_ATI_RAGE_IIC_PCI:
case DX8Caps::DEVICE_ATI_RAGE_IIC_AGP:
case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY:
case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M3:
case DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M4:
case DX8Caps::DEVICE_ATI_RAGE_128_PRO_ULTRA:
case DX8Caps::DEVICE_ATI_RAGE_128_4X:
case DX8Caps::DEVICE_ATI_RAGE_128_PRO_GL:
case DX8Caps::DEVICE_ATI_RAGE_128_PRO_VR:
case DX8Caps::DEVICE_ATI_RAGE_128_GL:
case DX8Caps::DEVICE_ATI_RAGE_128_VR:
case DX8Caps::DEVICE_ATI_RAGE_PRO:
case DX8Caps::DEVICE_ATI_RAGE_PRO_MOBILITY:
registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,0);
// It seems the bias needs to be adjusted on Rage128 as well...
if (caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_PRO ||
caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_PRO_MOBILITY ||
caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY ||
caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M3 ||
caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_128_MOBILITY_M4 ||
caps.Get_Device()==DX8Caps::DEVICE_ATI_RAGE_128_PRO_ULTRA) {
registry_options.Set_Int( "ScreenUVBias", 0 );
}
break;
default:
registry.Set_Int(VALUE_NAME_TEXTURE_FILTER,1); // New ATI cards default to trilinear
break;
}
break;
case DX8Caps::VENDOR_POWERVR:
// not sure how this goes. Kyro at the office requires 1, but some other powervr
// card seems to require 0...
registry_options.Set_Int( "ScreenUVBias", 0 );
switch (caps.Get_Device()) {
case DX8Caps::DEVICE_POWERVR_KYRO:
registry_options.Set_Int( "ScreenUVBias", 1 );
break;
}
break;
}
d3d->Release();
}
/////////////////////////////////////////////////////////////////////////////
//
// OnShowWindow
//
// Modified: 12/06/2001 by MML - Retrieving strings from Locomoto file.
//
/////////////////////////////////////////////////////////////////////////////
void
PerformanceConfigDialogClass::OnShowWindow(BOOL bShow, UINT nStatus)
{
char string[ _MAX_PATH ];
CDialog::OnShowWindow(bShow, nStatus);
if (bShow) {
//
// Insert code here
//
RegistryClass registry (KEY_NAME_SETTINGS);
if (!registry.Is_Valid ()) return;
VideoConfigDialogClass* video=VideoConfigDialogClass::Get_Instance();
if (video) {
IDirect3D8* d3d=DX8Wrapper::_Get_D3D8();
d3d->AddRef();
D3DADAPTER_IDENTIFIER8 adapter_id=video->Get_Current_Adapter_Identifier();
D3DFORMAT display_format;
if (video->Get_Current_Bit_Depth()==32) {
display_format=D3DFMT_X8R8G8B8;
}
else {
display_format=D3DFMT_R5G6B5;
}
DX8Caps caps(d3d,video->Get_Current_Caps(),D3DFormat_To_WW3DFormat(display_format),adapter_id);
CanDoMultiPass=caps.Can_Do_Multi_Pass();
//
// Populate the lighting combobox
//
// Get the current selection
char cur_sel_string[256];
unsigned sel=SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_GETCURSEL, 0, 0);
if (sel!=CB_ERR) {
SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_GETLBTEXT, sel, (LPARAM)cur_sel_string);
}
else {
cur_sel_string[0]=0;
sel=registry.Get_Int (VALUE_NAME_PRELIT_MODE, WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE);
}
// Reset content and add available modes
SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_RESETCONTENT, 0, 0);
SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)Locale_GetString( IDS_VERTEX, string ));
if (caps.Can_Do_Multi_Pass()) {
SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)Locale_GetString( IDS_MULTI_PASS, string ));
}
if (caps.Get_Max_Textures_Per_Pass()>1) {
SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)Locale_GetString( IDS_MULTI_TEXTURE, string ));
}
// Try to set the previous selection
unsigned res=SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_FINDSTRINGEXACT, -1, (LPARAM)cur_sel_string);
if (res==CB_ERR) {
if (sel==0) res=0;
else {
res=SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_GETCOUNT, 0, 0)-1;
if (sel<res) res=sel;
}
}
SendDlgItemMessage (IDC_LIGHTING_MODE_COMBO, CB_SETCURSEL, res, 0);
//
// Populate the texture filtering combobox
//
// Get the current selection
sel=SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_GETCURSEL, 0, 0);
if (sel!=CB_ERR) {
SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_GETLBTEXT, sel, (LPARAM)cur_sel_string);
}
else {
cur_sel_string[0]=0;
sel=registry.Get_Int (VALUE_NAME_TEXTURE_FILTER, TextureClass::TEXTURE_FILTER_BILINEAR);
}
SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_RESETCONTENT, 0, 0);
SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_ADDSTRING, 0, (LPARAM)Locale_GetString( IDS_BILINEAR, string ));
SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_ADDSTRING, 0, (LPARAM)Locale_GetString( IDS_TRILINEAR, string ));
if (caps.Support_Anisotropic_Filtering()) {
SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_ADDSTRING, 0, (LPARAM)Locale_GetString( IDS_ANISOTROPIC, string ));
}
// Try to set the previous selection
res=SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_FINDSTRINGEXACT, -1, (LPARAM)cur_sel_string);
if (res==CB_ERR) {
if (sel==0) res=0;
else {
res=SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_GETCOUNT, 0, 0)-1;
if (sel<res) res=sel;
}
}
SendDlgItemMessage (IDC_TEXTURE_FILTER_COMBO, CB_SETCURSEL, res, 0);
d3d->Release();
Determine_Performance_Setting ();
}
}
return ;
}