Counter Strike : Global Offensive Source Code
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.

713 lines
16 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #if defined( DX_TO_GL_ABSTRACTION )
  9. #include "tier1/keyvalues.h"
  10. #endif
  11. #include "shaderapi/ishaderapi.h"
  12. // NOTE: This has to be the last file included!
  13. #include "tier0/memdbgon.h"
  14. using namespace SF::GFx;
  15. using namespace SF::Render;
  16. #if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
  17. #define MEM_ALLOC_CREDIT_FORMATF( formatStr, slotNumber ) \
  18. char szName[64]; \
  19. V_snprintf( szName, ARRAYSIZE(szName), formatStr, slotNumber ); \
  20. MEM_ALLOC_CREDIT_( szName );
  21. #else
  22. #define MEM_ALLOC_CREDIT_FORMATF (void)
  23. #endif
  24. #if defined( _PS3 ) || defined( _X360 )
  25. ConVar scaleform_mesh_caching_enable( "scaleform_mesh_caching_enable", "1" );
  26. static void scaleform_dump_mesh_caching_stats_f( const CCommand &args );
  27. ConCommand scaleform_dump_mesh_caching_stats( "scaleform_dump_mesh_caching_stats", scaleform_dump_mesh_caching_stats_f, "Dumps stats about scaleform mesh caching" );
  28. bool g_bScaleformMeshCaching = true; // Cache VBs & IBs for scaleform batches to reuse across frames
  29. // Counters to track usage of scaleform mesh caching
  30. int g_nScaleformCachedVBAlive = 0; // number of VBs currently allocated for mesh caching
  31. int g_nScaleformCachedIBAlive = 0; // number of IBs currently allocated for mesh caching
  32. int g_nScaleformCachedVBDead = 0; // number of cached VBs that have been cleaned up (add to # alive to get total ever allocated)
  33. int g_nScaleformCachedIBDead = 0; // number of cached IBs that have been cleaned up (add to # alive to get total ever allocated)
  34. static void scaleform_dump_mesh_caching_stats_f( const CCommand &args )
  35. {
  36. Msg( "VBs alive: %d\nIBs alive: %d\nVBs dead: %d\nIBs dead: %d\n", g_nScaleformCachedVBAlive, g_nScaleformCachedIBAlive, g_nScaleformCachedVBDead, g_nScaleformCachedIBDead );
  37. }
  38. #endif
  39. ConVar r_drawscaleform( "r_drawscaleform", "1",
  40. #if defined( DEVELOPMENT_ONLY ) || defined( ALLOW_TEXT_MODE )
  41. FCVAR_RELEASE
  42. #else
  43. 0
  44. #endif
  45. );
  46. void ScaleformUIImpl::InitMovieSlotImpl( void )
  47. {
  48. V_memset( m_SlotPtrs, 0, sizeof( m_SlotPtrs ) );
  49. V_memset( m_SlotDeniesInputRefCount, 0, sizeof( m_SlotDeniesInputRefCount ) );
  50. }
  51. void ScaleformUIImpl::ShutdownMovieSlotImpl( void )
  52. {
  53. #if defined ( _DEBUG )
  54. for ( int i = 0; i < MAX_SLOTS; i++ )
  55. {
  56. const char* slotName;
  57. if ( m_SlotPtrs[i] != NULL )
  58. {
  59. switch( i )
  60. {
  61. case SF_RESERVED_CURSOR_SLOT:
  62. slotName = "Cursor";
  63. break;
  64. case SF_FULL_SCREEN_SLOT:
  65. slotName = "Full Screen";
  66. break;
  67. case SF_FIRST_SS_SLOT:
  68. slotName = "Base Client";
  69. break;
  70. default:
  71. slotName= "Other Split Screen";
  72. break;
  73. }
  74. LogPrintf( "Scaleform: UI slot \"%s Slot\" ( #%d ) not released\n", slotName, i );
  75. }
  76. }
  77. #endif
  78. }
  79. BaseSlot* ScaleformUIImpl::LockSlotPtr( int slot )
  80. {
  81. AssertMsg( slot >= 0 && slot < MAX_SLOTS, "Invalid slot index in LockSlotPtr" );
  82. // gurjeets - locks commented out, left here for reference
  83. // Currently we only queue a couple of SF-related functions to be called from the render thread (see cmatqueuedrendercontext.h)
  84. // These are RenderSlot() and SetSlotViewport(). It's safe to call these in parallel along with whatever's
  85. // happening on the main thread. They are also called from the main thread but only at times when when QMS is not enabled
  86. // The Lock/Unlock slot ptr functions are effectively just for ref counting, which is thread safe
  87. //m_SlotMutexes[slot].Lock();
  88. BaseSlot* presult = m_SlotPtrs[slot];
  89. if ( presult )
  90. {
  91. presult->AddRef();
  92. }
  93. return presult;
  94. }
  95. void ScaleformUIImpl::UnlockSlotPtr( int slot )
  96. {
  97. AssertMsg( slot >= 0 && slot < MAX_SLOTS, "Invalid slot index in UnlockSlotPtr" );
  98. if ( m_SlotPtrs[slot] && m_SlotPtrs[slot]->Release() )
  99. {
  100. m_SlotPtrs[slot] = NULL;
  101. }
  102. // gurjeets - locks commented out, left here for reference, see comment in LockSlotPtr
  103. //m_SlotMutexes[slot].Unlock();
  104. }
  105. void ScaleformUIImpl::LockSlot( int slot )
  106. {
  107. AssertMsg( slot >= 0 && slot < MAX_SLOTS, "Invalid slot index in LockSlot" );
  108. // gurjeets - locks commented out, left here for reference, see comment in LockSlotPtr
  109. //m_SlotMutexes[slot].Lock();
  110. }
  111. void ScaleformUIImpl::UnlockSlot( int slot )
  112. {
  113. AssertMsg( slot >= 0 && slot < MAX_SLOTS, "Invalid slot index in UnlockSlot" );
  114. // gurjeets - locks commented out, left here for reference, see comment in LockSlotPtr
  115. //m_SlotMutexes[slot].Unlock();
  116. }
  117. void ScaleformUIImpl::SlotAddRef( int slot )
  118. {
  119. AssertMsg( slot >= 0 && slot < MAX_SLOTS, "Invalid slot index in SlotAddRef" );
  120. LockSlotPtr( slot );
  121. // gurjeets - locks commented out, left here for reference, see comment in LockSlotPtr
  122. //m_SlotMutexes[slot].Unlock();
  123. }
  124. void ScaleformUIImpl::SlotRelease( int slot )
  125. {
  126. AssertMsg( slot >= 0 && slot < MAX_SLOTS, "Invalid slot index in SlotRelease" );
  127. // gurjeets - locks commented out, left here for reference, see comment in LockSlotPtr
  128. //m_SlotMutexes[slot].Lock();
  129. UnlockSlotPtr( slot );
  130. }
  131. IScaleformSlotInitController *g_pExternalScaleformSlotInitController = NULL;
  132. void ScaleformUIImpl::InitSlot( int slotID, const char* rootMovie, IScaleformSlotInitController *pController )
  133. {
  134. g_pExternalScaleformSlotInitController = pController;
  135. MEM_ALLOC_CREDIT_FORMATF( "ScaleformUIImpl::InitSlot%d", slotID );
  136. // gurjeets - locks commented out, left here for reference, see comment in LockSlotPtr
  137. //m_SlotMutexes[slotID].Lock();
  138. if ( !m_SlotPtrs[slotID] )
  139. {
  140. MovieSlot* slotptr = new MovieSlot();
  141. m_SlotPtrs[slotID] = slotptr;
  142. m_SlotDeniesInputRefCount[slotID] = 0;
  143. slotptr->Init( rootMovie, slotID );
  144. if ( pController )
  145. pController->ConfigureNewSlotPostInit( slotID );
  146. }
  147. else
  148. {
  149. m_SlotPtrs[slotID]->AddRef();
  150. }
  151. SFDevMsg("ScaleformUIImpl::InitSlot( %d, %s) refcount=%d\n", slotID, rootMovie, m_SlotPtrs[slotID]->m_iRefCount);
  152. // gurjeets - locks commented out, left here for reference, see comment in LockSlotPtr
  153. //m_SlotMutexes[slotID].Unlock();
  154. }
  155. void ScaleformUIImpl::RequestElement( int slot, const char* elementName, ScaleformUIFunctionHandlerObject* object, const IScaleformUIFunctionHandlerDefinitionTable* tableObject )
  156. {
  157. MEM_ALLOC_CREDIT();
  158. BaseSlot* pslot = LockSlotPtr( slot );
  159. if ( pslot )
  160. {
  161. SFDevMsg("ScaleformUIImpl::RequestElement( %d, %s)\n", slot, elementName);
  162. pslot->RequestElement( elementName, object, tableObject );
  163. }
  164. UnlockSlotPtr( slot );
  165. }
  166. void ScaleformUIImpl::RemoveElement( int slot, SFVALUE element )
  167. {
  168. MEM_ALLOC_CREDIT();
  169. BaseSlot* pslot = LockSlotPtr( slot );
  170. if ( pslot )
  171. {
  172. pslot->RemoveElement( (Scaleform::GFx::Value*)element );
  173. }
  174. UnlockSlotPtr( slot );
  175. }
  176. void ScaleformUIImpl::InstallGlobalObject( int slot, const char* elementName, ScaleformUIFunctionHandlerObject* object, const IScaleformUIFunctionHandlerDefinitionTable* tableObject, SFVALUE *pInstalledGlobalObjectResult )
  177. {
  178. MEM_ALLOC_CREDIT();
  179. BaseSlot* pslot = LockSlotPtr( slot );
  180. if ( pslot )
  181. {
  182. SFDevMsg("ScaleformUIImpl::InstallGlobalObject( %d, %s)\n", slot, elementName);
  183. pslot->InstallGlobalObject( elementName, object, tableObject, (Scaleform::GFx::Value* *) pInstalledGlobalObjectResult );
  184. }
  185. UnlockSlotPtr( slot );
  186. }
  187. void ScaleformUIImpl::RemoveGlobalObject( int slot, SFVALUE element )
  188. {
  189. MEM_ALLOC_CREDIT();
  190. BaseSlot* pslot = LockSlotPtr( slot );
  191. if ( pslot )
  192. {
  193. pslot->RemoveGlobalObject( (Scaleform::GFx::Value*)element );
  194. }
  195. UnlockSlotPtr( slot );
  196. }
  197. void ScaleformUIImpl::SetSlotViewport( int slot, int x, int y, int width, int height )
  198. {
  199. MEM_ALLOC_CREDIT();
  200. BaseSlot* pslot = LockSlotPtr( slot );
  201. if ( pslot )
  202. {
  203. pslot->m_pMovieView->SetViewport( m_iScreenWidth, m_iScreenHeight, x, y, width, height );
  204. }
  205. UnlockSlotPtr( slot );
  206. }
  207. static bool s_bScaleformInFrame = false;
  208. void ScaleformUIImpl::RenderSlot( int slot )
  209. {
  210. if ( !r_drawscaleform.GetBool() )
  211. return;
  212. MEM_ALLOC_CREDIT_FORMATF( "ScaleformUIImpl::RenderSlot%d", slot );
  213. if (slot == SF_RESERVED_BEGINFRAME_SLOT)
  214. {
  215. m_pShaderAPI->ResetRenderState( false );
  216. #if defined( DX_TO_GL_ABSTRACTION )
  217. // Removed for Linux merge (trunk in 2002 -> //console/csgo/trunk in 2001) - do we need these
  218. // m_pDevice->FlushStates( 0xFFFFFFFF );
  219. // m_pDevice->FlushSamplers();
  220. #endif
  221. s_bScaleformInFrame = m_pRenderer2D->BeginFrame();
  222. return;
  223. }
  224. if (slot == SF_RESERVED_ENDFRAME_SLOT)
  225. {
  226. m_pRenderer2D->EndFrame();
  227. m_pShaderAPI->ResetRenderState( false );
  228. #if defined( DX_TO_GL_ABSTRACTION )
  229. // Removed for Linux merge (trunk in 2002 -> //console/csgo/trunk in 2001) - do we need these
  230. // m_pDevice->FlushStates( 0xFFFFFFFF );
  231. // m_pDevice->FlushSamplers();
  232. #endif
  233. return;
  234. }
  235. if ( !s_bScaleformInFrame )
  236. {
  237. // Device lost, but still need to call NextCapture to avoid leaking memory
  238. BaseSlot* pslot = LockSlotPtr( slot );
  239. if (pslot)
  240. {
  241. MovieDisplayHandle hMovieDisplay = ((Movie*)pslot->m_pMovieView)->GetDisplayHandle();
  242. hMovieDisplay.NextCapture( m_pRenderer2D->GetContextNotify() );
  243. }
  244. UnlockSlotPtr( slot );
  245. return;
  246. }
  247. SaveRenderingState();
  248. if ( m_pRenderHAL )
  249. {
  250. m_pRenderHAL->GetTextureManager()->SetRenderThreadIdToCurrentThread();
  251. if ( m_bClearMeshCacheQueued )
  252. {
  253. // Clear the mesh cache to recover memory. The mesh cache will clear itself after hitting a threshold,
  254. // but in practice this threshold can large enough that it bleeds a lot of memory on console.
  255. // We also want to avoid performance spikes caused by clearing and refilling this cache in the middle
  256. // of gameplay. So this accessor allows us to reset the cache on demand at a less noticeable point,
  257. // e.g. the end of a round, or when we transition between maps.
  258. MeshCache& meshCache = m_pRenderHAL->GetMeshCache();
  259. meshCache.ClearCache();
  260. m_bClearMeshCacheQueued = false;
  261. }
  262. #ifdef DX_TO_GL_ABSTRACTION
  263. // On Linux, we have to flip the display.
  264. SF::Render::Matrix2F matrix;
  265. matrix.Sy() = -1.0f;
  266. matrix.Ty() = m_iScreenHeight;
  267. m_pRenderHAL->SetUserMatrix(matrix);
  268. #endif
  269. }
  270. BaseSlot* pslot = LockSlotPtr( slot );
  271. if ( pslot )
  272. {
  273. MovieView_Display( ToSFMOVIE( pslot->m_pMovieView ) );
  274. }
  275. UnlockSlotPtr( slot );
  276. RestoreRenderingState();
  277. }
  278. void ScaleformUIImpl::ForkRenderSlot( int slot )
  279. {
  280. }
  281. void ScaleformUIImpl::JoinRenderSlot( int slot )
  282. {
  283. }
  284. void ScaleformUIImpl::AdvanceSlot( int slot )
  285. {
  286. if ( !r_drawscaleform.GetBool() )
  287. return;
  288. MEM_ALLOC_CREDIT_FORMATF( "ScaleformUIImpl::AdvanceSlot%d", slot );
  289. BaseSlot* pslot = LockSlotPtr( slot );
  290. if ( pslot )
  291. {
  292. // Using m_fTime set in RunFrame
  293. pslot->Advance( m_fTime );
  294. }
  295. UnlockSlotPtr( slot );
  296. }
  297. bool ScaleformUIImpl::SlotConsumesInputEvents( int slot )
  298. {
  299. MEM_ALLOC_CREDIT_FORMATF( "ScaleformUIImpl::SlotConsumesInputEvents%d", slot );
  300. bool result = false;
  301. BaseSlot* pslot = m_SlotPtrs[ slot ];
  302. if ( pslot )
  303. {
  304. result = pslot->ConsumesInputEvents();
  305. }
  306. return result;
  307. }
  308. bool ScaleformUIImpl::SlotDeniesInputToGame( int slot )
  309. {
  310. MEM_ALLOC_CREDIT_FORMATF( "ScaleformUIImpl::SlotDeniesInputToGame%d", slot );
  311. if ( m_bDenyAllInputToGame )
  312. return true;
  313. if ( slot < MAX_SLOTS )
  314. return ( m_SlotDeniesInputRefCount[slot] > 0 );
  315. else
  316. return false;
  317. }
  318. void ScaleformUIImpl::DenyInputToGameFromFlash( int slot, bool value )
  319. {
  320. if ( value )
  321. {
  322. m_SlotDeniesInputRefCount[slot]++;
  323. }
  324. else
  325. {
  326. Assert( m_SlotDeniesInputRefCount[slot] > 0 );
  327. m_SlotDeniesInputRefCount[slot]--;
  328. }
  329. SFDevMsg( "ScaleformUIImpl::DenyInputToGameFromFlash(%d,%d) m_SlotDeniesInputRefCount[%d]=%d \n", slot, value?1:0, slot, m_SlotDeniesInputRefCount[slot] );
  330. }
  331. bool ScaleformUIImpl::AnalogStickNavigationDisabled( int slot )
  332. {
  333. MEM_ALLOC_CREDIT_FORMATF( "ScaleformUIImpl::AnalogStickNavigationDisabled%d", slot );
  334. bool result = false;
  335. if ( slot < MAX_SLOTS )
  336. {
  337. BaseSlot* pslot = m_SlotPtrs[ slot ];
  338. if ( pslot )
  339. {
  340. MovieSlot* pMovieSlot = dynamic_cast<MovieSlot*>( pslot );
  341. if ( pMovieSlot )
  342. {
  343. result = pMovieSlot->AnalogStickNavigationDisabled();
  344. }
  345. }
  346. }
  347. return result;
  348. }
  349. void ScaleformUIImpl::UpdateSafeZone( void )
  350. {
  351. MEM_ALLOC_CREDIT();
  352. for ( int i = SF_FIRST_UNRESERVED_SLOT; i < MAX_SLOTS; i++ )
  353. {
  354. BaseSlot* pslot = LockSlotPtr( i );
  355. if ( pslot )
  356. {
  357. pslot->UpdateSafeZone();
  358. }
  359. UnlockSlotPtr( i );
  360. }
  361. }
  362. void ScaleformUIImpl::UpdateTint( void )
  363. {
  364. MEM_ALLOC_CREDIT();
  365. for ( int i = SF_FIRST_UNRESERVED_SLOT; i < MAX_SLOTS; i++ )
  366. {
  367. BaseSlot* pslot = LockSlotPtr( i );
  368. if ( pslot )
  369. {
  370. pslot->UpdateTint();
  371. }
  372. UnlockSlotPtr( i );
  373. }
  374. }
  375. bool ScaleformUIImpl::ConsumesInputEvents( void )
  376. {
  377. MEM_ALLOC_CREDIT();
  378. if ( m_bDenyAllInputToGame )
  379. return true;
  380. for ( int i = SF_FIRST_UNRESERVED_SLOT; i < MAX_SLOTS; i++ )
  381. {
  382. if ( SlotConsumesInputEvents( i ) )
  383. {
  384. return true;
  385. }
  386. }
  387. return false;
  388. }
  389. void ScaleformUIImpl::ForceUpdateImages()
  390. {
  391. MEM_ALLOC_CREDIT();
  392. for ( int i = SF_FIRST_UNRESERVED_SLOT; i < MAX_SLOTS; i++ )
  393. {
  394. BaseSlot* pSlot = LockSlotPtr( i );
  395. if ( pSlot && pSlot->m_pMovieView )
  396. {
  397. pSlot->m_pMovieView->ForceUpdateImages();
  398. }
  399. UnlockSlotPtr( i );
  400. }
  401. }
  402. void ScaleformUIImpl::DenyInputToGame( bool value )
  403. {
  404. m_bDenyAllInputToGame = value;
  405. SFDevMsg( "ScaleformUIImpl::DenyInputToGame(%d)\n", value?1:0 );
  406. }
  407. SFVALUE ScaleformUIImpl::CreateNewObject( int slot )
  408. {
  409. MEM_ALLOC_CREDIT();
  410. SFVALUE result = NULL;
  411. BaseSlot* pslot = LockSlotPtr( slot );
  412. if ( pslot )
  413. {
  414. Movie* pmovie = pslot->m_pMovieView;
  415. Value* pResult = (Value*)CreateGFxValue();
  416. pmovie->CreateObject( pResult );
  417. result = ( SFVALUE )pResult;
  418. }
  419. UnlockSlotPtr( slot );
  420. return result;
  421. }
  422. SFVALUE ScaleformUIImpl::CreateNewArray( int slot, int size )
  423. {
  424. MEM_ALLOC_CREDIT();
  425. SFVALUE result = NULL;
  426. BaseSlot* pslot = LockSlotPtr( slot );
  427. if ( pslot )
  428. {
  429. Movie* pmovie = pslot->m_pMovieView;
  430. Value* pResult = (Value*)CreateGFxValue();
  431. pmovie->CreateArray( pResult );
  432. if ( size != -1 )
  433. pResult->SetArraySize( size );
  434. result = ( SFVALUE )pResult;
  435. }
  436. UnlockSlotPtr( slot );
  437. return result;
  438. }
  439. SFVALUE ScaleformUIImpl::CreateNewString( int slot, const char* value )
  440. {
  441. MEM_ALLOC_CREDIT();
  442. SFVALUE result = NULL;
  443. BaseSlot* pslot = LockSlotPtr( slot );
  444. if ( pslot )
  445. {
  446. Movie* pmovie = pslot->m_pMovieView;
  447. Value* pResult = (Value*)CreateGFxValue();
  448. pmovie->CreateString( pResult, value );
  449. result = ( SFVALUE )pResult;
  450. }
  451. UnlockSlotPtr( slot );
  452. return result;
  453. }
  454. SFVALUE ScaleformUIImpl::CreateNewString( int slot, const wchar_t* value )
  455. {
  456. MEM_ALLOC_CREDIT();
  457. SFVALUE result = NULL;
  458. BaseSlot* pslot = LockSlotPtr( slot );
  459. if ( pslot )
  460. {
  461. Movie* pmovie = pslot->m_pMovieView;
  462. Value* pResult = (Value*)CreateGFxValue();
  463. pmovie->CreateStringW( pResult, value );
  464. result = ( SFVALUE )pResult;
  465. }
  466. UnlockSlotPtr( slot );
  467. return result;
  468. }
  469. void ScaleformUIImpl::LockInputToSlot( int slot )
  470. {
  471. MEM_ALLOC_CREDIT_FORMATF( "ScaleformUIImpl::LockInputToSlot%d", slot );
  472. BaseSlot* pslot = LockSlotPtr( SF_FULL_SCREEN_SLOT );
  473. if ( pslot )
  474. {
  475. pslot->LockInputToSlot( slot );
  476. }
  477. UnlockSlotPtr( SF_FULL_SCREEN_SLOT );
  478. }
  479. void ScaleformUIImpl::UnlockInput( void )
  480. {
  481. MEM_ALLOC_CREDIT();
  482. BaseSlot* pslot = LockSlotPtr( SF_FULL_SCREEN_SLOT );
  483. if ( pslot )
  484. {
  485. pslot->UnlockInput();
  486. }
  487. UnlockSlotPtr( SF_FULL_SCREEN_SLOT );
  488. }
  489. void ScaleformUIImpl::ForceCollectGarbage( int slot )
  490. {
  491. BaseSlot* pslot = m_SlotPtrs[ slot ];
  492. if ( pslot )
  493. {
  494. pslot->ForceCollectGarbage( );
  495. }
  496. }
  497. void ScaleformUIImpl::SetToControllerUI( int slot, bool value )
  498. {
  499. BaseSlot* pslot = LockSlotPtr( slot );
  500. if ( pslot )
  501. {
  502. pslot->SetToControllerUI( value, true );
  503. }
  504. UnlockSlotPtr( slot );
  505. }
  506. void ScaleformUIImpl::LockMostRecentInputDevice( int slot )
  507. {
  508. BaseSlot* pslot = m_SlotPtrs[ slot ];
  509. if ( pslot )
  510. {
  511. pslot->LockMostRecentInputDevice();
  512. }
  513. }
  514. bool ScaleformUIImpl::IsSetToControllerUI( int slot )
  515. {
  516. bool result = false;
  517. BaseSlot* pslot = m_SlotPtrs[ slot ];
  518. if ( pslot == NULL || !pslot->ConsumesInputEvents() )
  519. {
  520. // Specified slot does not consume input events, or does not exist. Test the full screen slot instead.
  521. slot = SF_FULL_SCREEN_SLOT;
  522. pslot = m_SlotPtrs[ slot ];
  523. }
  524. if ( pslot )
  525. {
  526. result = pslot->IsSetToControllerUI();
  527. }
  528. return result;
  529. }