You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
7.6 KiB
239 lines
7.6 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: To accomplish X360 TCR 22, we need to call present ever 66msec |
|
// at least during loading screens. This amazing hack will do it |
|
// by overriding the allocator to tick it every so often. |
|
// |
|
// $NoKeywords: $ |
|
//===========================================================================// |
|
|
|
#include "LoadScreenUpdate.h" |
|
#include "tier0/memalloc.h" |
|
#include "tier1/delegates.h" |
|
#include "tier0/threadtools.h" |
|
#include "tier2/tier2.h" |
|
#include "materialsystem/imaterialsystem.h" |
|
#include "tier0/dbg.h" |
|
|
|
#ifdef _X360 |
|
|
|
#define LOADING_UPDATE_INTERVAL 0.015f |
|
#define UNINITIALIZED_LAST_TIME -1000.0f |
|
|
|
//----------------------------------------------------------------------------- |
|
// Used to tick the loading screen every so often |
|
//----------------------------------------------------------------------------- |
|
class CLoaderMemAlloc : public IMemAlloc |
|
{ |
|
// Methods of IMemAlloc |
|
public: |
|
virtual void *Alloc( size_t nSize ); |
|
virtual void *Realloc( void *pMem, size_t nSize ); |
|
virtual void Free( void *pMem ); |
|
DELEGATE_TO_OBJECT_2( void *, Expand_NoLongerSupported, void *, size_t, m_pMemAlloc ); |
|
virtual void *Alloc( size_t nSize, const char *pFileName, int nLine ); |
|
virtual void *Realloc( void *pMem, size_t nSize, const char *pFileName, int nLine ); |
|
virtual void Free( void *pMem, const char *pFileName, int nLine ); |
|
DELEGATE_TO_OBJECT_4( void*, Expand_NoLongerSupported, void *, size_t, const char *, int, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_1( size_t, GetSize, void *, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_2V( PushAllocDbgInfo, const char *, int, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_0V( PopAllocDbgInfo, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_1( long, CrtSetBreakAlloc, long, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_2( int, CrtSetReportMode, int, int, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_1( int, CrtIsValidHeapPointer, const void *, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_3( int, CrtIsValidPointer, const void *, unsigned int, int, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_0( int, CrtCheckMemory, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_1( int, CrtSetDbgFlag, int, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_1V( CrtMemCheckpoint, _CrtMemState *, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_0V( DumpStats, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_1V( DumpStatsFileBase, const char *, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_2( void*, CrtSetReportFile, int, void*, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_1( void*, CrtSetReportHook, void*, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_5( int, CrtDbgReport, int, const char *, int, const char *, const char *, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_0( int, heapchk, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_0( bool, IsDebugHeap, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_2V( GetActualDbgInfo, const char *&, int &, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_5V( RegisterAllocation, const char *, int, size_t, size_t, unsigned, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_5V( RegisterDeallocation, const char *, int, size_t, size_t, unsigned, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_0( int, GetVersion, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_0V( CompactHeap, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_1( MemAllocFailHandler_t, SetAllocFailHandler, MemAllocFailHandler_t, m_pMemAlloc ); |
|
DELEGATE_TO_OBJECT_1V( DumpBlockStats, void *, m_pMemAlloc ); |
|
#if defined( _MEMTEST ) |
|
DELEGATE_TO_OBJECT_2V( SetStatsExtraInfo, const char *, const char *, m_pMemAlloc ); |
|
#endif |
|
DELEGATE_TO_OBJECT_0(size_t, MemoryAllocFailed, m_pMemAlloc ); |
|
virtual uint32 GetDebugInfoSize() { return 0; } |
|
virtual void SaveDebugInfo( void *pvDebugInfo ) { } |
|
virtual void RestoreDebugInfo( const void *pvDebugInfo ) {} |
|
virtual void InitDebugInfo( void *pvDebugInfo, const char *pchRootFileName, int nLine ) {} |
|
|
|
// Other public methods |
|
public: |
|
CLoaderMemAlloc(); |
|
void Start( MaterialNonInteractiveMode_t mode ); |
|
void Stop(); |
|
|
|
// Check if we need to call swap. Do so if necessary. |
|
void CheckSwap( ); |
|
|
|
private: |
|
IMemAlloc *m_pMemAlloc; |
|
float m_flLastUpdateTime; |
|
bool m_bInSwap; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Activate, deactivate loadermemalloc |
|
//----------------------------------------------------------------------------- |
|
static CLoaderMemAlloc s_LoaderMemAlloc; |
|
|
|
void BeginLoadingUpdates( MaterialNonInteractiveMode_t mode ) |
|
{ |
|
if ( IsX360() ) |
|
{ |
|
s_LoaderMemAlloc.Start( mode ); |
|
} |
|
} |
|
|
|
void RefreshScreenIfNecessary() |
|
{ |
|
if ( IsX360() ) |
|
{ |
|
s_LoaderMemAlloc.CheckSwap(); |
|
} |
|
} |
|
|
|
void EndLoadingUpdates() |
|
{ |
|
if ( IsX360() ) |
|
{ |
|
s_LoaderMemAlloc.Stop(); |
|
} |
|
} |
|
|
|
static int LoadLibraryThreadFunc() |
|
{ |
|
RefreshScreenIfNecessary(); |
|
return 15; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Used to tick the loading screen every so often |
|
//----------------------------------------------------------------------------- |
|
CLoaderMemAlloc::CLoaderMemAlloc() |
|
{ |
|
m_pMemAlloc = 0; |
|
} |
|
|
|
void CLoaderMemAlloc::Start( MaterialNonInteractiveMode_t mode ) |
|
{ |
|
if ( m_pMemAlloc || ( mode == MATERIAL_NON_INTERACTIVE_MODE_NONE ) ) |
|
return; |
|
|
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); |
|
pRenderContext->EnableNonInteractiveMode( mode ); |
|
|
|
if ( mode == MATERIAL_NON_INTERACTIVE_MODE_STARTUP ) |
|
{ |
|
SetThreadedLoadLibraryFunc( LoadLibraryThreadFunc ); |
|
} |
|
|
|
// NOTE: This is necessary to avoid a one-frame black flash |
|
// since Present is what copies the back buffer into the temp buffer |
|
if ( mode == MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD ) |
|
{ |
|
extern void V_RenderVGuiOnly( void ); |
|
V_RenderVGuiOnly(); |
|
} |
|
|
|
m_flLastUpdateTime = UNINITIALIZED_LAST_TIME; |
|
m_bInSwap = false; |
|
m_pMemAlloc = g_pMemAlloc; |
|
g_pMemAlloc = this; |
|
} |
|
|
|
void CLoaderMemAlloc::Stop() |
|
{ |
|
if ( !m_pMemAlloc ) |
|
return; |
|
|
|
g_pMemAlloc = m_pMemAlloc; |
|
m_pMemAlloc = 0; |
|
|
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); |
|
pRenderContext->EnableNonInteractiveMode( MATERIAL_NON_INTERACTIVE_MODE_NONE ); |
|
SetThreadedLoadLibraryFunc( NULL ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Check if we need to call swap. Do so if necessary. |
|
//----------------------------------------------------------------------------- |
|
void CLoaderMemAlloc::CheckSwap( ) |
|
{ |
|
if ( !m_pMemAlloc ) |
|
return; |
|
|
|
float t = Plat_FloatTime(); |
|
float dt = t - m_flLastUpdateTime; |
|
if ( dt >= LOADING_UPDATE_INTERVAL ) |
|
{ |
|
if ( ThreadInMainThread() && !m_bInSwap && !g_pMaterialSystem->IsInFrame() ) |
|
{ |
|
m_bInSwap = true; |
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); |
|
pRenderContext->RefreshFrontBufferNonInteractive(); |
|
m_bInSwap = false; |
|
|
|
// NOTE: It is necessary to re-read time, since Refresh |
|
// may block, and if it does, it'll force a refresh every allocation |
|
// if we don't resample time after the block |
|
m_flLastUpdateTime = Plat_FloatTime(); |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Hook allocations, render when appropriate |
|
//----------------------------------------------------------------------------- |
|
void *CLoaderMemAlloc::Alloc( size_t nSize ) |
|
{ |
|
CheckSwap(); |
|
return m_pMemAlloc->Alloc( nSize ); |
|
} |
|
|
|
void *CLoaderMemAlloc::Realloc( void *pMem, size_t nSize ) |
|
{ |
|
CheckSwap(); |
|
return m_pMemAlloc->Realloc( pMem, nSize ); |
|
} |
|
|
|
void CLoaderMemAlloc::Free( void *pMem ) |
|
{ |
|
CheckSwap(); |
|
m_pMemAlloc->Free( pMem ); |
|
} |
|
|
|
void *CLoaderMemAlloc::Alloc( size_t nSize, const char *pFileName, int nLine ) |
|
{ |
|
CheckSwap(); |
|
return m_pMemAlloc->Alloc( nSize, pFileName, nLine ); |
|
} |
|
|
|
void *CLoaderMemAlloc::Realloc( void *pMem, size_t nSize, const char *pFileName, int nLine ) |
|
{ |
|
CheckSwap(); |
|
return m_pMemAlloc->Realloc( pMem, nSize, pFileName, nLine ); |
|
} |
|
|
|
void CLoaderMemAlloc::Free( void *pMem, const char *pFileName, int nLine ) |
|
{ |
|
CheckSwap(); |
|
m_pMemAlloc->Free( pMem, pFileName, nLine ); |
|
} |
|
|
|
#endif // _X360
|
|
|