Serious-Engine/Sources/Engine/Graphics/GfxLibrary.cpp
Daniel Gibson 72edf1c720 Commented out unused functions and variables
many unused functions and variables are now commented out

You'll still get tons of warnings, which should mostly fall in one of
the following categories:
1. Unnecessary variables or values generated from .es scripts
2. Pointers assigned to from functions with side-effects: DO NOT REMOVE!
   Like CEntity *penNew = CreateEntity_t(...); - even if penNew isn't
   used, CreateEntity() must be called there!
2016-05-09 18:51:03 +02:00

2183 lines
80 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as published by
the Free Software Foundation
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#include "Engine/StdH.h"
#include <Engine/Graphics/GfxLibrary.h>
#include <Engine/Base/Translation.h>
#include <Engine/Base/ErrorReporting.h>
#include <Engine/Base/Console.h>
#include <Engine/Base/Shell.h>
#include <Engine/Base/Statistics_Internal.h>
#include <Engine/Base/ListIterator.inl>
#include <Engine/Math/Functions.h>
#include <Engine/Math/AABBox.h>
#include <Engine/Models/Normals.h>
#include <Engine/Sound/SoundLibrary.h>
#include <Engine/Templates/Stock_CModelData.h>
#include <Engine/Graphics/OpenGL.h>
#include <Engine/Graphics/Adapter.h>
#include <Engine/Graphics/ShadowMap.h>
#include <Engine/Graphics/Texture.h>
#include <Engine/Graphics/GfxProfile.h>
#include <Engine/Graphics/Raster.h>
#include <Engine/Graphics/ViewPort.h>
#include <Engine/Graphics/DrawPort.h>
#include <Engine/Graphics/Color.h>
#include <Engine/Graphics/Font.h>
#include <Engine/Graphics/MultiMonitor.h>
#include <Engine/Templates/DynamicStackArray.h>
#include <Engine/Templates/DynamicStackArray.cpp>
#include <Engine/Templates/DynamicContainer.cpp>
#include <Engine/Templates/Stock_CTextureData.h>
// !!! FIXME: rcg10112001 This just screams to be broken up into subclasses.
// !!! FIXME: rcg10112001 That would get rid of all the #ifdef'ing and
// !!! FIXME: rcg10112001 the need to continually assert that the current
// !!! FIXME: rcg10112001 driver type is valid.
// !!! FIXME: rcg11052001 ... and I could get rid of this, too...
#ifdef PLATFORM_UNIX
#include <SDL.h>
#endif
// control for partial usage of compiled vertex arrays
BOOL CVA_b2D = FALSE;
BOOL CVA_bWorld = FALSE;
BOOL CVA_bModels = FALSE;
// common element arrays
CStaticStackArray<GFXVertex> _avtxCommon;
CStaticStackArray<GFXTexCoord> _atexCommon;
CStaticStackArray<GFXColor> _acolCommon;
CStaticStackArray<INDEX> _aiCommonElements;
CStaticStackArray<INDEX> _aiCommonQuads; // predefined array for rendering quads thru triangles in glDrawElements()
// global texture parameters
CTexParams _tpGlobal[GFX_MAXTEXUNITS];
// pointer to global graphics library object
CGfxLibrary *_pGfx = NULL;
// forced texture upload quality (0 = default, 16 = force 16-bit, 32 = force 32-bit)
INDEX _iTexForcedQuality = 0;
extern PIX _fog_pixSizeH;
extern PIX _fog_pixSizeL;
extern PIX _haze_pixSize;
// control for partial usage of compiled vertex arrays
extern BOOL CVA_b2D;
extern BOOL CVA_bWorld;
extern BOOL CVA_bModels;
// gamma control
static FLOAT _fLastBrightness, _fLastContrast, _fLastGamma;
static FLOAT _fLastBiasR, _fLastBiasG, _fLastBiasB;
static INDEX _iLastLevels;
#ifdef PLATFORM_WIN32 // DG: not used on other platforms
static UWORD _auwGammaTable[256*3];
#endif
// table for clipping [-512..+1024] to [0..255]
static UBYTE aubClipByte[256*2+ 256 +256*3];
const UBYTE *pubClipByte = &aubClipByte[256*2];
// fast square root and 1/sqrt tables
UBYTE aubSqrt[SQRTTABLESIZE];
UWORD auw1oSqrt[SQRTTABLESIZE];
// table for conversion from compressed 16-bit gouraud normals to 8-bit
UBYTE aubGouraudConv[16384];
// flag for scene rendering in progress (i.e. between 1st lock in frame & swap-buffers)
static BOOL GFX_bRenderingScene = FALSE;
// ID of the last drawport that has been locked
static ULONG GFX_ulLastDrawPortID = 0;
// last size of vertex buffers
INDEX _iLastVertexBufferSize = 0;
// pretouch flag
extern BOOL _bNeedPretouch;
// flat texture
CTextureData *_ptdFlat = NULL;
static ULONG _ulWhite = 0xFFFFFFFF;
// fast sin/cos table
static FLOAT afSinTable[256+256+64];
const FLOAT *pfSinTable = afSinTable +256;
const FLOAT *pfCosTable = afSinTable +256+64;
// texture/shadow control
INDEX tex_iNormalQuality = 00; // 0=optimal, 1=16bit, 2=32bit, 3=compressed (1st num=opaque tex, 2nd=alpha tex)
INDEX tex_iAnimationQuality = 11; // 0=optimal, 1=16bit, 2=32bit, 3=compressed (1st num=opaque tex, 2nd=alpha tex)
INDEX tex_iNormalSize = 9; // log2 of texture area /2 for max texture size allowed
INDEX tex_iAnimationSize = 7;
INDEX tex_iEffectSize = 7;
INDEX tex_bDynamicMipmaps = FALSE; // how many mipmaps will be bilineary filtered (0-15)
INDEX tex_iDithering = 3; // 0=none, 1-3=low, 4-7=medium, 8-10=high
INDEX tex_bCompressAlphaChannel = FALSE; // for compressed textures, compress alpha channel too
INDEX tex_bAlternateCompression = FALSE; // basically, this is fix for GFs (compress opaque texture as translucent)
INDEX tex_bFineEffect = FALSE; // 32bit effect? (works only if base texture hasn't been dithered)
INDEX tex_bFineFog = TRUE; // should fog be 8/32bit? (or just plain 4/16bit)
INDEX tex_iFogSize = 7; // limit fog texture size
INDEX tex_iFiltering = 0; // -6 - +6; negative = sharpen, positive = blur, 0 = none
INDEX tex_iEffectFiltering = +4; // filtering of fire effect textures
INDEX tex_bProgressiveFilter = FALSE; // filter mipmaps in creation time (not afterwards)
INDEX tex_bColorizeMipmaps = FALSE; // DEBUG: colorize texture's mipmap levels in various colors
INDEX shd_iStaticSize = 8;
INDEX shd_iDynamicSize = 8;
INDEX shd_bFineQuality = FALSE;
INDEX shd_iFiltering = 3; // >0 = blurring, 0 = no filtering
INDEX shd_iDithering = 1; // 0=none, 1,2=low, 3,4=medium, 5=high
INDEX shd_iAllowDynamic = 1; // 0=disallow, 1=allow on polys w/o 'NoDynamicLights' flag, 2=allow unconditionally
INDEX shd_bDynamicMipmaps = TRUE;
FLOAT shd_tmFlushDelay = 30.0f; // in seconds
FLOAT shd_fCacheSize = 8.0f; // in megabytes
INDEX shd_bCacheAll = FALSE; // cache all shadowmap at the level loading time (careful - memory eater!)
INDEX shd_bAllowFlats = TRUE; // allow optimization of single-color shadowmaps
INDEX shd_iForceFlats = 0; // force all shadowmaps to be flat (internal!) - 0=don't, 1=w/o overbrighting, 2=w/ overbrighting
INDEX shd_bShowFlats = FALSE; // show shadows that have been optimized as flat
INDEX shd_bColorize = FALSE; // colorize shadows by size (gradieng from red=big to green=little)
// OpenGL control
INDEX ogl_iTextureCompressionType = 1; // 0=none, 1=default (ARB), 2=S3TC, 3=FXT1, 4=old S3TC
INDEX ogl_bUseCompiledVertexArrays = 101; // =XYZ; X=2D, Y=world, Z=models
INDEX ogl_bAllowQuadArrays = FALSE;
INDEX ogl_bExclusive = TRUE;
INDEX ogl_bGrabDepthBuffer = FALSE;
INDEX ogl_iMaxBurstSize = 0; // unlimited
INDEX ogl_bTruformLinearNormals = TRUE;
INDEX ogl_bAlternateClipPlane = FALSE; // signal when user clip plane requires a texture unit
INDEX ogl_iTBufferEffect = 0; // 0=none, 1=partial FSAA, 2=Motion Blur
INDEX ogl_iTBufferSamples = 2; // 2, 4 or 8 (for now)
INDEX ogl_iFinish = 1; // 0=never, 1=before rendering of next frame, 2=at the end of this frame, 3=at projection change
// Direct3D control
INDEX d3d_bUseHardwareTnL = TRUE;
INDEX d3d_bAlternateDepthReads = FALSE; // should check delayed depth reads at the end of current frame (FALSE) or at begining of the next (TRUE)
INDEX d3d_bOptimizeVertexBuffers = TRUE; // enables circular buffers
INDEX d3d_iVertexBuffersSize = 1024; // KBs reserved for vertex buffers
INDEX d3d_iVertexRangeTreshold = 99; // minimum vertices in buffer that triggers range optimization
INDEX d3d_iMaxBurstSize = 0; // 0=unlimited
INDEX d3d_iFinish = 0;
// API common controls
INDEX gap_iUseTextureUnits = 4;
INDEX gap_iTextureFiltering = 21; // bilinear by default
INDEX gap_iTextureAnisotropy = 1; // 1=isotropic, 2=min anisotropy
FLOAT gap_fTextureLODBias = 0.0f;
INDEX gap_bOptimizeStateChanges = TRUE;
INDEX gap_iOptimizeDepthReads = 1; // 0=imediately, 1=after frame, 2=every 0.1 seconds
INDEX gap_iOptimizeClipping = 2; // 0=no, 1=mirror plane only, 2=mirror and frustum
INDEX gap_bAllowGrayTextures = TRUE;
INDEX gap_bAllowSingleMipmap = TRUE;
INDEX gap_iSwapInterval = 0;
INDEX gap_iRefreshRate = 0;
INDEX gap_iDithering = 2; // 16-bit dithering: 0=none, 1=no alpha, 2=all
INDEX gap_bForceTruform = 0; // 0 = only for models that allow truform, 1=for every model
INDEX gap_iTruformLevel = 3; // 0 = no tesselation
INDEX gap_iDepthBits = 0; // 0 (as color depth), 16, 24 or 32
INDEX gap_iStencilBits = 0; // 0 (no stencil buffer), 4 or 8
// models control
INDEX mdl_bShowTriangles = FALSE;
INDEX mdl_bShowStrips = FALSE;
INDEX mdl_bTruformWeapons = FALSE;
INDEX mdl_bCreateStrips = TRUE;
INDEX mdl_bRenderDetail = TRUE;
INDEX mdl_bRenderSpecular = TRUE;
INDEX mdl_bRenderReflection = TRUE;
INDEX mdl_bAllowOverbright = TRUE;
INDEX mdl_bFineQuality = TRUE;
INDEX mdl_iShadowQuality = 1;
FLOAT mdl_fLODMul = 1.0f;
FLOAT mdl_fLODAdd = 0.0f;
INDEX mdl_iLODDisappear = 1; // 0=never, 1=ignore bias, 2=with bias
// ska controls
INDEX ska_bShowSkeleton = FALSE;
INDEX ska_bShowColision = FALSE;
FLOAT ska_fLODMul = 1.0f;
FLOAT ska_fLODAdd = 0.0f;
// terrain controls
INDEX ter_bShowQuadTree = FALSE;
INDEX ter_bShowWireframe = FALSE;
INDEX ter_bLerpVertices = TRUE;
INDEX ter_bShowInfo = FALSE;
INDEX ter_bOptimizeRendering = TRUE;
INDEX ter_bTempFreezeCast = FALSE;
INDEX ter_bNoRegeneration = FALSE;
// !!! FIXME : rcg11232001 Hhmm...I'm failing an assertion in the
// !!! FIXME : rcg11232001 Advanced Rendering Options menu because
// !!! FIXME : rcg11232001 Scripts/CustomOptions/GFX-AdvancedRendering.cfg
// !!! FIXME : rcg11232001 references non-existing cvars, so I'm adding them
// !!! FIXME : rcg11232001 here for now.
static INDEX mdl_bRenderBump = TRUE;
static FLOAT ogl_fTextureAnisotropy = 0.0f;
static FLOAT tex_fNormalSize = 0.0f;
// rendering control
INDEX wld_bAlwaysAddAll = FALSE;
INDEX wld_bRenderMirrors = TRUE;
INDEX wld_bRenderEmptyBrushes = TRUE;
INDEX wld_bRenderShadowMaps = TRUE;
INDEX wld_bRenderTextures = TRUE;
INDEX wld_bRenderDetailPolygons = TRUE;
INDEX wld_bTextureLayers = 111;
INDEX wld_bShowTriangles = FALSE;
INDEX wld_bShowDetailTextures = FALSE;
INDEX wld_iDetailRemovingBias = 3;
FLOAT wld_fEdgeOffsetI = 0.0f; //0.125f;
FLOAT wld_fEdgeAdjustK = 1.0f; //1.0001f;
INDEX gfx_bRenderWorld = TRUE;
INDEX gfx_bRenderParticles = TRUE;
INDEX gfx_bRenderModels = TRUE;
INDEX gfx_bRenderPredicted = FALSE;
INDEX gfx_bRenderFog = TRUE;
INDEX gfx_iLensFlareQuality = 3; // 0=none, 1=corona only, 2=corona and reflections, 3=corona, reflections and glare
INDEX gfx_bDecoratedText = TRUE;
INDEX gfx_bClearScreen = FALSE;
FLOAT gfx_tmProbeDecay = 30.00f; // seconds
INDEX gfx_iProbeSize = 256; // in KBs
INDEX gfx_ctMonitors = 0;
INDEX gfx_bMultiMonDisabled = FALSE;
INDEX gfx_bDisableMultiMonSupport = TRUE;
INDEX gfx_bDisableWindowsKeys = TRUE;
INDEX wed_bIgnoreTJunctions = FALSE;
INDEX wed_bUseBaseForReplacement = FALSE;
// some nifty features
INDEX gfx_iHueShift = 0; // 0-359
FLOAT gfx_fSaturation = 1.0f; // 0.0f = min, 1.0f = default
// the following vars can be influenced by corresponding gfx_ vars
INDEX tex_iHueShift = 0; // added to gfx_
FLOAT tex_fSaturation = 1.0f; // multiplied by gfx_
INDEX shd_iHueShift = 0; // added to gfx_
FLOAT shd_fSaturation = 1.0f; // multiplied by gfx_
// gamma table control
FLOAT gfx_fBrightness = 0.0f; // -0.9 - 0.9
FLOAT gfx_fContrast = 1.0f; // 0.1 - 1.9
FLOAT gfx_fGamma = 1.0f; // 0.1 - 9.0
FLOAT gfx_fBiasR = 1.0f; // 0.0 - 1.0
FLOAT gfx_fBiasG = 1.0f; // 0.0 - 1.0
FLOAT gfx_fBiasB = 1.0f; // 0.0 - 1.0
INDEX gfx_iLevels = 256; // 2 - 256
// stereo rendering control
INDEX gfx_iStereo = 0; // 0=off, 1=red/cyan
INDEX gfx_bStereoInvert = FALSE; // is left eye RED or CYAN
INDEX gfx_iStereoOffset = 10; // view offset (or something:)
FLOAT gfx_fStereoSeparation = 0.25f; // distance between eyes
// cached integers for faster calculation
SLONG _slTexSaturation = 256; // 0 = min, 256 = default
SLONG _slTexHueShift = 0;
SLONG _slShdSaturation = 256;
SLONG _slShdHueShift = 0;
// 'supported' console variable flags
static INDEX sys_bHasTextureCompression = 0;
static INDEX sys_bHasTextureAnisotropy = 0;
static INDEX sys_bHasAdjustableGamma = 0;
static INDEX sys_bHasTextureLODBias = 0;
static INDEX sys_bHasMultitexturing = 0;
static INDEX sys_bHas32bitTextures = 0;
static INDEX sys_bHasSwapInterval = 0;
static INDEX sys_bHasHardwareTnL = 1;
static INDEX sys_bHasTruform = 0;
static INDEX sys_bHasCVAs = 0;
static INDEX sys_bUsingOpenGL = 0;
INDEX sys_bUsingDirect3D = 0;
/*
* Low level hook flags
*/
#define WH_KEYBOARD_LL 13
#ifdef PLATFORM_WIN32
void EnableWindowsKeys(void);
#pragma message(">> doublecheck me!!!")
// these are commented because they are already defined in winuser.h
//#define LLKHF_EXTENDED 0x00000001
//#define LLKHF_INJECTED 0x00000010
//#define LLKHF_ALTDOWN 0x00000020
//#define LLKHF_UP 0x00000080
//#define LLMHF_INJECTED 0x00000001
/*
* Structure used by WH_KEYBOARD_LL
*/
// this is commented because there's a variant for this struct in winuser.h
/*typedef struct tagKBDLLHOOKSTRUCT {
DWORD vkCode;
DWORD scanCode;
DWORD flags;
DWORD time;
DWORD dwExtraInfo;
} KBDLLHOOKSTRUCT, FAR *LPKBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;*/
static HHOOK _hLLKeyHook = NULL;
LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LPARAM lParam)
{
// By returning a non-zero value from the hook procedure, the
// message does not get passed to the target window
KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
BOOL bControlKeyDown = 0;
switch (nCode)
{
case HC_ACTION:
{
// Check to see if the CTRL key is pressed
bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);
// Disable CTRL+ESC
if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown)
return 1;
// Disable ALT+TAB
if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
// Disable ALT+ESC
if (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
break;
}
default:
break;
}
return CallNextHookEx (_hLLKeyHook, nCode, wParam, lParam);
}
void DisableWindowsKeys(void)
{
//if( _hLLKeyHook!=NULL) UnhookWindowsHookEx(_hLLKeyHook);
//_hLLKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, &LowLevelKeyboardProc, NULL, GetCurrentThreadId());
INDEX iDummy;
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &iDummy, 0);
}
void EnableWindowsKeys(void)
{
INDEX iDummy;
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, FALSE, &iDummy, 0);
// if( _hLLKeyHook!=NULL) UnhookWindowsHookEx(_hLLKeyHook);
}
#else
#define DisableWindowsKeys()
#define EnableWindowsKeys()
#endif
// texture size reporting
static CTString ReportQuality( INDEX iQuality)
{
if( iQuality==0) return "optimal";
if( iQuality==1) return "16-bit";
if( iQuality==2) return "32-bit";
if( iQuality==3) return "compressed";
ASSERTALWAYS( "Invalid texture quality.");
return "?";
}
static void TexturesInfo(void)
{
UpdateTextureSettings();
INDEX ctNo04O=0, ctNo64O=0, ctNoMXO=0;
PIX pixK04O=0, pixK64O=0, pixKMXO=0;
SLONG slKB04O=0, slKB64O=0, slKBMXO=0;
INDEX ctNo04A=0, ctNo64A=0, ctNoMXA=0;
PIX pixK04A=0, pixK64A=0, pixKMXA=0;
SLONG slKB04A=0, slKB64A=0, slKBMXA=0;
// walk thru all textures on stock
{FOREACHINDYNAMICCONTAINER( _pTextureStock->st_ctObjects, CTextureData, ittd)
{ // get texture info
CTextureData &td = *ittd;
BOOL bAlpha = td.td_ulFlags&TEX_ALPHACHANNEL;
INDEX ctFrames = td.td_ctFrames;
SLONG slBytes = td.GetUsedMemory();
ASSERT( slBytes>=0);
// get texture size
PIX pixTextureSize = td.GetPixWidth() * td.GetPixHeight();
PIX pixMipmapSize = pixTextureSize;
if( !gap_bAllowSingleMipmap || td.td_ctFineMipLevels>1) pixMipmapSize = pixMipmapSize *4/3;
// increase corresponding counters
if( pixTextureSize<4096) {
if( bAlpha) { pixK04A+=pixMipmapSize; slKB04A+=slBytes; ctNo04A+=ctFrames; }
else { pixK04O+=pixMipmapSize; slKB04O+=slBytes; ctNo04O+=ctFrames; }
} else if( pixTextureSize<=65536) {
if( bAlpha) { pixK64A+=pixMipmapSize; slKB64A+=slBytes; ctNo64A+=ctFrames; }
else { pixK64O+=pixMipmapSize; slKB64O+=slBytes; ctNo64O+=ctFrames; }
} else {
if( bAlpha) { pixKMXA+=pixMipmapSize; slKBMXA+=slBytes; ctNoMXA+=ctFrames; }
else { pixKMXO+=pixMipmapSize; slKBMXO+=slBytes; ctNoMXO+=ctFrames; }
}
}}
// report
const PIX pixNormDim = (PIX) (sqrt(TS.ts_pixNormSize));
const PIX pixAnimDim = (PIX) (sqrt(TS.ts_pixAnimSize));
const PIX pixEffDim = 1L<<tex_iEffectSize;
CTString strTmp;
strTmp = tex_bFineEffect ? "32-bit" : "16-bit";
CPrintF( "\n");
CPrintF( "Normal-opaque textures quality: %s\n", (const char *) ReportQuality(TS.ts_iNormQualityO));
CPrintF( "Normal-translucent textures quality: %s\n", (const char *) ReportQuality(TS.ts_iNormQualityA));
CPrintF( "Animation-opaque textures quality: %s\n", (const char *) ReportQuality(TS.ts_iAnimQualityO));
CPrintF( "Animation-translucent textures quality: %s\n", (const char *) ReportQuality(TS.ts_iAnimQualityA));
CPrintF( "Effect textures quality: %s\n", (const char *) strTmp);
CPrintF( "\n");
CPrintF( "Max allowed normal texture area size: %3dx%d\n", pixNormDim, pixNormDim);
CPrintF( "Max allowed animation texture area size: %3dx%d\n", pixAnimDim, pixAnimDim);
CPrintF( "Max allowed effect texture area size: %3dx%d\n", pixEffDim, pixEffDim);
CPrintF( "\n");
CPrintF( "Opaque textures memory usage:\n");
CPrintF( " <64 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNo04O, pixK04O/1024.0f, slKB04O/1024);
CPrintF( " 64-256 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNo64O, pixK64O/1024.0f, slKB64O/1024);
CPrintF( " >256 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNoMXO, pixKMXO/1024.0f, slKBMXO/1024);
CPrintF( "Translucent textures memory usage:\n");
CPrintF( " <64 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNo04A, pixK04A/1024.0f, slKB04A/1024);
CPrintF( " 64-256 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNo64A, pixK64A/1024.0f, slKB64A/1024);
CPrintF( " >256 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNoMXA, pixKMXA/1024.0f, slKBMXA/1024);
CPrintF("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n");
}
// reformat an extensions string to cross multiple lines
extern CTString ReformatExtensionsString( CTString strUnformatted)
{
CTString strTmp, strDst = "\n";
char *pcSrc = (char*)(const char*)strUnformatted;
FOREVER {
char *pcSpace = strchr( pcSrc, ' ');
if( pcSpace==NULL) break;
*pcSpace = 0;
strTmp.PrintF( " %s\n", pcSrc);
strDst += strTmp;
*pcSpace = ' ';
pcSrc = pcSpace +1;
}
if(strDst=="\n") {
strDst = "none\n";
}
// done
return strDst;
}
// printout extensive OpenGL/Direct3D info to console
static void GAPInfo(void)
{
// check API
const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI;
CPrintF( "\n");
ASSERT( GfxValidApi(eAPI) );
// in case of driver hasn't been initialized yet
if( (_pGfx->go_hglRC==NULL
#ifdef SE1_D3D
&& _pGfx->gl_pd3dDevice==NULL
#endif // SE1_D3D
) || eAPI==GAT_NONE) {
// be brief, be quick
CPrintF( TRANS("Display driver hasn't been initialized.\n\n"));
return;
}
// report API
CPrintF( "- Graphics API: ");
if( eAPI==GAT_OGL) CPrintF( "OpenGL\n");
else CPrintF( "Direct3D\n");
// and number of adapters
CPrintF( "- Adapters found: %d\n", _pGfx->gl_gaAPI[eAPI].ga_ctAdapters);
CPrintF( "\n");
// report renderer
CDisplayAdapter &da = _pGfx->gl_gaAPI[eAPI].ga_adaAdapter[_pGfx->gl_iCurrentAdapter];
if( eAPI==GAT_OGL) CPrintF( "- Vendor: %s\n", (const char *) da.da_strVendor);
CPrintF( "- Renderer: %s\n", (const char *) da.da_strRenderer);
CPrintF( "- Version: %s\n", (const char *) da.da_strVersion);
CPrintF( "\n");
// Z-buffer depth
CPrintF( "- Z-buffer precision: ");
if( _pGfx->gl_iCurrentDepth==0) CPrintF( "default\n");
else CPrintF( "%d bits\n", _pGfx->gl_iCurrentDepth);
// 32-bit textures
CPrintF( "- 32-bit textures: ");
if( _pGfx->gl_ulFlags & GLF_32BITTEXTURES) CPrintF( "supported\n");
else CPrintF( "not supported\n");
// grayscale textures
CPrintF( "- Grayscale textures: ");
if( gap_bAllowGrayTextures) CPrintF( "allowed\n");
else CPrintF( "not allowed\n");
// report maximum texture dimension
CPrintF( "- Max texture dimension: %d pixels\n", _pGfx->gl_pixMaxTextureDimension);
// report multitexturing capabilities
CPrintF( "- Multi-texturing: ");
if( _pGfx->gl_ctRealTextureUnits<2) CPrintF( "not supported\n");
else {
if( gap_iUseTextureUnits>1) CPrintF( "enabled (using %d texture units)\n", gap_iUseTextureUnits);
else CPrintF( "disabled\n");
CPrintF( "- Texture units: %d", _pGfx->gl_ctRealTextureUnits);
if( _pGfx->gl_ctTextureUnits < _pGfx->gl_ctRealTextureUnits) {
CPrintF(" (%d can be used)\n", _pGfx->gl_ctTextureUnits);
} else CPrintF("\n");
}
// report texture anisotropy degree
if( _pGfx->gl_iMaxTextureAnisotropy>=2) {
CPrintF( "- Texture anisotropy: %d of %d\n", _tpGlobal[0].tp_iAnisotropy, _pGfx->gl_iMaxTextureAnisotropy);
} else CPrintF( "- Anisotropic texture filtering: not supported\n");
// report texture LOD bias range
const FLOAT fMaxLODBias = _pGfx->gl_fMaxTextureLODBias;
if( fMaxLODBias>0) {
CPrintF( "- Texture LOD bias: %.1f of +/-%.1f\n", _pGfx->gl_fTextureLODBias, fMaxLODBias);
} else CPrintF( "- Texture LOD biasing: not supported\n");
// OpenGL only stuff ...
if( eAPI==GAT_OGL)
{
// report truform tessellation
CPrintF( "- Truform tessellation: ");
if( _pGfx->gl_iMaxTessellationLevel>0) {
if( _pGfx->gl_iTessellationLevel>0) {
CPrintF( "enabled ");
if( gap_bForceTruform) CPrintF( "(for all models)\n");
else CPrintF( "(only for Truform-ready models)\n");
CTString strNormalMode = ogl_bTruformLinearNormals ? "linear" : "quadratic";
CPrintF( "- Tesselation level: %d of %d (%s normals)\n", _pGfx->gl_iTessellationLevel, _pGfx->gl_iMaxTessellationLevel, (const char *) strNormalMode);
} else CPrintF( "disabled\n");
} else CPrintF( "not supported\n");
// report current swap interval (only if fullscreen)
STUBBED("Swap interval shouldn't just be for fullscreen"); // !!! FIXME --ryan.
if( _pGfx->gl_ulFlags&GLF_FULLSCREEN) {
// report current swap interval
STUBBED("I don't think the non-D3D path sets GLF_VSYNC anywhere. Mismerge?"); // !!! FIXME --ryan.
CPrintF( "- Swap interval: ");
if( _pGfx->gl_ulFlags&GLF_VSYNC) {
#if PLATFORM_WIN32
const int gliWaits = (int) pwglGetSwapIntervalEXT();
if( gliWaits>=0) {
ASSERT( gliWaits==_pGfx->gl_iSwapInterval);
CPrintF( "%d frame(s)\n", gliWaits);
} else CPrintF( "not readable\n");
#else
const int gliWaits = SDL_GL_GetSwapInterval();
if( gliWaits>=0) {
ASSERT( gliWaits==_pGfx->gl_iSwapInterval);
CPrintF( "%d frame(s)\n", gliWaits);
} else CPrintF( "adaptive vsync\n");
#endif
} else CPrintF( "not adjustable\n");
}
// report T-Buffer support
if( _pGfx->gl_ulFlags & GLF_EXT_TBUFFER) {
CPrintF( "- T-Buffer effect: ");
if( _pGfx->go_ctSampleBuffers==0) CPrintF( "disabled\n");
else {
ogl_iTBufferEffect = Clamp( ogl_iTBufferEffect, 0, 2);
CTString strEffect = "Partial anti-aliasing";
if( ogl_iTBufferEffect<1) strEffect = "none";
if( ogl_iTBufferEffect>1) strEffect = "Motion blur";
CPrintF( "%s (%d buffers used)\n", (const char *) strEffect, _pGfx->go_ctSampleBuffers);
}
}
// compiled vertex arrays support
CPrintF( "- Compiled Vertex Arrays: ");
if( _pGfx->gl_ulFlags & GLF_EXT_COMPILEDVERTEXARRAY) {
extern BOOL CVA_b2D;
extern BOOL CVA_bWorld;
extern BOOL CVA_bModels;
if( ogl_bUseCompiledVertexArrays) {
CTString strSep="";
CPrintF( "enabled (for ");
if( CVA_bWorld) { CPrintF( "world"); strSep="/"; }
if( CVA_bModels) { CPrintF( "%smodels", (const char *) strSep); strSep="/"; }
if( CVA_b2D) { CPrintF( "%sparticles", (const char *) strSep); }
CPrintF( ")\n");
} else CPrintF( "disabled\n");
} else CPrintF( "not supported\n");
// report texture compression type
CPrintF( "- Supported texture compression system(s): ");
if( !(_pGfx->gl_ulFlags&GLF_TEXTURECOMPRESSION)) CPrintF( "none\n");
else {
CTString strSep="";
if( _pGfx->gl_ulFlags & GLF_EXTC_ARB) { CPrintF( "ARB"); strSep=", "; }
if( _pGfx->gl_ulFlags & GLF_EXTC_S3TC) { CPrintF( "%sS3TC", (const char *) strSep); strSep=", "; }
if( _pGfx->gl_ulFlags & GLF_EXTC_FXT1) { CPrintF( "%sFTX1", (const char *) strSep); strSep=", "; }
if( _pGfx->gl_ulFlags & GLF_EXTC_LEGACY) { CPrintF( "%sold S3TC", (const char *) strSep); }
CPrintF( "\n- Current texture compression system: ");
switch( ogl_iTextureCompressionType) {
case 0: CPrintF( "none\n"); break;
case 1: CPrintF( "ARB wrapper\n"); break;
case 2: CPrintF( "S3TC\n"); break;
case 3: CPrintF( "FXT1\n"); break;
default: CPrintF( "old S3TC\n"); break;
}
}
/* if exist, report vertex array range extension usage
if( ulExt & GOEXT_VERTEXARRAYRANGE) {
extern BOOL VB_bSetupFailed;
extern SLONG VB_slVertexBufferSize;
extern INDEX VB_iVertexBufferType;
extern INDEX ogl_iVertexBuffers;
if( VB_bSetupFailed) { // didn't manage to setup vertex buffers
CPrintF( "- Enhanced HW T&L: fail\n");
} else if( VB_iVertexBufferType==0) { // not used
CPrintF( "- Enhanced HW T&L: disabled\n");
} else { // works! :)
CTString strBufferType("AGP");
if( VB_iVertexBufferType==2) strBufferType = "video";
const SLONG slMemSize = VB_slVertexBufferSize/1024;
CPrintF( "- Enhanced hardware T&L: %d buffers in %d KB of %s memory",
ogl_iVertexBuffers, slMemSize, strBufferType);
}
} */
// report OpenGL externsions
CPrintF("\n");
CPrintF("- Published extensions: %s", (const char *) ReformatExtensionsString(_pGfx->go_strExtensions));
if( _pGfx->go_strWinExtensions != "") CPrintF("%s", (const char *) ReformatExtensionsString(_pGfx->go_strWinExtensions));
CPrintF("\n- Supported extensions: %s\n", (const char *) ReformatExtensionsString(_pGfx->go_strSupportedExtensions));
}
#ifdef SE1_D3D
// Direct3D only stuff
if( eAPI==GAT_D3D)
{
// HW T&L
CPrintF( "- Hardware T&L: ");
if( _pGfx->gl_ulFlags&GLF_D3D_HASHWTNL) {
if( _pGfx->gl_ctMaxStreams<GFX_MINSTREAMS) CPrintF( "cannot be used\n");
else if( _pGfx->gl_ulFlags&GLF_D3D_USINGHWTNL) CPrintF( "enabled (%d streams)\n", _pGfx->gl_ctMaxStreams);
else CPrintF( "disabled\n");
} else CPrintF( "not present\n");
// report vtx/idx buffers size
extern SLONG SizeFromVertices_D3D( INDEX ctVertices);
const SLONG slMemoryUsed = SizeFromVertices_D3D(_pGfx->gl_ctVertices);
CPrintF( "- Vertex buffer size: %.1f KB (%d vertices)\n", slMemoryUsed/1024.0f, _pGfx->gl_ctVertices);
// N-Patches tessellation (Truform)
CPrintF( "- N-Patches: ");
if( _pGfx->gl_iMaxTessellationLevel>0) {
if( !(_pGfx->gl_ulFlags&GLF_D3D_USINGHWTNL)) CPrintF( "not possible with SW T&L\n");
else if( _pGfx->gl_iTessellationLevel>0) {
CPrintF( "enabled ");
if( gap_bForceTruform) CPrintF( "(for all models)\n");
else CPrintF( "(only for Truform-ready models)\n");
CPrintF( "- Tesselation level: %d of %d\n", _pGfx->gl_iTessellationLevel, _pGfx->gl_iMaxTessellationLevel);
} else CPrintF( "disabled\n");
} else CPrintF( "not supported\n");
// texture compression
CPrintF( "- Texture compression: ");
if( _pGfx->gl_ulFlags&GLF_TEXTURECOMPRESSION) CPrintF( "supported\n");
else CPrintF( "not supported\n");
// custom clip plane support
CPrintF( "- Custom clip plane: ");
if( _pGfx->gl_ulFlags&GLF_D3D_CLIPPLANE) CPrintF( "supported\n");
else CPrintF( "not supported\n");
// color buffer writes enable/disable support
CPrintF( "- Color masking: ");
if( _pGfx->gl_ulFlags&GLF_D3D_COLORWRITES) CPrintF( "supported\n");
else CPrintF( "not supported\n");
// depth (Z) bias support
CPrintF( "- Depth biasing: ");
if( _pGfx->gl_ulFlags&GLF_D3D_ZBIAS) CPrintF( "supported\n");
else CPrintF( "not supported\n");
// current swap interval (only if fullscreen)
if( _pGfx->gl_ulFlags&GLF_FULLSCREEN) {
CPrintF( "- Swap interval: ");
if( _pGfx->gl_ulFlags&GLF_VSYNC) {
CPrintF( "%d frame(s)\n", _pGfx->gl_iSwapInterval);
} else CPrintF( "not adjustable\n");
}
}
#endif // SE1_D3D
}
// update console system vars
extern void UpdateGfxSysCVars(void)
{
sys_bHasTextureCompression = 0;
sys_bHasTextureAnisotropy = 0;
sys_bHasAdjustableGamma = 0;
sys_bHasTextureLODBias = 0;
sys_bHasMultitexturing = 0;
sys_bHas32bitTextures = 0;
sys_bHasSwapInterval = 0;
sys_bHasHardwareTnL = 1;
sys_bHasTruform = 0;
sys_bHasCVAs = 1;
sys_bUsingOpenGL = 0;
sys_bUsingDirect3D = 0;
if( _pGfx->gl_iMaxTextureAnisotropy>1) sys_bHasTextureAnisotropy = 1;
if( _pGfx->gl_fMaxTextureLODBias>0) sys_bHasTextureLODBias = 1;
if( _pGfx->gl_ctTextureUnits>1) sys_bHasMultitexturing = 1;
if( _pGfx->gl_iMaxTessellationLevel>0) sys_bHasTruform = 1;
if( _pGfx->gl_ulFlags & GLF_TEXTURECOMPRESSION) sys_bHasTextureCompression = 1;
if( _pGfx->gl_ulFlags & GLF_ADJUSTABLEGAMMA) sys_bHasAdjustableGamma = 1;
if( _pGfx->gl_ulFlags & GLF_32BITTEXTURES) sys_bHas32bitTextures = 1;
if( _pGfx->gl_ulFlags & GLF_VSYNC) sys_bHasSwapInterval = 1;
if( _pGfx->gl_eCurrentAPI==GAT_OGL && !(_pGfx->gl_ulFlags&GLF_EXT_COMPILEDVERTEXARRAY)) sys_bHasCVAs = 0;
#ifdef SE1_D3D
if( _pGfx->gl_eCurrentAPI==GAT_D3D && !(_pGfx->gl_ulFlags&GLF_D3D_HASHWTNL)) sys_bHasHardwareTnL = 0;
#endif // SE1_D3D
if( _pGfx->gl_eCurrentAPI==GAT_OGL) sys_bUsingOpenGL = 1;
#ifdef SE1_D3D
if( _pGfx->gl_eCurrentAPI==GAT_D3D) sys_bUsingDirect3D = 1;
#endif // SE1_D3D
}
// determine whether texture or shadowmap needs probing
extern BOOL ProbeMode( CTimerValue tvLast)
{
// probing off ?
if( !_pGfx->gl_bAllowProbing) return FALSE;
if( gfx_tmProbeDecay<1) {
gfx_tmProbeDecay = 0;
return FALSE;
}
// clamp and determine probe mode
if( gfx_tmProbeDecay>999) gfx_tmProbeDecay = 999;
CTimerValue tvNow = _pTimer->GetHighPrecisionTimer();
const TIME tmDelta = (tvNow-tvLast).GetSeconds();
if( tmDelta>gfx_tmProbeDecay) return TRUE;
return FALSE;
}
// uncache all cached shadow maps
extern void UncacheShadows(void)
{
// mute all sounds
_pSound->Mute();
// prepare new saturation factors for shadowmaps
gfx_fSaturation = ClampDn( gfx_fSaturation, 0.0f);
shd_fSaturation = ClampDn( shd_fSaturation, 0.0f);
gfx_iHueShift = Clamp( gfx_iHueShift, 0, 359);
shd_iHueShift = Clamp( shd_iHueShift, 0, 359);
_slShdSaturation = (SLONG)( gfx_fSaturation*shd_fSaturation*256.0f);
_slShdHueShift = Clamp( (gfx_iHueShift+shd_iHueShift)*255/359, 0, 255);
CListHead &lhOriginal = _pGfx->gl_lhCachedShadows;
// while there is some shadow in main list
while( !lhOriginal.IsEmpty()) {
CShadowMap &sm = *LIST_HEAD( lhOriginal, CShadowMap, sm_lnInGfx);
sm.Uncache();
}
// mark that we need pretouching
_bNeedPretouch = TRUE;
}
// refresh (uncache and eventually cache) all cached shadow maps
extern void CacheShadows(void);
static void RecacheShadows(void)
{
// mute all sounds
_pSound->Mute();
UncacheShadows();
if( shd_bCacheAll) CacheShadows();
else CPrintF( TRANS("All shadows uncached.\n"));
}
// reload all textures that were loaded
extern void ReloadTextures(void)
{
// mute all sounds
_pSound->Mute();
// prepare new saturation factors for textures
gfx_fSaturation = ClampDn( gfx_fSaturation, 0.0f);
tex_fSaturation = ClampDn( tex_fSaturation, 0.0f);
gfx_iHueShift = Clamp( gfx_iHueShift, 0, 359);
tex_iHueShift = Clamp( tex_iHueShift, 0, 359);
_slTexSaturation = (SLONG)( gfx_fSaturation*tex_fSaturation*256.0f);
_slTexHueShift = Clamp( (gfx_iHueShift+tex_iHueShift)*255/359, 0, 255);
// update texture settings
UpdateTextureSettings();
// loop thru texture stock
{FOREACHINDYNAMICCONTAINER( _pTextureStock->st_ctObjects, CTextureData, ittd) {
CTextureData &td = *ittd;
td.Reload();
td.td_tpLocal.Clear();
}}
// reset fog/haze texture
_fog_pixSizeH = 0;
_fog_pixSizeL = 0;
_haze_pixSize = 0;
// reinit flat texture
ASSERT( _ptdFlat!=NULL);
_ptdFlat->td_tpLocal.Clear();
_ptdFlat->Unbind();
_ptdFlat->td_ulFlags = TEX_ALPHACHANNEL | TEX_32BIT | TEX_STATIC;
_ptdFlat->td_mexWidth = 1;
_ptdFlat->td_mexHeight = 1;
_ptdFlat->td_iFirstMipLevel = 0;
_ptdFlat->td_ctFineMipLevels = 1;
_ptdFlat->td_slFrameSize = 1*1* BYTES_PER_TEXEL;
_ptdFlat->td_ctFrames = 1;
_ptdFlat->td_ulInternalFormat = TS.ts_tfRGBA8;
_ptdFlat->td_pulFrames = &_ulWhite;
_ptdFlat->SetAsCurrent();
/*
// reset are renderable textures, too
CListHead &lhOriginal = _pGfx->gl_lhRenderTextures;
while( !lhOriginal.IsEmpty()) {
CRenderTexture &rt = *LIST_HEAD( lhOriginal, CRenderTexture, rt_lnInGfx);
rt.Reset();
}
*/
// mark that we need pretouching
_bNeedPretouch = TRUE;
CPrintF( TRANS("All textures reloaded.\n"));
}
// refreshes all textures and shadow maps
static void RefreshTextures(void)
{
// refresh
ReloadTextures();
RecacheShadows();
}
// reload all models that were loaded
static void ReloadModels(void)
{
// mute all sounds
_pSound->Mute();
// loop thru model stock
{FOREACHINDYNAMICCONTAINER( _pModelStock->st_ctObjects, CModelData, itmd) {
CModelData &md = *itmd;
md.Reload();
}}
// mark that we need pretouching
_bNeedPretouch = TRUE;
// all done
CPrintF( TRANS("All models reloaded.\n"));
}
// variable change post functions
static BOOL _bLastModelQuality = -1;
static void MdlPostFunc(void *pvVar)
{
mdl_bFineQuality = Clamp( mdl_bFineQuality, 0, 1);
if( _bLastModelQuality!=mdl_bFineQuality) {
_bLastModelQuality = mdl_bFineQuality;
ReloadModels();
}
}
/*
* GfxLibrary functions
*/
static void PrepareTables(void)
{
INDEX i;
// prepare array for fast clamping to 0..255
for( i=-256*2; i<256*4; i++) aubClipByte[i+256*2] = (UBYTE)Clamp( i, 0, 255);
// prepare fast sqrt tables
for( i=0; i<SQRTTABLESIZE; i++) aubSqrt[i] = (UBYTE)(sqrt((FLOAT)(i*65536/SQRTTABLESIZE)));
for( i=1; i<SQRTTABLESIZE; i++) auw1oSqrt[i] = (UWORD)(sqrt((FLOAT)(SQRTTABLESIZE-1)/i)*255.0f);
auw1oSqrt[0] = MAX_UWORD;
// prepare fast sin/cos table
for( i=-256; i<256+64; i++) afSinTable[i+256] = Sin((i-128)/256.0f*360.0f);
// prepare gouraud conversion table
for( INDEX h=0; h<128; h++) {
for( INDEX p=0; p<128; p++) {
const FLOAT fSinH = pfSinTable[h*2];
const FLOAT fSinP = pfSinTable[p*2];
const FLOAT fCosH = pfCosTable[h*2];
const FLOAT fCosP = pfCosTable[p*2];
const FLOAT3D v( -fSinH*fCosP, +fSinP, -fCosH*fCosP);
aubGouraudConv[h*128+p] = (UBYTE)GouraudNormal(v);
}
}
// !!! FIXME: rcg01082002
// You can't count on these arrays to be identical on every system, due to
// floating point unit differences. This includes Linux and win32 on the
// x86 platform, and win32 debug builds vs. win32 release builds. Hell, I
// wouldn't be surprised if they gave different values between AMD and Intel
// processors. The tables generate identically between a win32 release and
// Linux release build at this point...except the Gouraud table, which has
// several minor variances. I recommend you get a table you like, use the
// below code to dump it to disk, and then make it a static array that you
// never need to calculate at runtime in the first place. Then you can remove
// this code and this godawful long comment. :)
#if 0
FILE *feh;
feh = fopen("aubClipByte.bin", "wb");
fwrite(aubClipByte, sizeof (aubClipByte), 1, feh);
fclose(feh);
feh = fopen("aubSqrt.bin", "wb");
fwrite(aubSqrt, sizeof (aubSqrt), 1, feh);
fclose(feh);
feh = fopen("auw1oSqrt.bin", "wb");
fwrite(auw1oSqrt, sizeof (auw1oSqrt), 1, feh);
fclose(feh);
feh = fopen("afSinTable.bin", "wb");
fwrite(afSinTable, sizeof (afSinTable), 1, feh);
fclose(feh);
feh = fopen("aubGouraudConv.bin", "wb");
fwrite(aubGouraudConv, sizeof (aubGouraudConv), 1, feh);
fclose(feh);
printf("w00t.\n");
exit(0);
#endif
}
/*
* Construct uninitialized gfx library.
*/
CGfxLibrary::CGfxLibrary(void)
{
// reset some variables to default
gl_iFrameNumber = 0;
gl_slAllowedUploadBurst = 0;
gl_bAllowProbing = FALSE;
gl_iSwapInterval = 1234;
gl_pixMaxTextureDimension = 8192;
gl_ctTextureUnits = 0;
gl_ctRealTextureUnits = 0;
gl_fTextureLODBias = 0;
gl_fMaxTextureLODBias = 0;
gl_iMaxTextureAnisotropy = 0;
gl_iMaxTessellationLevel = 0;
gl_iTessellationLevel = 0;
gl_ulFlags = NONE;
// create some internal tables
PrepareTables();
// no driver loaded
gl_eCurrentAPI = GAT_NONE;
gl_hiDriver = NONE;
go_hglRC = NONE;
gl_ctDriverChanges = 0;
// DX8 not loaded either
#ifdef SE1_D3D
gl_pD3D = NONE;
gl_pd3dDevice = NULL;
gl_d3dColorFormat = (D3DFORMAT)NONE;
gl_d3dDepthFormat = (D3DFORMAT)NONE;
#endif // SE1_D3D
gl_pvpActive = NULL;
gl_ctMaxStreams = 0;
gl_dwVertexShader = 0;
#ifdef SE1_D3D
gl_pd3dIdx = NULL;
gl_pd3dVtx = NULL;
gl_pd3dNor = NULL;
for( INDEX i=0; i<GFX_MAXLAYERS; i++) gl_pd3dCol[i] = gl_pd3dTex[i] = NULL;
#endif // SE1_D3D
gl_ctVertices = 0;
gl_ctIndices = 0;
// reset profiling counters
gl_ctWorldTriangles = 0;
gl_ctModelTriangles = 0;
gl_ctParticleTriangles = 0;
gl_ctTotalTriangles = 0;
// init flat texture
_ptdFlat = new CTextureData;
_ptdFlat->td_ulFlags = TEX_ALPHACHANNEL | TEX_32BIT | TEX_STATIC;
// prepare some quad elements
extern void AddQuadElements( const INDEX ctQuads);
AddQuadElements(1024); // should be enough (at least for a start)
// reset GFX API function pointers
GFX_SetFunctionPointers( (INDEX)GAT_NONE);
}
/*
* Destruct (and clean up).
*/
CGfxLibrary::~CGfxLibrary()
{
EnableWindowsKeys();
// free common arrays
_avtxCommon.Clear();
_atexCommon.Clear();
_acolCommon.Clear();
_aiCommonElements.Clear();
_aiCommonQuads.Clear();
// stop current display mode
StopDisplayMode();
// safe release of flat texture
ASSERT( _ptdFlat!=NULL);
_ptdFlat->td_pulFrames = NULL;
delete _ptdFlat;
_ptdFlat = NULL;
}
#define SM_CXVIRTUALSCREEN 78
#define SM_CYVIRTUALSCREEN 79
#define SM_CMONITORS 80
/* Initialize library for application main window. */
void CGfxLibrary::Init(void)
{
ASSERT( this!=NULL);
#ifdef PLATFORM_WIN32
// we will never allow glide splash screen
putenv( "FX_GLIDE_NO_SPLASH=1");
// report desktop settings
CPrintF(TRANSV("Desktop settings...\n"));
HDC hdc = GetDC(NULL);
SLONG slBPP = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
gfx_ctMonitors = GetSystemMetrics(SM_CMONITORS);
CPrintF(TRANSV(" Color Depth: %dbit\n"), slBPP);
CPrintF(TRANSV(" Screen: %dx%d\n"), GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
CPrintF(TRANSV(" Virtual screen: %dx%d\n"), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN));
CPrintF(TRANSV(" Monitors directly reported: %d\n"), gfx_ctMonitors);
#else
// we will never allow glide splash screen
setenv("FX_GLIDE_NO_SPLASH", "1", 1);
gfx_ctMonitors = 1;
#endif
CPrintF("\n");
gfx_bMultiMonDisabled = FALSE;
_pfGfxProfile.Reset();
// declare some console vars
_pShell->DeclareSymbol("user void MonitorsOn(void);", (void *) &MonitorsOn);
_pShell->DeclareSymbol("user void MonitorsOff(void);", (void *) &MonitorsOff);
_pShell->DeclareSymbol("user void GAPInfo(void);", (void *) &GAPInfo);
_pShell->DeclareSymbol("user void TexturesInfo(void);", (void *) &TexturesInfo);
_pShell->DeclareSymbol("user void UncacheShadows(void);", (void *) &UncacheShadows);
_pShell->DeclareSymbol("user void RecacheShadows(void);", (void *) &RecacheShadows);
_pShell->DeclareSymbol("user void RefreshTextures(void);", (void *) &RefreshTextures);
_pShell->DeclareSymbol("user void ReloadModels(void);", (void *) &ReloadModels);
_pShell->DeclareSymbol("persistent user INDEX ogl_bUseCompiledVertexArrays;", (void *) &ogl_bUseCompiledVertexArrays);
_pShell->DeclareSymbol("persistent user INDEX ogl_bExclusive;", (void *) &ogl_bExclusive);
_pShell->DeclareSymbol("persistent user INDEX ogl_bAllowQuadArrays;", (void *) &ogl_bAllowQuadArrays);
_pShell->DeclareSymbol("persistent user INDEX ogl_iTextureCompressionType;", (void *) &ogl_iTextureCompressionType);
_pShell->DeclareSymbol("persistent user INDEX ogl_iMaxBurstSize;", (void *) &ogl_iMaxBurstSize);
_pShell->DeclareSymbol("persistent user INDEX ogl_bGrabDepthBuffer;", (void *) &ogl_bGrabDepthBuffer);
_pShell->DeclareSymbol("persistent user INDEX ogl_iFinish;", (void *) &ogl_iFinish);
_pShell->DeclareSymbol("persistent user INDEX ogl_iTBufferEffect;", (void *) &ogl_iTBufferEffect);
_pShell->DeclareSymbol("persistent user INDEX ogl_iTBufferSamples;", (void *) &ogl_iTBufferSamples);
_pShell->DeclareSymbol("persistent user INDEX ogl_bTruformLinearNormals;", (void *) &ogl_bTruformLinearNormals);
_pShell->DeclareSymbol("persistent user INDEX ogl_bAlternateClipPlane;", (void *) &ogl_bAlternateClipPlane);
_pShell->DeclareSymbol("persistent user INDEX d3d_bUseHardwareTnL;", (void *) &d3d_bUseHardwareTnL);
_pShell->DeclareSymbol("persistent user INDEX d3d_iMaxBurstSize;", (void *) &d3d_iMaxBurstSize);
_pShell->DeclareSymbol("persistent user INDEX d3d_iVertexBuffersSize;", (void *) &d3d_iVertexBuffersSize);
_pShell->DeclareSymbol("persistent user INDEX d3d_iVertexRangeTreshold;", (void *) &d3d_iVertexRangeTreshold);
_pShell->DeclareSymbol("persistent user INDEX d3d_bAlternateDepthReads;", (void *) &d3d_bAlternateDepthReads);
_pShell->DeclareSymbol("persistent user INDEX d3d_bOptimizeVertexBuffers;", (void *) &d3d_bOptimizeVertexBuffers);
_pShell->DeclareSymbol("persistent user INDEX d3d_iFinish;", (void *) &d3d_iFinish);
_pShell->DeclareSymbol("persistent user INDEX gap_iUseTextureUnits;", (void *) &gap_iUseTextureUnits);
_pShell->DeclareSymbol("persistent user INDEX gap_iTextureFiltering;", (void *) &gap_iTextureFiltering);
_pShell->DeclareSymbol("persistent user INDEX gap_iTextureAnisotropy;", (void *) &gap_iTextureAnisotropy);
_pShell->DeclareSymbol("persistent user FLOAT gap_fTextureLODBias;", (void *) &gap_fTextureLODBias);
_pShell->DeclareSymbol("persistent user INDEX gap_bAllowGrayTextures;", (void *) &gap_bAllowGrayTextures);
_pShell->DeclareSymbol("persistent user INDEX gap_bAllowSingleMipmap;", (void *) &gap_bAllowSingleMipmap);
_pShell->DeclareSymbol("persistent user INDEX gap_bOptimizeStateChanges;", (void *) &gap_bOptimizeStateChanges);
_pShell->DeclareSymbol("persistent user INDEX gap_iOptimizeDepthReads;", (void *) &gap_iOptimizeDepthReads);
_pShell->DeclareSymbol("persistent user INDEX gap_iOptimizeClipping;", (void *) &gap_iOptimizeClipping);
_pShell->DeclareSymbol("persistent user INDEX gap_iSwapInterval;", (void *) &gap_iSwapInterval);
_pShell->DeclareSymbol("persistent user INDEX gap_iRefreshRate;", (void *) &gap_iRefreshRate);
_pShell->DeclareSymbol("persistent user INDEX gap_iDithering;", (void *) &gap_iDithering);
_pShell->DeclareSymbol("persistent user INDEX gap_bForceTruform;", (void *) &gap_bForceTruform);
_pShell->DeclareSymbol("persistent user INDEX gap_iTruformLevel;", (void *) &gap_iTruformLevel);
_pShell->DeclareSymbol("persistent user INDEX gap_iDepthBits;", (void *) &gap_iDepthBits);
_pShell->DeclareSymbol("persistent user INDEX gap_iStencilBits;", (void *) &gap_iStencilBits);
_pShell->DeclareSymbol("void MdlPostFunc(INDEX);", (void *) &MdlPostFunc);
_pShell->DeclareSymbol(" user INDEX gfx_bRenderPredicted;", (void *) &gfx_bRenderPredicted);
_pShell->DeclareSymbol(" user INDEX gfx_bRenderModels;", (void *) &gfx_bRenderModels);
_pShell->DeclareSymbol(" user INDEX mdl_bShowTriangles;", (void *) &mdl_bShowTriangles);
_pShell->DeclareSymbol(" user INDEX mdl_bCreateStrips;", (void *) &mdl_bCreateStrips);
_pShell->DeclareSymbol(" user INDEX mdl_bShowStrips;", (void *) &mdl_bShowStrips);
_pShell->DeclareSymbol("persistent user FLOAT mdl_fLODMul;", (void *) &mdl_fLODMul);
_pShell->DeclareSymbol("persistent user FLOAT mdl_fLODAdd;", (void *) &mdl_fLODAdd);
_pShell->DeclareSymbol("persistent user INDEX mdl_iLODDisappear;", (void *) &mdl_iLODDisappear);
_pShell->DeclareSymbol("persistent user INDEX mdl_bRenderDetail;", (void *) &mdl_bRenderDetail);
_pShell->DeclareSymbol("persistent user INDEX mdl_bRenderSpecular;", (void *) &mdl_bRenderSpecular);
_pShell->DeclareSymbol("persistent user INDEX mdl_bRenderReflection;", (void *) &mdl_bRenderReflection);
_pShell->DeclareSymbol("persistent user INDEX mdl_bAllowOverbright;", (void *) &mdl_bAllowOverbright);
_pShell->DeclareSymbol("persistent user INDEX mdl_bFineQuality post:MdlPostFunc;", (void *) &mdl_bFineQuality);
_pShell->DeclareSymbol("persistent user INDEX mdl_iShadowQuality;", (void *) &mdl_iShadowQuality);
// !!! FIXME : rcg11232001 Hhmm...I'm failing an assertion in the
// !!! FIXME : rcg11232001 Advanced Rendering Options menu because
// !!! FIXME : rcg11232001 Scripts/CustomOptions/GFX-AdvancedRendering.cfg
// !!! FIXME : rcg11232001 references non-existing cvars, so I'm adding
// !!! FIXME : rcg11232001 them here for now.
// FXME: DG: so why are they commented out?
// _pShell->DeclareSymbol("persistent user INDEX mdl_bRenderBump;", (void *) &mdl_bRenderBump);
// _pShell->DeclareSymbol("persistent user FLOAT ogl_fTextureAnisotropy;", (void *) &ogl_fTextureAnisotropy);
_pShell->DeclareSymbol("persistent user FLOAT tex_fNormalSize;", (void *) &tex_fNormalSize);
_pShell->DeclareSymbol(" INDEX mdl_bTruformWeapons;", (void *) &mdl_bTruformWeapons);
_pShell->DeclareSymbol("persistent user FLOAT gfx_tmProbeDecay;", (void *) &gfx_tmProbeDecay);
_pShell->DeclareSymbol("persistent user INDEX gfx_iProbeSize;", (void *) &gfx_iProbeSize);
_pShell->DeclareSymbol("persistent user INDEX gfx_bClearScreen;", (void *) &gfx_bClearScreen);
_pShell->DeclareSymbol("persistent user INDEX gfx_bDisableMultiMonSupport;", (void *) &gfx_bDisableMultiMonSupport);
_pShell->DeclareSymbol("persistent user INDEX gfx_bDisableWindowsKeys;", (void *) &gfx_bDisableWindowsKeys);
_pShell->DeclareSymbol("persistent user INDEX gfx_bDecoratedText;", (void *) &gfx_bDecoratedText);
_pShell->DeclareSymbol(" const user INDEX gfx_ctMonitors;", (void *) &gfx_ctMonitors);
_pShell->DeclareSymbol(" const user INDEX gfx_bMultiMonDisabled;", (void *) &gfx_bMultiMonDisabled);
_pShell->DeclareSymbol("persistent user INDEX tex_iNormalQuality;", (void *) &tex_iNormalQuality);
_pShell->DeclareSymbol("persistent user INDEX tex_iAnimationQuality;", (void *) &tex_iAnimationQuality);
_pShell->DeclareSymbol("persistent user INDEX tex_iNormalSize;", (void *) &tex_iNormalSize);
_pShell->DeclareSymbol("persistent user INDEX tex_iAnimationSize;", (void *) &tex_iAnimationSize);
_pShell->DeclareSymbol("persistent user INDEX tex_iEffectSize;", (void *) &tex_iEffectSize);
_pShell->DeclareSymbol("persistent user INDEX tex_bFineEffect;", (void *) &tex_bFineEffect);
_pShell->DeclareSymbol("persistent user INDEX tex_bFineFog;", (void *) &tex_bFineFog);
_pShell->DeclareSymbol("persistent user INDEX tex_iFogSize;", (void *) &tex_iFogSize);
_pShell->DeclareSymbol("persistent user INDEX tex_bCompressAlphaChannel;", &tex_bCompressAlphaChannel);
_pShell->DeclareSymbol("persistent user INDEX tex_bAlternateCompression;", &tex_bAlternateCompression);
_pShell->DeclareSymbol("persistent user INDEX tex_bDynamicMipmaps;", &tex_bDynamicMipmaps);
_pShell->DeclareSymbol("persistent user INDEX tex_iDithering;", (void *) &tex_iDithering);
_pShell->DeclareSymbol("persistent user INDEX tex_iFiltering;", (void *) &tex_iFiltering);
_pShell->DeclareSymbol("persistent user INDEX tex_iEffectFiltering;", (void *) &tex_iEffectFiltering);
_pShell->DeclareSymbol("persistent user INDEX tex_bProgressiveFilter;", (void *) &tex_bProgressiveFilter);
_pShell->DeclareSymbol(" user INDEX tex_bColorizeMipmaps;", (void *) &tex_bColorizeMipmaps);
_pShell->DeclareSymbol("persistent user INDEX shd_iStaticSize;", (void *) &shd_iStaticSize);
_pShell->DeclareSymbol("persistent user INDEX shd_iDynamicSize;", (void *) &shd_iDynamicSize);
_pShell->DeclareSymbol("persistent user INDEX shd_bFineQuality;", (void *) &shd_bFineQuality);
_pShell->DeclareSymbol("persistent user INDEX shd_iAllowDynamic;", (void *) &shd_iAllowDynamic);
_pShell->DeclareSymbol("persistent user INDEX shd_bDynamicMipmaps;", (void *) &shd_bDynamicMipmaps);
_pShell->DeclareSymbol("persistent user INDEX shd_iFiltering;", (void *) &shd_iFiltering);
_pShell->DeclareSymbol("persistent user INDEX shd_iDithering;", (void *) &shd_iDithering);
_pShell->DeclareSymbol("persistent user FLOAT shd_tmFlushDelay;", (void *) &shd_tmFlushDelay);
_pShell->DeclareSymbol("persistent user FLOAT shd_fCacheSize;", (void *) &shd_fCacheSize);
_pShell->DeclareSymbol("persistent user INDEX shd_bCacheAll;", (void *) &shd_bCacheAll);
_pShell->DeclareSymbol("persistent user INDEX shd_bAllowFlats;", (void *) &shd_bAllowFlats);
_pShell->DeclareSymbol("persistent INDEX shd_iForceFlats;", (void *) &shd_iForceFlats);
_pShell->DeclareSymbol(" user INDEX shd_bShowFlats;", (void *) &shd_bShowFlats);
_pShell->DeclareSymbol(" user INDEX shd_bColorize;", (void *) &shd_bColorize);
_pShell->DeclareSymbol(" user INDEX gfx_bRenderParticles;", (void *) &gfx_bRenderParticles);
_pShell->DeclareSymbol(" user INDEX gfx_bRenderFog;", (void *) &gfx_bRenderFog);
_pShell->DeclareSymbol(" user INDEX gfx_bRenderWorld;", (void *) &gfx_bRenderWorld);
_pShell->DeclareSymbol("persistent user INDEX gfx_iLensFlareQuality;", (void *) &gfx_iLensFlareQuality);
_pShell->DeclareSymbol("persistent user INDEX wld_bTextureLayers;", (void *) &wld_bTextureLayers);
_pShell->DeclareSymbol("persistent user INDEX wld_bRenderMirrors;", (void *) &wld_bRenderMirrors);
_pShell->DeclareSymbol("persistent user FLOAT wld_fEdgeOffsetI;", (void *) &wld_fEdgeOffsetI);
_pShell->DeclareSymbol("persistent user FLOAT wld_fEdgeAdjustK;", (void *) &wld_fEdgeAdjustK);
_pShell->DeclareSymbol("persistent user INDEX wld_iDetailRemovingBias;", (void *) &wld_iDetailRemovingBias);
_pShell->DeclareSymbol(" user INDEX wld_bRenderEmptyBrushes;", (void *) &wld_bRenderEmptyBrushes);
_pShell->DeclareSymbol(" user INDEX wld_bRenderShadowMaps;", (void *) &wld_bRenderShadowMaps);
_pShell->DeclareSymbol(" user INDEX wld_bRenderTextures;", (void *) &wld_bRenderTextures);
_pShell->DeclareSymbol(" user INDEX wld_bRenderDetailPolygons;", &wld_bRenderDetailPolygons);
_pShell->DeclareSymbol(" user INDEX wld_bShowTriangles;", (void *) &wld_bShowTriangles);
_pShell->DeclareSymbol(" user INDEX wld_bShowDetailTextures;", (void *) &wld_bShowDetailTextures);
_pShell->DeclareSymbol(" user INDEX wed_bIgnoreTJunctions;", (void *) &wed_bIgnoreTJunctions);
_pShell->DeclareSymbol("persistent user INDEX wed_bUseBaseForReplacement;", (void *) &wed_bUseBaseForReplacement);
_pShell->DeclareSymbol("persistent user INDEX tex_iHueShift;", (void *) &tex_iHueShift);
_pShell->DeclareSymbol("persistent user FLOAT tex_fSaturation;", (void *) &tex_fSaturation);
_pShell->DeclareSymbol("persistent user INDEX shd_iHueShift;", (void *) &shd_iHueShift);
_pShell->DeclareSymbol("persistent user FLOAT shd_fSaturation;", (void *) &shd_fSaturation);
_pShell->DeclareSymbol("persistent user INDEX gfx_iHueShift;", (void *) &gfx_iHueShift);
_pShell->DeclareSymbol("persistent user FLOAT gfx_fSaturation;", (void *) &gfx_fSaturation);
_pShell->DeclareSymbol("persistent user FLOAT gfx_fBrightness;", (void *) &gfx_fBrightness);
_pShell->DeclareSymbol("persistent user FLOAT gfx_fContrast;", (void *) &gfx_fContrast);
_pShell->DeclareSymbol("persistent user FLOAT gfx_fGamma;", (void *) &gfx_fGamma);
_pShell->DeclareSymbol("persistent user FLOAT gfx_fBiasR;", (void *) &gfx_fBiasR);
_pShell->DeclareSymbol("persistent user FLOAT gfx_fBiasG;", (void *) &gfx_fBiasG);
_pShell->DeclareSymbol("persistent user FLOAT gfx_fBiasB;", (void *) &gfx_fBiasB);
_pShell->DeclareSymbol("persistent user INDEX gfx_iLevels;", (void *) &gfx_iLevels);
_pShell->DeclareSymbol("persistent user INDEX gfx_iStereo;", (void *) &gfx_iStereo);
_pShell->DeclareSymbol("persistent user INDEX gfx_bStereoInvert;", (void *) &gfx_bStereoInvert);
_pShell->DeclareSymbol("persistent user INDEX gfx_iStereoOffset;", (void *) &gfx_iStereoOffset);
_pShell->DeclareSymbol("persistent user FLOAT gfx_fStereoSeparation;", (void *) &gfx_fStereoSeparation);
_pShell->DeclareSymbol( "INDEX sys_bHasTextureCompression;", (void *) &sys_bHasTextureCompression);
_pShell->DeclareSymbol( "INDEX sys_bHasTextureAnisotropy;", (void *) &sys_bHasTextureAnisotropy);
_pShell->DeclareSymbol( "INDEX sys_bHasAdjustableGamma;", (void *) &sys_bHasAdjustableGamma);
_pShell->DeclareSymbol( "INDEX sys_bHasTextureLODBias;", (void *) &sys_bHasTextureLODBias);
_pShell->DeclareSymbol( "INDEX sys_bHasMultitexturing;", (void *) &sys_bHasMultitexturing);
_pShell->DeclareSymbol( "INDEX sys_bHas32bitTextures;", (void *) &sys_bHas32bitTextures);
_pShell->DeclareSymbol( "INDEX sys_bHasSwapInterval;", (void *) &sys_bHasSwapInterval);
_pShell->DeclareSymbol( "INDEX sys_bHasHardwareTnL;", (void *) &sys_bHasHardwareTnL);
_pShell->DeclareSymbol( "INDEX sys_bHasTruform;", (void *) &sys_bHasTruform);
_pShell->DeclareSymbol( "INDEX sys_bHasCVAs;", (void *) &sys_bHasCVAs);
_pShell->DeclareSymbol( "INDEX sys_bUsingOpenGL;", (void *) &sys_bUsingOpenGL);
_pShell->DeclareSymbol( "INDEX sys_bUsingDirect3D;", (void *) &sys_bUsingDirect3D);
// initialize gfx APIs support
InitAPIs();
}
// set new display mode
BOOL CGfxLibrary::SetDisplayMode( enum GfxAPIType eAPI, INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ,
enum DisplayDepth eColorDepth)
{
// some safeties
ASSERT( pixSizeI>0 && pixSizeJ>0);
// determine new API
GfxAPIType eNewAPI = eAPI;
if( eNewAPI==GAT_CURRENT) eNewAPI = gl_eCurrentAPI;
// shutdown old and startup new API, and mode and ... stuff, you know!
StopDisplayMode();
BOOL bRet = StartDisplayMode( eNewAPI, iAdapter, pixSizeI, pixSizeJ, eColorDepth);
if( !bRet) return FALSE; // didn't make it?
// update some info
gl_iCurrentAdapter = gl_gaAPI[gl_eCurrentAPI].ga_iCurrentAdapter = iAdapter;
gl_dmCurrentDisplayMode.dm_pixSizeI = pixSizeI;
gl_dmCurrentDisplayMode.dm_pixSizeJ = pixSizeJ;
gl_dmCurrentDisplayMode.dm_ddDepth = eColorDepth;
// prepare texture formats for this display mode
extern void DetermineSupportedTextureFormats( GfxAPIType eAPI);
DetermineSupportedTextureFormats(gl_eCurrentAPI);
// made it! (eventually disable windows system keys)
if( gfx_bDisableWindowsKeys) DisableWindowsKeys();
return TRUE;
}
// set display mode to original desktop display mode and default ICD driver
BOOL CGfxLibrary::ResetDisplayMode( enum GfxAPIType eAPI/*=GAT_CURRENT*/)
{
// determine new API
GfxAPIType eNewAPI = eAPI;
if( eNewAPI==GAT_CURRENT) eNewAPI = gl_eCurrentAPI;
// shutdown old and startup new API, and mode and ... stuff, you know!
StopDisplayMode();
BOOL bRet = StartDisplayMode( eNewAPI, 0, 0, 0, DD_DEFAULT);
if( !bRet) return FALSE; // didn't make it?
// update some info
gl_iCurrentAdapter = 0;
gl_dmCurrentDisplayMode.dm_pixSizeI = 0;
gl_dmCurrentDisplayMode.dm_pixSizeJ = 0;
gl_dmCurrentDisplayMode.dm_ddDepth = DD_DEFAULT;
// prepare texture formats for this display mode
extern void DetermineSupportedTextureFormats( GfxAPIType eAPI);
DetermineSupportedTextureFormats(gl_eCurrentAPI);
// made it!
EnableWindowsKeys();
return TRUE;
}
// startup gfx API and set given display mode
BOOL CGfxLibrary::StartDisplayMode( enum GfxAPIType eAPI, INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ,
enum DisplayDepth eColorDepth)
{
// reinit gamma table
_fLastBrightness = 999;
_fLastContrast = 999;
_fLastGamma = 999;
_iLastLevels = 999;
_fLastBiasR = 999;
_fLastBiasG = 999;
_fLastBiasB = 999;
// prepare
BOOL bSuccess;
ASSERT( iAdapter>=0);
const BOOL bFullScreen = (pixSizeI>0 && pixSizeJ>0);
gl_ulFlags &= GLF_ADJUSTABLEGAMMA;
gl_ctDriverChanges++;
GFX_bRenderingScene = FALSE;
GFX_ulLastDrawPortID = 0;
gl_iTessellationLevel = 0;
gl_ctRealTextureUnits = 0;
_iLastVertexBufferSize = 0;
// OpenGL driver ?
if( eAPI==GAT_OGL)
{
// disable multimonitor support if it can interfere with OpenGL
MonitorsOff();
if( bFullScreen) {
// set windows mode to fit same size
bSuccess = CDS_SetMode( pixSizeI, pixSizeJ, eColorDepth);
if( !bSuccess) return FALSE;
} else {
// reset windows mode
CDS_ResetMode();
}
// startup OpenGL
bSuccess = InitDriver_OGL(iAdapter!=0);
// try to setup sub-driver
if( !bSuccess) {
// reset windows mode and fail
CDS_ResetMode();
return FALSE;
} // made it
gl_eCurrentAPI = GAT_OGL;
gl_iSwapInterval = 1234; // need to reset
}
// DirectX driver ?
#ifdef SE1_D3D
else if( eAPI==GAT_D3D)
{
// startup D3D
bSuccess = InitDriver_D3D();
if( !bSuccess) return FALSE; // what, didn't make it?
bSuccess = InitDisplay_D3D( iAdapter, pixSizeI, pixSizeJ, eColorDepth);
if( !bSuccess) return FALSE;
// made it
gl_eCurrentAPI = GAT_D3D;
}
#endif // SE1_D3D
// no driver
else
{
ASSERT( eAPI==GAT_NONE);
gl_eCurrentAPI = GAT_NONE;
}
// initialize on first child window
gl_iFrameNumber = 0;
gl_pvpActive = NULL;
gl_ulFlags |= GLF_INITONNEXTWINDOW;
bFullScreen ? gl_ulFlags|=GLF_FULLSCREEN : gl_ulFlags&=~GLF_FULLSCREEN;
// mark that some things needs to be reinitialized
gl_fTextureLODBias = 0.0f;
// set function pointers
GFX_SetFunctionPointers( (INDEX)gl_eCurrentAPI);
// all done
return TRUE;
}
// Stop display mode and shutdown API
void CGfxLibrary::StopDisplayMode(void)
{
// release all cached shadows and models' arrays
extern void Models_ClearVertexArrays(void);
extern void UncacheShadows(void);
Models_ClearVertexArrays();
UncacheShadows();
// shutdown API
if( gl_eCurrentAPI==GAT_OGL)
{ // OpenGL
EndDriver_OGL();
MonitorsOn(); // re-enable multimonitor support if disabled
CDS_ResetMode();
}
#ifdef SE1_D3D
else if( gl_eCurrentAPI==GAT_D3D)
{ // Direct3D
EndDriver_D3D();
MonitorsOn();
}
#endif
else
{ // none
ASSERT( gl_eCurrentAPI==GAT_NONE);
}
// free driver DLL
if (gl_hiDriver != NULL)
delete gl_hiDriver;
gl_hiDriver = NULL;
// reset some vars
gl_ctRealTextureUnits = 0;
gl_eCurrentAPI = GAT_NONE;
gl_pvpActive = NULL;
gl_ulFlags &= GLF_ADJUSTABLEGAMMA;
// reset function pointers
GFX_SetFunctionPointers( (INDEX)GAT_NONE);
}
// prepare current viewport for rendering
BOOL CGfxLibrary::SetCurrentViewport(CViewPort *pvp)
{
if( gl_eCurrentAPI==GAT_OGL) return SetCurrentViewport_OGL(pvp);
#ifdef SE1_D3D
if( gl_eCurrentAPI==GAT_D3D) return SetCurrentViewport_D3D(pvp);
#endif // SE1_D3D
if( gl_eCurrentAPI==GAT_NONE) return TRUE;
ASSERTALWAYS( "SetCurrenViewport: Wrong API!");
return FALSE;
}
// Lock a drawport for drawing
BOOL CGfxLibrary::LockDrawPort( CDrawPort *pdpToLock)
{
// check API
#ifdef SE1_D3D
ASSERT( gl_eCurrentAPI==GAT_OGL || gl_eCurrentAPI==GAT_D3D || gl_eCurrentAPI==GAT_NONE);
#else // SE1_D3D
ASSERT( gl_eCurrentAPI==GAT_OGL || gl_eCurrentAPI==GAT_NONE);
#endif // SE1_D3D
// don't allow locking if drawport is too small
if( pdpToLock->dp_Width<1 || pdpToLock->dp_Height<1) return FALSE;
// don't set if same as last
const ULONG ulThisDrawPortID = pdpToLock->GetID();
if( GFX_ulLastDrawPortID==ulThisDrawPortID && gap_bOptimizeStateChanges) {
// just set projection
pdpToLock->SetOrtho();
return TRUE;
}
// OpenGL ...
if( gl_eCurrentAPI==GAT_OGL)
{
// pass drawport dimensions to OpenGL
const PIX pixMinSI = pdpToLock->dp_ScissorMinI;
const PIX pixMaxSI = pdpToLock->dp_ScissorMaxI;
const PIX pixMinSJ = pdpToLock->dp_Raster->ra_Height -1 - pdpToLock->dp_ScissorMaxJ;
const PIX pixMaxSJ = pdpToLock->dp_Raster->ra_Height -1 - pdpToLock->dp_ScissorMinJ;
pglViewport( pixMinSI, pixMinSJ, pixMaxSI-pixMinSI+1, pixMaxSJ-pixMinSJ+1);
pglScissor( pixMinSI, pixMinSJ, pixMaxSI-pixMinSI+1, pixMaxSJ-pixMinSJ+1);
OGL_CHECKERROR;
}
// Direct3D ...
#ifdef SE1_D3D
else if( gl_eCurrentAPI==GAT_D3D)
{
// set viewport
const PIX pixMinSI = pdpToLock->dp_ScissorMinI;
const PIX pixMaxSI = pdpToLock->dp_ScissorMaxI;
const PIX pixMinSJ = pdpToLock->dp_ScissorMinJ;
const PIX pixMaxSJ = pdpToLock->dp_ScissorMaxJ;
D3DVIEWPORT8 d3dViewPort = { pixMinSI, pixMinSJ, pixMaxSI-pixMinSI+1, pixMaxSJ-pixMinSJ+1, 0,1 };
HRESULT hr = gl_pd3dDevice->SetViewport( &d3dViewPort);
D3D_CHECKERROR(hr);
}
#endif // SE1_D3D
// mark and set default projection
GFX_ulLastDrawPortID = ulThisDrawPortID;
pdpToLock->SetOrtho();
return TRUE;
}
// Unlock a drawport after drawing
void CGfxLibrary::UnlockDrawPort( CDrawPort *pdpToUnlock)
{
// check API
#ifdef SE1_D3D
ASSERT(gl_eCurrentAPI == GAT_OGL || gl_eCurrentAPI == GAT_D3D || gl_eCurrentAPI == GAT_NONE);
#else // SE1_D3D
ASSERT(gl_eCurrentAPI == GAT_OGL || gl_eCurrentAPI == GAT_NONE);
#endif // SE1_D3D
// eventually signalize that scene rendering has ended
}
/////////////////////////////////////////////////////////////////////
// Window canvas functions
/* Create a new window canvas. */
void CGfxLibrary::CreateWindowCanvas(void *hWnd, CViewPort **ppvpNew, CDrawPort **ppdpNew)
{
// get the dimensions from the window
// !!! FIXME : rcg11052001 Abstract this.
#ifdef PLATFORM_WIN32
RECT rectWindow; // rectangle for the client area of the window
GetClientRect( (HWND)hWnd, &rectWindow);
const PIX pixWidth = rectWindow.right - rectWindow.left;
const PIX pixHeight = rectWindow.bottom - rectWindow.top;
#else
int w, h;
SDL_GL_GetDrawableSize((SDL_Window *) hWnd, &w, &h);
const PIX pixWidth = (PIX) w;
const PIX pixHeight = (PIX) h;
#endif
*ppvpNew = NULL;
*ppdpNew = NULL;
// create a new viewport
if((*ppvpNew = new CViewPort( pixWidth, pixHeight, (HWND)hWnd))) {
// and it's drawport
*ppdpNew = &(*ppvpNew)->vp_Raster.ra_MainDrawPort;
} else {
delete *ppvpNew;
*ppvpNew = NULL;
}
}
/* Destroy a window canvas. */
void CGfxLibrary::DestroyWindowCanvas(CViewPort *pvpOld) {
// delete the viewport
delete pvpOld;
}
/////////////////////////////////////////////////////////////////////
// Work canvas functions
#ifdef PLATFORM_WIN32
#define WorkCanvasCLASS "WorkCanvas Window"
static BOOL _bClassRegistered = FALSE;
/* Create a work canvas. */
void CGfxLibrary::CreateWorkCanvas(PIX pixWidth, PIX pixHeight, CDrawPort **ppdpNew)
{
// must have dimensions
ASSERT (pixWidth>0 || pixHeight>0);
if (!_bClassRegistered) {
_bClassRegistered = TRUE;
WNDCLASSA wc;
// must have owndc for opengl and dblclks to give to parent
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = NULL;
wc.hIcon = NULL;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = WorkCanvasCLASS;
RegisterClassA(&wc);
}
// create a window
HWND hWnd = ::CreateWindowExA(
0,
WorkCanvasCLASS,
"", // title
WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_POPUP,
0,0,
pixWidth, pixHeight, // window size
NULL,
NULL,
NULL, //hInstance,
NULL);
ASSERT(hWnd != NULL);
*ppdpNew = NULL;
CViewPort *pvp;
CreateWindowCanvas(hWnd, &pvp, ppdpNew);
}
/* Destroy a work canvas. */
void CGfxLibrary::DestroyWorkCanvas(CDrawPort *pdpOld)
{
CViewPort *pvp = pdpOld->dp_Raster->ra_pvpViewPort;
HWND hwnd = pvp->vp_hWndParent;
DestroyWindowCanvas(pvp);
::DestroyWindow(hwnd);
}
#endif
// optimize memory used by cached shadow maps
#define SHADOWMAXBYTES (256*256*4*4/3)
static SLONG slCachedShadowMemory=0, slDynamicShadowMemory=0;
static INDEX ctCachedShadows=0, ctFlatShadows=0, ctDynamicShadows=0;
BOOL _bShadowsUpdated = TRUE;
void CGfxLibrary::ReduceShadows(void)
{
_sfStats.StartTimer( CStatForm::STI_SHADOWUPDATE);
// clamp shadow caching variables
shd_fCacheSize = Clamp( shd_fCacheSize, 0.1f, 128.0f);
shd_tmFlushDelay = Clamp( shd_tmFlushDelay, 0.1f, 120.0f);
CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); // readout current time
const TIME tmAcientDelay = Clamp( shd_tmFlushDelay*3, 60.0f, 300.0f);
// determine cached shadowmaps stats (if needed)
if( _bShadowsUpdated)
{
_bShadowsUpdated = FALSE;
slCachedShadowMemory=0; slDynamicShadowMemory=0;
ctCachedShadows=0; ctFlatShadows=0; ctDynamicShadows=0;
{FORDELETELIST( CShadowMap, sm_lnInGfx, _pGfx->gl_lhCachedShadows, itsm) {
CShadowMap &sm = *itsm;
ASSERT( sm.sm_pulCachedShadowMap!=NULL); // must be cached
ASSERT( sm.sm_slMemoryUsed>0 && sm.sm_slMemoryUsed<=SHADOWMAXBYTES); // and have valid size
// remove acient shadowmaps from list (if allowed)
const TIME tmDelta = (tvNow-sm.sm_tvLastDrawn).GetSeconds();
if( tmDelta>tmAcientDelay && !(sm.sm_ulFlags&SMF_PROBED) && !shd_bCacheAll) {
sm.Uncache();
continue;
}
// determine type and occupied space
const BOOL bDynamic = sm.sm_pulDynamicShadowMap!=NULL;
const BOOL bFlat = sm.sm_pulCachedShadowMap==&sm.sm_colFlat;
if( bDynamic) { slDynamicShadowMemory += sm.sm_slMemoryUsed; ctDynamicShadows++; }
if( !bFlat) { slCachedShadowMemory += sm.sm_slMemoryUsed; ctCachedShadows++; }
else { slCachedShadowMemory += sizeof(sm.sm_colFlat); ctFlatShadows++; }
}}
}
// update statistics counters
_pfGfxProfile.IncrementCounter(CGfxProfile::PCI_CACHEDSHADOWBYTES, slCachedShadowMemory);
_pfGfxProfile.IncrementCounter(CGfxProfile::PCI_CACHEDSHADOWS, ctCachedShadows);
_pfGfxProfile.IncrementCounter(CGfxProfile::PCI_FLATSHADOWS, ctFlatShadows);
_pfGfxProfile.IncrementCounter(CGfxProfile::PCI_DYNAMICSHADOWBYTES, slDynamicShadowMemory);
_pfGfxProfile.IncrementCounter(CGfxProfile::PCI_DYNAMICSHADOWS, ctDynamicShadows);
_sfStats.IncrementCounter( CStatForm::SCI_CACHEDSHADOWBYTES, slCachedShadowMemory);
_sfStats.IncrementCounter( CStatForm::SCI_CACHEDSHADOWS, ctCachedShadows);
_sfStats.IncrementCounter( CStatForm::SCI_FLATSHADOWS, ctFlatShadows);
_sfStats.IncrementCounter( CStatForm::SCI_DYNAMICSHADOWBYTES, slDynamicShadowMemory);
_sfStats.IncrementCounter( CStatForm::SCI_DYNAMICSHADOWS, ctDynamicShadows);
// done if reducing is not allowed
if( shd_bCacheAll) {
_sfStats.StopTimer( CStatForm::STI_SHADOWUPDATE);
return;
}
// optimize only if low on memory
ULONG ulShadowCacheSize = (ULONG)(shd_fCacheSize*1024*1024); // in bytes
ULONG ulUsedShadowMemory = slCachedShadowMemory + slDynamicShadowMemory;
if( ulUsedShadowMemory <= ulShadowCacheSize) {
_sfStats.StopTimer( CStatForm::STI_SHADOWUPDATE);
return;
}
// reduce shadow delay if needed
// (lineary from specified value to 2sec for cachedsize>specsize to cachedsize>2*specsize)
TIME tmFlushDelay = shd_tmFlushDelay;
if( tmFlushDelay>2.0f) {
FLOAT fRatio = (FLOAT)ulUsedShadowMemory / ulShadowCacheSize;
ASSERT( fRatio>=1.0f);
fRatio = ClampUp( fRatio/2.0f, 1.0f);
tmFlushDelay = Lerp( tmFlushDelay, 2.0f, fRatio);
}
// loop thru cached shadowmaps list
{FORDELETELIST( CShadowMap, sm_lnInGfx, _pGfx->gl_lhCachedShadows, itsm)
{ // stop iteration if current shadow map it is not too old (list is sorted by time)
// or we have enough memory for cached shadows that remain
CShadowMap &sm = *itsm;
const TIME tmDelta = (tvNow-sm.sm_tvLastDrawn).GetSeconds();
if( tmDelta<tmFlushDelay || ulUsedShadowMemory<ulShadowCacheSize) break;
// uncache shadow (this returns ammount of memory that has been freed)
ulUsedShadowMemory -= sm.Uncache();
ASSERT( ulUsedShadowMemory>=0);
}}
// done
_sfStats.StopTimer( CStatForm::STI_SHADOWUPDATE);
}
// some vars for probing
INDEX _ctProbeTexs = 0;
INDEX _ctProbeShdU = 0;
INDEX _ctProbeShdB = 0;
INDEX _ctFullShdU = 0;
SLONG _slFullShdUBytes = 0;
#ifdef PLATFORM_WIN32 // only used there
static BOOL GenerateGammaTable(void);
#endif
/*
* Swap buffers in a viewport.
*/
void CGfxLibrary::SwapBuffers(CViewPort *pvp)
{
// check API
#ifdef SE1_D3D
ASSERT(gl_eCurrentAPI == GAT_OGL || gl_eCurrentAPI == GAT_D3D || gl_eCurrentAPI == GAT_NONE);
#else // SE1_D3D
ASSERT(gl_eCurrentAPI == GAT_OGL || gl_eCurrentAPI == GAT_NONE);
#endif // SE1_D3D
// safety check
ASSERT( gl_pvpActive!=NULL);
if( pvp!=gl_pvpActive) {
ASSERTALWAYS( "Swapping viewport that was not last drawn to!");
return;
}
// optimize memory used by cached shadow maps and update shadowmap counters
ReduceShadows();
// check and eventually adjust texture filtering and LOD biasing
gfxSetTextureFiltering( gap_iTextureFiltering, gap_iTextureAnisotropy);
gfxSetTextureBiasing( gap_fTextureLODBias);
// clamp some cvars
gap_iDithering = Clamp( gap_iDithering, 0, 2);
gap_iSwapInterval = Clamp( gap_iSwapInterval, 0, 4);
gap_iOptimizeClipping = Clamp( gap_iOptimizeClipping, 0, 2);
gap_iTruformLevel = Clamp( gap_iTruformLevel, 0, _pGfx->gl_iMaxTessellationLevel);
ogl_iFinish = Clamp( ogl_iFinish, 0, 3);
d3d_iFinish = Clamp( d3d_iFinish, 0, 3);
// OpenGL
if( gl_eCurrentAPI==GAT_OGL)
{
// force finishing of all rendering operations (if required)
if( ogl_iFinish==2) gfxFinish();
// check state of swap interval extension usage
if( gl_ulFlags & GLF_VSYNC) {
if( gl_iSwapInterval != gap_iSwapInterval) {
gl_iSwapInterval = gap_iSwapInterval;
#ifdef PLATFORM_WIN32
pwglSwapIntervalEXT( gl_iSwapInterval);
#else
SDL_GL_SetSwapInterval( gl_iSwapInterval);
#endif
}
}
// swap buffers
// !!! FIXME: Move this to platform-specific directories.
#ifdef PLATFORM_WIN32
CTempDC tdc(pvp->vp_hWnd);
pwglSwapBuffers(tdc.hdc);
#else
SDL_GL_SwapWindow((SDL_Window *) pvp->vp_hWnd);
#endif
// force finishing of all rendering operations (if required)
if( ogl_iFinish==3) gfxFinish();
// reset CVA usage if ext is not present
if( !(gl_ulFlags&GLF_EXT_COMPILEDVERTEXARRAY)) ogl_bUseCompiledVertexArrays = 0;
}
// Direct3D
#ifdef SE1_D3D
else if( gl_eCurrentAPI==GAT_D3D)
{
// force finishing of all rendering operations (if required)
if( d3d_iFinish==2) gfxFinish();
// end scene rendering
HRESULT hr;
if( GFX_bRenderingScene) {
hr = gl_pd3dDevice->EndScene();
D3D_CHECKERROR(hr);
}
CDisplayMode dm;
GetCurrentDisplayMode(dm);
ASSERT( (dm.dm_pixSizeI==0 && dm.dm_pixSizeJ==0) || (dm.dm_pixSizeI!=0 && dm.dm_pixSizeJ!=0));
if( dm.dm_pixSizeI==0 || dm.dm_pixSizeJ==0 ) {
// windowed mode
hr = pvp->vp_pSwapChain->Present( NULL, NULL, NULL, NULL);
} else {
// full screen mode
hr = gl_pd3dDevice->Present( NULL, NULL, NULL, NULL);
} // done swapping
D3D_CHECKERROR(hr);
// force finishing of all rendering operations (if required)
if( d3d_iFinish==3) gfxFinish();
// eventually reset vertex buffer if something got changed
if( _iLastVertexBufferSize!=d3d_iVertexBuffersSize
|| (gl_iTessellationLevel<1 && gap_iTruformLevel>0)
|| (gl_iTessellationLevel>0 && gap_iTruformLevel<1)) {
extern void SetupVertexArrays_D3D( INDEX ctVertices);
extern void SetupIndexArray_D3D( INDEX ctVertices);
extern DWORD SetupShader_D3D( ULONG ulStreamsMask);
SetupShader_D3D(NONE);
SetupVertexArrays_D3D(0);
SetupIndexArray_D3D(0);
extern INDEX VerticesFromSize_D3D( SLONG &slSize);
const INDEX ctVertices = VerticesFromSize_D3D(d3d_iVertexBuffersSize);
SetupVertexArrays_D3D(ctVertices);
SetupIndexArray_D3D(2*ctVertices);
_iLastVertexBufferSize = d3d_iVertexBuffersSize;
}
}
#endif // SE1_D3D
// update tessellation level
gl_iTessellationLevel = gap_iTruformLevel;
// must reset drawport and rendering status for subsequent locks
GFX_ulLastDrawPortID = 0;
GFX_bRenderingScene = FALSE;
// reset frustum/ortho matrix, too
extern BOOL GFX_bViewMatrix;
extern FLOAT GFX_fLastL, GFX_fLastR, GFX_fLastT, GFX_fLastB, GFX_fLastN, GFX_fLastF;
GFX_fLastL = GFX_fLastR = GFX_fLastT = GFX_fLastB = GFX_fLastN = GFX_fLastF = 0;
GFX_bViewMatrix = TRUE;
// set maximum allowed upload ammount
gfx_iProbeSize = Clamp( gfx_iProbeSize, 1, 16384);
gl_slAllowedUploadBurst = gfx_iProbeSize *1024;
_ctProbeTexs = 0;
_ctProbeShdU = 0;
_ctProbeShdB = 0;
_ctFullShdU = 0;
_slFullShdUBytes = 0;
// keep time when swap buffer occured and maintain counter of frames for temporal coherence checking
gl_tvFrameTime = _pTimer->GetHighPrecisionTimer();
gl_iFrameNumber++;
// reset profiling counters
gl_ctWorldTriangles = 0;
gl_ctModelTriangles = 0;
gl_ctParticleTriangles = 0;
gl_ctTotalTriangles = 0;
// re-adjust multi-texturing support
gap_iUseTextureUnits = Clamp( gap_iUseTextureUnits, 1, _pGfx->gl_ctTextureUnits);
ASSERT( gap_iUseTextureUnits>=1 && gap_iUseTextureUnits<=GFX_MAXTEXUNITS);
// re-get usage of compiled vertex arrays
CVA_b2D = ogl_bUseCompiledVertexArrays /100;
CVA_bWorld = ogl_bUseCompiledVertexArrays /10 %10;
CVA_bModels = ogl_bUseCompiledVertexArrays %10;
ogl_bUseCompiledVertexArrays = 0;
if( CVA_b2D) ogl_bUseCompiledVertexArrays += 100;
if( CVA_bWorld) ogl_bUseCompiledVertexArrays += 10;
if( CVA_bModels) ogl_bUseCompiledVertexArrays += 1;
// eventually advance to next sample buffer
if( (gl_ulFlags&GLF_EXT_TBUFFER) && go_ctSampleBuffers>1) {
go_iCurrentWriteBuffer--;
if( go_iCurrentWriteBuffer<0) go_iCurrentWriteBuffer = go_ctSampleBuffers-1;
pglDisable( GL_MULTISAMPLE_3DFX);
}
// clear viewport if needed
if( gfx_bClearScreen) pvp->vp_Raster.ra_MainDrawPort.Fill( C_BLACK|CT_OPAQUE);
//pvp->vp_Raster.ra_MainDrawPort.FillZBuffer(ZBUF_BACK);
// adjust gamma table if supported ...
#ifdef PLATFORM_WIN32
if( gl_ulFlags & GLF_ADJUSTABLEGAMMA) {
// ... and required
const BOOL bTableSet = GenerateGammaTable();
if( bTableSet) {
if( gl_eCurrentAPI==GAT_OGL) {
CTempDC tdc(pvp->vp_hWnd);
SetDeviceGammaRamp( tdc.hdc, &_auwGammaTable[0]);
}
#ifdef SE1_D3D
else if( gl_eCurrentAPI==GAT_D3D) {
gl_pd3dDevice->SetGammaRamp( D3DSGR_NO_CALIBRATION, (D3DGAMMARAMP*)&_auwGammaTable[0]);
}
#endif // SE1_D3D
}
}
else
#elif defined(PLATFORM_PANDORA)
if( gl_ulFlags & GLF_ADJUSTABLEGAMMA) {
//hacky Gamma only (no Contrast/Brightness) support.
static float old_pandora_gamma = 0.0f;
if (old_pandora_gamma!=gfx_fGamma) {
char buf[50];
sprintf(buf,"sudo /usr/pandora/scripts/op_gamma.sh %.2f", gfx_fGamma);
system(buf);
old_pandora_gamma = gfx_fGamma;
}
}
else
#endif
// if not supported
{
// just reset settings to default
gfx_fBrightness = 0;
gfx_fContrast = 1;
gfx_fGamma = 1;
gfx_fBiasR = 1;
gfx_fBiasG = 1;
gfx_fBiasB = 1;
gfx_iLevels = 256;
}
}
// get array of all supported display modes
CDisplayMode *CGfxLibrary::EnumDisplayModes( INDEX &ctModes, enum GfxAPIType eAPI/*=GAT_CURRENT*/, INDEX iAdapter/*=0*/)
{
if( eAPI==GAT_CURRENT) eAPI = gl_eCurrentAPI;
if( iAdapter==0) iAdapter = gl_iCurrentAdapter;
CDisplayAdapter *pda = &gl_gaAPI[eAPI].ga_adaAdapter[iAdapter];
ctModes = pda->da_ctDisplayModes;
return &pda->da_admDisplayModes[0];
}
// Lock a raster for drawing.
BOOL CGfxLibrary::LockRaster( CRaster *praToLock)
{
// don't do this! it can break sync consistency in entities!
// SetFPUPrecision(FPT_24BIT);
ASSERT( praToLock->ra_pvpViewPort!=NULL);
BOOL bRes = SetCurrentViewport( praToLock->ra_pvpViewPort);
if( bRes) {
// must signal to picky Direct3D
#ifdef SE1_D3D
if( gl_eCurrentAPI==GAT_D3D && !GFX_bRenderingScene) {
HRESULT hr = gl_pd3dDevice->BeginScene();
D3D_CHECKERROR(hr);
bRes = (hr==D3D_OK);
} // mark it
#endif // SE1_D3D
GFX_bRenderingScene = TRUE;
} // done
return bRes;
}
// Unlock a raster after drawing.
void CGfxLibrary::UnlockRaster( CRaster *praToUnlock)
{
// don't do this! it can break sync consistency in entities!
// SetFPUPrecision(FPT_53BIT);
ASSERT( GFX_bRenderingScene);
}
#ifdef PLATFORM_WIN32 // DG: only used on windows
// generates gamma table and returns true if gamma table has been changed
static BOOL GenerateGammaTable(void)
{
// only if needed
if( _fLastBrightness == gfx_fBrightness
&& _fLastContrast == gfx_fContrast
&& _fLastGamma == gfx_fGamma
&& _iLastLevels == gfx_iLevels
&& _fLastBiasR == gfx_fBiasR
&& _fLastBiasG == gfx_fBiasG
&& _fLastBiasB == gfx_fBiasB) return FALSE;
// guess it's needed
INDEX i;
gfx_fBrightness = Clamp( gfx_fBrightness, -0.8f, 0.8f);
gfx_fContrast = Clamp( gfx_fContrast, 0.2f, 4.0f);
gfx_fGamma = Clamp( gfx_fGamma, 0.2f, 4.0f);
gfx_iLevels = Clamp( gfx_iLevels, 2, 256);
gfx_fBiasR = Clamp( gfx_fBiasR, 0.0f, 2.0f);
gfx_fBiasG = Clamp( gfx_fBiasG, 0.0f, 2.0f);
gfx_fBiasB = Clamp( gfx_fBiasB, 0.0f, 2.0f);
_fLastBrightness = gfx_fBrightness;
_fLastContrast = gfx_fContrast;
_fLastGamma = gfx_fGamma;
_iLastLevels = gfx_iLevels;
_fLastBiasR = gfx_fBiasR;
_fLastBiasG = gfx_fBiasG;
_fLastBiasB = gfx_fBiasB;
// fill and adjust gamma
const FLOAT f1oGamma = 1.0f / gfx_fGamma;
for( i=0; i<256; i++) {
FLOAT fVal = i/255.0f;
fVal = Clamp( (FLOAT)pow(fVal,f1oGamma), 0.0f, 1.0f);
_auwGammaTable[i] = (UWORD)(fVal*65280);
}
// adjust contrast
for( i=0; i<256; i++) {
FLOAT fVal = _auwGammaTable[i]/65280.0f;
fVal = Clamp( (fVal-0.5f)*gfx_fContrast +0.5f, 0.0f, 1.0f);
_auwGammaTable[i] = (UWORD)(fVal*65280);
}
// adjust brightness
INDEX iAdd = (INDEX) (256* 256*gfx_fBrightness);
for( i=0; i<256; i++) {
_auwGammaTable[i] = Clamp( _auwGammaTable[i]+iAdd, 0, 65280);
}
// adjust levels (posterize)
if( gfx_iLevels<256) {
const FLOAT fLevels = 256 * 256.0f/gfx_iLevels;
for( i=0; i<256; i++) {
INDEX iVal = _auwGammaTable[i];
iVal = (INDEX) (((INDEX)(iVal/fLevels)) *fLevels);
_auwGammaTable[i] = ClampUp( iVal, 0xFF00);
}
}
// copy R to G and B array
for( i=0; i<256; i++) {
FLOAT fR,fG,fB;
fR=fG=fB = _auwGammaTable[i]/65280.0f;
fR = Clamp( fR*gfx_fBiasR, 0.0f, 1.0f);
fG = Clamp( fG*gfx_fBiasG, 0.0f, 1.0f);
fB = Clamp( fB*gfx_fBiasB, 0.0f, 1.0f);
_auwGammaTable[i+0] = (UWORD)(fR*65280);
_auwGammaTable[i+256] = (UWORD)(fG*65280);
_auwGammaTable[i+512] = (UWORD)(fB*65280);
}
// done
return TRUE;
}
#endif // PLATFORM_WIN32
#if 0
DeclareSymbol( "[persistent] [hidden] [const] [type] name [minval] [maxval] [func()]", &shd_iStaticQuality, func()=NULL);
_pShell->DeclareSymbol( "INDEX GfxVarPreFunc(INDEX);", &GfxVarPreFunc);
_pShell->DeclareSymbol( "void GfxVarPostFunc(INDEX);", &GfxVarPostFunc);
static BOOL GfxVarPreFunc(void *pvVar)
{
if (pvVar==&gfx_fSaturation) {
CPrintF("cannot change saturation: just for test\n");
return FALSE;
} else {
CPrintF("gfx var about to be changed\n");
return TRUE;
}
}
static void GfxVarPostFunc(void *pvVar)
{
if (pvVar==&shd_bFineQuality) {
CPrintF("This requires RefreshTextures() to take effect!\n");
}
}
#endif