mirror of
https://github.com/OpenTrespasser/JurassicParkTrespasser.git
synced 2024-12-24 01:21:57 +00:00
2115 lines
57 KiB
C++
2115 lines
57 KiB
C++
/***********************************************************************************************
|
|
*
|
|
* Copyright © DreamWorks Interactive, 1997.
|
|
*
|
|
* Contents:
|
|
* Implementation of Direct3D.hpp.
|
|
*
|
|
***********************************************************************************************
|
|
*
|
|
* $Log:: /JP2_PC/Source/Lib/W95/Direct3D.cpp $
|
|
*
|
|
* 134 10/08/98 10:58p Pkeet
|
|
* Changed memory allocation slightly.
|
|
*
|
|
* 133 10/07/98 7:52a Pkeet
|
|
*
|
|
* 132 10/07/98 6:10a Pkeet
|
|
* Made a minimum texture allocation.
|
|
*
|
|
* 131 10/06/98 5:51a Pkeet
|
|
* Added the page managed flag.
|
|
*
|
|
* 130 10/05/98 11:41p Pkeet
|
|
* Tweaked numbers.
|
|
*
|
|
* 129 10/05/98 5:45a Pkeet
|
|
* Increased memory for terrain.
|
|
*
|
|
* 128 10/02/98 5:18p Pkeet
|
|
* Allocation is less for non-shared buffers.
|
|
*
|
|
* 127 10/01/98 8:39p Pkeet
|
|
* Reserved more memory for Direct3D.
|
|
*
|
|
* 126 10/01/98 7:10p Pkeet
|
|
* Paranoid setting of the 'bUse' flag.
|
|
*
|
|
* 125 9/29/98 5:41p Pkeet
|
|
* Tweaked memory allocations.
|
|
*
|
|
* 124 9/27/98 10:02p Pkeet
|
|
* Added a global function to reset conversion tables.
|
|
*
|
|
* 123 9/27/98 2:08a Mmouni
|
|
* Changed d3d surface load progress.
|
|
*
|
|
* 122 9/17/98 11:12p Shernd
|
|
* First pass on updating during d3d surface setup
|
|
*
|
|
* 121 9/15/98 5:34p Pkeet
|
|
* Removed unnecessary code in 'Uninitialize.'
|
|
*
|
|
* 120 9/11/98 3:28p Pkeet
|
|
* Disabled crash bug when switching resolutions.
|
|
*
|
|
* 119 9/09/98 7:41p Pkeet
|
|
* Added functions to show that the computer is working while it loads Direct3D surfaces.
|
|
*
|
|
* 118 9/05/98 7:52p Pkeet
|
|
* Added support for the Matrox G100.
|
|
*
|
|
* 117 9/02/98 6:05p Pkeet
|
|
* Added the 'EvictManagedTextures' call before purging.
|
|
*
|
|
* 116 9/01/98 12:44a Pkeet
|
|
* The default render state is now set only once in the 'Restore' member function. Fixed bug
|
|
* clearing the viewport when it is shrunk.
|
|
*
|
|
*
|
|
**********************************************************************************************/
|
|
|
|
#include <memory.h>
|
|
#include "Common.hpp"
|
|
#include "Direct3D.hpp"
|
|
|
|
#include "Lib/View/Clut.hpp"
|
|
#include "Lib/Sys/RegInit.hpp"
|
|
#include "Lib/GeomDBase/Terrain.hpp"
|
|
#include "Lib/GeomDBase/TerrainTexture.hpp"
|
|
#include "Lib/GeomDBase/WaveletQuadTree.hpp"
|
|
#include "Lib/EntityDBase/Query/QTerrain.hpp"
|
|
#include "Lib/Renderer/Sky.hpp"
|
|
#include "Lib/EntityDBase/Water.hpp"
|
|
#include "Lib/Renderer/Pipeline.hpp"
|
|
#include "Lib/Sys/W95/Render.hpp"
|
|
#include "Lib/Renderer/RenderCache.hpp"
|
|
#include "Lib/Std/MemLimits.hpp"
|
|
#include "Lib/Std/PrivSelf.hpp"
|
|
#include "Lib/View/Direct3DRenderState.hpp"
|
|
#include "Lib/View/AGPTextureMemManager.hpp"
|
|
#include "Lib/View/RasterPool.hpp"
|
|
#include "Lib/Renderer/ScreenRenderAuxD3D.hpp"
|
|
#include "Lib/Sys/Reg.h"
|
|
#include "Lib/View/Direct3DRenderState.hpp"
|
|
#include "Lib/W95/Direct3DQuery.hpp"
|
|
#include "Lib/Sys/Profile.hpp"
|
|
#include "Lib/View/ColourBase.hpp"
|
|
#include "Lib/View/RasterConvertD3D.hpp"
|
|
|
|
#include "Lib/Sys/DebugConsole.hpp"
|
|
|
|
|
|
//
|
|
// Macros.
|
|
//
|
|
|
|
// Convert kilobytes to bytes.
|
|
#define iBytesKB(X) (X << 10)
|
|
|
|
// Convert megabytes to bytes.
|
|
#define iBytesMB(X) (X << 20)
|
|
|
|
// Convert bytes to kilobytes.
|
|
#define iKB(X) (X >> 10)
|
|
|
|
// Convert bytes to megabytes.
|
|
#define iMB(X) (X >> 20)
|
|
|
|
#ifndef PFNWORLDLOADNOTIFY
|
|
typedef uint32 (__stdcall * PFNWORLDLOADNOTIFY)(uint32 dwContext, uint32 dwParam1, uint32 dwParam2, uint32 dwParam3);
|
|
#endif
|
|
|
|
//
|
|
// Constants.
|
|
//
|
|
|
|
// Minimum and maximum allowed texture memory for terrain.
|
|
const int iMinTerrain = iBytesKB(1280);
|
|
const int iMaxTerrain = iBytesKB(1920);
|
|
|
|
// Minimum amount of memory for AGP texturing.
|
|
const int iMinTexture = iBytesKB(2560);
|
|
|
|
// Fixed texture memory allocations.
|
|
const int iAllocSky = iBytesKB(128);
|
|
const int iAllocWater = iBytesKB(384);
|
|
|
|
// Threshold for using a large memory model.
|
|
static const uint u64MbThreshold = iBytesMB(56);
|
|
|
|
// Threshold for using a very large memory model.
|
|
static const uint u96MbThreshold = iBytesMB(92);
|
|
|
|
// Percentage for caches.
|
|
const int iCachePercent = 40;
|
|
|
|
|
|
//
|
|
// External declaractions.
|
|
//
|
|
extern rptr<CTexturePageManager> ptexmCacheTextures;
|
|
extern PFNWORLDLOADNOTIFY g_pfnWorldLoadNotify;
|
|
extern uint32 g_u4NotifyParam;
|
|
extern bool bIsTrespasser;
|
|
|
|
#if bTRACK_D3D_RASTERS
|
|
void PrintLeftoverD3D();
|
|
#endif // bTRACK_D3D_RASTERS
|
|
|
|
static CProfileStat psExecuteHardwareClear("HW Clear", &proProfile.psRender);
|
|
|
|
|
|
//
|
|
// Function prototypes and simple functions.
|
|
//
|
|
|
|
//*********************************************************************************************
|
|
//
|
|
uint uGetMaskBits
|
|
(
|
|
uint32 u4 // Value to count bits in.
|
|
)
|
|
//
|
|
// Returns the number of bits set in the value, or zero if no bits are set.
|
|
//
|
|
//**************************************
|
|
{
|
|
uint u_num_bits = 0;
|
|
|
|
while ((u4 & 1) == 0 && u4 != 0)
|
|
{
|
|
++u_num_bits;
|
|
u4 >>= 1;
|
|
}
|
|
return u_num_bits;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
inline bool bRedLow
|
|
(
|
|
const DDPIXELFORMAT& ddpf
|
|
)
|
|
//
|
|
// Returns 'true' if red is low.
|
|
//
|
|
//**********************************
|
|
{
|
|
return ddpf.dwRBitMask == 0x001F;
|
|
}
|
|
|
|
static DWORD
|
|
FlagsToBitDepth(DWORD dwFlags)
|
|
{
|
|
if (dwFlags & DDBD_1)
|
|
return 1;
|
|
else if (dwFlags & DDBD_2)
|
|
return 2;
|
|
else if (dwFlags & DDBD_4)
|
|
return 4;
|
|
else if (dwFlags & DDBD_8)
|
|
return 8;
|
|
else if (dwFlags & DDBD_16)
|
|
return 16;
|
|
else if (dwFlags & DDBD_24)
|
|
return 24;
|
|
else if (dwFlags & DDBD_32)
|
|
return 32;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Class definitions.
|
|
//
|
|
|
|
//**********************************************************************************************
|
|
//
|
|
class CDirect3D::CPriv : public CDirect3D
|
|
//
|
|
// Private member functions for class 'CDirect3D.'
|
|
//
|
|
//**************************************
|
|
{
|
|
public:
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetMemoryModel
|
|
(
|
|
);
|
|
//
|
|
// Sets the 'emmMemoryModel' data member based on available system memory.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
uint uLargePool
|
|
(
|
|
)
|
|
//
|
|
// Returns the amount of memory to use for a pool based on the 'emmMemoryModel' data member.
|
|
//
|
|
//**************************************
|
|
{
|
|
// Small memory allocatation.
|
|
if (iTotalFreeMem < iBytesMB(6))
|
|
return iBytesKB(512);
|
|
|
|
// Non-shared texture allocation.
|
|
if (iTotalFreeMem < iBytesMB(18))
|
|
return iBytesKB(1152);
|
|
|
|
// Default normal memory model allocation.
|
|
return iBytesKB(1792);
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
bool bUseNonLocalMemory
|
|
(
|
|
);
|
|
//
|
|
// Returns 'true' if nonlocal (AGP system) memory is to be used for texturing.
|
|
//
|
|
// Notes:
|
|
// If this function is successful, the 'easAllocation' data member should be set to
|
|
// 'easNonLocal.'
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
bool bUseManagedMemory
|
|
(
|
|
);
|
|
//
|
|
// Returns 'true' if managed memory is to be used for texturing.
|
|
//
|
|
// Notes:
|
|
// If this function is successful, the 'easAllocation' data member should be set to
|
|
// 'easManaged.'
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
bool bAllocateManagedMemory
|
|
(
|
|
);
|
|
//
|
|
// Returns 'true' if managed memory is to be used for texturing.
|
|
//
|
|
// Notes:
|
|
// If this function is successful, the 'easAllocation' data member should be set to
|
|
// 'easManaged.'
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
bool bAllocateNonLocalMemory
|
|
(
|
|
);
|
|
//
|
|
// Returns 'true' if non-local (agp system) memory is to be used for texturing.
|
|
//
|
|
// Notes:
|
|
// If this function is successful, the 'easAllocation' data member should be set to
|
|
// 'easNonLocal.'
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
int iGetMaxTextureRam
|
|
(
|
|
);
|
|
//
|
|
// Returns the maximum amount of texture memory that may be used.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
int iGetWaterAlloc
|
|
(
|
|
);
|
|
//
|
|
// Returns the amount of memory in bytes allocated for water.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetupLoadingScreens
|
|
(
|
|
);
|
|
//
|
|
// Prepares the animating loading screens for use.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void WriteTextToLoadScreen
|
|
(
|
|
const char* str // String to write.
|
|
);
|
|
//
|
|
// Clears the load screen and writes text to it.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetModulatedAlpha
|
|
(
|
|
);
|
|
//
|
|
// Sets the modulate alpha flag if modulated alpha can be supported.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
bool bSetupViewport
|
|
(
|
|
LPDIRECTDRAWSURFACE4 pdds_backbuffer
|
|
);
|
|
//
|
|
// Adds a viewport to the D3D object.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
bool bEnumerateTextureFormats
|
|
(
|
|
);
|
|
//
|
|
// Builds a list of valid texture formats for the D3D device.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SpecialCaseSetup
|
|
(
|
|
);
|
|
//
|
|
// Performs awkward special case code for specific video cards.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetAlphaFormat
|
|
(
|
|
);
|
|
//
|
|
// Sets the alpha format.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetScreenFormat
|
|
(
|
|
LPDIRECTDRAWSURFACE4 pdds_backbuffer // Pointer to the backbuffer.
|
|
);
|
|
//
|
|
// Sets the screen pixel format.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetTransparentFormat
|
|
(
|
|
);
|
|
//
|
|
// Sets the transparent format.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetTotalTextureMem
|
|
(
|
|
);
|
|
//
|
|
// Sets the total amount of texture memory available.
|
|
//
|
|
// Notes:
|
|
// This function must take into account the amount of memory allocated to the front
|
|
// and back buffers in cards that have unified memory architectures.
|
|
//
|
|
// To do:
|
|
// Ensure that allocations for cards that can have system memory texturing reflects
|
|
// the amount available to it.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetFog
|
|
(
|
|
);
|
|
//
|
|
// Sets the necessary flags in D3D for fogging.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetD3DFlag
|
|
(
|
|
);
|
|
//
|
|
// Sets the 'bUse' flag.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetCommonFormats
|
|
(
|
|
);
|
|
//
|
|
// Sets common formats for Direct3D textures.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetDeviceDescriptions
|
|
(
|
|
);
|
|
//
|
|
// Sets Direct3D descriptions and capabilites structures.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void SetLocalVideoMemFlag
|
|
(
|
|
);
|
|
//
|
|
// Set the 'bLocalVideoMem' flag.
|
|
//
|
|
//**************************************
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
int iLargeMemAllocMB
|
|
(
|
|
);
|
|
//
|
|
// Returns the recommended allocation in megabytes.
|
|
//
|
|
//**************************************
|
|
|
|
};
|
|
|
|
|
|
//
|
|
// Class implementations.
|
|
//
|
|
|
|
//*********************************************************************************************
|
|
//
|
|
// Implementation of CDirect3D.
|
|
//
|
|
|
|
//******************************************************************************************
|
|
//
|
|
// class CError implementation.
|
|
//
|
|
|
|
//**************************************************************************************
|
|
void CDirect3D::CError::ProcessError(HRESULT hres_error)
|
|
{
|
|
//
|
|
// Convert i_err to a resource symbol, and call the standard TerminalError function.
|
|
// The app resources contain strings for all DirectDraw error codes.
|
|
// The conversion consists of taking the low 16 bits of the error code, and adding
|
|
// it to ERROR_DD_BASE.
|
|
//
|
|
if (srd3dRenderer.bIsBusy())
|
|
srd3dRenderer.SetD3DMode(ed3drSOFTWARE_LOCK);
|
|
TerminalError(ERROR_D3D_BASE + (hres_error & 0xFFFF), true, "Direct3D Error.");
|
|
}
|
|
|
|
//******************************************************************************************
|
|
//
|
|
// class CCount implementation.
|
|
//
|
|
|
|
//**************************************************************************************
|
|
void CDirect3D::CCount::operator =(int i_count)
|
|
{
|
|
//
|
|
// Convert i_err to a resource symbol, and call the standard TerminalError function.
|
|
// The app resources contain strings for all DirectDraw error codes.
|
|
// The conversion consists of taking the low 16 bits of the error code, and adding
|
|
// it to ERROR_DD_BASE.
|
|
//
|
|
if (i_count == 0)
|
|
return;
|
|
TerminalError(ERROR_D3D_REFERENCECOUNT, true, "Direct3D Error.");
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
// Constructors and destructors.
|
|
//
|
|
|
|
//*****************************************************************************************
|
|
CDirect3D::CDirect3D()
|
|
: bInitialized(false), pD3D(0), pDevice(0), pd3dViewport(0), bPower2(true),
|
|
bSquareTextures(true), iTotalTextureMem(-1), iTerrainTextureMem(iMinTerrain),
|
|
bPurged(true), iTotalFreeMem(0), bFullTexturing(false),
|
|
bModulatedAlpha(false), bHardwareWater(false), easAllocation(easNone),
|
|
bTransparentAlpha(true), iRecommendedMaxDim(128), bDeviceTested(false),
|
|
emmMemoryModel(emmSmall), evcVideoCard(evcUnknown), bD3DCacheFog(true),
|
|
bSecondaryCard(false), bLocalVideoMem(true), bAlphaTransparency(false),
|
|
bShowLoadingScreen(false), bFlipClear(false)
|
|
{
|
|
// Test if D3D should be used.
|
|
priv_self.SetD3DFlag();
|
|
SetInitEnable(true);
|
|
|
|
bRegionUploads = true;
|
|
bSharedSysBuffers = true;
|
|
bFilterCaches = false;
|
|
|
|
// Set the memory model.
|
|
priv_self.SetMemoryModel();
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
CDirect3D::~CDirect3D()
|
|
{
|
|
// Put Direct3D away.
|
|
Uninitialize();
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
// Member functions.
|
|
//
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::bInitEnabled() const
|
|
{
|
|
return bEnableInit && bGetD3D();
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::SetInitEnable(bool b_enable)
|
|
{
|
|
bEnableInit = b_enable;
|
|
Assert(!(bUse && !bEnableInit));
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::bInitializeD3D()
|
|
{
|
|
AlwaysAssert(pD3D == 0);
|
|
|
|
HRESULT hres;
|
|
|
|
// If Direct3D is already initialized, uninitialize it.
|
|
if (bInitialized)
|
|
return true;
|
|
|
|
// Do nothing if Direct3D is not is use.
|
|
priv_self.SetD3DFlag();
|
|
if (!bUse)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// If Direct3D does not have its initialization flag enabled, do nothing.
|
|
if (!bInitEnabled())
|
|
{
|
|
SetD3D(false);
|
|
bUse = false;
|
|
return false;
|
|
|
|
}
|
|
|
|
//
|
|
// Set up Direct3D.
|
|
//
|
|
AlwaysAssert(DirectDraw::pdd4);
|
|
|
|
// Query the DirectDraw object to get the D3D object.
|
|
hres = DirectDraw::pdd4->QueryInterface(IID_IDirect3D3, (void**)&pD3D);
|
|
if (FAILED(hres))
|
|
{
|
|
SetD3D(false);
|
|
bUse = false;
|
|
return false;
|
|
}
|
|
Assert(pD3D);
|
|
PrintD3D(">>>>>>New direct 3d object created\n");
|
|
|
|
SetInitEnable(true);
|
|
bDeviceTested = false;
|
|
return true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::ReleaseD3D()
|
|
{
|
|
if (pD3D)
|
|
{
|
|
int i_ref = pD3D->Release();
|
|
pD3D = 0;
|
|
PrintD3D2(">>>>>>Direct3D object released (%ld).\n", i_ref);
|
|
};
|
|
bUse = false;
|
|
bDeviceTested = false;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::bInitialize(LPDIRECTDRAWSURFACE4 pdds_backbuffer, LPDIRECTDRAWSURFACE4 pdds_frontbuffer)
|
|
{
|
|
// If Direct3D is already initialized, uninitialize it.
|
|
if (bInitialized)
|
|
return true;
|
|
|
|
// Determine the video card type.
|
|
evcVideoCard = evcGetCard(DirectDraw::pdd4);
|
|
|
|
#if bDEBUG_DIRECT3D
|
|
|
|
// Output card name if specifically detected.
|
|
switch (evcVideoCard)
|
|
{
|
|
case evcMatroxG100:
|
|
dprintf("Video card: Matrox MGA-G100 Productiva\n");
|
|
break;
|
|
case evcATIRage:
|
|
dprintf("Video card: ATI\n");
|
|
break;
|
|
case evcNVidia128:
|
|
dprintf("Video card: NVidia Riva 128\n");
|
|
break;
|
|
case evcPermedia2:
|
|
dprintf("Video card: Permedia 2\n");
|
|
break;
|
|
default:
|
|
dprintf("Video card unknown\n");
|
|
break;
|
|
}
|
|
|
|
#endif // bDEBUG_DIRECT3D
|
|
|
|
// Set defaults.
|
|
iMaxTotalMemory = priv_self.iGetMaxTextureRam();
|
|
iRecommendedMaxDim = iGetRecommendedTextureMaxDim();
|
|
|
|
PrintD3D2("\nRecommended D3D max texture dimension: %ld\n", iRecommendedMaxDim);
|
|
|
|
// Set the screen pixel format as 555 or 565.
|
|
priv_self.SetScreenFormat(pdds_backbuffer);
|
|
|
|
//
|
|
// Create the D3D device.
|
|
//
|
|
|
|
// Get the GUID for the specific Direct3D driver.
|
|
GUID guid = ReadD3DGUID();
|
|
if (!pConvertGUID(guid))
|
|
{
|
|
Uninitialize();
|
|
bUse = false;
|
|
return false;
|
|
}
|
|
|
|
// Create the device using the guid.
|
|
#if VER_DEBUG
|
|
err = pD3D->CreateDevice(guid, pdds_backbuffer, &pDevice, 0);
|
|
Assert(pDevice);
|
|
#else // VER_DEBUG
|
|
if (pD3D->CreateDevice(guid, pdds_backbuffer, &pDevice, 0) != D3D_OK)
|
|
{
|
|
SetD3D(false);
|
|
Uninitialize();
|
|
bUse = false;
|
|
return false;
|
|
}
|
|
AlwaysAssert(pDevice);
|
|
#endif // VER_DEBUG
|
|
PrintD3D(">>>>>>New direct 3d device created\n");
|
|
|
|
//3D->EvictManagedTextures();
|
|
|
|
// Set device description and capability structures.
|
|
priv_self.SetDeviceDescriptions();
|
|
|
|
// Set up the viewport.
|
|
if (!priv_self.bSetupViewport(pdds_backbuffer))
|
|
{
|
|
SetD3D(false);
|
|
Uninitialize();
|
|
bUse = false;
|
|
return false;
|
|
}
|
|
PrintD3D(">>>>>>New direct 3d viewport created\n");
|
|
|
|
//
|
|
// Get texture formats.
|
|
//
|
|
// Notes:
|
|
// This enumeration call will set the following private member functions:
|
|
//
|
|
// Set capabilities.
|
|
//
|
|
if (!priv_self.bEnumerateTextureFormats())
|
|
{
|
|
SetD3D(false);
|
|
Uninitialize();
|
|
bUse = false;
|
|
return false;
|
|
}
|
|
|
|
// Perform card specific setup.
|
|
priv_self.SpecialCaseSetup();
|
|
|
|
// Set filtering on by default for Direct3D.
|
|
Assert(prnshMain);
|
|
prnshMain->rensetSettings.seterfState += erfFILTER;
|
|
|
|
CEntityWater::bInterp = false;
|
|
|
|
// Enable fog.
|
|
priv_self.SetFog();
|
|
|
|
// Set common formats.
|
|
priv_self.SetCommonFormats();
|
|
|
|
// Run conformance tests.
|
|
if (!bDeviceTested)
|
|
{
|
|
ScreenTests(pdds_backbuffer, pdds_frontbuffer);
|
|
bDeviceTested = true;
|
|
}
|
|
|
|
if (!bSharedSysBuffers && emmMemoryModel == emmSmall)
|
|
iMaxTotalMemory = Min(iMaxTotalMemory, 5500 * 1024);
|
|
|
|
// Set the dithering flag.
|
|
bDither = bGetDither();
|
|
|
|
// Set the various flags.
|
|
bD3DCacheFog = true;
|
|
bAlphaTransparency = false;
|
|
switch (evcVideoCard)
|
|
{
|
|
case evcMatroxG100:
|
|
bAlphaTransparency = true;
|
|
bD3DCacheFog = true;
|
|
break;
|
|
|
|
case evcATIRage:
|
|
bD3DCacheFog = false;
|
|
break;
|
|
}
|
|
|
|
// Set the secondary card flag.
|
|
{
|
|
GUID guid = ReadDDGUID();
|
|
bSecondaryCard = pConvertGUID(guid) != 0;
|
|
}
|
|
|
|
// Set the 'bLocalVideoMem' flag.
|
|
priv_self.SetLocalVideoMemFlag();
|
|
|
|
ResetD3DConversions();
|
|
|
|
// Return a flag indicating success.
|
|
bUse = true;
|
|
bInitialized = true;
|
|
return true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::bInitialize()
|
|
{
|
|
if (!prasMainScreen)
|
|
{
|
|
Uninitialize();
|
|
return false;
|
|
}
|
|
if (!bD3DCapable())
|
|
{
|
|
Uninitialize();
|
|
return false;
|
|
}
|
|
LPDIRECTDRAWSURFACE4 pdds_back = prasMainScreen->pddsDraw4;
|
|
LPDIRECTDRAWSURFACE4 pdds_front = prasMainScreen->GetPrimarySurface4();
|
|
return bInitialize(pdds_back, pdds_front);
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::bD3DCapable()
|
|
{
|
|
bool b_vid_raster = true;
|
|
if (prasMainScreen && prasMainScreen->pddsDraw)
|
|
{
|
|
CDDSize<DDSURFACEDESC2> sd;
|
|
|
|
// Test to ensure that the backbuffer is in video memory.
|
|
LPDIRECTDRAWSURFACE4 pdds = prasMainScreen->pddsDraw4;
|
|
Assert(pdds);
|
|
|
|
// Retrieve the surface format info (for pitch only).
|
|
DirectDraw::err = pdds->GetSurfaceDesc(&sd);
|
|
//b_vid_raster = b_vid_raster && (sd.ddsCaps.dwCaps & DDSCAPS_3DDEVICE);
|
|
//b_vid_raster = b_vid_raster && (sd.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER);
|
|
b_vid_raster = b_vid_raster && (sd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY);
|
|
b_vid_raster = b_vid_raster && bGetD3D();
|
|
}
|
|
return bGetD3D() && b_vid_raster;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::Uninitialize()
|
|
{
|
|
// If Direct3D is already uninitialized, do nothing.
|
|
if (!bInitialized)
|
|
{
|
|
bUse = false;
|
|
return;
|
|
}
|
|
|
|
// Remove all dependant textures.
|
|
Purge();
|
|
|
|
// Release the viewport.
|
|
if (pd3dViewport)
|
|
{
|
|
int i_ref = pd3dViewport->Release();
|
|
pd3dViewport = 0;
|
|
PrintD3D2(">>>>>>New direct 3d viewport released (%ld).\n", i_ref);
|
|
}
|
|
|
|
// Release the device.
|
|
if (pDevice)
|
|
{
|
|
int i_ref = pDevice->Release();
|
|
pDevice = 0;
|
|
PrintD3D2(">>>>>>New direct 3d device released (%ld).\n", i_ref);
|
|
}
|
|
|
|
// Turn off water alpha.
|
|
CEntityWater::bAlpha = false;
|
|
|
|
// Turn on water interpolation.
|
|
CEntityWater::bInterp = true;
|
|
|
|
#if !BILINEAR_FILTER
|
|
// Switch filtering off by if required for the software rasterizer.
|
|
Assert(prnshMain);
|
|
prnshMain->rensetSettings.seterfState -= erfFILTER;
|
|
#endif // !BILINEAR_FILTER
|
|
|
|
// Indicated that the Direct3D object is uninitialized.
|
|
bUse = false;
|
|
bInitialized = false;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
DDPIXELFORMAT CDirect3D::ddpfGetPixelFormat(ED3DTextureType ed3dtex) const
|
|
{
|
|
Assert(ddpfFormats[ed3dtex].dwSize);
|
|
|
|
return ddpfFormats[ed3dtex];
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
uint32 CDirect3D::u4ConvertToAlpha(float f_red, float f_green, float f_blue, float f_alpha) const
|
|
{
|
|
uint32 u4_red = uint32(f_red * float(u4AlphaRedMask) + 0.5f);
|
|
uint32 u4_green = uint32(f_green * float(u4AlphaGreenMask) + 0.5f);
|
|
uint32 u4_blue = uint32(f_blue * float(u4AlphaBlueMask) + 0.5f);
|
|
uint32 u4_retval;
|
|
|
|
if (u4_red > u4AlphaRedMask)
|
|
u4_red = u4AlphaRedMask;
|
|
|
|
if (u4_green > u4AlphaGreenMask)
|
|
u4_green = u4AlphaGreenMask;
|
|
|
|
if (u4_blue > u4AlphaBlueMask)
|
|
u4_blue = u4AlphaBlueMask;
|
|
|
|
u4_retval = (u4_red << u4AlphaRedShift) | (u4_green << u4AlphaGreenShift) |
|
|
(u4_blue << u4AlphaBlueShift);
|
|
|
|
// Add alpha only if it is available.
|
|
if (bModulatedAlpha)
|
|
{
|
|
uint32 u4_alpha = uint32(f_alpha * float(u4AlphaAlphaMask) + 0.5f);
|
|
if (u4_alpha > u4AlphaAlphaMask)
|
|
u4_alpha = u4AlphaAlphaMask;
|
|
u4_retval |= u4_alpha << u4AlphaAlphaShift;
|
|
}
|
|
|
|
return u4_retval;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
uint32 CDirect3D::u4ConvertToTranparency(float f_red, float f_green, float f_blue, bool b_transparent) const
|
|
{
|
|
uint32 u4_red = uint32(f_red * float(u4TransRedMask) + 0.5f);
|
|
uint32 u4_green = uint32(f_green * float(u4TransGreenMask) + 0.5f);
|
|
uint32 u4_blue = uint32(f_blue * float(u4TransBlueMask) + 0.5f);
|
|
uint32 u4_retval;
|
|
|
|
if (u4_red > u4TransRedMask)
|
|
u4_red = u4TransRedMask;
|
|
|
|
if (u4_green > u4TransGreenMask)
|
|
u4_green = u4TransGreenMask;
|
|
|
|
if (u4_blue > u4TransBlueMask)
|
|
u4_blue = u4TransBlueMask;
|
|
|
|
u4_retval = (u4_red << u4TransRedShift) | (u4_green << u4TransGreenShift) |
|
|
(u4_blue << u4TransBlueShift);
|
|
|
|
// Add Trans only if it is available.
|
|
if (b_transparent)
|
|
{
|
|
u4_retval |= u4TransAlphaMask << u4TransAlphaShift;
|
|
}
|
|
|
|
return u4_retval;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::SetTextureMinMax(int& ri_width, int& ri_height, bool b_truncate) const
|
|
{
|
|
// Do nothing if Direct3D is not in use.
|
|
if (!bUse)
|
|
return;
|
|
|
|
if (b_truncate)
|
|
{
|
|
ri_width = (ri_width * 2) / 3;
|
|
ri_height = (ri_height * 2) / 3;
|
|
if (bSquareTextures)
|
|
{
|
|
int i_dim = Max(ri_width, ri_height);
|
|
if (bPower2)
|
|
{
|
|
if (!bPowerOfTwo(i_dim))
|
|
i_dim = NextPowerOfTwo(i_dim) >> 1;
|
|
}
|
|
SetTextureMinMaxSquare(i_dim);
|
|
ri_width = i_dim;
|
|
ri_height = i_dim;
|
|
}
|
|
else
|
|
{
|
|
if (bPower2)
|
|
{
|
|
if (!bPowerOfTwo(ri_width))
|
|
ri_width = NextPowerOfTwo(ri_width) >> 1;
|
|
if (!bPowerOfTwo(ri_height))
|
|
ri_height = NextPowerOfTwo(ri_height) >> 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bSquareTextures)
|
|
{
|
|
int i_dim = Max(ri_width, ri_height);
|
|
if (bPower2)
|
|
i_dim = NextPowerOfTwo(i_dim);
|
|
SetTextureMinMaxSquare(i_dim);
|
|
ri_width = i_dim;
|
|
ri_height = i_dim;
|
|
}
|
|
else
|
|
{
|
|
if (bPower2)
|
|
{
|
|
ri_width = NextPowerOfTwo(ri_width);
|
|
ri_height = NextPowerOfTwo(ri_height);
|
|
}
|
|
}
|
|
}
|
|
SetMinMax(ri_width, iMinWidth, iMaxWidth);
|
|
SetMinMax(ri_height, iMinHeight, iMaxHeight);
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::SetTextureMinMaxSquare(int& ri_dim) const
|
|
{
|
|
// Do nothing if Direct3D is not in use.
|
|
if (!bUse)
|
|
return;
|
|
|
|
if (bPower2)
|
|
{
|
|
ri_dim = NextPowerOfTwo(ri_dim);
|
|
}
|
|
SetMinMax(ri_dim, iMinDim, iMaxDim);
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::bValidTextureDimensions(int i_width, int i_height) const
|
|
{
|
|
// Check only that the dimensions are positive if Direct3D is not being used.
|
|
if (!bUse)
|
|
{
|
|
return i_width > 0 && i_height > 0;
|
|
}
|
|
|
|
// Test that the texture is square if required.
|
|
if (bSquareTextures)
|
|
if (i_width != i_height)
|
|
return false;
|
|
|
|
// Test that the texture dimensions are a power of two if required.
|
|
if (bPower2)
|
|
if (!bPowerOfTwo(i_width) || !bPowerOfTwo(i_height))
|
|
return false;
|
|
|
|
// Test that the dimensions are within the specified minimum and maximum.
|
|
if (!bWithin(i_width, iMinWidth, iMaxWidth) || !bWithin(i_height, iMinHeight, iMaxHeight))
|
|
return false;
|
|
|
|
// Success.
|
|
return true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::PurgePrimary()
|
|
{
|
|
// Do nothing if Direct3D has already been purged.
|
|
if (bPurged)
|
|
return;
|
|
|
|
// If the card has no local texture memory, do nothing.
|
|
if (!bLocalVideoMem)
|
|
return;
|
|
|
|
// If the card is a secondary card, do nothing.
|
|
if (bSecondaryCard)
|
|
return;
|
|
|
|
// All else has failed. Purge it.
|
|
Purge();
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::Purge()
|
|
{
|
|
// Do nothing if Direct3D has already been purged.
|
|
if (bPurged)
|
|
return;
|
|
|
|
if (bUse)
|
|
srd3dRenderer.SetD3DMode(ed3drSOFTWARE_LOCK);
|
|
bFlipClear = false;
|
|
|
|
PrintD3D("Purging D3D\n");
|
|
|
|
// Delete existing D3D rasters.
|
|
if (easAllocation == easManaged)
|
|
pD3D->EvictManagedTextures();
|
|
|
|
// Remove all image caches.
|
|
PurgeRenderCaches();
|
|
|
|
// Remove all water textures.
|
|
PurgeWaterTextures();
|
|
|
|
// Reset the Direct3D auxilary screen renderer.
|
|
srd3dRenderer.Reset();
|
|
agpAGPTextureMemManager.Purge();
|
|
if (gpskyRender)
|
|
gpskyRender->PurgeD3D();
|
|
CEntityWater::SetTextureMemSize(0);
|
|
NMultiResolution::CTextureNode::SetTextureMemSize(0);
|
|
CRenderCache::SetTextureMemSize(0, 0);
|
|
|
|
// Turn scheduler off for a while.
|
|
srd3dRenderer.SetScheduler();
|
|
|
|
// Remove shared system memory DirectDraw surfaces used by d3d rasters for uploading.
|
|
CRasterD3D::ReleaseSharedSurfaces();
|
|
|
|
#if bTRACK_D3D_RASTERS
|
|
// Print leftover d3d rasters to the debugger.
|
|
PrintLeftoverD3D();
|
|
#endif // bTRACK_D3D_RASTERS
|
|
|
|
// Set the purge flag.
|
|
bPurged = true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::Restore()
|
|
{
|
|
// Do nothing if Direct3D is not is use or Direct3D is not purged.
|
|
if (!bUse || !bPurged)
|
|
return;
|
|
|
|
srd3dRenderer.SetD3DMode(ed3drSOFTWARE_LOCK);
|
|
d3dstState.SetDefault();
|
|
|
|
// Give the user a sign that stuff is happening.
|
|
priv_self.SetupLoadingScreens();
|
|
bShowLoadingScreen = true;
|
|
iAnimateCount = 0;
|
|
bFlipClear = false;
|
|
|
|
// Assign texture memory to the various subsystems.
|
|
AllocateTextureMemory();
|
|
|
|
// Restore sky.
|
|
if (gpskyRender)
|
|
{
|
|
gpskyRender->InitializeForD3D();
|
|
}
|
|
bPurged = false;
|
|
|
|
// Restore non-pageable textures for full agp texturing.
|
|
agpAGPTextureMemManager.RestoreNonpageable();
|
|
|
|
// Clear screens.
|
|
bShowLoadingScreen = false;
|
|
bFlipClear = true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
int CDirect3D::iGetTotalTextureMem() const
|
|
{
|
|
return iTotalTextureMem;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::AllocateTextureMemory()
|
|
{
|
|
// Do nothing if Direct3D is not in use.
|
|
if (!bUse)
|
|
return;
|
|
|
|
Purge();
|
|
|
|
// Set the page managed flag.
|
|
bPageManaged = bGetPageManaged();
|
|
|
|
#if VER_TEST
|
|
|
|
if (bPageManaged)
|
|
PrintD3D("D3D using page manager\n");
|
|
else
|
|
PrintD3D("D3D not using page manager\n");
|
|
|
|
#endif
|
|
|
|
// Attempt to implement non-local (agp sytem) memory for large memory cards/machines.
|
|
if (priv_self.bUseNonLocalMemory())
|
|
if (priv_self.bAllocateNonLocalMemory())
|
|
return;
|
|
|
|
// Attempt to implement the managed memory scheme.
|
|
if (priv_self.bUseManagedMemory())
|
|
if (priv_self.bAllocateManagedMemory())
|
|
return;
|
|
|
|
// If no scheme is successful, forget Direct3D.
|
|
bUse = false;
|
|
Uninitialize();
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::ReportPerFrameStats() const
|
|
{
|
|
#if bDEBUG_DIRECT3D
|
|
DDSCAPS2 ddscaps;
|
|
DWORD dw_total;
|
|
DWORD dw_free;
|
|
|
|
// Query to get the available amount of texture memory.
|
|
memset(&ddscaps, 0, sizeof(ddscaps));
|
|
ddscaps.dwCaps = DDSCAPS_TEXTURE;
|
|
HRESULT hres = d3dDriver.err = DirectDraw::pdd4->GetAvailableVidMem(&ddscaps, &dw_total, &dw_free);
|
|
if (FAILED(hres))
|
|
{
|
|
PrintD3D("\nNo texture memory available!\n\n");
|
|
}
|
|
else
|
|
{
|
|
PrintD3D2("\nTotal texture memory: %ld Kb\n", iKB(dw_total));
|
|
PrintD3D2( "Free texture memory : %ld Kb\n", iKB(dw_free));
|
|
}
|
|
#endif // bDEBUG_DIRECT3D
|
|
}
|
|
|
|
|
|
|
|
//*********************************************************************************************
|
|
//
|
|
// Implementation of CDirect3D::CPriv.
|
|
//
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetTotalTextureMem()
|
|
{
|
|
DDSCAPS2 ddscaps;
|
|
DWORD dw_total;
|
|
DWORD dw_free;
|
|
|
|
// Query to get the available amount of texture memory.
|
|
memset(&ddscaps, 0, sizeof(ddscaps));
|
|
ddscaps.dwCaps = DDSCAPS_TEXTURE;
|
|
HRESULT hres = d3dDriver.err = DirectDraw::pdd4->GetAvailableVidMem(&ddscaps, &dw_total, &dw_free);
|
|
if (FAILED(hres))
|
|
{
|
|
iTotalTextureMem = 0;
|
|
PrintD3D("\nNo texture memory available!\n\n");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Calculated the amount of available texture memory. This assumes that front and
|
|
// backbuffers have been allocated, but that there are currently no textures allocated.
|
|
//
|
|
iTotalTextureMem = Min(iMaxTotalMemory, dw_free);
|
|
|
|
#if bDEBUG_DIRECT3D
|
|
PrintD3D2("D3D Systems Texture memory available: %ld Kb\n", iKB(iTotalTextureMem));
|
|
if (bFullTexturing)
|
|
{
|
|
PrintD3D("Full hardware texturing mode enabled.\n");
|
|
}
|
|
PrintD3D("\n");
|
|
#endif // bDEBUG_DIRECT3D
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetFog()
|
|
{
|
|
// Get the RGB values for fog.
|
|
float f_red = float(clrDefEndDepth.u1Red) / 255.0f;
|
|
float f_green = float(clrDefEndDepth.u1Green) / 255.0f;
|
|
float f_blue = float(clrDefEndDepth.u1Blue) / 255.0f;
|
|
|
|
// Set the appropriate renderstates for fogging.
|
|
d3dDriver.err = pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
|
|
d3dDriver.err = pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, D3DRGB(f_red, f_green, f_blue));
|
|
|
|
// Set the constant fog colour.
|
|
d3dcolFogColour = D3DRGBA(f_red, f_green, f_blue, 1);
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
int CDirect3D::CPriv::iGetMaxTextureRam()
|
|
{
|
|
// Maximum amount of texture memory that will be considered.
|
|
static const int iMaxD3DTextureRam = 8192 * 1024;
|
|
|
|
if (emmMemoryModel == emmSmall)
|
|
return (iMaxD3DTextureRam * 3) / 2;
|
|
return iMaxD3DTextureRam;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
int CDirect3D::CPriv::iGetWaterAlloc()
|
|
{
|
|
return (bD3DWater()) ? (iAllocWater) : (0);
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::CPriv::bSetupViewport(LPDIRECTDRAWSURFACE4 pdds_backbuffer)
|
|
{
|
|
Assert(pdds_backbuffer);
|
|
Assert(pD3D);
|
|
Assert(pDevice);
|
|
Assert(!pd3dViewport);
|
|
|
|
// Get a description of the backbuffer.
|
|
CDDSize<DDSURFACEDESC2> sd; // Backbuffer surface information.
|
|
DirectDraw::err = pdds_backbuffer->GetSurfaceDesc(&sd);
|
|
|
|
iViewportWidth = int(sd.dwWidth);
|
|
iViewportHeight = int(sd.dwHeight);
|
|
|
|
// Intialize viewport values.
|
|
D3DVIEWPORT2 d3d_viewport; // Viewport information..
|
|
d3d_viewport.dwSize = sizeof(d3d_viewport);
|
|
d3d_viewport.dwX = 0;
|
|
d3d_viewport.dwY = 0;
|
|
d3d_viewport.dwWidth = iViewportWidth;
|
|
d3d_viewport.dwHeight = iViewportHeight;
|
|
d3d_viewport.dvClipX = D3DVAL(0);
|
|
d3d_viewport.dvClipY = D3DVAL(0);
|
|
d3d_viewport.dvClipWidth = D3DVAL(d3d_viewport.dwWidth);
|
|
d3d_viewport.dvClipHeight = D3DVAL(d3d_viewport.dwHeight);
|
|
d3d_viewport.dvMinZ = D3DVAL(0);
|
|
d3d_viewport.dvMaxZ = D3DVAL(1);
|
|
|
|
// Create and add the viewport.
|
|
if (pD3D->CreateViewport(&pd3dViewport, NULL) != D3D_OK)
|
|
return false;
|
|
if (pDevice->AddViewport(pd3dViewport) != D3D_OK)
|
|
return false;
|
|
if (pd3dViewport->SetViewport2(&d3d_viewport) != D3D_OK)
|
|
return false;
|
|
if (pDevice->SetCurrentViewport(pd3dViewport) != D3D_OK)
|
|
return false;
|
|
|
|
// Success.
|
|
return true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::CPriv::bEnumerateTextureFormats()
|
|
{
|
|
// Clear the texture formats.
|
|
memset(ddpfFormats, 0, sizeof(ddpfFormats));
|
|
|
|
if (pDevice->EnumTextureFormats(D3DEnumTextureFormatCallback, (void*)ddpfFormats)
|
|
!= D3D_OK)
|
|
return false;
|
|
|
|
// Set alpha flag.
|
|
SetModulatedAlpha();
|
|
|
|
if (!ddpfFormats[ed3dtexSCREEN_OPAQUE].dwSize)
|
|
return false;
|
|
|
|
// Alpha textures are not supported, use the existing opaque 16 bit format.
|
|
if (!bModulatedAlpha)
|
|
{
|
|
ddpfFormats[ed3dtexSCREEN_ALPHA] = ddpfFormats[ed3dtexSCREEN_OPAQUE];
|
|
}
|
|
priv_self.SetAlphaFormat();
|
|
|
|
#if bCOLOUR_KEY
|
|
ddpfFormats[ed3dtexSCREEN_TRANSPARENT] = ddpfFormats[ed3dtexSCREEN_OPAQUE];
|
|
#else
|
|
// Use the alpha format for transparencies if no one bit alpha was found.
|
|
if (ddpfFormats[ed3dtexSCREEN_TRANSPARENT].dwSize == 0)
|
|
ddpfFormats[ed3dtexSCREEN_TRANSPARENT] = ddpfFormats[ed3dtexSCREEN_ALPHA];
|
|
priv_self.SetTransparentFormat();
|
|
#endif
|
|
|
|
// Return success.
|
|
return true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SpecialCaseSetup()
|
|
{
|
|
//
|
|
// Set texture capabilities.
|
|
//
|
|
|
|
// Test if square textures are required.
|
|
bSquareTextures = (d3ddescHardware.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0;
|
|
//if (b_riva_128)
|
|
//bSquareTextures = true;
|
|
|
|
// Test if the textures must be a power of two.
|
|
bPower2 = (d3ddescHardware.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) != 0;
|
|
|
|
// Get the minimum and maximum dimensions of a texture.
|
|
iMinWidth = int(d3ddescHardware.dwMinTextureWidth);
|
|
iMaxWidth = int(d3ddescHardware.dwMaxTextureWidth);
|
|
iMinHeight = int(d3ddescHardware.dwMinTextureHeight);
|
|
iMaxHeight = int(d3ddescHardware.dwMaxTextureHeight);
|
|
|
|
// Alter settings if no information has been provided.
|
|
if (iMinWidth == 0)
|
|
iMinWidth = 16;
|
|
if (iMaxWidth == 0)
|
|
iMaxWidth = 256;
|
|
if (iMinHeight == 0)
|
|
iMinHeight = 16;
|
|
if (iMaxHeight == 0)
|
|
iMaxHeight = 256;
|
|
|
|
// Set the dimension values.
|
|
iMinDim = Max(iMinWidth, iMinHeight);
|
|
iMaxDim = Min(iMaxWidth, iMaxHeight);
|
|
|
|
// Make sure the dimensions are square if only square textures are allowed.
|
|
if (bSquareTextures)
|
|
{
|
|
iMinWidth = iMinDim;
|
|
iMaxWidth = iMaxDim;
|
|
iMinHeight = iMinDim;
|
|
iMaxHeight = iMaxDim;
|
|
}
|
|
|
|
//
|
|
// If alpha textures with destination blends are not supported, use the existing
|
|
// opaque 16 bit format.
|
|
//
|
|
if (!bModulatedAlpha)
|
|
{
|
|
ddpfFormats[ed3dtexSCREEN_ALPHA] = ddpfFormats[ed3dtexSCREEN_OPAQUE];
|
|
priv_self.SetAlphaFormat();
|
|
}
|
|
CEntityWater::bAlpha = bD3DWater();
|
|
|
|
//
|
|
// If shared system memory surfaces are not supported this also means that the entire
|
|
// surface is being uploaded to the card regardless if region uploads are on or not.
|
|
// To prevent slow times in uploading, make the maximum page size much smaller. Also
|
|
// limit the maximum amount of memory that can be allocated.
|
|
//
|
|
|
|
//
|
|
// Determine if alpha should be used for transparencies.
|
|
//
|
|
{
|
|
// On by default.
|
|
bTransparentAlpha = true;
|
|
|
|
// Detect NVidia Riva 128's.
|
|
if (evcGetVideoCard() == evcNVidia128)
|
|
bTransparentAlpha = false;
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetAlphaFormat()
|
|
{
|
|
//
|
|
// Set conversion values for Alpha.
|
|
//
|
|
|
|
// Get the raw masks.
|
|
u4AlphaRedMask = ddpfFormats[ed3dtexSCREEN_ALPHA].dwRBitMask;
|
|
u4AlphaGreenMask = ddpfFormats[ed3dtexSCREEN_ALPHA].dwGBitMask;
|
|
u4AlphaBlueMask = ddpfFormats[ed3dtexSCREEN_ALPHA].dwBBitMask;
|
|
u4AlphaAlphaMask = ddpfFormats[ed3dtexSCREEN_ALPHA].dwRGBAlphaBitMask;
|
|
|
|
// Get the shift.
|
|
u4AlphaRedShift = uGetMaskBits(u4AlphaRedMask);
|
|
u4AlphaGreenShift = uGetMaskBits(u4AlphaGreenMask);
|
|
u4AlphaBlueShift = uGetMaskBits(u4AlphaBlueMask);
|
|
u4AlphaAlphaShift = uGetMaskBits(u4AlphaAlphaMask);
|
|
|
|
// Shift masks.
|
|
u4AlphaRedMask >>= u4AlphaRedShift;
|
|
u4AlphaGreenMask >>= u4AlphaGreenShift;
|
|
u4AlphaBlueMask >>= u4AlphaBlueShift;
|
|
u4AlphaAlphaMask >>= u4AlphaAlphaShift;
|
|
}
|
|
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetTransparentFormat()
|
|
{
|
|
// If no 5551 or 1555 format is found, use 4444.
|
|
//if (ddpfFormats[ed3dtexSCREEN_TRANSPARENT].dwSize == 0)
|
|
//ddpfFormats[ed3dtexSCREEN_TRANSPARENT] = ddpfFormats[ed3dtexSCREEN_ALPHA];
|
|
|
|
//
|
|
// Set conversion values for transparency.
|
|
//
|
|
|
|
// Get the raw masks.
|
|
u4TransRedMask = ddpfFormats[ed3dtexSCREEN_TRANSPARENT].dwRBitMask;
|
|
u4TransGreenMask = ddpfFormats[ed3dtexSCREEN_TRANSPARENT].dwGBitMask;
|
|
u4TransBlueMask = ddpfFormats[ed3dtexSCREEN_TRANSPARENT].dwBBitMask;
|
|
u4TransAlphaMask = ddpfFormats[ed3dtexSCREEN_TRANSPARENT].dwRGBAlphaBitMask;
|
|
|
|
// Get the shift.
|
|
u4TransRedShift = uGetMaskBits(u4TransRedMask);
|
|
u4TransGreenShift = uGetMaskBits(u4TransGreenMask);
|
|
u4TransBlueShift = uGetMaskBits(u4TransBlueMask);
|
|
u4TransAlphaShift = uGetMaskBits(u4TransAlphaMask);
|
|
|
|
// Shift masks.
|
|
u4TransRedMask >>= u4TransRedShift;
|
|
u4TransGreenMask >>= u4TransGreenShift;
|
|
u4TransBlueMask >>= u4TransBlueShift;
|
|
u4TransAlphaMask >>= u4TransAlphaShift;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetD3DFlag()
|
|
{
|
|
if (!DirectDraw::pdd4)
|
|
{
|
|
bUse = false;
|
|
return;
|
|
}
|
|
|
|
bUse = bGetD3D();
|
|
if (bUse)
|
|
{
|
|
GUID guid_d3d = ReadD3DGUID();
|
|
GUID guid_null;
|
|
memset(&guid_null, 0, sizeof(guid_null));
|
|
if (memcmp((void*)&guid_d3d, (void*)&guid_null, sizeof(GUID)) == 0)
|
|
bUse = false;
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetCommonFormats()
|
|
{
|
|
// Set format for 'ed3dtexSCREEN_OPAQUE.'
|
|
{
|
|
DDPIXELFORMAT ddpf = ddpfFormats[ed3dtexSCREEN_OPAQUE];
|
|
|
|
// Count bits in the green mask.
|
|
int i_green_bits = iCountBits(ddpf.dwGBitMask);
|
|
|
|
switch (i_green_bits)
|
|
{
|
|
case 5:
|
|
AlwaysAssert(!bRedLow(ddpf));
|
|
ad3dcomFormats[ed3dtexSCREEN_OPAQUE] = ed3dcom555_RGB;
|
|
break;
|
|
case 6:
|
|
{
|
|
// Now select between RGB and BGR formats.
|
|
if (bRedLow(ddpf))
|
|
ad3dcomFormats[ed3dtexSCREEN_OPAQUE] = ed3dcom565_BGR;
|
|
else
|
|
ad3dcomFormats[ed3dtexSCREEN_OPAQUE] = ed3dcom565_RGB;
|
|
break;
|
|
}
|
|
default:
|
|
ad3dcomFormats[ed3dtexSCREEN_OPAQUE] = ed3dcomUnknown;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set format for 'ed3dtexSCREEN_TRANSPARENT.'
|
|
{
|
|
DDPIXELFORMAT ddpf = ddpfFormats[ed3dtexSCREEN_TRANSPARENT];
|
|
AlwaysAssert(!bRedLow(ddpf));
|
|
|
|
// Look for a particular mask.
|
|
if (ddpf.dwRGBAlphaBitMask == 0x8000)
|
|
ad3dcomFormats[ed3dtexSCREEN_TRANSPARENT] = ed3dcom1555_ARGB;
|
|
else
|
|
ad3dcomFormats[ed3dtexSCREEN_TRANSPARENT] = ed3dcom5551_BRGA;
|
|
}
|
|
|
|
// Set format for 'ed3dtexSCREEN_ALPHA.'
|
|
{
|
|
DDPIXELFORMAT ddpf = ddpfFormats[ed3dtexSCREEN_ALPHA];
|
|
AlwaysAssert(!bRedLow(ddpf));
|
|
|
|
// Look for a particular mask.
|
|
if (ddpf.dwRGBAlphaBitMask == 0xF000)
|
|
ad3dcomFormats[ed3dtexSCREEN_ALPHA] = ed3dcom4444_ARGB;
|
|
else
|
|
ad3dcomFormats[ed3dtexSCREEN_ALPHA] = ed3dcom4444_BRGA;
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetDeviceDescriptions()
|
|
{
|
|
Assert(DirectDraw::pdd4);
|
|
|
|
// Get the device description.
|
|
{
|
|
CDDSize<D3DDEVICEDESC> d3ddesc_hard; // Hardware device information.
|
|
CDDSize<D3DDEVICEDESC> d3ddesc_soft; // Software device information.
|
|
err = pDevice->GetCaps(&d3ddesc_hard, &d3ddesc_soft);
|
|
|
|
// Copy the secription over.
|
|
d3ddescHardware = d3ddesc_hard;
|
|
}
|
|
|
|
// Get the device identifier.
|
|
HRESULT hres = DirectDraw::pdd4->GetDeviceIdentifier(&devidIdentifier, 0);
|
|
if (FAILED(hres))
|
|
{
|
|
memset(&devidIdentifier, 0, sizeof(devidIdentifier));
|
|
}
|
|
|
|
#if bDEBUG_DIRECT3D
|
|
{
|
|
CConsoleBuffer con;
|
|
|
|
con.OpenFileSession("3DDevice.txt");
|
|
con.Print("\n\nDirectDraw 3D Device Identifier.\n\n");
|
|
con.Print("Driver : %s\n", devidIdentifier.szDriver);
|
|
con.Print("Description : %s\n", devidIdentifier.szDescription);
|
|
con.Print("Driver Version: %8x, %8x\n", devidIdentifier.liDriverVersion.HighPart,
|
|
devidIdentifier.liDriverVersion.LowPart);
|
|
con.Print("Vendor ID : %8x\n", devidIdentifier.dwVendorId);
|
|
con.Print("Device ID : %8x\n", devidIdentifier.dwDeviceId);
|
|
con.Print("SubSystem ID : %8x\n", devidIdentifier.dwSubSysId);
|
|
con.Print("Revision ID : %8x\n", devidIdentifier.dwRevision);
|
|
con.Print("GUID : %8x", devidIdentifier.guidDeviceIdentifier.Data1);
|
|
con.Print(" %4x", devidIdentifier.guidDeviceIdentifier.Data2);
|
|
con.Print(" %4x", devidIdentifier.guidDeviceIdentifier.Data3);
|
|
for (uint u = 0; u < 8; ++u)
|
|
con.Print(" %2x", devidIdentifier.guidDeviceIdentifier.Data4[u]);
|
|
con.Print("\n\n\n");
|
|
con.CloseFileSession();
|
|
}
|
|
#endif // bDEBUG_DIRECT3D
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::ClearZBuffer()
|
|
{
|
|
// Do nothing if Direct3D is not in use.
|
|
if (!bUse)
|
|
return;
|
|
|
|
CCycleTimer cmtr;
|
|
D3DRECT d3dRect;
|
|
uint32 u4_flags = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER;
|
|
|
|
d3dRect.lX1 = prasMainScreen->iOffsetX;
|
|
d3dRect.lX2 = prasMainScreen->iOffsetX + prasMainScreen->iWidth;
|
|
d3dRect.lY1 = prasMainScreen->iOffsetY;
|
|
d3dRect.lY2 = prasMainScreen->iOffsetY + prasMainScreen->iHeight;
|
|
|
|
d3dDriver.err = pd3dViewport->Clear2(1, &d3dRect, u4_flags, d3dDriver.d3dcolGetFogColour(), 0.0f, 0);
|
|
psExecuteHardwareClear.Add(cmtr(), 1);
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetModulatedAlpha()
|
|
{
|
|
// Assume that the feature is not supported until otherwise established.
|
|
bModulatedAlpha = false;
|
|
bHardwareWater = false;
|
|
|
|
// Test the modulate caps bit.
|
|
if (!(d3ddescHardware.dwTextureOpCaps & D3DTEXOPCAPS_MODULATE))
|
|
return;
|
|
|
|
// Test to ensure a 4444 texture format is supported.
|
|
DDPIXELFORMAT pixform = ddpfFormats[ed3dtexSCREEN_ALPHA];
|
|
if (iCountBits(pixform.dwRGBAlphaBitMask) != 4 || !(pixform.dwFlags & DDPF_ALPHAPIXELS))
|
|
return;
|
|
|
|
// Test if source alpha blending is supported.
|
|
//if (!(d3ddescHardware.dpcTriCaps.dwDestBlendCaps & D3DPBLENDCAPS_SRCALPHA))
|
|
//return;
|
|
|
|
PrintD3D("Modulated alpha textures are supported.\n");
|
|
|
|
// Get the registry setting for hardware accelerated water.
|
|
bHardwareWater = GetRegValue(strHARDWARE_WATER, bModulatedAlpha);
|
|
|
|
// This feature is supported.
|
|
bModulatedAlpha = true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetScreenFormat(LPDIRECTDRAWSURFACE4 pdds_backbuffer)
|
|
{
|
|
HRESULT hres;
|
|
|
|
// Set to unknown format, assumed to be 565 because it is the most common format.
|
|
esfScreenFormat = esfOther;
|
|
|
|
// Get a description of the pixel format.
|
|
CDDSize<DDSURFACEDESC2> sd; // Backbuffer surface information.
|
|
hres = pdds_backbuffer->GetSurfaceDesc(&sd);
|
|
if (FAILED(hres))
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
// Test for 555 format.
|
|
if (sd.ddpfPixelFormat.dwGBitMask == 0x03E0)
|
|
{
|
|
esfScreenFormat = esf555;
|
|
return;
|
|
}
|
|
|
|
// Test for 565 format.
|
|
if (sd.ddpfPixelFormat.dwGBitMask == 0x07E0)
|
|
{
|
|
esfScreenFormat = esf565;
|
|
return;
|
|
}
|
|
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetMemoryModel()
|
|
{
|
|
if (u4TotalPhysicalMemory() > u64MbThreshold)
|
|
{
|
|
emmMemoryModel = emmLarge;
|
|
return;
|
|
}
|
|
emmMemoryModel = emmSmall;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::CPriv::bUseManagedMemory()
|
|
{
|
|
//
|
|
// The card must have a sufficient amount of available local texture memory.
|
|
//
|
|
// Notes:
|
|
// Managed memory seems to work on a variety of cards regardless of available texture
|
|
// memory, therefore the code that tested for available texture memory has been removed.
|
|
//
|
|
|
|
// The card cannot be a NVidia Riva 128.
|
|
// To do: test the device ID for this.
|
|
|
|
//
|
|
// Get the total amount of managed memory.
|
|
//
|
|
// Notes:
|
|
//
|
|
// What it should do is use 20 Mb for every 32 Mb over 32 Mb:
|
|
//
|
|
// iTotalFreeMem = ((u4_system - iBytesMB(32)) * 20) / 32;
|
|
//
|
|
// Sadly, for a demo hack (given that memory usage has not yet been reigned in),
|
|
// the system will be given 20 Mb and no more.
|
|
//
|
|
switch (emmMemoryModel)
|
|
{
|
|
case emmSmall:
|
|
iTotalFreeMem = iBytesMB(5);
|
|
break;
|
|
|
|
case emmLarge:
|
|
iTotalFreeMem = iBytesMB(priv_self.iLargeMemAllocMB());
|
|
break;
|
|
}
|
|
iTotalFreeMem -= uLargePool();
|
|
|
|
iTotalTextureMem = iTotalFreeMem;
|
|
AlwaysAssert(iTotalFreeMem >= 0);
|
|
|
|
// Use managed memory.
|
|
PrintD3D("\n\nTexturing will be done using Direct3D managed memory.\n");
|
|
PrintD3D2("Managed texture memory : %ld Kb\n", iKB(iTotalFreeMem));
|
|
return true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::CPriv::bAllocateManagedMemory()
|
|
{
|
|
//
|
|
// Calculate system allocations.
|
|
//
|
|
int i_running_total = iTotalTextureMem;
|
|
|
|
// Allocate memory for the pool manager.
|
|
poolD3DRaster.SetTextureMemSize(uLargePool());
|
|
i_running_total -= uLargePool();
|
|
PrintD3D2("Pooled free textures : %ld Kb\n", iKB(uLargePool()));
|
|
|
|
// Allocate sky. Sky uses the fixed amount of 128 Kb.
|
|
i_running_total -= iAllocSky;
|
|
PrintD3D2("Sky : %ld Kb\n", iKB(iAllocSky));
|
|
|
|
// Allocate caches. Use 1/3 of available memory.
|
|
int i_cache = (iTotalTextureMem * iCachePercent) / 100;
|
|
CRenderCache::SetTextureMemSize(0, i_cache / 1024);
|
|
i_running_total -= i_cache;
|
|
PrintD3D2("Render Caches : %ld Kb\n", iKB(i_cache));
|
|
|
|
// Allocate water.
|
|
int i_water = iTotalFreeMem / 40;
|
|
SetMinMax(i_water, iBytesKB(384), iBytesKB(1024));
|
|
CEntityWater::SetTextureMemSize(i_water / 1024);
|
|
i_water = CEntityWater::iGetManagedMemSize();
|
|
i_running_total -= i_water;
|
|
PrintD3D2("Water : %ld Kb\n", iKB(i_water));
|
|
|
|
// Allocate terrain.
|
|
iTerrainTextureMem = iTotalTextureMem / 9;
|
|
SetMinMax(iTerrainTextureMem, iMinTerrain, iMaxTerrain);
|
|
NMultiResolution::CTextureNode::SetTextureMemSize(iTerrainTextureMem / 1024);
|
|
iTerrainTextureMem = NMultiResolution::CTextureNode::ptexmTexturePages->iGetManagedMemSize();
|
|
i_running_total -= iTerrainTextureMem;
|
|
PrintD3D2("Terrain : %ld Kb\n", iKB(iTerrainTextureMem));
|
|
|
|
// Attempt to use the agp memory allocator.
|
|
agpAGPTextureMemManager.AllocateMemory(Max(iMinTexture, i_running_total));
|
|
if (!agpAGPTextureMemManager.bIsActive())
|
|
{
|
|
agpAGPTextureMemManager.AllocateMemory(0);
|
|
Assert(0);
|
|
Purge();
|
|
return false;
|
|
}
|
|
PrintD3D2("Memory for regular texturing : %ld Kb\n", iKB(i_running_total));
|
|
|
|
// Set appropriate flags and return.
|
|
bFullTexturing = true;
|
|
easAllocation = easManaged;
|
|
PrintD3D("\n");
|
|
return true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::CPriv::bUseNonLocalMemory()
|
|
{
|
|
const uint uMinLocal = iBytesKB(12000);
|
|
// Minimum amount of local texture memory required
|
|
// for using memory management.
|
|
uint32 u4_available = 0; // Available texture memory.
|
|
|
|
// Get the amount of texture memory available.
|
|
{
|
|
DDSCAPS2 ddscaps;
|
|
DWORD dw_total;
|
|
DWORD dw_free;
|
|
|
|
// Query to get the available amount of local texture memory.
|
|
memset(&ddscaps, 0, sizeof(ddscaps));
|
|
ddscaps.dwCaps = DDSCAPS_NONLOCALVIDMEM | DDSCAPS_TEXTURE;
|
|
HRESULT hres = d3dDriver.err = DirectDraw::pdd4->GetAvailableVidMem(&ddscaps, &dw_total, &dw_free);
|
|
if (!FAILED(hres))
|
|
{
|
|
u4_available = dw_free;
|
|
}
|
|
}
|
|
// The card must have a sufficient amount of available local texture memory.
|
|
if (u4_available < uMinLocal)
|
|
return false;
|
|
|
|
// The card cannot be a NVidia Riva 128.
|
|
// To do: test the device ID for this.
|
|
|
|
//
|
|
// Get the total amount of managed memory.
|
|
//
|
|
// Notes:
|
|
//
|
|
// What it should do is use 20 Mb for every 32 Mb over 32 Mb:
|
|
//
|
|
// iTotalFreeMem = ((u4_system - iBytesMB(32)) * 20) / 32;
|
|
//
|
|
// Sadly, for a demo hack (given that memory usage has not yet been reigned in),
|
|
// the system will be given 20 Mb and no more.
|
|
//
|
|
switch (emmMemoryModel)
|
|
{
|
|
case emmSmall:
|
|
iTotalFreeMem = Min(iBytesMB(5), u4_available);
|
|
break;
|
|
|
|
case emmLarge:
|
|
iTotalFreeMem = Min(iBytesMB(priv_self.iLargeMemAllocMB()), u4_available);
|
|
break;
|
|
}
|
|
iTotalFreeMem -= uLargePool();
|
|
|
|
iTotalTextureMem = iTotalFreeMem;
|
|
AlwaysAssert(iTotalFreeMem >= 0);
|
|
|
|
// Use managed memory.
|
|
PrintD3D("\n\nTexturing will be done using Direct3D nonlocal video memory.\n");
|
|
PrintD3D2("Available texture memory : %ld Kb\n", iKB(iTotalFreeMem));
|
|
return true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
bool CDirect3D::CPriv::bAllocateNonLocalMemory()
|
|
{
|
|
//
|
|
// Calculate system allocations.
|
|
//
|
|
int i_running_total = iTotalTextureMem;
|
|
|
|
// Allocate memory for the pool manager.
|
|
poolD3DRaster.SetTextureMemSize(uLargePool());
|
|
i_running_total -= uLargePool();
|
|
PrintD3D2("Pooled free textures : %ld Kb\n", iKB(uLargePool()));
|
|
|
|
// Allocate sky. Sky uses the fixed amount of 128 Kb.
|
|
i_running_total -= iAllocSky;
|
|
PrintD3D2("Sky : %ld Kb\n", iKB(iAllocSky));
|
|
|
|
// Allocate caches. Use 1/3 of available memory.
|
|
int i_cache = (iTotalTextureMem * iCachePercent) / 100;
|
|
CRenderCache::SetTextureMemSize(0, i_cache / 1024);
|
|
i_running_total -= i_cache;
|
|
PrintD3D2("Render Caches : %ld Kb\n", iKB(i_cache));
|
|
|
|
// Allocate water.
|
|
int i_water = iTotalFreeMem / 40;
|
|
SetMinMax(i_water, iBytesKB(384), iBytesKB(1024));
|
|
CEntityWater::SetTextureMemSize(i_water / 1024);
|
|
i_water = CEntityWater::iGetManagedMemSize();
|
|
i_running_total -= i_water;
|
|
PrintD3D2("Water : %ld Kb\n", iKB(i_water));
|
|
|
|
// Allocate terrain.
|
|
iTerrainTextureMem = iTotalTextureMem / 9;
|
|
SetMinMax(iTerrainTextureMem, iMinTerrain, iMaxTerrain);
|
|
NMultiResolution::CTextureNode::SetTextureMemSize(iTerrainTextureMem / 1024);
|
|
iTerrainTextureMem = NMultiResolution::CTextureNode::ptexmTexturePages->iGetManagedMemSize();
|
|
i_running_total -= iTerrainTextureMem;
|
|
PrintD3D2("Terrain : %ld Kb\n", iKB(iTerrainTextureMem));
|
|
|
|
// Attempt to use the agp memory allocator.
|
|
agpAGPTextureMemManager.AllocateMemory(Max(iMinTexture, i_running_total));
|
|
if (!agpAGPTextureMemManager.bIsActive())
|
|
{
|
|
agpAGPTextureMemManager.AllocateMemory(0);
|
|
Assert(0);
|
|
Purge();
|
|
return false;
|
|
}
|
|
PrintD3D2("Memory for regular texturing : %ld Kb\n", iKB(i_running_total));
|
|
|
|
// Set appropriate flags and return.
|
|
easAllocation = easNonLocal;
|
|
bFullTexturing = true;
|
|
return true;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetLocalVideoMemFlag()
|
|
{
|
|
DDSCAPS2 ddscaps;
|
|
DWORD dw_total;
|
|
DWORD dw_free;
|
|
|
|
// Query to get the available amount of local texture memory.
|
|
memset(&ddscaps, 0, sizeof(ddscaps));
|
|
ddscaps.dwCaps = DDSCAPS_LOCALVIDMEM | DDSCAPS_TEXTURE;
|
|
HRESULT hres = d3dDriver.err = DirectDraw::pdd4->GetAvailableVidMem(&ddscaps, &dw_total, &dw_free);
|
|
if (FAILED(hres))
|
|
{
|
|
// Assume the worst.
|
|
bLocalVideoMem = true;
|
|
return;
|
|
}
|
|
bLocalVideoMem = dw_total != 0 || dw_free != 0;
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
//
|
|
void CDirect3D::AnimateLoadingScreenPriv
|
|
(
|
|
int i_width,
|
|
int i_height
|
|
)
|
|
//
|
|
// Animates the loading screen every eight calls.
|
|
//
|
|
//**************************************
|
|
{
|
|
if (g_pfnWorldLoadNotify)
|
|
{
|
|
// Use the main loading bar call every N textures.
|
|
// N = approximate number of surfaces / 5
|
|
if ((++iAnimateCount & 511) == 0)
|
|
{
|
|
// Increment loading percentage.
|
|
(g_pfnWorldLoadNotify)(g_u4NotifyParam, 5, 0, 0);
|
|
}
|
|
}
|
|
else if (!bIsTrespasser)
|
|
{
|
|
int i_size = i_width * i_height;
|
|
i_size >>= 12;
|
|
if (i_size < 1)
|
|
i_size = 1;
|
|
iAnimateCount += i_size;
|
|
if (iAnimateCount < 16)
|
|
return;
|
|
iAnimateCount = 0;
|
|
if (!prasMainScreen)
|
|
return;
|
|
prasMainScreen->Flip();
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::WriteTextToLoadScreen(const char* str)
|
|
{
|
|
prasMainScreen->Unlock();
|
|
prasMainScreen->Clear(0);
|
|
if (!str || !*str)
|
|
{
|
|
prasMainScreen->Flip();
|
|
return;
|
|
}
|
|
|
|
COLORREF col = 0x00FFFFFF;
|
|
|
|
HDC hdc = prasMainScreen->hdcGet();
|
|
|
|
int i_bk_mode = SetBkMode(hdc, TRANSPARENT);
|
|
col = SetTextColor(hdc, col);
|
|
uint u_text_align = SetTextAlign(hdc, TA_TOP | TA_LEFT);
|
|
|
|
TextOut(hdc, 16, 16, str, strlen(str));
|
|
|
|
SetTextAlign(hdc, u_text_align);
|
|
SetTextColor(hdc, col);
|
|
SetBkMode(hdc, i_bk_mode);
|
|
|
|
prasMainScreen->ReleaseDC(hdc);
|
|
prasMainScreen->Flip();
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CDirect3D::CPriv::SetupLoadingScreens()
|
|
{
|
|
if (!prasMainScreen)
|
|
return;
|
|
|
|
if (g_pfnWorldLoadNotify)
|
|
{
|
|
(g_pfnWorldLoadNotify)(g_u4NotifyParam, 4, 0, 0);
|
|
}
|
|
else if (!bIsTrespasser)
|
|
{
|
|
WriteTextToLoadScreen("Loading surfaces -");
|
|
WriteTextToLoadScreen("Loading surfaces \\");
|
|
WriteTextToLoadScreen("Loading surfaces /");
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
int CDirect3D::CPriv::iLargeMemAllocMB()
|
|
{
|
|
// If a very large amount of memory is available, use everything.
|
|
if (u4TotalPhysicalMemory() > u96MbThreshold)
|
|
return 24;
|
|
|
|
// Shared buffers reduce the memory load.
|
|
if (bSharedSysBuffers)
|
|
return 18;
|
|
|
|
// Non-shared buffers eat more memory.
|
|
return 16;
|
|
}
|
|
|
|
|
|
//
|
|
// Global variables.
|
|
//
|
|
CDirect3D d3dDriver; |