Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: To accomplish X360 TCR 22, we need to call present ever 66msec
  4. // at least during loading screens. This amazing hack will do it
  5. // by overriding the allocator to tick it every so often.
  6. //
  7. // $NoKeywords: $
  8. //===========================================================================//
  9. #include "LoadScreenUpdate.h"
  10. #include "tier0/memalloc.h"
  11. #include "tier1/delegates.h"
  12. #include "tier0/threadtools.h"
  13. #include "tier2/tier2.h"
  14. #include "materialsystem/imaterialsystem.h"
  15. #include "tier0/dbg.h"
  16. #ifdef _X360
  17. #define LOADING_UPDATE_INTERVAL 0.015f
  18. #define UNINITIALIZED_LAST_TIME -1000.0f
  19. //-----------------------------------------------------------------------------
  20. // Used to tick the loading screen every so often
  21. //-----------------------------------------------------------------------------
  22. class CLoaderMemAlloc : public IMemAlloc
  23. {
  24. // Methods of IMemAlloc
  25. public:
  26. virtual void *Alloc( size_t nSize );
  27. virtual void *Realloc( void *pMem, size_t nSize );
  28. virtual void Free( void *pMem );
  29. DELEGATE_TO_OBJECT_2( void *, Expand_NoLongerSupported, void *, size_t, m_pMemAlloc );
  30. virtual void *Alloc( size_t nSize, const char *pFileName, int nLine );
  31. virtual void *Realloc( void *pMem, size_t nSize, const char *pFileName, int nLine );
  32. virtual void Free( void *pMem, const char *pFileName, int nLine );
  33. DELEGATE_TO_OBJECT_4( void*, Expand_NoLongerSupported, void *, size_t, const char *, int, m_pMemAlloc );
  34. DELEGATE_TO_OBJECT_1( size_t, GetSize, void *, m_pMemAlloc );
  35. DELEGATE_TO_OBJECT_2V( PushAllocDbgInfo, const char *, int, m_pMemAlloc );
  36. DELEGATE_TO_OBJECT_0V( PopAllocDbgInfo, m_pMemAlloc );
  37. DELEGATE_TO_OBJECT_1( long, CrtSetBreakAlloc, long, m_pMemAlloc );
  38. DELEGATE_TO_OBJECT_2( int, CrtSetReportMode, int, int, m_pMemAlloc );
  39. DELEGATE_TO_OBJECT_1( int, CrtIsValidHeapPointer, const void *, m_pMemAlloc );
  40. DELEGATE_TO_OBJECT_3( int, CrtIsValidPointer, const void *, unsigned int, int, m_pMemAlloc );
  41. DELEGATE_TO_OBJECT_0( int, CrtCheckMemory, m_pMemAlloc );
  42. DELEGATE_TO_OBJECT_1( int, CrtSetDbgFlag, int, m_pMemAlloc );
  43. DELEGATE_TO_OBJECT_1V( CrtMemCheckpoint, _CrtMemState *, m_pMemAlloc );
  44. DELEGATE_TO_OBJECT_0V( DumpStats, m_pMemAlloc );
  45. DELEGATE_TO_OBJECT_1V( DumpStatsFileBase, const char *, m_pMemAlloc );
  46. DELEGATE_TO_OBJECT_2( void*, CrtSetReportFile, int, void*, m_pMemAlloc );
  47. DELEGATE_TO_OBJECT_1( void*, CrtSetReportHook, void*, m_pMemAlloc );
  48. DELEGATE_TO_OBJECT_5( int, CrtDbgReport, int, const char *, int, const char *, const char *, m_pMemAlloc );
  49. DELEGATE_TO_OBJECT_0( int, heapchk, m_pMemAlloc );
  50. DELEGATE_TO_OBJECT_0( bool, IsDebugHeap, m_pMemAlloc );
  51. DELEGATE_TO_OBJECT_2V( GetActualDbgInfo, const char *&, int &, m_pMemAlloc );
  52. DELEGATE_TO_OBJECT_5V( RegisterAllocation, const char *, int, int, int, unsigned, m_pMemAlloc );
  53. DELEGATE_TO_OBJECT_5V( RegisterDeallocation, const char *, int, int, int, unsigned, m_pMemAlloc );
  54. DELEGATE_TO_OBJECT_0( int, GetVersion, m_pMemAlloc );
  55. DELEGATE_TO_OBJECT_0V( CompactHeap, m_pMemAlloc );
  56. DELEGATE_TO_OBJECT_1( MemAllocFailHandler_t, SetAllocFailHandler, MemAllocFailHandler_t, m_pMemAlloc );
  57. DELEGATE_TO_OBJECT_1V( DumpBlockStats, void *, m_pMemAlloc );
  58. #if defined( _MEMTEST )
  59. DELEGATE_TO_OBJECT_2V( SetStatsExtraInfo, const char *, const char *, m_pMemAlloc );
  60. #endif
  61. DELEGATE_TO_OBJECT_0(size_t, MemoryAllocFailed, m_pMemAlloc );
  62. virtual uint32 GetDebugInfoSize() { return 0; }
  63. virtual void SaveDebugInfo( void *pvDebugInfo ) { }
  64. virtual void RestoreDebugInfo( const void *pvDebugInfo ) {}
  65. virtual void InitDebugInfo( void *pvDebugInfo, const char *pchRootFileName, int nLine ) {}
  66. // Other public methods
  67. public:
  68. CLoaderMemAlloc();
  69. void Start( MaterialNonInteractiveMode_t mode );
  70. void Stop();
  71. // Check if we need to call swap. Do so if necessary.
  72. void CheckSwap( );
  73. private:
  74. IMemAlloc *m_pMemAlloc;
  75. float m_flLastUpdateTime;
  76. bool m_bInSwap;
  77. };
  78. //-----------------------------------------------------------------------------
  79. // Activate, deactivate loadermemalloc
  80. //-----------------------------------------------------------------------------
  81. static CLoaderMemAlloc s_LoaderMemAlloc;
  82. void BeginLoadingUpdates( MaterialNonInteractiveMode_t mode )
  83. {
  84. if ( IsX360() )
  85. {
  86. s_LoaderMemAlloc.Start( mode );
  87. }
  88. }
  89. void RefreshScreenIfNecessary()
  90. {
  91. if ( IsX360() )
  92. {
  93. s_LoaderMemAlloc.CheckSwap();
  94. }
  95. }
  96. void EndLoadingUpdates()
  97. {
  98. if ( IsX360() )
  99. {
  100. s_LoaderMemAlloc.Stop();
  101. }
  102. }
  103. static int LoadLibraryThreadFunc()
  104. {
  105. RefreshScreenIfNecessary();
  106. return 15;
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Used to tick the loading screen every so often
  110. //-----------------------------------------------------------------------------
  111. CLoaderMemAlloc::CLoaderMemAlloc()
  112. {
  113. m_pMemAlloc = 0;
  114. }
  115. void CLoaderMemAlloc::Start( MaterialNonInteractiveMode_t mode )
  116. {
  117. if ( m_pMemAlloc || ( mode == MATERIAL_NON_INTERACTIVE_MODE_NONE ) )
  118. return;
  119. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  120. pRenderContext->EnableNonInteractiveMode( mode );
  121. if ( mode == MATERIAL_NON_INTERACTIVE_MODE_STARTUP )
  122. {
  123. SetThreadedLoadLibraryFunc( LoadLibraryThreadFunc );
  124. }
  125. // NOTE: This is necessary to avoid a one-frame black flash
  126. // since Present is what copies the back buffer into the temp buffer
  127. if ( mode == MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD )
  128. {
  129. extern void V_RenderVGuiOnly( void );
  130. V_RenderVGuiOnly();
  131. }
  132. m_flLastUpdateTime = UNINITIALIZED_LAST_TIME;
  133. m_bInSwap = false;
  134. m_pMemAlloc = g_pMemAlloc;
  135. g_pMemAlloc = this;
  136. }
  137. void CLoaderMemAlloc::Stop()
  138. {
  139. if ( !m_pMemAlloc )
  140. return;
  141. g_pMemAlloc = m_pMemAlloc;
  142. m_pMemAlloc = 0;
  143. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  144. pRenderContext->EnableNonInteractiveMode( MATERIAL_NON_INTERACTIVE_MODE_NONE );
  145. SetThreadedLoadLibraryFunc( NULL );
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Check if we need to call swap. Do so if necessary.
  149. //-----------------------------------------------------------------------------
  150. void CLoaderMemAlloc::CheckSwap( )
  151. {
  152. if ( !m_pMemAlloc )
  153. return;
  154. float t = Plat_FloatTime();
  155. float dt = t - m_flLastUpdateTime;
  156. if ( dt >= LOADING_UPDATE_INTERVAL )
  157. {
  158. if ( ThreadInMainThread() && !m_bInSwap && !g_pMaterialSystem->IsInFrame() )
  159. {
  160. m_bInSwap = true;
  161. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  162. pRenderContext->RefreshFrontBufferNonInteractive();
  163. m_bInSwap = false;
  164. // NOTE: It is necessary to re-read time, since Refresh
  165. // may block, and if it does, it'll force a refresh every allocation
  166. // if we don't resample time after the block
  167. m_flLastUpdateTime = Plat_FloatTime();
  168. }
  169. }
  170. }
  171. //-----------------------------------------------------------------------------
  172. // Hook allocations, render when appropriate
  173. //-----------------------------------------------------------------------------
  174. void *CLoaderMemAlloc::Alloc( size_t nSize )
  175. {
  176. CheckSwap();
  177. return m_pMemAlloc->Alloc( nSize );
  178. }
  179. void *CLoaderMemAlloc::Realloc( void *pMem, size_t nSize )
  180. {
  181. CheckSwap();
  182. return m_pMemAlloc->Realloc( pMem, nSize );
  183. }
  184. void CLoaderMemAlloc::Free( void *pMem )
  185. {
  186. CheckSwap();
  187. m_pMemAlloc->Free( pMem );
  188. }
  189. void *CLoaderMemAlloc::Alloc( size_t nSize, const char *pFileName, int nLine )
  190. {
  191. CheckSwap();
  192. return m_pMemAlloc->Alloc( nSize, pFileName, nLine );
  193. }
  194. void *CLoaderMemAlloc::Realloc( void *pMem, size_t nSize, const char *pFileName, int nLine )
  195. {
  196. CheckSwap();
  197. return m_pMemAlloc->Realloc( pMem, nSize, pFileName, nLine );
  198. }
  199. void CLoaderMemAlloc::Free( void *pMem, const char *pFileName, int nLine )
  200. {
  201. CheckSwap();
  202. m_pMemAlloc->Free( pMem, pFileName, nLine );
  203. }
  204. #endif // _X360