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.

3455 lines
97 KiB

  1. //========== Copyright Valve Corporation, All rights reserved. ========
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "pch_materialsystem.h"
  7. #ifndef _PS3
  8. #define MATSYS_INTERNAL
  9. #endif
  10. #include <math.h>
  11. #include "cmatrendercontext.h"
  12. #include "tier2/renderutils.h"
  13. #include "cmaterialsystem.h"
  14. #include "occlusionquerymgr.h"
  15. #include "texturemanager.h"
  16. #include "IHardwareConfigInternal.h"
  17. #include "ctype.h"
  18. #include "tier1/fmtstr.h"
  19. //#include "glmgr/glmdebug.h"
  20. // NOTE: This must be the last file included!!!
  21. #include "tier0/memdbgon.h"
  22. //-----------------------------------------------------------------------------
  23. // FIXME: right now, always keeping shader API in sync, because debug overlays don't seem to work 100% with the delayed matrix loading
  24. #define FORCE_MATRIX_SYNC 1
  25. #ifdef VALIDATE_MATRICES
  26. #define ShouldValidateMatrices() true
  27. #else
  28. #define ShouldValidateMatrices() false
  29. #endif
  30. #ifdef VALIDATE_MATRICES
  31. #define AllowLazyMatrixSync() false
  32. #define ForceSync() ((void)(0))
  33. #elif defined(FORCE_MATRIX_SYNC)
  34. #define AllowLazyMatrixSync() false
  35. #define ForceSync() ForceSyncMatrix( m_MatrixMode )
  36. #else
  37. #define AllowLazyMatrixSync() true
  38. #define ForceSync() ((void)(0))
  39. #endif
  40. #ifdef _X360
  41. static bool s_bDirtyDisk = false;
  42. #endif
  43. void ValidateMatrices( const VMatrix &m1, const VMatrix &m2, float eps = .001 )
  44. {
  45. if ( ShouldValidateMatrices() )
  46. {
  47. for ( int i = 0; i < 16; i++ )
  48. {
  49. AssertFloatEquals( m1.Base()[i], m1.Base()[i], eps );
  50. }
  51. }
  52. }
  53. //-----------------------------------------------------------------------------
  54. // The dirty disk error report function (NOTE: Could be called from any thread!)
  55. //-----------------------------------------------------------------------------
  56. #ifdef _X360
  57. unsigned ThreadedDirtyDiskErrorDisplay( void *pParam )
  58. {
  59. XShowDirtyDiscErrorUI( XBX_GetPrimaryUserId() );
  60. }
  61. #endif
  62. void SpinPresent()
  63. {
  64. while ( true )
  65. {
  66. g_pShaderAPI->ClearColor3ub( 0, 0, 0 );
  67. g_pShaderAPI->ClearBuffers( true, true, true, -1, -1 );
  68. g_pShaderDevice->Present();
  69. }
  70. }
  71. void ReportDirtyDisk()
  72. {
  73. #ifdef _X360
  74. s_bDirtyDisk = true;
  75. ThreadHandle_t h = CreateSimpleThread( ThreadedDirtyDiskErrorDisplay, NULL );
  76. ThreadSetPriority( h, THREAD_PRIORITY_HIGHEST );
  77. // If this is being called from the render thread, immediately swap
  78. if ( ( ThreadGetCurrentId() == MaterialSystem()->GetRenderThreadId() ) ||
  79. ( ThreadInMainThread() && g_pMaterialSystem->GetThreadMode() != MATERIAL_QUEUED_THREADED ) )
  80. {
  81. SpinPresent();
  82. }
  83. #endif
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Install dirty disk error reporting function (call after SetMode)
  87. //-----------------------------------------------------------------------------
  88. void SetupDirtyDiskReportFunc()
  89. {
  90. g_pFullFileSystem->InstallDirtyDiskReportFunc( ReportDirtyDisk );
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Globals
  94. //-----------------------------------------------------------------------------
  95. CMemoryStack CMatRenderContextBase::sm_RenderData[2];
  96. int CMatRenderContextBase::sm_nRenderLockCount = 0;
  97. int CMatRenderContextBase::sm_nRenderStack = 0;
  98. MemoryStackMark_t CMatRenderContextBase::sm_nRenderCurrentAllocPoint = 0;
  99. int CMatRenderContextBase::sm_nInitializeCount = 0;
  100. //-----------------------------------------------------------------------------
  101. // Constructor
  102. //-----------------------------------------------------------------------------
  103. CMatRenderContextBase::CMatRenderContextBase() :
  104. m_pMaterialSystem( NULL ), m_RenderTargetStack( 16, 32 ), m_ScissorRectStack( 16, 32 ), m_MatrixMode( NUM_MATRIX_MODES )
  105. {
  106. int i;
  107. m_bDirtyViewState = true;
  108. // Put a special element at the top of the RT stack (indicating back buffer is current top of stack)
  109. // NULL indicates back buffer, -1 indicates full-size viewport
  110. #if !defined( _X360 ) && !defined( _PS3 )
  111. RenderTargetStackElement_t initialElement = { {NULL, NULL, NULL, NULL}, NULL, 0, 0, -1, -1 };
  112. #else
  113. RenderTargetStackElement_t initialElement = { {NULL}, NULL, 0, 0, -1, -1 };
  114. #endif
  115. m_RenderTargetStack.Push( initialElement );
  116. for ( i = 0; i < MAX_FB_TEXTURES; i++ )
  117. {
  118. m_pCurrentFrameBufferCopyTexture[i] = NULL;
  119. }
  120. m_pCurrentMaterial = NULL;
  121. m_pCurrentProxyData = NULL;
  122. m_pUserDefinedLightmap = NULL;
  123. m_HeightClipMode = MATERIAL_HEIGHTCLIPMODE_DISABLE;
  124. m_HeightClipZ = 0.0f;
  125. m_bEnableClipping = true;
  126. m_bFlashlightEnable = false;
  127. m_bCascadedShadowMappingEnabled = false;
  128. m_bRenderingPaint = false;
  129. m_bFullFrameDepthIsValid = false;
  130. m_bCullingEnabledForSinglePassFlashlight = false;
  131. for ( i = 0; i < NUM_MATRIX_MODES; i++ )
  132. {
  133. m_MatrixStacks[i].Push();
  134. m_MatrixStacks[i].Top().matrix.Identity();
  135. m_MatrixStacks[i].Top().flags |= ( MSF_DIRTY| MSF_IDENTITY );
  136. }
  137. m_pCurMatrixItem = &m_MatrixStacks[0].Top();
  138. m_Viewport.Init( 0, 0, 0, 0 );
  139. m_LastSetToneMapScale = Vector(1,1,1);
  140. }
  141. const char *COM_GetModDirectory()
  142. {
  143. static char modDir[MAX_PATH];
  144. if ( Q_strlen( modDir ) == 0 )
  145. {
  146. const char *gamedir = CommandLine()->ParmValue("-game", CommandLine()->ParmValue( "-defaultgamedir", "hl2" ) );
  147. Q_strncpy( modDir, gamedir, sizeof(modDir) );
  148. if ( strchr( modDir, '/' ) || strchr( modDir, '\\' ) )
  149. {
  150. Q_StripLastDir( modDir, sizeof(modDir) );
  151. int dirlen = Q_strlen( modDir );
  152. Q_strncpy( modDir, gamedir + dirlen, sizeof(modDir) - dirlen );
  153. }
  154. }
  155. return modDir;
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Init, shutdown
  159. //-----------------------------------------------------------------------------
  160. InitReturnVal_t CMatRenderContextBase::Init( )
  161. {
  162. if ( !sm_nInitializeCount )
  163. {
  164. int nSize = 2200 * 1024;
  165. int nCommitSize = 32 * 1024;
  166. if ( !Q_stricmp( "infested", COM_GetModDirectory() ) )
  167. {
  168. nSize = 4400 * 1024;
  169. }
  170. else if ( !Q_stricmp( "swarm", COM_GetModDirectory() ) )
  171. {
  172. nSize = 4400 * 1024;
  173. }
  174. else if ( !Q_stricmp( "portal2", COM_GetModDirectory() ) )
  175. {
  176. nSize = 6600 * 1024;
  177. }
  178. else if ( !Q_stricmp( "csgo", COM_GetModDirectory() ) )
  179. {
  180. nSize = 6600 * 1024;
  181. }
  182. #ifdef DEDICATED
  183. nSize = nCommitSize = 1024;
  184. #endif
  185. sm_RenderData[0].Init( "CMatRenderContextBase::sm_RenderData[0]", nSize, nCommitSize, 0, 32 );
  186. sm_RenderData[1].Init( "CMatRenderContextBase::sm_RenderData[1]", nSize, nCommitSize, 0, 32 );
  187. sm_nRenderStack = 0;
  188. sm_nRenderLockCount = 0;
  189. sm_nRenderCurrentAllocPoint = 0;
  190. }
  191. ++sm_nInitializeCount;
  192. return INIT_OK;
  193. }
  194. void CMatRenderContextBase::Shutdown( )
  195. {
  196. Assert( sm_nInitializeCount >= 0 );
  197. if ( --sm_nInitializeCount == 0 )
  198. {
  199. sm_RenderData[0].Term();
  200. sm_RenderData[1].Term();
  201. }
  202. }
  203. void CMatRenderContextBase::CompactMemory()
  204. {
  205. if ( sm_nRenderLockCount )
  206. {
  207. DevWarning( "CMatRenderContext: Trying to compact with render data still locked!\n" );
  208. sm_nRenderLockCount = 0;
  209. }
  210. sm_RenderData[0].FreeAll();
  211. sm_RenderData[1].FreeAll();
  212. }
  213. void CMatRenderContextBase::MarkRenderDataUnused( bool bFrameBegin )
  214. {
  215. if ( sm_nRenderLockCount )
  216. {
  217. DevWarning( "CMatRenderContext: Trying to clear render data with render data still locked (%d)!\n", sm_nRenderLockCount );
  218. sm_nRenderLockCount = 0;
  219. }
  220. if ( bFrameBegin )
  221. {
  222. // Switch stacks
  223. sm_nRenderStack = 1 - sm_nRenderStack;
  224. // Clear the new stack
  225. #ifdef _DEBUG
  226. memset( sm_RenderData[sm_nRenderStack].GetBase(), 0xFF, RenderDataSizeUsed() );
  227. #endif
  228. sm_RenderData[ sm_nRenderStack ].FreeAll( false );
  229. sm_nRenderCurrentAllocPoint = 0;
  230. }
  231. else
  232. {
  233. // Clear to the previous alloc point
  234. #ifdef _DEBUG
  235. char *pClearFrom = (char*)sm_RenderData[sm_nRenderStack].GetBase() + sm_nRenderCurrentAllocPoint;
  236. int nSizeToClear = RenderDataSizeUsed() - sm_nRenderCurrentAllocPoint;
  237. memset( pClearFrom, 0xFF, nSizeToClear );
  238. #endif
  239. sm_RenderData[sm_nRenderStack].FreeToAllocPoint( sm_nRenderCurrentAllocPoint, false );
  240. }
  241. }
  242. int CMatRenderContextBase::RenderDataSizeUsed() const
  243. {
  244. return sm_RenderData[sm_nRenderStack].GetUsed();
  245. }
  246. bool CMatRenderContextBase::IsRenderData( const void *pData ) const
  247. {
  248. intp nData = (intp)pData;
  249. intp nBaseAddress = (intp)sm_RenderData[sm_nRenderStack].GetBase();
  250. intp nLastAddress = nBaseAddress + RenderDataSizeUsed();
  251. return ( nData == 0 ) || ( nData >= nBaseAddress && nData < nLastAddress );
  252. }
  253. //-----------------------------------------------------------------------------
  254. // debug logging - empty in base class
  255. //-----------------------------------------------------------------------------
  256. void CMatRenderContextBase::PrintfVA( char *fmt, va_list vargs )
  257. {
  258. }
  259. void CMatRenderContextBase::Printf( char *fmt, ... )
  260. {
  261. }
  262. float CMatRenderContextBase::Knob( char *knobname, float *setvalue )
  263. {
  264. return 0.0f;
  265. }
  266. //-----------------------------------------------------------------------------
  267. //
  268. //-----------------------------------------------------------------------------
  269. #define g_pShaderAPI Cannot_use_ShaderAPI_in_CMatRenderContextBase
  270. void CMatRenderContextBase::InitializeFrom( CMatRenderContextBase *pInitialState )
  271. {
  272. int i;
  273. m_pCurrentMaterial = pInitialState->m_pCurrentMaterial;
  274. m_pCurrentProxyData = pInitialState->m_pCurrentProxyData;
  275. m_lightmapPageID = pInitialState->m_lightmapPageID;
  276. m_pUserDefinedLightmap = pInitialState->m_pUserDefinedLightmap;
  277. m_pLocalCubemapTexture = pInitialState->m_pLocalCubemapTexture;
  278. memcpy( m_pCurrentFrameBufferCopyTexture, pInitialState->m_pCurrentFrameBufferCopyTexture, MAX_FB_TEXTURES * sizeof(ITexture *) );
  279. m_bEnableClipping = pInitialState->m_bEnableClipping;
  280. m_HeightClipMode = pInitialState->m_HeightClipMode;
  281. m_HeightClipZ = pInitialState->m_HeightClipZ;
  282. m_pBoundMorph = pInitialState->m_pBoundMorph; // not reference counted?
  283. m_RenderTargetStack.Clear();
  284. m_RenderTargetStack.EnsureCapacity( pInitialState->m_RenderTargetStack.Count() );
  285. for ( i = 0; i < pInitialState->m_RenderTargetStack.Count(); i++ )
  286. {
  287. m_RenderTargetStack.Push( pInitialState->m_RenderTargetStack[i] );
  288. }
  289. m_ScissorRectStack.Clear();
  290. m_ScissorRectStack.EnsureCapacity( pInitialState->m_ScissorRectStack.Count() );
  291. for ( i = 0; i < pInitialState->m_ScissorRectStack.Count(); i++ )
  292. {
  293. m_ScissorRectStack.Push( pInitialState->m_ScissorRectStack[i] );
  294. }
  295. m_MatrixMode = pInitialState->m_MatrixMode;
  296. for ( i = 0; i < NUM_MATRIX_MODES; i++ )
  297. {
  298. m_MatrixStacks[i].CopyFrom( pInitialState->m_MatrixStacks[i] );
  299. }
  300. m_bFlashlightEnable = pInitialState->m_bFlashlightEnable;
  301. m_bCascadedShadowMappingEnabled = pInitialState->m_bCascadedShadowMappingEnabled;
  302. m_bRenderingPaint = pInitialState->m_bRenderingPaint;
  303. m_LastSetToneMapScale = pInitialState->m_LastSetToneMapScale;
  304. }
  305. void CMatRenderContextBase::Bind( IMaterial *pMaterial, void *proxyData )
  306. {
  307. IMaterialInternal *material = static_cast<IMaterialInternal *>( pMaterial );
  308. if ( !material )
  309. {
  310. Warning( "Programming error: CMatRenderContextBase::Bind: NULL material\n" );
  311. material = static_cast<IMaterialInternal *>( g_pErrorMaterial );
  312. }
  313. material = material->GetRealTimeVersion(); //always work with the real time versions of materials internally
  314. if ( m_pCurrentMaterial != material )
  315. {
  316. if( !material->IsPrecached() )
  317. {
  318. // This model is supposed to come in like this, skip the warning message
  319. if( V_strcmp(material->GetName(), "engine/preloadtexture" ) != 0 )
  320. {
  321. DevWarning( "Binding uncached material \"%s\", artificially incrementing refcount\n", material->GetName() );
  322. }
  323. material->ArtificialAddRef();
  324. material->Precache();
  325. }
  326. m_pCurrentMaterial = material;
  327. }
  328. m_pCurrentProxyData = proxyData;
  329. }
  330. void CMatRenderContextBase::BindLightmapPage( int lightmapPageID )
  331. {
  332. m_lightmapPageID = lightmapPageID;
  333. }
  334. void CMatRenderContextBase::SetRenderTargetEx( int nRenderTargetID, ITexture *pNewTarget )
  335. {
  336. // Verify valid top of RT stack
  337. Assert ( m_RenderTargetStack.Count() > 0 );
  338. // Reset the top of stack to the new target with old viewport
  339. RenderTargetStackElement_t newTOS = m_RenderTargetStack.Top();
  340. newTOS.m_pRenderTargets[nRenderTargetID] = pNewTarget;
  341. m_RenderTargetStack.Pop( );
  342. m_RenderTargetStack.Push( newTOS );
  343. }
  344. void CMatRenderContextBase::BindLocalCubemap( ITexture *pTexture )
  345. {
  346. if( pTexture )
  347. {
  348. m_pLocalCubemapTexture = pTexture;
  349. }
  350. else
  351. {
  352. m_pLocalCubemapTexture = TextureManager()->ErrorTexture();
  353. }
  354. }
  355. ITexture *CMatRenderContextBase::GetRenderTarget( void )
  356. {
  357. if (m_RenderTargetStack.Count() > 0)
  358. {
  359. return m_RenderTargetStack.Top().m_pRenderTargets[0];
  360. }
  361. else
  362. {
  363. return NULL; // should this be something else, since NULL indicates back buffer?
  364. }
  365. }
  366. ITexture *CMatRenderContextBase::GetRenderTargetEx( int nRenderTargetID )
  367. {
  368. // Verify valid top of stack
  369. Assert ( m_RenderTargetStack.Count() > 0 );
  370. // Top of render target stack
  371. ITexture *pTexture = m_RenderTargetStack.Top().m_pRenderTargets[ nRenderTargetID ];
  372. return pTexture;
  373. }
  374. void CMatRenderContextBase::SetFrameBufferCopyTexture( ITexture *pTexture, int textureIndex )
  375. {
  376. if( textureIndex < 0 || textureIndex > MAX_FB_TEXTURES )
  377. {
  378. Assert( 0 );
  379. return;
  380. }
  381. // FIXME: Do I need to increment/decrement ref counts here, or assume that the app is going to do it?
  382. m_pCurrentFrameBufferCopyTexture[textureIndex] = pTexture;
  383. }
  384. ITexture *CMatRenderContextBase::GetFrameBufferCopyTexture( int textureIndex )
  385. {
  386. if( textureIndex < 0 || textureIndex > MAX_FB_TEXTURES )
  387. {
  388. Assert( 0 );
  389. return NULL; // FIXME! This should return the error texture.
  390. }
  391. return m_pCurrentFrameBufferCopyTexture[textureIndex];
  392. }
  393. void CMatRenderContextBase::MatrixMode( MaterialMatrixMode_t mode )
  394. {
  395. Assert( m_MatrixStacks[mode].Count() );
  396. m_MatrixMode = mode;
  397. m_pCurMatrixItem = &m_MatrixStacks[mode].Top();
  398. }
  399. void CMatRenderContextBase::CurrentMatrixChanged()
  400. {
  401. if ( m_MatrixMode == MATERIAL_VIEW )
  402. {
  403. m_bDirtyViewState = true;
  404. m_bDirtyViewProjState = true;
  405. }
  406. else if ( m_MatrixMode == MATERIAL_PROJECTION )
  407. {
  408. m_bDirtyViewProjState = true;
  409. }
  410. }
  411. void CMatRenderContextBase::PushMatrix()
  412. {
  413. CUtlStack<MatrixStackItem_t> &curStack = m_MatrixStacks[ m_MatrixMode ];
  414. Assert( curStack.Count() );
  415. int iNew = curStack.Push();
  416. curStack[ iNew ] = curStack[ iNew - 1 ];
  417. m_pCurMatrixItem = &curStack.Top();
  418. CurrentMatrixChanged();
  419. }
  420. void CMatRenderContextBase::PopMatrix()
  421. {
  422. Assert( m_MatrixStacks[m_MatrixMode].Count() > 1 );
  423. m_MatrixStacks[ m_MatrixMode ].Pop();
  424. m_pCurMatrixItem = &m_MatrixStacks[m_MatrixMode].Top();
  425. CurrentMatrixChanged();
  426. }
  427. void CMatRenderContextBase::LoadMatrix( const VMatrix& matrix )
  428. {
  429. m_pCurMatrixItem->matrix = matrix;
  430. m_pCurMatrixItem->flags = MSF_DIRTY; // clearing identity implicitly
  431. CurrentMatrixChanged();
  432. }
  433. void CMatRenderContextBase::LoadMatrix( const matrix3x4_t& matrix )
  434. {
  435. m_pCurMatrixItem->matrix.Init( matrix );
  436. m_pCurMatrixItem->flags = MSF_DIRTY; // clearing identity implicitly
  437. CurrentMatrixChanged();
  438. }
  439. void CMatRenderContextBase::MultMatrix( const VMatrix& matrix )
  440. {
  441. VMatrix result;
  442. MatrixMultiply( matrix, m_pCurMatrixItem->matrix, result );
  443. m_pCurMatrixItem->matrix = result;
  444. m_pCurMatrixItem->flags = MSF_DIRTY; // clearing identity implicitly
  445. CurrentMatrixChanged();
  446. }
  447. void CMatRenderContextBase::MultMatrix( const matrix3x4_t& matrix )
  448. {
  449. CMatRenderContextBase::MultMatrix( VMatrix( matrix ) );
  450. }
  451. void CMatRenderContextBase::MultMatrixLocal( const VMatrix& matrix )
  452. {
  453. VMatrix result;
  454. MatrixMultiply( m_pCurMatrixItem->matrix, matrix, result );
  455. m_pCurMatrixItem->matrix = result;
  456. m_pCurMatrixItem->flags = MSF_DIRTY; // clearing identity implicitly
  457. CurrentMatrixChanged();
  458. }
  459. void CMatRenderContextBase::MultMatrixLocal( const matrix3x4_t& matrix )
  460. {
  461. CMatRenderContextBase::MultMatrixLocal( VMatrix( matrix ) );
  462. }
  463. void CMatRenderContextBase::LoadIdentity()
  464. {
  465. // FIXME: possibly track is identity so can call shader API LoadIdentity() later instead of LoadMatrix()?
  466. m_pCurMatrixItem->matrix.Identity();
  467. m_pCurMatrixItem->flags = ( MSF_DIRTY | MSF_IDENTITY );
  468. CurrentMatrixChanged();
  469. }
  470. void CMatRenderContextBase::Ortho( double left, double top, double right, double bottom, double zNear, double zFar )
  471. {
  472. MatrixOrtho( m_pCurMatrixItem->matrix, left, top, right, bottom, zNear, zFar );
  473. m_pCurMatrixItem->flags = MSF_DIRTY;
  474. }
  475. void CMatRenderContextBase::PerspectiveX( double flFovX, double flAspect, double flZNear, double flZFar )
  476. {
  477. MatrixPerspectiveX( m_pCurMatrixItem->matrix, flFovX, flAspect, flZNear, flZFar );
  478. m_pCurMatrixItem->flags = MSF_DIRTY;
  479. }
  480. void CMatRenderContextBase::PerspectiveOffCenterX( double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right )
  481. {
  482. MatrixPerspectiveOffCenterX( m_pCurMatrixItem->matrix, flFovX, flAspect, flZNear, flZFar, bottom, top, left, right );
  483. m_pCurMatrixItem->flags = MSF_DIRTY;
  484. }
  485. void CMatRenderContextBase::PickMatrix( int x, int y, int nWidth, int nHeight )
  486. {
  487. int vx, vy, vwidth, vheight;
  488. GetViewport( vx, vy, vwidth, vheight );
  489. // Compute the location of the pick region in projection space...
  490. float px = 2.0 * (float)(x - vx) / (float)vwidth - 1;
  491. float py = 2.0 * (float)(y - vy)/ (float)vheight - 1;
  492. float pw = 2.0 * (float)nWidth / (float)vwidth;
  493. float ph = 2.0 * (float)nHeight / (float)vheight;
  494. // we need to translate (px, py) to the origin
  495. // and scale so (pw,ph) -> (2, 2)
  496. VMatrix mat;
  497. MatrixSetIdentity( mat );
  498. mat.m[0][0] = 2.0 / pw;
  499. mat.m[1][1] = 2.0 / ph;
  500. mat.m[0][3] = -2.0 * px / pw;
  501. mat.m[1][3] = -2.0 * py / ph;
  502. CMatRenderContextBase::MultMatrixLocal( mat );
  503. }
  504. void CMatRenderContextBase::Rotate( float flAngle, float x, float y, float z )
  505. {
  506. MatrixRotate( m_pCurMatrixItem->matrix, Vector( x, y, z ), flAngle );
  507. m_pCurMatrixItem->flags = MSF_DIRTY;
  508. }
  509. void CMatRenderContextBase::Translate( float x, float y, float z )
  510. {
  511. MatrixTranslate( m_pCurMatrixItem->matrix, Vector( x, y, z ) );
  512. m_pCurMatrixItem->flags = MSF_DIRTY;
  513. }
  514. void CMatRenderContextBase::Scale( float x, float y, float z )
  515. {
  516. VMatrix mat;
  517. MatrixBuildScale( mat, x, y, z );
  518. CMatRenderContextBase::MultMatrixLocal( mat );
  519. }
  520. void CMatRenderContextBase::GetMatrix( MaterialMatrixMode_t matrixMode, VMatrix *pMatrix )
  521. {
  522. CUtlStack<MatrixStackItem_t> &stack = m_MatrixStacks[ matrixMode ];
  523. if ( !stack.Count() )
  524. {
  525. pMatrix->Identity();
  526. return;
  527. }
  528. *pMatrix = stack.Top().matrix;
  529. }
  530. void CMatRenderContextBase::GetMatrix( MaterialMatrixMode_t matrixMode, matrix3x4_t *pMatrix )
  531. {
  532. CUtlStack<MatrixStackItem_t> &stack = m_MatrixStacks[ matrixMode ];
  533. if ( !stack.Count() )
  534. {
  535. SetIdentityMatrix( *pMatrix );
  536. return;
  537. }
  538. *pMatrix = stack.Top().matrix.As3x4();
  539. }
  540. void CMatRenderContextBase::RecomputeViewState()
  541. {
  542. if ( !m_bDirtyViewState )
  543. return;
  544. m_bDirtyViewState = false;
  545. // FIXME: Cache this off to make it less expensive?
  546. matrix3x4_t viewMatrix;
  547. GetMatrix( MATERIAL_VIEW, &viewMatrix );
  548. m_vecViewOrigin.x =
  549. -( viewMatrix[0][3] * viewMatrix[0][0] +
  550. viewMatrix[1][3] * viewMatrix[1][0] +
  551. viewMatrix[2][3] * viewMatrix[2][0] );
  552. m_vecViewOrigin.y =
  553. -( viewMatrix[0][3] * viewMatrix[0][1] +
  554. viewMatrix[1][3] * viewMatrix[1][1] +
  555. viewMatrix[2][3] * viewMatrix[2][1] );
  556. m_vecViewOrigin.z =
  557. -( viewMatrix[0][3] * viewMatrix[0][2] +
  558. viewMatrix[1][3] * viewMatrix[1][2] +
  559. viewMatrix[2][3] * viewMatrix[2][2] );
  560. m_vecViewForward.Init( viewMatrix[2][0], viewMatrix[2][1], viewMatrix[2][2]);
  561. m_vecViewForward *= -1.0f;
  562. m_vecViewRight.Init( viewMatrix[0][0], viewMatrix[0][1], viewMatrix[0][2] );
  563. m_vecViewUp.Init( viewMatrix[1][0], viewMatrix[1][1], viewMatrix[1][2] );
  564. }
  565. void CMatRenderContextBase::GetWorldSpaceCameraPosition( Vector *pCameraPos )
  566. {
  567. RecomputeViewState();
  568. VectorCopy( m_vecViewOrigin, *pCameraPos );
  569. }
  570. void CMatRenderContextBase::GetWorldSpaceCameraVectors( Vector *pVecForward, Vector *pVecRight, Vector *pVecUp )
  571. {
  572. RecomputeViewState();
  573. if ( pVecForward )
  574. {
  575. VectorCopy( m_vecViewForward, *pVecForward );
  576. }
  577. if ( pVecRight )
  578. {
  579. VectorCopy( m_vecViewRight, *pVecRight );
  580. }
  581. if ( pVecUp )
  582. {
  583. VectorCopy( m_vecViewUp, *pVecUp );
  584. }
  585. }
  586. void *CMatRenderContextBase::LockRenderData( int nSizeInBytes )
  587. {
  588. void *pDest = sm_RenderData[ sm_nRenderStack ].Alloc( nSizeInBytes, false );
  589. if ( !pDest )
  590. {
  591. ExecuteNTimes( 10, Warning( "MaterialSystem: Out of memory in render data! (Attempted size = %d)\n", nSizeInBytes ) );
  592. MemOutOfMemory(nSizeInBytes);
  593. }
  594. AddRefRenderData();
  595. return pDest;
  596. }
  597. void CMatRenderContextBase::UnlockRenderData( void *pData )
  598. {
  599. ReleaseRenderData();
  600. }
  601. void CMatRenderContextBase::AddRefRenderData()
  602. {
  603. ++sm_nRenderLockCount;
  604. }
  605. void CMatRenderContextBase::ReleaseRenderData()
  606. {
  607. --sm_nRenderLockCount;
  608. Assert( sm_nRenderLockCount >= 0 );
  609. if ( sm_nRenderLockCount == 0 )
  610. {
  611. OnRenderDataUnreferenced();
  612. // Keep track of the current allocation point for the current render data stack
  613. // in case the render context switches from CMatRenderContext to CMatQueuedRenderContext
  614. // Note that both render context mode write to the same render data stack
  615. // and OnRenderDataUnreferenced will have different implementation:
  616. // * CMatQueuedRenderContext - render data stack keeps growing until the next BeginFrame
  617. // where we switch to the next render data stack and clear the new one
  618. // * CMatRenderContext - free render data previously allocated. Therefore ensure that
  619. // render data added by CMatQueuedRenderContext are not overwritten by only freeing
  620. // up to the current allocation point
  621. sm_nRenderCurrentAllocPoint = sm_RenderData [sm_nRenderStack ].GetCurrentAllocPoint();
  622. }
  623. }
  624. void CMatRenderContextBase::SyncMatrices()
  625. {
  626. }
  627. void CMatRenderContextBase::SyncMatrix( MaterialMatrixMode_t mode )
  628. {
  629. }
  630. ShaderAPITextureHandle_t CMatRenderContextBase::GetLightmapTexture( int nLightmapPage )
  631. {
  632. // Should never be called
  633. Assert( 0 );
  634. return INVALID_SHADERAPI_TEXTURE_HANDLE;
  635. }
  636. ShaderAPITextureHandle_t CMatRenderContextBase::GetPaintmapTexture( int nLightmapPage )
  637. {
  638. // Should never be called
  639. Assert( 0 );
  640. return INVALID_SHADERAPI_TEXTURE_HANDLE;
  641. }
  642. void CMatRenderContextBase::SetHeightClipMode( enum MaterialHeightClipMode_t heightClipMode )
  643. {
  644. if( m_HeightClipMode != heightClipMode )
  645. {
  646. m_HeightClipMode = heightClipMode;
  647. UpdateHeightClipUserClipPlane();
  648. /*if ( HardwareConfig()->MaxUserClipPlanes() >= 1 && !HardwareConfig()->UseFastClipping())
  649. {
  650. UpdateHeightClipUserClipPlane();
  651. }
  652. else
  653. {
  654. g_pShaderAPI->SetHeightClipMode( heightClipMode );
  655. }*/
  656. }
  657. }
  658. void CMatRenderContextBase::SetHeightClipZ( float z )
  659. {
  660. if( z != m_HeightClipZ )
  661. {
  662. m_HeightClipZ = z;
  663. UpdateHeightClipUserClipPlane();
  664. }
  665. // FIXME! : Need to move user clip plane support back to pre-dx9 cards (all of the pixel shaders
  666. // have texkill in them. . blich.)
  667. /*if ( HardwareConfig()->MaxUserClipPlanes() >= 1 && !HardwareConfig()->UseFastClipping() )
  668. {
  669. UpdateHeightClipUserClipPlane();
  670. }
  671. else
  672. {
  673. g_pShaderAPI->SetHeightClipZ( z );
  674. }*/
  675. }
  676. bool CMatRenderContextBase::EnableClipping( bool bEnable )
  677. {
  678. if( bEnable != m_bEnableClipping )
  679. {
  680. m_bEnableClipping = bEnable;
  681. ApplyCustomClipPlanes();
  682. return !bEnable;
  683. }
  684. return bEnable;
  685. }
  686. void CMatRenderContextBase::Viewport( int x, int y, int width, int height )
  687. {
  688. // Verify valid top of RT stack
  689. Assert ( m_RenderTargetStack.Count() > 0 );
  690. // Reset the top of stack to the new viewport
  691. RenderTargetStackElement_t newTOS;
  692. memcpy(&newTOS,&(m_RenderTargetStack.Top()),sizeof(newTOS));
  693. newTOS.m_nViewX = x;
  694. newTOS.m_nViewY = y;
  695. newTOS.m_nViewW = width;
  696. newTOS.m_nViewH = height;
  697. m_RenderTargetStack.Pop( );
  698. m_RenderTargetStack.Push( newTOS );
  699. }
  700. //-----------------------------------------------------------------------------
  701. // This version will push the current rendertarget + current viewport onto the stack
  702. //-----------------------------------------------------------------------------
  703. void CMatRenderContextBase::PushRenderTargetAndViewport( )
  704. {
  705. // Necessary to push the stack top onto itself; realloc could happen otherwise
  706. m_RenderTargetStack.EnsureCapacity( m_RenderTargetStack.Count() + 1 );
  707. m_RenderTargetStack.Push( m_RenderTargetStack.Top() );
  708. CommitRenderTargetAndViewport();
  709. }
  710. //-----------------------------------------------------------------------------
  711. // Pushes a render target on the render target stack. Without a specific
  712. // viewport also being pushed, this function uses dummy values which indicate
  713. // that the viewport should span the the full render target and pushes
  714. // the RenderTargetStackElement_t onto the stack
  715. //
  716. // The push and pop methods also implicitly set the render target to the new top of stack
  717. //
  718. // NULL for pTexture indicates rendering to the back buffer
  719. //-----------------------------------------------------------------------------
  720. void CMatRenderContextBase::PushRenderTargetAndViewport( ITexture *pTexture )
  721. {
  722. // Just blindly push the data on the stack with flags indicating full bounds
  723. #if !defined( _X360 ) && !defined( _PS3 )
  724. RenderTargetStackElement_t element = { {pTexture, NULL, NULL, NULL}, NULL, 0, 0, -1, -1 };
  725. #else
  726. RenderTargetStackElement_t element = { {pTexture}, NULL, 0, 0, -1, -1 };
  727. #endif
  728. m_RenderTargetStack.Push( element );
  729. CommitRenderTargetAndViewport();
  730. }
  731. //-----------------------------------------------------------------------------
  732. // Pushes a render target on the render target stack and sets the viewport
  733. //
  734. // NULL for pTexture indicates rendering to the back buffer
  735. //
  736. // The push and pop methods also implicitly set the render target to the new top of stack
  737. //-----------------------------------------------------------------------------
  738. void CMatRenderContextBase::PushRenderTargetAndViewport( ITexture *pTexture, int nViewX, int nViewY, int nViewW, int nViewH )
  739. {
  740. CMatRenderContextBase::PushRenderTargetAndViewport( pTexture, NULL, nViewX, nViewY, nViewW, nViewH );
  741. }
  742. //-----------------------------------------------------------------------------
  743. // Pushes a render target on the render target stack and sets the viewport
  744. // The push and pop methods also implicitly set the render target to the new top of stack
  745. //-----------------------------------------------------------------------------
  746. void CMatRenderContextBase::PushRenderTargetAndViewport( ITexture *pTexture, ITexture *pDepthTexture, int nViewX, int nViewY, int nViewW, int nViewH )
  747. {
  748. // Just blindly push the data on the stack
  749. #if !defined( _X360 ) && !defined( _PS3 )
  750. RenderTargetStackElement_t element = { {pTexture, NULL, NULL, NULL}, pDepthTexture, nViewX, nViewY, nViewW, nViewH };
  751. #else
  752. RenderTargetStackElement_t element = { {pTexture}, pDepthTexture, nViewX, nViewY, nViewW, nViewH };
  753. #endif
  754. m_RenderTargetStack.Push( element );
  755. CommitRenderTargetAndViewport();
  756. }
  757. //-----------------------------------------------------------------------------
  758. // Pops from the render target stack
  759. // Also implicitly sets the render target to the new top of stack
  760. //-----------------------------------------------------------------------------
  761. void CMatRenderContextBase::PopRenderTargetAndViewport( void )
  762. {
  763. // Check for underflow
  764. if ( m_RenderTargetStack.Count() == 0 )
  765. {
  766. Assert( !"CMatRenderContext::PopRenderTargetAndViewport: Stack is empty!!!" );
  767. return;
  768. }
  769. Flush();
  770. // Remove the top of stack
  771. m_RenderTargetStack.Pop( );
  772. CommitRenderTargetAndViewport();
  773. }
  774. void CMatRenderContextBase::RecomputeViewProjState()
  775. {
  776. if ( m_bDirtyViewProjState )
  777. {
  778. VMatrix viewMatrix, projMatrix;
  779. // FIXME: Should consider caching this upon change for projection or view matrix.
  780. GetMatrix( MATERIAL_VIEW, &viewMatrix );
  781. GetMatrix( MATERIAL_PROJECTION, &projMatrix );
  782. m_viewProjMatrix = projMatrix * viewMatrix;
  783. m_bDirtyViewProjState = false;
  784. }
  785. }
  786. //-----------------------------------------------------------------------------
  787. // This returns the diameter of the sphere in pixels based on
  788. // the current model, view, + projection matrices and viewport.
  789. //-----------------------------------------------------------------------------
  790. float CMatRenderContextBase::ComputePixelDiameterOfSphere( const Vector& vecAbsOrigin, float flRadius )
  791. {
  792. RecomputeViewState();
  793. RecomputeViewProjState();
  794. // This is sort of faked, but it's faster that way
  795. // FIXME: Also, there's a much faster way to do this with similar triangles
  796. // but I want to make sure it exactly matches the current matrices, so
  797. // for now, I do it this conservative way
  798. Vector4D testPoint1, testPoint2;
  799. VectorMA( vecAbsOrigin, flRadius, m_vecViewUp, testPoint1.AsVector3D() );
  800. VectorMA( vecAbsOrigin, -flRadius, m_vecViewUp, testPoint2.AsVector3D() );
  801. testPoint1.w = testPoint2.w = 1.0f;
  802. Vector4D clipPos1, clipPos2;
  803. Vector4DMultiply( m_viewProjMatrix, testPoint1, clipPos1 );
  804. Vector4DMultiply( m_viewProjMatrix, testPoint2, clipPos2 );
  805. if (clipPos1.w >= 0.001f)
  806. {
  807. clipPos1.y /= clipPos1.w;
  808. }
  809. else
  810. {
  811. clipPos1.y *= 1000;
  812. }
  813. if (clipPos2.w >= 0.001f)
  814. {
  815. clipPos2.y /= clipPos2.w;
  816. }
  817. else
  818. {
  819. clipPos2.y *= 1000;
  820. }
  821. int vx, vy, vwidth, vheight;
  822. GetViewport( vx, vy, vwidth, vheight );
  823. // The divide-by-two here is because y goes from -1 to 1 in projection space
  824. return vheight * fabs( clipPos2.y - clipPos1.y ) / 2.0f;
  825. }
  826. Vector CMatRenderContextBase::GetToneMappingScaleLinear( void )
  827. {
  828. if ( HardwareConfig()->GetHDRType() == HDR_TYPE_NONE )
  829. return Vector( 1.0f, 1.0f, 1.0f );
  830. else
  831. return m_LastSetToneMapScale;
  832. }
  833. #undef g_pShaderAPI
  834. #if defined( _PS3 ) || defined( _OSX )
  835. #define g_pShaderAPI ShaderAPI()
  836. #endif
  837. //-----------------------------------------------------------------------------
  838. //
  839. //-----------------------------------------------------------------------------
  840. CMatRenderContext::CMatRenderContext()
  841. {
  842. g_FrameNum = 0;
  843. m_pBatchIndices = NULL;
  844. m_pBatchMesh = NULL;
  845. m_pCurrentIndexBuffer = NULL;
  846. m_pMorphRenderContext = NULL;
  847. m_NonInteractiveMode = MATERIAL_NON_INTERACTIVE_MODE_NONE;
  848. }
  849. InitReturnVal_t CMatRenderContext::Init( CMaterialSystem *pMaterialSystem )
  850. {
  851. InitReturnVal_t nRetVal = BaseClass::Init();
  852. if ( nRetVal != INIT_OK )
  853. return nRetVal;
  854. m_pMaterialSystem = pMaterialSystem;
  855. m_pBoundMorph = NULL;
  856. // Create some lovely textures
  857. m_pLocalCubemapTexture = TextureManager()->ErrorTexture();
  858. m_pMorphRenderContext = g_pMorphMgr->AllocateRenderContext();
  859. return INIT_OK;
  860. }
  861. void CMatRenderContext::Shutdown( )
  862. {
  863. if ( m_pUserDefinedLightmap )
  864. {
  865. m_pUserDefinedLightmap->DecrementReferenceCount();
  866. m_pUserDefinedLightmap = NULL;
  867. }
  868. if ( m_pMorphRenderContext )
  869. {
  870. g_pMorphMgr->FreeRenderContext( m_pMorphRenderContext );
  871. m_pMorphRenderContext = NULL;
  872. }
  873. BaseClass::Shutdown();
  874. }
  875. void CMatRenderContext::OnReleaseShaderObjects()
  876. {
  877. // alt-tab unbinds the morph
  878. m_pBoundMorph = NULL;
  879. }
  880. #if defined( DX_TO_GL_ABSTRACTION ) && !defined( _GAMECONSOLE )
  881. void CMatRenderContext::DoStartupShaderPreloading( void )
  882. {
  883. g_pShaderDevice->DoStartupShaderPreloading();
  884. }
  885. #endif
  886. inline IMaterialInternal *CMatRenderContext::GetMaterialInternal( MaterialHandle_t h ) const
  887. {
  888. return GetMaterialSystem()->GetMaterialInternal( h );
  889. }
  890. inline IMaterialInternal *CMatRenderContext::GetDrawFlatMaterial()
  891. {
  892. return GetMaterialSystem()->GetDrawFlatMaterial();
  893. }
  894. inline IMaterialInternal *CMatRenderContext::GetBufferClearObeyStencil( int i )
  895. {
  896. return GetMaterialSystem()->GetBufferClearObeyStencil( i );
  897. }
  898. inline IMaterialInternal *CMatRenderContext::GetReloadZcullMaterial()
  899. {
  900. return GetMaterialSystem()->GetReloadZcullMaterial();
  901. }
  902. inline ShaderAPITextureHandle_t CMatRenderContext::GetFullbrightLightmapTextureHandle() const
  903. {
  904. return GetMaterialSystem()->GetFullbrightLightmapTextureHandle();
  905. }
  906. inline ShaderAPITextureHandle_t CMatRenderContext::GetFullbrightBumpedLightmapTextureHandle() const
  907. {
  908. return GetMaterialSystem()->GetFullbrightBumpedLightmapTextureHandle();
  909. }
  910. inline ShaderAPITextureHandle_t CMatRenderContext::GetBlackTextureHandle() const
  911. {
  912. return GetMaterialSystem()->GetBlackTextureHandle();
  913. }
  914. inline ShaderAPITextureHandle_t CMatRenderContext::GetBlackAlphaZeroTextureHandle() const
  915. {
  916. return GetMaterialSystem()->GetBlackAlphaZeroTextureHandle();
  917. }
  918. inline ShaderAPITextureHandle_t CMatRenderContext::GetFlatNormalTextureHandle() const
  919. {
  920. return GetMaterialSystem()->GetFlatNormalTextureHandle();
  921. }
  922. inline ShaderAPITextureHandle_t CMatRenderContext::GetFlatSSBumpTextureHandle() const
  923. {
  924. return GetMaterialSystem()->GetFlatSSBumpTextureHandle();
  925. }
  926. inline ShaderAPITextureHandle_t CMatRenderContext::GetGreyTextureHandle() const
  927. {
  928. return GetMaterialSystem()->GetGreyTextureHandle();
  929. }
  930. inline ShaderAPITextureHandle_t CMatRenderContext::GetGreyAlphaZeroTextureHandle() const
  931. {
  932. return GetMaterialSystem()->GetGreyAlphaZeroTextureHandle();
  933. }
  934. inline ShaderAPITextureHandle_t CMatRenderContext::GetWhiteTextureHandle() const
  935. {
  936. return GetMaterialSystem()->GetWhiteTextureHandle();
  937. }
  938. inline const CMatLightmaps *CMatRenderContext::GetLightmaps() const
  939. {
  940. return GetMaterialSystem()->GetLightmaps();
  941. }
  942. inline CMatLightmaps *CMatRenderContext::GetLightmaps()
  943. {
  944. return GetMaterialSystem()->GetLightmaps();
  945. }
  946. inline const CMatPaintmaps *CMatRenderContext::GetPaintmaps() const
  947. {
  948. return GetMaterialSystem()->GetPaintmaps();
  949. }
  950. inline CMatPaintmaps *CMatRenderContext::GetPaintmaps()
  951. {
  952. return GetMaterialSystem()->GetPaintmaps();
  953. }
  954. inline ShaderAPITextureHandle_t CMatRenderContext::GetMaxDepthTextureHandle() const
  955. {
  956. return GetMaterialSystem()->GetMaxDepthTextureHandle();
  957. }
  958. void CMatRenderContext::BeginRender()
  959. {
  960. if ( GetMaterialSystem()->GetThreadMode() != MATERIAL_SINGLE_THREADED )
  961. {
  962. // VPROF_INCREMENT_GROUP_COUNTER( "render/CMatBeginRender", COUNTER_GROUP_TELEMETRY, 1 );
  963. TelemetrySetLockName( TELEMETRY_LEVEL0, (char const *)&g_MatSysMutex, "MatSysMutex" );
  964. tmTryLock( TELEMETRY_LEVEL0, (char const *)&g_MatSysMutex, "BeginRender" );
  965. g_MatSysMutex.Lock();
  966. tmEndTryLock( TELEMETRY_LEVEL0, (char const *)&g_MatSysMutex, TMLR_SUCCESS );
  967. tmSetLockState( TELEMETRY_LEVEL0, (char const *)&g_MatSysMutex, TMLS_LOCKED, "BeginRender" );
  968. }
  969. }
  970. void CMatRenderContext::EndRender()
  971. {
  972. if ( GetMaterialSystem()->GetThreadMode() != MATERIAL_SINGLE_THREADED )
  973. {
  974. g_MatSysMutex.Unlock();
  975. tmSetLockState( TELEMETRY_LEVEL0, (char const *)&g_MatSysMutex, TMLS_RELEASED, "EndRender" );
  976. }
  977. }
  978. void CMatRenderContext::Flush( bool flushHardware )
  979. {
  980. }
  981. bool CMatRenderContext::TestMatrixSync( MaterialMatrixMode_t mode )
  982. {
  983. if ( !ShouldValidateMatrices() )
  984. {
  985. return true;
  986. }
  987. VMatrix transposeMatrix, matrix;
  988. g_pShaderAPI->GetMatrix( mode, (float*)transposeMatrix.m );
  989. MatrixTranspose( transposeMatrix, matrix );
  990. ValidateMatrices( matrix, m_MatrixStacks[mode].Top().matrix );
  991. return true;
  992. }
  993. void CMatRenderContext::MatrixMode( MaterialMatrixMode_t mode )
  994. {
  995. CMatRenderContextBase::MatrixMode( mode );
  996. g_pShaderAPI->MatrixMode( mode );
  997. if ( ShouldValidateMatrices() )
  998. {
  999. TestMatrixSync( mode );
  1000. }
  1001. }
  1002. void CMatRenderContext::PushMatrix()
  1003. {
  1004. if ( ShouldValidateMatrices() )
  1005. {
  1006. TestMatrixSync( m_MatrixMode );
  1007. }
  1008. CMatRenderContextBase::PushMatrix();
  1009. g_pShaderAPI->PushMatrix();
  1010. if ( ShouldValidateMatrices() )
  1011. {
  1012. TestMatrixSync( m_MatrixMode );
  1013. }
  1014. }
  1015. void CMatRenderContext::PopMatrix()
  1016. {
  1017. if ( ShouldValidateMatrices() )
  1018. {
  1019. TestMatrixSync( m_MatrixMode );
  1020. }
  1021. CMatRenderContextBase::PopMatrix();
  1022. g_pShaderAPI->PopMatrix();
  1023. if ( ShouldValidateMatrices() )
  1024. {
  1025. TestMatrixSync( m_MatrixMode );
  1026. }
  1027. }
  1028. void CMatRenderContext::LoadMatrix( const VMatrix& matrix )
  1029. {
  1030. CMatRenderContextBase::LoadMatrix( matrix );
  1031. ForceSync();
  1032. if ( ShouldValidateMatrices() )
  1033. {
  1034. VMatrix transposeMatrix;
  1035. MatrixTranspose( matrix, transposeMatrix );
  1036. g_pShaderAPI->LoadMatrix( transposeMatrix.Base() );
  1037. TestMatrixSync( m_MatrixMode );
  1038. }
  1039. }
  1040. void CMatRenderContext::LoadMatrix( const matrix3x4_t& matrix )
  1041. {
  1042. CMatRenderContextBase::LoadMatrix( matrix );
  1043. ForceSync();
  1044. if ( ShouldValidateMatrices() )
  1045. {
  1046. VMatrix transposeMatrix;
  1047. MatrixTranspose( VMatrix(matrix), transposeMatrix );
  1048. g_pShaderAPI->LoadMatrix( transposeMatrix.Base() );
  1049. TestMatrixSync( m_MatrixMode );
  1050. }
  1051. }
  1052. void CMatRenderContext::MultMatrix( const VMatrix& matrix )
  1053. {
  1054. CMatRenderContextBase::MultMatrix( matrix );
  1055. ForceSync();
  1056. if ( ShouldValidateMatrices() )
  1057. {
  1058. VMatrix transposeMatrix;
  1059. MatrixTranspose( matrix, transposeMatrix );
  1060. g_pShaderAPI->MultMatrix( transposeMatrix.Base() );
  1061. TestMatrixSync( m_MatrixMode );
  1062. }
  1063. }
  1064. void CMatRenderContext::MultMatrix( const matrix3x4_t& matrix )
  1065. {
  1066. CMatRenderContextBase::MultMatrix( VMatrix( matrix ) );
  1067. ForceSync();
  1068. if ( ShouldValidateMatrices() )
  1069. {
  1070. VMatrix transposeMatrix;
  1071. MatrixTranspose( VMatrix(matrix), transposeMatrix );
  1072. g_pShaderAPI->MultMatrix( transposeMatrix.Base() );
  1073. TestMatrixSync( m_MatrixMode );
  1074. }
  1075. }
  1076. void CMatRenderContext::MultMatrixLocal( const VMatrix& matrix )
  1077. {
  1078. CMatRenderContextBase::MultMatrixLocal( matrix );
  1079. ForceSync();
  1080. if ( ShouldValidateMatrices() )
  1081. {
  1082. VMatrix transposeMatrix;
  1083. MatrixTranspose( matrix, transposeMatrix );
  1084. g_pShaderAPI->MultMatrixLocal( transposeMatrix.Base() );
  1085. TestMatrixSync( m_MatrixMode );
  1086. }
  1087. }
  1088. void CMatRenderContext::MultMatrixLocal( const matrix3x4_t& matrix )
  1089. {
  1090. CMatRenderContextBase::MultMatrixLocal( VMatrix( matrix ) );
  1091. ForceSync();
  1092. if ( ShouldValidateMatrices() )
  1093. {
  1094. VMatrix transposeMatrix;
  1095. MatrixTranspose( VMatrix(matrix), transposeMatrix );
  1096. g_pShaderAPI->MultMatrixLocal( transposeMatrix.Base() );
  1097. TestMatrixSync( m_MatrixMode );
  1098. }
  1099. }
  1100. void CMatRenderContext::LoadIdentity()
  1101. {
  1102. CMatRenderContextBase::LoadIdentity();
  1103. ForceSync();
  1104. if ( ShouldValidateMatrices() )
  1105. {
  1106. g_pShaderAPI->LoadIdentity();
  1107. TestMatrixSync( m_MatrixMode );
  1108. }
  1109. }
  1110. void CMatRenderContext::Ortho( double left, double top, double right, double bottom, double zNear, double zFar )
  1111. {
  1112. CMatRenderContextBase::Ortho( left, top, right, bottom, zNear, zFar );
  1113. ForceSync();
  1114. if ( ShouldValidateMatrices() )
  1115. {
  1116. g_pShaderAPI->Ortho( left, top, right, bottom, zNear, zFar );
  1117. TestMatrixSync( m_MatrixMode );
  1118. }
  1119. }
  1120. void CMatRenderContext::PerspectiveX( double flFovX, double flAspect, double flZNear, double flZFar )
  1121. {
  1122. CMatRenderContextBase::PerspectiveX( flFovX, flAspect, flZNear, flZFar );
  1123. ForceSync();
  1124. if ( ShouldValidateMatrices() )
  1125. {
  1126. g_pShaderAPI->PerspectiveX( flFovX, flAspect, flZNear, flZFar );
  1127. TestMatrixSync( m_MatrixMode );
  1128. }
  1129. }
  1130. void CMatRenderContext::PerspectiveOffCenterX( double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right )
  1131. {
  1132. CMatRenderContextBase::PerspectiveOffCenterX( flFovX, flAspect, flZNear, flZFar, bottom, top, left, right );
  1133. ForceSync();
  1134. if ( ShouldValidateMatrices() )
  1135. {
  1136. g_pShaderAPI->PerspectiveOffCenterX( flFovX, flAspect, flZNear, flZFar, bottom, top, left, right );
  1137. TestMatrixSync( m_MatrixMode );
  1138. }
  1139. }
  1140. void CMatRenderContext::PickMatrix( int x, int y, int nWidth, int nHeight )
  1141. {
  1142. CMatRenderContextBase::PickMatrix( x, y, nWidth, nHeight );
  1143. ForceSync();
  1144. if ( ShouldValidateMatrices() )
  1145. {
  1146. g_pShaderAPI->PickMatrix( x, y, nWidth, nHeight );
  1147. TestMatrixSync( m_MatrixMode );
  1148. }
  1149. }
  1150. void CMatRenderContext::Rotate( float flAngle, float x, float y, float z )
  1151. {
  1152. CMatRenderContextBase::Rotate( flAngle, x, y, z );
  1153. ForceSync();
  1154. if ( ShouldValidateMatrices() )
  1155. {
  1156. g_pShaderAPI->Rotate( flAngle, x, y, z );
  1157. TestMatrixSync( m_MatrixMode );
  1158. }
  1159. }
  1160. void CMatRenderContext::Translate( float x, float y, float z )
  1161. {
  1162. CMatRenderContextBase::Translate( x, y, z );
  1163. ForceSync();
  1164. if ( ShouldValidateMatrices() )
  1165. {
  1166. g_pShaderAPI->Translate( x, y, z );
  1167. TestMatrixSync( m_MatrixMode );
  1168. }
  1169. }
  1170. void CMatRenderContext::Scale( float x, float y, float z )
  1171. {
  1172. CMatRenderContextBase::Scale( x, y, z );
  1173. ForceSync();
  1174. if ( ShouldValidateMatrices() )
  1175. {
  1176. g_pShaderAPI->Scale( x, y, z );
  1177. TestMatrixSync( m_MatrixMode );
  1178. }
  1179. }
  1180. void CMatRenderContext::GetMatrix( MaterialMatrixMode_t matrixMode, VMatrix *pMatrix )
  1181. {
  1182. CMatRenderContextBase::GetMatrix( matrixMode, pMatrix );
  1183. ForceSync();
  1184. if ( ShouldValidateMatrices() )
  1185. {
  1186. VMatrix testMatrix;
  1187. VMatrix transposeMatrix;
  1188. g_pShaderAPI->GetMatrix( matrixMode, (float*)transposeMatrix.m );
  1189. MatrixTranspose( transposeMatrix, testMatrix );
  1190. ValidateMatrices( testMatrix, *pMatrix );
  1191. }
  1192. }
  1193. void CMatRenderContext::GetMatrix( MaterialMatrixMode_t matrixMode, matrix3x4_t *pMatrix )
  1194. {
  1195. if ( !ShouldValidateMatrices() )
  1196. {
  1197. CMatRenderContextBase::GetMatrix( matrixMode, pMatrix );
  1198. }
  1199. else
  1200. {
  1201. VMatrix matrix;
  1202. CMatRenderContext::GetMatrix( matrixMode, &matrix );
  1203. *pMatrix = matrix.As3x4();
  1204. }
  1205. }
  1206. void CMatRenderContext::SyncMatrices()
  1207. {
  1208. if ( !ShouldValidateMatrices() && AllowLazyMatrixSync() )
  1209. {
  1210. for( int i = 0; i < NUM_MATRIX_MODES; i++ )
  1211. {
  1212. MatrixStackItem_t &top = m_MatrixStacks[i].Top();
  1213. if ( top.flags & MSF_DIRTY )
  1214. {
  1215. g_pShaderAPI->MatrixMode( (MaterialMatrixMode_t)i );
  1216. if ( !( top.flags & MSF_IDENTITY ) )
  1217. {
  1218. VMatrix transposeTop;
  1219. MatrixTranspose( top.matrix, transposeTop );
  1220. g_pShaderAPI->LoadMatrix( transposeTop.Base() );
  1221. }
  1222. else
  1223. {
  1224. g_pShaderAPI->LoadIdentity();
  1225. }
  1226. top.flags &= ~MSF_DIRTY;
  1227. }
  1228. }
  1229. }
  1230. }
  1231. void CMatRenderContext::ForceSyncMatrix( MaterialMatrixMode_t mode )
  1232. {
  1233. MatrixStackItem_t &top = m_MatrixStacks[mode].Top();
  1234. if ( top.flags & MSF_DIRTY )
  1235. {
  1236. bool bSetMode = ( m_MatrixMode != mode );
  1237. if ( bSetMode )
  1238. {
  1239. g_pShaderAPI->MatrixMode( (MaterialMatrixMode_t)mode );
  1240. }
  1241. if ( !( top.flags & MSF_IDENTITY ) )
  1242. {
  1243. VMatrix transposeTop;
  1244. MatrixTranspose( top.matrix, transposeTop );
  1245. g_pShaderAPI->LoadMatrix( transposeTop.Base() );
  1246. }
  1247. else
  1248. {
  1249. g_pShaderAPI->LoadIdentity();
  1250. }
  1251. if ( bSetMode )
  1252. {
  1253. g_pShaderAPI->MatrixMode( (MaterialMatrixMode_t)mode );
  1254. }
  1255. top.flags &= ~MSF_DIRTY;
  1256. }
  1257. }
  1258. void CMatRenderContext::SyncMatrix( MaterialMatrixMode_t mode )
  1259. {
  1260. if ( !ShouldValidateMatrices() && AllowLazyMatrixSync() )
  1261. {
  1262. ForceSyncMatrix( mode );
  1263. }
  1264. }
  1265. ShaderAPITextureHandle_t CMatRenderContext::GetLightmapTexture( int nLightmapPage )
  1266. {
  1267. switch ( nLightmapPage )
  1268. {
  1269. default:
  1270. Assert( ( nLightmapPage == 0 && GetLightmaps()->GetNumLightmapPages() == 0 ) || ( nLightmapPage >= 0 && nLightmapPage < GetLightmaps()->GetNumLightmapPages() ) );
  1271. if( nLightmapPage >= 0 && nLightmapPage < GetLightmaps()->GetNumLightmapPages() )
  1272. return GetLightmaps()->GetLightmapPageTextureHandle( nLightmapPage );
  1273. return INVALID_SHADERAPI_TEXTURE_HANDLE;
  1274. case MATERIAL_SYSTEM_LIGHTMAP_PAGE_USER_DEFINED:
  1275. AssertOnce( m_pUserDefinedLightmap );
  1276. return m_pUserDefinedLightmap->GetTextureHandle( 0 );
  1277. case MATERIAL_SYSTEM_LIGHTMAP_PAGE_WHITE:
  1278. return GetFullbrightLightmapTextureHandle();
  1279. case MATERIAL_SYSTEM_LIGHTMAP_PAGE_WHITE_BUMP:
  1280. return GetFullbrightBumpedLightmapTextureHandle();
  1281. case MATERIAL_SYSTEM_LIGHTMAP_PAGE_INVALID:
  1282. return INVALID_SHADERAPI_TEXTURE_HANDLE;
  1283. }
  1284. }
  1285. //-----------------------------------------------------------------------------
  1286. // Swap buffers
  1287. //-----------------------------------------------------------------------------
  1288. extern void OnFrameTimestampAvailableMST(float);
  1289. extern void OnGpuStartFrame(uint32 context);
  1290. extern void OnGpuEndFrame(uint32 context);
  1291. void CMatRenderContext::SwapBuffers()
  1292. {
  1293. g_pMorphMgr->AdvanceFrame();
  1294. g_pOcclusionQueryMgr->AdvanceFrame();
  1295. #if X360_ALLOW_TIMESTAMPS
  1296. OnFrameTimestampAvailableMST(1.0f);
  1297. IDirect3DDevice9* pDevice = ( IDirect3DDevice9* ) g_pMaterialSystem->GetD3DDevice();
  1298. pDevice->InsertCallback(D3DCALLBACK_IMMEDIATE, (D3DCALLBACK)OnGpuEndFrame, 0 );
  1299. #endif
  1300. #ifdef GCM_ALLOW_TIMESTAMPS
  1301. OnFrameTimestampAvailableMST(1.0f);
  1302. #endif
  1303. g_pShaderDevice->Present();
  1304. #if X360_ALLOW_TIMESTAMPS
  1305. pDevice->InsertCallback(D3DCALLBACK_IMMEDIATE, (D3DCALLBACK)OnGpuStartFrame, 0 );
  1306. #endif
  1307. #ifdef _X360
  1308. if ( s_bDirtyDisk )
  1309. {
  1310. SpinPresent();
  1311. }
  1312. #endif
  1313. }
  1314. //-----------------------------------------------------------------------------
  1315. // Clears the render data after we're done with it
  1316. //-----------------------------------------------------------------------------
  1317. void CMatRenderContext::OnRenderDataUnreferenced()
  1318. {
  1319. MarkRenderDataUnused( false );
  1320. }
  1321. //-----------------------------------------------------------------------------
  1322. // Custom clip planes
  1323. //-----------------------------------------------------------------------------
  1324. void CMatRenderContext::PushCustomClipPlane( const float *pPlane )
  1325. {
  1326. PlaneStackElement psePlane;
  1327. memcpy( psePlane.fValues, pPlane, sizeof( float ) * 4 );
  1328. psePlane.bHack_IsHeightClipPlane = false;
  1329. m_CustomClipPlanes.AddToTail( psePlane ); //we're doing this as a UtlVector so height clip planes never change their cached index
  1330. ApplyCustomClipPlanes();
  1331. }
  1332. void CMatRenderContext::PopCustomClipPlane( void )
  1333. {
  1334. Assert( m_CustomClipPlanes.Count() );
  1335. //remove the endmost non-height plane found
  1336. int i;
  1337. for( i = m_CustomClipPlanes.Count(); --i >= 0; )
  1338. {
  1339. if( m_CustomClipPlanes[i].bHack_IsHeightClipPlane == false )
  1340. {
  1341. m_CustomClipPlanes.Remove(i);
  1342. break;
  1343. }
  1344. }
  1345. Assert( i != -1 ); //only the height clip plane was found, which means this pop had no associated push
  1346. ApplyCustomClipPlanes();
  1347. }
  1348. void CMatRenderContext::ApplyCustomClipPlanes( void )
  1349. {
  1350. int iMaxClipPlanes = HardwareConfig()->MaxUserClipPlanes();
  1351. int iCustomPlanes;
  1352. if( m_bEnableClipping )
  1353. iCustomPlanes = m_CustomClipPlanes.Count();
  1354. else
  1355. iCustomPlanes = 0;
  1356. float fFakePlane[4];
  1357. unsigned int iFakePlaneVal = 0xFFFFFFFF;
  1358. fFakePlane[0] = fFakePlane[1] = fFakePlane[2] = fFakePlane[3] = *((float *)&iFakePlaneVal);
  1359. SyncMatrices();
  1360. if( iMaxClipPlanes >= 1 && !HardwareConfig()->UseFastClipping() )
  1361. {
  1362. //yay, we get to be the cool clipping club
  1363. if( iMaxClipPlanes >= iCustomPlanes )
  1364. {
  1365. int i;
  1366. for( i = 0; i < iCustomPlanes; ++i )
  1367. {
  1368. g_pShaderAPI->SetClipPlane( i, m_CustomClipPlanes[i].fValues );
  1369. g_pShaderAPI->EnableClipPlane( i, true );
  1370. }
  1371. for( ; i < iMaxClipPlanes; ++i ) //disable unused planes
  1372. {
  1373. g_pShaderAPI->EnableClipPlane( i, false );
  1374. g_pShaderAPI->SetClipPlane( i, fFakePlane );
  1375. }
  1376. }
  1377. else
  1378. {
  1379. int iCustomPlaneOffset = iCustomPlanes - iMaxClipPlanes;
  1380. //can't enable them all
  1381. for( int i = iCustomPlaneOffset; i < iCustomPlanes; ++i )
  1382. {
  1383. g_pShaderAPI->SetClipPlane( i % iMaxClipPlanes, m_CustomClipPlanes[i].fValues );
  1384. g_pShaderAPI->EnableClipPlane( i % iMaxClipPlanes, true );
  1385. }
  1386. }
  1387. }
  1388. else
  1389. {
  1390. //hmm, at most we can make 1 clip plane work
  1391. if( iCustomPlanes == 0 )
  1392. {
  1393. //no planes at all
  1394. g_pShaderAPI->EnableFastClip( false );
  1395. g_pShaderAPI->SetFastClipPlane( fFakePlane );
  1396. }
  1397. else
  1398. {
  1399. //we have to wire the topmost plane into the fast clipping scheme
  1400. g_pShaderAPI->EnableFastClip( true );
  1401. g_pShaderAPI->SetFastClipPlane( m_CustomClipPlanes[iCustomPlanes - 1].fValues );
  1402. }
  1403. }
  1404. }
  1405. //-----------------------------------------------------------------------------
  1406. // Creates/destroys morph data associated w/ a particular material
  1407. //-----------------------------------------------------------------------------
  1408. IMorph *CMatRenderContext::CreateMorph( MorphFormat_t format, const char *pDebugName )
  1409. {
  1410. Assert( format != 0 );
  1411. IMorphInternal *pMorph = g_pMorphMgr->CreateMorph( );
  1412. pMorph->Init( format, pDebugName );
  1413. return pMorph;
  1414. }
  1415. void CMatRenderContext::DestroyMorph( IMorph *pMorph )
  1416. {
  1417. g_pMorphMgr->DestroyMorph( static_cast<IMorphInternal*>(pMorph) );
  1418. }
  1419. void CMatRenderContext::BindMorph( IMorph *pMorph )
  1420. {
  1421. IMorphInternal *pMorphInternal = static_cast<IMorphInternal*>(pMorph);
  1422. if ( m_pBoundMorph != pMorphInternal )
  1423. {
  1424. m_pBoundMorph = pMorphInternal;
  1425. bool bEnableHWMorph = false;
  1426. if ( pMorphInternal == MATERIAL_MORPH_DECAL )
  1427. {
  1428. bEnableHWMorph = true;
  1429. }
  1430. else if ( pMorphInternal )
  1431. {
  1432. bEnableHWMorph = pMorphInternal->Bind( m_pMorphRenderContext );
  1433. }
  1434. g_pShaderAPI->EnableHWMorphing( bEnableHWMorph );
  1435. }
  1436. }
  1437. IMesh* CMatRenderContext::GetDynamicMesh( bool buffered, IMesh* pVertexOverride, IMesh* pIndexOverride, IMaterial *pAutoBind )
  1438. {
  1439. VPROF_ASSERT_ACCOUNTED( "CMatRenderContext::GetDynamicMesh" );
  1440. if( pAutoBind )
  1441. {
  1442. Bind( pAutoBind, NULL );
  1443. }
  1444. if ( pVertexOverride )
  1445. {
  1446. if ( CompressionType( pVertexOverride->GetVertexFormat() ) != VERTEX_COMPRESSION_NONE )
  1447. {
  1448. // UNDONE: support compressed dynamic meshes if needed (pro: less VB memory, con: time spent compressing)
  1449. DebuggerBreak();
  1450. return NULL;
  1451. }
  1452. }
  1453. // For anything more than 1 bone, imply the last weight from the 1 - the sum of the others.
  1454. int nCurrentBoneCount = GetCurrentNumBones();
  1455. Assert( nCurrentBoneCount <= 4 );
  1456. if ( nCurrentBoneCount > 1 )
  1457. {
  1458. --nCurrentBoneCount;
  1459. }
  1460. return g_pShaderAPI->GetDynamicMesh( GetCurrentMaterialInternal(), nCurrentBoneCount,
  1461. buffered, pVertexOverride, pIndexOverride);
  1462. }
  1463. IMesh* CMatRenderContext::GetDynamicMeshEx( VertexFormat_t vertexFormat, bool bBuffered, IMesh* pVertexOverride, IMesh* pIndexOverride, IMaterial *pAutoBind )
  1464. {
  1465. VPROF_ASSERT_ACCOUNTED( "CMatRenderContext::GetDynamicMesh" );
  1466. if( pAutoBind )
  1467. {
  1468. Bind( pAutoBind, NULL );
  1469. }
  1470. if ( pVertexOverride )
  1471. {
  1472. if ( CompressionType( pVertexOverride->GetVertexFormat() ) != VERTEX_COMPRESSION_NONE )
  1473. {
  1474. // UNDONE: support compressed dynamic meshes if needed (pro: less VB memory, con: time spent compressing)
  1475. DebuggerBreak();
  1476. return NULL;
  1477. }
  1478. }
  1479. // For anything more than 1 bone, imply the last weight from the 1 - the sum of the others.
  1480. // FIXME: this seems wrong - in common_vs_fxc.h, we only infer the last weight if we have 3 (not 2)
  1481. int nCurrentBoneCount = GetCurrentNumBones();
  1482. Assert( nCurrentBoneCount <= 4 );
  1483. if ( nCurrentBoneCount > 1 )
  1484. {
  1485. --nCurrentBoneCount;
  1486. }
  1487. return g_pShaderAPI->GetDynamicMeshEx( GetCurrentMaterialInternal(), vertexFormat, nCurrentBoneCount,
  1488. bBuffered, pVertexOverride, pIndexOverride );
  1489. }
  1490. //-----------------------------------------------------------------------------
  1491. // Deals with depth range
  1492. //-----------------------------------------------------------------------------
  1493. void CMatRenderContext::DepthRange( float zNear, float zFar )
  1494. {
  1495. m_Viewport.m_flMinZ = zNear;
  1496. m_Viewport.m_flMaxZ = zFar;
  1497. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  1498. }
  1499. //-----------------------------------------------------------------------------
  1500. // Private utility function to actually commit the top of the RT/Viewport stack
  1501. // to the device. Only called by the push and pop routines above.
  1502. //-----------------------------------------------------------------------------
  1503. void CMatRenderContext::CommitRenderTargetAndViewport( void )
  1504. {
  1505. Assert( m_RenderTargetStack.Count() > 0 );
  1506. const RenderTargetStackElement_t &element = m_RenderTargetStack.Top( );
  1507. for( int rt=0; rt<NELEMS(element.m_pRenderTargets); rt++ )
  1508. {
  1509. // If we're dealing with the back buffer
  1510. if ( element.m_pRenderTargets[rt] == NULL )
  1511. {
  1512. g_pShaderAPI->SetRenderTargetEx(rt); // No texture parameter here indicates back buffer
  1513. if (rt == 0) // the first rt sets the viewport
  1514. {
  1515. if (IsPC() || IsPS3())
  1516. {
  1517. Assert(ImageLoader::SizeInBytes(g_pShaderDevice->GetBackBufferFormat()) <= 4);
  1518. g_pShaderAPI->EnableLinearColorSpaceFrameBuffer(false);
  1519. }
  1520. // If either dimension is negative, set to full bounds of back buffer
  1521. if ( (element.m_nViewW < 0) || (element.m_nViewH < 0) )
  1522. {
  1523. m_Viewport.m_nTopLeftX = 0;
  1524. m_Viewport.m_nTopLeftY = 0;
  1525. g_pShaderAPI->GetBackBufferDimensions( m_Viewport.m_nWidth, m_Viewport.m_nHeight );
  1526. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  1527. }
  1528. else // use the bounds in the element
  1529. {
  1530. m_Viewport.m_nTopLeftX = element.m_nViewX;
  1531. m_Viewport.m_nTopLeftY = element.m_nViewY;
  1532. m_Viewport.m_nWidth = element.m_nViewW;
  1533. m_Viewport.m_nHeight = element.m_nViewH;
  1534. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  1535. }
  1536. }
  1537. }
  1538. else // We're dealing with a texture
  1539. {
  1540. ITextureInternal *pTexInt = static_cast<ITextureInternal*>(element.m_pRenderTargets[rt]);
  1541. pTexInt->SetRenderTarget( rt, element.m_pDepthTexture );
  1542. if (rt == 0)
  1543. {
  1544. if ( IsPC() || IsPS3() )
  1545. {
  1546. if( ( element.m_pRenderTargets[rt]->GetImageFormat() == IMAGE_FORMAT_RGBA16161616F ) ||
  1547. ( element.m_pRenderTargets[rt]->GetImageFormat() == IMAGE_FORMAT_RGBA32323232F ) ||
  1548. ( element.m_pRenderTargets[rt]->GetImageFormat() == IMAGE_FORMAT_R32F ) )
  1549. {
  1550. g_pShaderAPI->EnableLinearColorSpaceFrameBuffer( true );
  1551. }
  1552. else
  1553. {
  1554. g_pShaderAPI->EnableLinearColorSpaceFrameBuffer( false );
  1555. }
  1556. }
  1557. // If either dimension is negative, set to full bounds of target
  1558. if ( (element.m_nViewW < 0) || (element.m_nViewH < 0) )
  1559. {
  1560. m_Viewport.m_nTopLeftX = 0;
  1561. m_Viewport.m_nTopLeftY = 0;
  1562. m_Viewport.m_nWidth = element.m_pRenderTargets[rt]->GetActualWidth();
  1563. m_Viewport.m_nHeight = element.m_pRenderTargets[rt]->GetActualHeight();
  1564. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  1565. }
  1566. else // use the bounds passed in
  1567. {
  1568. m_Viewport.m_nTopLeftX = element.m_nViewX;
  1569. m_Viewport.m_nTopLeftY = element.m_nViewY;
  1570. m_Viewport.m_nWidth = element.m_nViewW;
  1571. m_Viewport.m_nHeight = element.m_nViewH;
  1572. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  1573. }
  1574. }
  1575. }
  1576. }
  1577. }
  1578. void CMatRenderContext::SetFrameBufferCopyTexture( ITexture *pTexture, int textureIndex )
  1579. {
  1580. if( textureIndex < 0 || textureIndex > MAX_FB_TEXTURES )
  1581. {
  1582. Assert( 0 );
  1583. return;
  1584. }
  1585. // FIXME: Do I need to increment/decrement ref counts here, or assume that the app is going to do it?
  1586. m_pCurrentFrameBufferCopyTexture[textureIndex] = pTexture;
  1587. }
  1588. void CMatRenderContext::BindLocalCubemap( ITexture *pTexture )
  1589. {
  1590. CMatRenderContextBase::BindLocalCubemap( pTexture );
  1591. if ( g_pShaderDevice->IsUsingGraphics() )
  1592. {
  1593. if( pTexture )
  1594. {
  1595. ITextureInternal *pTextureInternal = static_cast<ITextureInternal*>( pTexture );
  1596. g_pShaderAPI->SetStandardTextureHandle( TEXTURE_LOCAL_ENV_CUBEMAP, pTextureInternal->GetTextureHandle( 0 ) );
  1597. }
  1598. else
  1599. {
  1600. g_pShaderAPI->SetStandardTextureHandle( TEXTURE_LOCAL_ENV_CUBEMAP, INVALID_SHADERAPI_TEXTURE_HANDLE );
  1601. }
  1602. }
  1603. }
  1604. void CMatRenderContext::SetNonInteractiveLogoTexture( ITexture *pTexture, float flNormalizedX, float flNormalizedY, float flNormalizedW, float flNormalizedH )
  1605. {
  1606. m_pNonInteractiveLogo.Init( pTexture );
  1607. m_flLogoNormalizedX = flNormalizedX;
  1608. m_flLogoNormalizedY = flNormalizedY;
  1609. m_flLogoNormalizedW = flNormalizedW;
  1610. m_flLogoNormalizedH = flNormalizedH;
  1611. }
  1612. void CMatRenderContext::SetNonInteractivePacifierTexture( ITexture *pTexture, float flNormalizedX, float flNormalizedY, float flNormalizedSize )
  1613. {
  1614. m_pNonInteractivePacifier.Init( pTexture );
  1615. m_flNormalizedX = flNormalizedX;
  1616. m_flNormalizedY = flNormalizedY;
  1617. m_flNormalizedSize = flNormalizedSize;
  1618. }
  1619. void CMatRenderContext::SetNonInteractiveTempFullscreenBuffer( ITexture *pTexture, MaterialNonInteractiveMode_t mode )
  1620. {
  1621. if ( mode != MATERIAL_NON_INTERACTIVE_MODE_NONE )
  1622. {
  1623. m_pNonInteractiveTempFullscreenBuffer[mode].Init( pTexture );
  1624. }
  1625. }
  1626. void CMatRenderContext::RefreshFrontBufferNonInteractive()
  1627. {
  1628. g_pShaderDevice->RefreshFrontBufferNonInteractive();
  1629. #ifdef _X360
  1630. if ( s_bDirtyDisk )
  1631. {
  1632. if ( m_NonInteractiveMode == MATERIAL_NON_INTERACTIVE_MODE_NONE )
  1633. {
  1634. SpinPresent();
  1635. }
  1636. else
  1637. {
  1638. while ( true )
  1639. {
  1640. g_pShaderDevice->RefreshFrontBufferNonInteractive();
  1641. }
  1642. }
  1643. }
  1644. #endif
  1645. }
  1646. void CMatRenderContext::EnableNonInteractiveMode( MaterialNonInteractiveMode_t mode )
  1647. {
  1648. m_NonInteractiveMode = mode;
  1649. if ( mode == MATERIAL_NON_INTERACTIVE_MODE_NONE )
  1650. {
  1651. g_pShaderDevice->EnableNonInteractiveMode( mode );
  1652. }
  1653. else
  1654. {
  1655. ShaderNonInteractiveInfo_t info;
  1656. // background
  1657. ITextureInternal *pTexInternal = static_cast<ITextureInternal*>( (ITexture*)m_pNonInteractiveTempFullscreenBuffer[mode] );
  1658. info.m_hTempFullscreenTexture = pTexInternal ? pTexInternal->GetTextureHandle(0) : INVALID_SHADERAPI_TEXTURE_HANDLE;
  1659. // logo
  1660. info.m_flLogoNormalizedX = m_flLogoNormalizedX;
  1661. info.m_flLogoNormalizedY = m_flLogoNormalizedY;
  1662. info.m_flLogoNormalizedW = m_flLogoNormalizedW;
  1663. info.m_flLogoNormalizedH = m_flLogoNormalizedH;
  1664. ITextureInternal *pTexLogoInternal = static_cast<ITextureInternal*>( (ITexture*)m_pNonInteractiveLogo );
  1665. info.m_hLogoTexture = pTexLogoInternal ? pTexLogoInternal->GetTextureHandle(0) : INVALID_SHADERAPI_TEXTURE_HANDLE;
  1666. // pacifier
  1667. info.m_flNormalizedX = m_flNormalizedX;
  1668. info.m_flNormalizedY = m_flNormalizedY;
  1669. info.m_flNormalizedSize = m_flNormalizedSize;
  1670. ITextureInternal *pTexPacifierInternal = static_cast<ITextureInternal*>( (ITexture*)m_pNonInteractivePacifier );
  1671. info.m_nPacifierCount = pTexPacifierInternal ? pTexPacifierInternal->GetNumAnimationFrames() : 0;
  1672. for ( int i = 0; i < info.m_nPacifierCount; ++i )
  1673. {
  1674. info.m_pPacifierTextures[i] = pTexPacifierInternal->GetTextureHandle( i );
  1675. }
  1676. g_pShaderDevice->EnableNonInteractiveMode( mode, &info );
  1677. }
  1678. }
  1679. void CMatRenderContext::SetRenderTargetEx( int nRenderTargetID, ITexture *pNewTarget )
  1680. {
  1681. // Verify valid top of RT stack
  1682. Assert ( m_RenderTargetStack.Count() > 0 );
  1683. // Grab the old target
  1684. ITexture *pOldTarget = m_RenderTargetStack.Top().m_pRenderTargets[nRenderTargetID];
  1685. CMatRenderContextBase::SetRenderTargetEx( nRenderTargetID, pNewTarget );
  1686. // If we're actually changing render targets
  1687. if( pNewTarget != pOldTarget )
  1688. {
  1689. // If we're going to render to the back buffer
  1690. if ( pNewTarget == NULL )
  1691. {
  1692. if ( nRenderTargetID == 0) // reset viewport on set of rt 0
  1693. {
  1694. m_Viewport.m_nTopLeftX = 0;
  1695. m_Viewport.m_nTopLeftY = 0;
  1696. g_pShaderAPI->GetBackBufferDimensions( m_Viewport.m_nWidth, m_Viewport.m_nHeight );
  1697. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  1698. }
  1699. g_pShaderAPI->SetRenderTargetEx( nRenderTargetID ); // No parameter here indicates back buffer
  1700. }
  1701. else
  1702. {
  1703. // If we're going to render to a texture
  1704. // Make sure the texture is a render target...
  1705. bool reset = true;
  1706. if ( nRenderTargetID == 0 )
  1707. {
  1708. // reset vp on change of rt#0
  1709. m_Viewport.m_nTopLeftX = 0;
  1710. m_Viewport.m_nTopLeftY = 0;
  1711. m_Viewport.m_nWidth = pNewTarget->GetActualWidth();
  1712. m_Viewport.m_nHeight = pNewTarget->GetActualHeight();
  1713. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  1714. }
  1715. ITextureInternal *pTexInt = static_cast<ITextureInternal*>(pNewTarget);
  1716. if ( pTexInt )
  1717. {
  1718. reset = !pTexInt->SetRenderTarget( nRenderTargetID );
  1719. if ( reset )
  1720. {
  1721. g_pShaderAPI->SetRenderTargetEx( nRenderTargetID );
  1722. }
  1723. }
  1724. if ( pNewTarget && ( ( pNewTarget->GetImageFormat() == IMAGE_FORMAT_RGBA16161616F ) ||
  1725. ( pNewTarget->GetImageFormat() == IMAGE_FORMAT_RGBA32323232F ) ) ||
  1726. ( pNewTarget->GetImageFormat() == IMAGE_FORMAT_R32F ) )
  1727. {
  1728. g_pShaderAPI->EnableLinearColorSpaceFrameBuffer( true );
  1729. }
  1730. else
  1731. {
  1732. g_pShaderAPI->EnableLinearColorSpaceFrameBuffer( false );
  1733. }
  1734. }
  1735. }
  1736. CommitRenderTargetAndViewport();
  1737. }
  1738. void CMatRenderContext::GetRenderTargetDimensions( int &width, int &height ) const
  1739. {
  1740. // Target at top of stack
  1741. ITexture *pTOS = m_RenderTargetStack.Top().m_pRenderTargets[0];
  1742. // If top of stack isn't the back buffer, get dimensions from the texture
  1743. if ( pTOS != NULL )
  1744. {
  1745. width = pTOS->GetActualWidth();
  1746. height = pTOS->GetActualHeight();
  1747. }
  1748. else // otherwise, get them from the shader API
  1749. {
  1750. g_pShaderAPI->GetBackBufferDimensions( width, height );
  1751. }
  1752. }
  1753. //-----------------------------------------------------------------------------
  1754. // What are the lightmap dimensions?
  1755. //-----------------------------------------------------------------------------
  1756. void CMatRenderContext::GetLightmapDimensions( int *w, int *h )
  1757. {
  1758. *w = GetMaterialSystem()->GetLightmapWidth( GetLightmapPage() );
  1759. *h = GetMaterialSystem()->GetLightmapHeight( GetLightmapPage() );
  1760. }
  1761. //-----------------------------------------------------------------------------
  1762. // FIXME: This is a hack required for NVidia/XBox, can they fix in drivers?
  1763. //-----------------------------------------------------------------------------
  1764. void CMatRenderContext::DrawScreenSpaceQuad( IMaterial* pMaterial )
  1765. {
  1766. // This is required because the texture coordinates for NVidia reading
  1767. // out of non-power-of-two textures is borked
  1768. int w, h;
  1769. GetRenderTargetDimensions( w, h );
  1770. if ( ( w == 0 ) || ( h == 0 ) )
  1771. return;
  1772. // This is the size of the back-buffer we're reading from.
  1773. int bw, bh;
  1774. bw = w; bh = h;
  1775. /* FIXME: Get this to work in hammer/engine integration
  1776. if ( m_pRenderTargetTexture )
  1777. {
  1778. }
  1779. else
  1780. {
  1781. MaterialVideoMode_t mode;
  1782. GetDisplayMode( mode );
  1783. if ( ( mode.m_Width == 0 ) || ( mode.m_Height == 0 ) )
  1784. return;
  1785. bw = mode.m_Width;
  1786. bh = mode.m_Height;
  1787. }
  1788. */
  1789. float s0, t0;
  1790. float s1, t1;
  1791. float flOffsetS = (bw != 0.0f) ? 1.0f / bw : 0.0f;
  1792. float flOffsetT = (bh != 0.0f) ? 1.0f / bh : 0.0f;
  1793. s0 = 0.5f * flOffsetS;
  1794. t0 = 0.5f * flOffsetT;
  1795. s1 = (w-0.5f) * flOffsetS;
  1796. t1 = (h-0.5f) * flOffsetT;
  1797. Bind( pMaterial );
  1798. IMesh* pMesh = GetDynamicMesh( true );
  1799. MatrixMode( MATERIAL_VIEW );
  1800. PushMatrix();
  1801. LoadIdentity();
  1802. MatrixMode( MATERIAL_PROJECTION );
  1803. PushMatrix();
  1804. LoadIdentity();
  1805. CMeshBuilder meshBuilder;
  1806. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  1807. meshBuilder.Position3f( -1.0f, -1.0f, 0.0f );
  1808. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  1809. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  1810. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  1811. meshBuilder.TexCoord2f( 0, s0, t1 );
  1812. meshBuilder.AdvanceVertex();
  1813. meshBuilder.Position3f( -1.0f, 1, 0.0f );
  1814. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  1815. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  1816. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  1817. meshBuilder.TexCoord2f( 0, s0, t0 );
  1818. meshBuilder.AdvanceVertex();
  1819. meshBuilder.Position3f( 1, 1, 0.0f );
  1820. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  1821. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  1822. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  1823. meshBuilder.TexCoord2f( 0, s1, t0 );
  1824. meshBuilder.AdvanceVertex();
  1825. meshBuilder.Position3f( 1, -1.0f, 0.0f );
  1826. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  1827. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  1828. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  1829. meshBuilder.TexCoord2f( 0, s1, t1 );
  1830. meshBuilder.AdvanceVertex();
  1831. meshBuilder.End();
  1832. pMesh->Draw();
  1833. MatrixMode( MATERIAL_VIEW );
  1834. PopMatrix();
  1835. MatrixMode( MATERIAL_PROJECTION );
  1836. PopMatrix();
  1837. }
  1838. void CMatRenderContext::DrawScreenSpaceRectangle(
  1839. IMaterial *pMaterial,
  1840. int destx, int desty,
  1841. int width, int height,
  1842. float src_texture_x0, float src_texture_y0, // which texel you want to appear at
  1843. // destx/y
  1844. float src_texture_x1, float src_texture_y1, // which texel you want to appear at
  1845. // destx+width-1, desty+height-1
  1846. int src_texture_width, int src_texture_height, // needed for fixup
  1847. void *pClientRenderable,
  1848. int nXDice, int nYDice ) // Amount to tessellate the quad
  1849. {
  1850. pMaterial = ((IMaterialInternal *)pMaterial)->GetRealTimeVersion();
  1851. ::DrawScreenSpaceRectangle( pMaterial, destx, desty, width, height,
  1852. src_texture_x0, src_texture_y0, src_texture_x1, src_texture_y1,
  1853. src_texture_width, src_texture_height, pClientRenderable, nXDice, nYDice );
  1854. return;
  1855. }
  1856. static int CompareVertexFormats( VertexFormat_t Fmt1, VertexFormat_t Fmt2 )
  1857. {
  1858. if ( Fmt1 != Fmt2 )
  1859. {
  1860. if ( Fmt1 > Fmt2 )
  1861. return 1;
  1862. else
  1863. return -1;
  1864. }
  1865. else
  1866. return 0;
  1867. }
  1868. int CMatRenderContext::CompareMaterialCombos( IMaterial *pMaterial1, IMaterial *pMaterial2, int lightMapID1, int lightMapID2 )
  1869. {
  1870. pMaterial1 = ((IMaterialInternal *)pMaterial1)->GetRealTimeVersion(); //always work with the real time version of materials internally.
  1871. pMaterial2 = ((IMaterialInternal *)pMaterial2)->GetRealTimeVersion(); //always work with the real time version of materials internally.
  1872. IMaterialInternal *pMat1 = (IMaterialInternal *)pMaterial1;
  1873. IMaterialInternal *pMat2 = (IMaterialInternal *)pMaterial2;
  1874. ShaderRenderState_t *pState1 = pMat1->GetRenderState();
  1875. ShaderRenderState_t *pState2 = pMat2->GetRenderState();
  1876. int dPass = pState2->m_pSnapshots->m_nPassCount - pState1->m_pSnapshots->m_nPassCount;
  1877. if ( dPass )
  1878. return dPass;
  1879. if ( pState1->m_pSnapshots->m_nPassCount > 1 )
  1880. {
  1881. int dFormat = CompareVertexFormats( pMat1->GetVertexFormat(), pMat2->GetVertexFormat() );
  1882. if ( dFormat )
  1883. return dFormat;
  1884. }
  1885. for ( int i = 0; i < pState1->m_pSnapshots->m_nPassCount; i++ )
  1886. {
  1887. // UNDONE: Compare snapshots in the shaderapi?
  1888. int dSnapshot = pState1->m_pSnapshots->m_Snapshot[i] - pState2->m_pSnapshots->m_Snapshot[i];
  1889. if ( dSnapshot )
  1890. {
  1891. dSnapshot = g_pShaderAPI->CompareSnapshots( pState1->m_pSnapshots->m_Snapshot[i], pState2->m_pSnapshots->m_Snapshot[i] );
  1892. if ( dSnapshot )
  1893. return dSnapshot;
  1894. }
  1895. }
  1896. int dFormat = CompareVertexFormats( pMat1->GetVertexFormat(), pMat2->GetVertexFormat() );
  1897. if ( dFormat )
  1898. return dFormat;
  1899. IMaterialVar **pParams1 = pMat1->GetShaderParams();
  1900. IMaterialVar **pParams2 = pMat2->GetShaderParams();
  1901. if( pParams1[BASETEXTURE]->GetType() == MATERIAL_VAR_TYPE_TEXTURE ||
  1902. pParams2[BASETEXTURE]->GetType() == MATERIAL_VAR_TYPE_TEXTURE )
  1903. {
  1904. if( pParams1[BASETEXTURE]->GetType() != pParams2[BASETEXTURE]->GetType() )
  1905. {
  1906. return pParams2[BASETEXTURE]->GetType() - pParams1[BASETEXTURE]->GetType();
  1907. }
  1908. int dBaseTexture = Q_stricmp( pParams1[BASETEXTURE]->GetTextureValue()->GetName(), pParams2[BASETEXTURE]->GetTextureValue()->GetName() );
  1909. if ( dBaseTexture )
  1910. return dBaseTexture;
  1911. }
  1912. int dLightmap = lightMapID1 - lightMapID2;
  1913. if ( dLightmap )
  1914. return dLightmap;
  1915. if ( pMat1 > pMat2 )
  1916. return 1;
  1917. if ( pMat1 < pMat2 )
  1918. return -1;
  1919. return 0;
  1920. }
  1921. void CMatRenderContext::Bind( IMaterial *pMaterial, void *proxyData )
  1922. {
  1923. IMaterialInternal *material = static_cast<IMaterialInternal *>( pMaterial );
  1924. if ( !material )
  1925. {
  1926. if ( !g_pErrorMaterial )
  1927. return;
  1928. Warning( "Programming error: CMatRenderContext::Bind: NULL material\n" );
  1929. material = static_cast<IMaterialInternal *>( g_pErrorMaterial );
  1930. }
  1931. material = material->GetRealTimeVersion(); //always work with the real time versions of materials internally
  1932. if (g_config.bDrawFlat && !material->NoDebugOverride())
  1933. {
  1934. material = static_cast<IMaterialInternal *>( GetDrawFlatMaterial() );
  1935. }
  1936. CMatRenderContextBase::Bind( pMaterial, proxyData );
  1937. IMaterialInternal* pMatInternal = GetCurrentMaterialInternal();
  1938. Assert( pMatInternal );
  1939. // We've always gotta call the bind proxy
  1940. SyncMatrices();
  1941. if ( GetMaterialSystem()->GetThreadMode() == MATERIAL_SINGLE_THREADED || pMatInternal->HasQueueFriendlyProxies() )
  1942. {
  1943. pMatInternal->CallBindProxy( proxyData, NULL );
  1944. }
  1945. g_pShaderAPI->Bind( GetCurrentMaterialInternal() );
  1946. }
  1947. void CMatRenderContext::CopyRenderTargetToTextureEx( ITexture *pTexture, int nRenderTargetID, Rect_t *pSrcRect, Rect_t *pDstRect )
  1948. {
  1949. if ( !pTexture )
  1950. {
  1951. Assert( 0 );
  1952. return;
  1953. }
  1954. GetMaterialSystem()->Flush( false );
  1955. ITextureInternal *pTextureInternal = (ITextureInternal *)pTexture;
  1956. if ( IsPC() || !IsX360() )
  1957. {
  1958. pTextureInternal->CopyFrameBufferToMe( nRenderTargetID, pSrcRect, pDstRect );
  1959. }
  1960. else
  1961. {
  1962. // X360 only does 1:1 resolves. So we can do full resolves to textures of size
  1963. // equal or greater than the viewport trivially. Downsizing is nasty.
  1964. Rect_t srcRect;
  1965. if ( !pSrcRect )
  1966. {
  1967. // build out source rect
  1968. pSrcRect = &srcRect;
  1969. int x, y, w, h;
  1970. GetViewport( x, y, w, h );
  1971. pSrcRect->x = 0;
  1972. pSrcRect->y = 0;
  1973. pSrcRect->width = w;
  1974. pSrcRect->height = h;
  1975. }
  1976. Rect_t dstRect;
  1977. if ( !pDstRect )
  1978. {
  1979. // build out target rect
  1980. pDstRect = &dstRect;
  1981. pDstRect->x = 0;
  1982. pDstRect->y = 0;
  1983. pDstRect->width = pTexture->GetActualWidth();
  1984. pDstRect->height = pTexture->GetActualHeight();
  1985. }
  1986. if ( pSrcRect->width == pDstRect->width && pSrcRect->height == pDstRect->height )
  1987. {
  1988. // 1:1 mapping, no stretching needed, use direct path
  1989. pTextureInternal->CopyFrameBufferToMe( nRenderTargetID, pSrcRect, pDstRect );
  1990. return;
  1991. }
  1992. if( (pDstRect->x == 0) && (pDstRect->y == 0) &&
  1993. (pDstRect->width == pTexture->GetActualWidth()) && (pDstRect->height == pTexture->GetActualHeight()) &&
  1994. (pDstRect->width >= pSrcRect->width) && (pDstRect->height >= pSrcRect->height) )
  1995. {
  1996. // Resolve takes up the whole texture, and the texture is large enough to hold the resolve.
  1997. // This is turned into a 1:1 resolve within shaderapi by making D3D think the texture is smaller from now on. (Until it resolves from a bigger source)
  1998. pTextureInternal->CopyFrameBufferToMe( nRenderTargetID, pSrcRect, pDstRect );
  1999. return;
  2000. }
  2001. // currently assuming disparate copies are only for FB blits
  2002. // ensure active render target is actually the back buffer
  2003. Assert( m_RenderTargetStack.Top().m_pRenderTargets[0] == NULL );
  2004. // nasty sequence:
  2005. // resolve FB surface to matching clone DDR texture
  2006. // gpu draw from clone DDR FB texture to disparate RT target surface
  2007. // resolve to its matching DDR clone texture
  2008. ITextureInternal *pFullFrameFB = (ITextureInternal*)GetMaterialSystem()->FindTexture( "_rt_FullFrameFB", TEXTURE_GROUP_RENDER_TARGET );
  2009. pFullFrameFB->CopyFrameBufferToMe( nRenderTargetID, NULL, NULL );
  2010. // target texture must be a render target
  2011. PushRenderTargetAndViewport( pTexture );
  2012. // blit FB source to render target
  2013. DrawScreenSpaceRectangle(
  2014. GetMaterialSystem()->GetRenderTargetBlitMaterial(),
  2015. pDstRect->x, pDstRect->y, pDstRect->width, pDstRect->height,
  2016. pSrcRect->x, pSrcRect->y, pSrcRect->x+pSrcRect->width-1, pSrcRect->y+pSrcRect->height-1,
  2017. pFullFrameFB->GetActualWidth(), pFullFrameFB->GetActualHeight() );
  2018. // resolve render target to texture
  2019. ((ITextureInternal *)pTexture)->CopyFrameBufferToMe( 0, NULL, NULL );
  2020. // restore render target and viewport
  2021. PopRenderTargetAndViewport();
  2022. }
  2023. }
  2024. void CMatRenderContext::CopyRenderTargetToTexture( ITexture *pTexture )
  2025. {
  2026. CopyRenderTargetToTextureEx( pTexture, NULL, NULL );
  2027. }
  2028. void CMatRenderContext::CopyTextureToRenderTargetEx( int nRenderTargetID, ITexture *pTexture, Rect_t *pSrcRect, Rect_t *pDstRect )
  2029. {
  2030. if ( !pTexture )
  2031. {
  2032. Assert( 0 );
  2033. return;
  2034. }
  2035. GetMaterialSystem()->Flush( false );
  2036. ITextureInternal *pTextureInternal = (ITextureInternal *)pTexture;
  2037. if ( IsPC() || !IsX360() )
  2038. {
  2039. pTextureInternal->CopyMeToFrameBuffer( nRenderTargetID, pSrcRect, pDstRect );
  2040. }
  2041. else
  2042. {
  2043. Assert( 0 );
  2044. }
  2045. }
  2046. void CMatRenderContext::ClearBuffers( bool bClearColor, bool bClearDepth, bool bClearStencil )
  2047. {
  2048. int width, height;
  2049. GetRenderTargetDimensions( width, height );
  2050. g_pShaderAPI->ClearBuffers( bClearColor, bClearDepth, bClearStencil, width, height );
  2051. }
  2052. void CMatRenderContext::DrawClearBufferQuad( unsigned char r, unsigned char g, unsigned char b, unsigned char a, bool bClearColor, bool bClearAlpha, bool bClearDepth )
  2053. {
  2054. IMaterialInternal *pClearMaterial = GetBufferClearObeyStencil( bClearColor + ( bClearAlpha << 1 ) + ( bClearDepth << 2 ) );
  2055. Bind( pClearMaterial );
  2056. IMesh* pMesh = GetDynamicMesh( true );
  2057. MatrixMode( MATERIAL_MODEL );
  2058. PushMatrix();
  2059. LoadIdentity();
  2060. MatrixMode( MATERIAL_VIEW );
  2061. PushMatrix();
  2062. LoadIdentity();
  2063. MatrixMode( MATERIAL_PROJECTION );
  2064. PushMatrix();
  2065. LoadIdentity();
  2066. float flDepth = GetMaterialSystem()->GetConfig().bReverseDepth ? 0.0f : 1.0f;
  2067. CMeshBuilder meshBuilder;
  2068. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  2069. //1.1 instead of 1.0 to fix small borders around the edges in full screen with anti-aliasing enabled
  2070. meshBuilder.Position3f( -1.1f, -1.1f, flDepth );
  2071. meshBuilder.Color4ub( r, g, b, a );
  2072. meshBuilder.AdvanceVertex();
  2073. meshBuilder.Position3f( -1.1f, 1.1f, flDepth );
  2074. meshBuilder.Color4ub( r, g, b, a );
  2075. meshBuilder.AdvanceVertex();
  2076. meshBuilder.Position3f( 1.1f, 1.1f, flDepth );
  2077. meshBuilder.Color4ub( r, g, b, a );
  2078. meshBuilder.AdvanceVertex();
  2079. meshBuilder.Position3f( 1.1f, -1.1f, flDepth );
  2080. meshBuilder.Color4ub( r, g, b, a );
  2081. meshBuilder.AdvanceVertex();
  2082. meshBuilder.End();
  2083. pMesh->Draw();
  2084. MatrixMode( MATERIAL_MODEL );
  2085. PopMatrix();
  2086. MatrixMode( MATERIAL_VIEW );
  2087. PopMatrix();
  2088. MatrixMode( MATERIAL_PROJECTION );
  2089. PopMatrix();
  2090. }
  2091. #ifdef _PS3
  2092. void CMatRenderContext::DrawReloadZcullQuad()
  2093. {
  2094. IMaterialInternal *pMaterial = GetReloadZcullMaterial();
  2095. Bind( pMaterial );
  2096. IMesh* pMesh = GetDynamicMesh( true );
  2097. MatrixMode( MATERIAL_MODEL );
  2098. PushMatrix();
  2099. LoadIdentity();
  2100. MatrixMode( MATERIAL_VIEW );
  2101. PushMatrix();
  2102. LoadIdentity();
  2103. MatrixMode( MATERIAL_PROJECTION );
  2104. PushMatrix();
  2105. LoadIdentity();
  2106. CMeshBuilder meshBuilder;
  2107. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  2108. meshBuilder.Position3f( -1.0f, -1.0f, 0.0f );
  2109. meshBuilder.Color4ub( 0, 0, 0, 0 );
  2110. meshBuilder.AdvanceVertex();
  2111. meshBuilder.Position3f( -1.0f, 1.0f, 0.0f );
  2112. meshBuilder.Color4ub( 0, 0, 0, 0 );
  2113. meshBuilder.AdvanceVertex();
  2114. meshBuilder.Position3f( 1.0f, 1.0f, 0.0f );
  2115. meshBuilder.Color4ub( 0, 0, 0, 0 );
  2116. meshBuilder.AdvanceVertex();
  2117. meshBuilder.Position3f( 1.0f, -1.0f, 0.0f );
  2118. meshBuilder.Color4ub( 0, 0, 0, 0 );
  2119. meshBuilder.AdvanceVertex();
  2120. meshBuilder.End();
  2121. pMesh->Draw();
  2122. MatrixMode( MATERIAL_MODEL );
  2123. PopMatrix();
  2124. MatrixMode( MATERIAL_VIEW );
  2125. PopMatrix();
  2126. MatrixMode( MATERIAL_PROJECTION );
  2127. PopMatrix();
  2128. }
  2129. #endif // _PS3
  2130. //-----------------------------------------------------------------------------
  2131. // Should really be called SetViewport
  2132. //-----------------------------------------------------------------------------
  2133. void CMatRenderContext::Viewport( int x, int y, int width, int height )
  2134. {
  2135. CMatRenderContextBase::Viewport( x, y, width, height );
  2136. // If either dimension is negative, set to full bounds of current target
  2137. if ( (width < 0) || (height < 0) )
  2138. {
  2139. ITexture *pTarget = m_RenderTargetStack.Top().m_pRenderTargets[0];
  2140. // If target is the back buffer
  2141. if ( pTarget == NULL )
  2142. {
  2143. m_Viewport.m_nTopLeftX = 0;
  2144. m_Viewport.m_nTopLeftY = 0;
  2145. g_pShaderAPI->GetBackBufferDimensions( m_Viewport.m_nWidth, m_Viewport.m_nHeight );
  2146. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  2147. }
  2148. else // target is a texture
  2149. {
  2150. m_Viewport.m_nTopLeftX = 0;
  2151. m_Viewport.m_nTopLeftY = 0;
  2152. m_Viewport.m_nWidth = pTarget->GetActualWidth();
  2153. m_Viewport.m_nHeight = pTarget->GetActualHeight();
  2154. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  2155. }
  2156. }
  2157. else // use the bounds passed in
  2158. {
  2159. m_Viewport.m_nTopLeftX = x;
  2160. m_Viewport.m_nTopLeftY = y;
  2161. m_Viewport.m_nWidth = width;
  2162. m_Viewport.m_nHeight = height;
  2163. g_pShaderAPI->SetViewports( 1, &m_Viewport );
  2164. }
  2165. }
  2166. void CMatRenderContext::GetViewport( int& x, int& y, int& width, int& height ) const
  2167. {
  2168. // Verify valid top of RT stack
  2169. Assert ( m_RenderTargetStack.Count() > 0 );
  2170. // Grab the top of stack
  2171. const RenderTargetStackElement_t& element = m_RenderTargetStack.Top();
  2172. // If either dimension is not positive, set to full bounds of current target
  2173. if ( (element.m_nViewW <= 0) || (element.m_nViewH <= 0) )
  2174. {
  2175. // Viewport origin at target origin
  2176. x = y = 0;
  2177. // If target is back buffer
  2178. if ( element.m_pRenderTargets[0] == NULL )
  2179. {
  2180. g_pShaderAPI->GetBackBufferDimensions( width, height );
  2181. }
  2182. else // if target is texture
  2183. {
  2184. width = element.m_pRenderTargets[0]->GetActualWidth();
  2185. height = element.m_pRenderTargets[0]->GetActualHeight();
  2186. }
  2187. }
  2188. else // use the bounds from the stack directly
  2189. {
  2190. x = element.m_nViewX;
  2191. y = element.m_nViewY;
  2192. width = element.m_nViewW;
  2193. height = element.m_nViewH;
  2194. }
  2195. }
  2196. //-----------------------------------------------------------------------------
  2197. // Methods related to user clip planes
  2198. //-----------------------------------------------------------------------------
  2199. void CMatRenderContext::UpdateHeightClipUserClipPlane( void )
  2200. {
  2201. PlaneStackElement pse;
  2202. pse.bHack_IsHeightClipPlane = true;
  2203. int iExistingHeightClipPlaneIndex;
  2204. for( iExistingHeightClipPlaneIndex = m_CustomClipPlanes.Count(); --iExistingHeightClipPlaneIndex >= 0; )
  2205. {
  2206. if( m_CustomClipPlanes[iExistingHeightClipPlaneIndex].bHack_IsHeightClipPlane )
  2207. break;
  2208. }
  2209. switch( m_HeightClipMode )
  2210. {
  2211. case MATERIAL_HEIGHTCLIPMODE_DISABLE:
  2212. if( iExistingHeightClipPlaneIndex != -1 )
  2213. m_CustomClipPlanes.Remove( iExistingHeightClipPlaneIndex );
  2214. break;
  2215. case MATERIAL_HEIGHTCLIPMODE_RENDER_ABOVE_HEIGHT:
  2216. pse.fValues[0] = 0.0f;
  2217. pse.fValues[1] = 0.0f;
  2218. pse.fValues[2] = 1.0f;
  2219. pse.fValues[3] = m_HeightClipZ;
  2220. if( iExistingHeightClipPlaneIndex != -1 )
  2221. {
  2222. memcpy( m_CustomClipPlanes.Base() + iExistingHeightClipPlaneIndex, &pse, sizeof( PlaneStackElement ) );
  2223. }
  2224. else
  2225. {
  2226. m_CustomClipPlanes.AddToTail( pse );
  2227. }
  2228. break;
  2229. case MATERIAL_HEIGHTCLIPMODE_RENDER_BELOW_HEIGHT:
  2230. pse.fValues[0] = 0.0f;
  2231. pse.fValues[1] = 0.0f;
  2232. pse.fValues[2] = -1.0f;
  2233. pse.fValues[3] = -m_HeightClipZ;
  2234. if( iExistingHeightClipPlaneIndex != -1 )
  2235. {
  2236. memcpy( m_CustomClipPlanes.Base() + iExistingHeightClipPlaneIndex, &pse, sizeof( PlaneStackElement ) );
  2237. }
  2238. else
  2239. {
  2240. m_CustomClipPlanes.AddToTail( pse );
  2241. }
  2242. break;
  2243. };
  2244. ApplyCustomClipPlanes();
  2245. /*switch( m_HeightClipMode )
  2246. {
  2247. case MATERIAL_HEIGHTCLIPMODE_DISABLE:
  2248. g_pShaderAPI->EnableClipPlane( 0, false );
  2249. break;
  2250. case MATERIAL_HEIGHTCLIPMODE_RENDER_ABOVE_HEIGHT:
  2251. plane[0] = 0.0f;
  2252. plane[1] = 0.0f;
  2253. plane[2] = 1.0f;
  2254. plane[3] = m_HeightClipZ;
  2255. g_pShaderAPI->SetClipPlane( 0, plane );
  2256. g_pShaderAPI->EnableClipPlane( 0, true );
  2257. break;
  2258. case MATERIAL_HEIGHTCLIPMODE_RENDER_BELOW_HEIGHT:
  2259. plane[0] = 0.0f;
  2260. plane[1] = 0.0f;
  2261. plane[2] = -1.0f;
  2262. plane[3] = -m_HeightClipZ;
  2263. g_pShaderAPI->SetClipPlane( 0, plane );
  2264. g_pShaderAPI->EnableClipPlane( 0, true );
  2265. break;
  2266. }*/
  2267. }
  2268. //-----------------------------------------------------------------------------
  2269. // Lightmap stuff
  2270. //-----------------------------------------------------------------------------
  2271. void CMatRenderContext::BindLightmapPage( int lightmapPageID )
  2272. {
  2273. if ( m_lightmapPageID == lightmapPageID )
  2274. return;
  2275. if ( g_pShaderDevice->IsUsingGraphics() )
  2276. {
  2277. g_pShaderAPI->SetStandardTextureHandle( TEXTURE_LIGHTMAP, GetLightmapTexture( lightmapPageID ) );
  2278. g_pShaderAPI->SetStandardTextureHandle( TEXTURE_PAINT, GetPaintmapTexture( lightmapPageID ) );
  2279. }
  2280. CMatRenderContextBase::BindLightmapPage( lightmapPageID );
  2281. }
  2282. void CMatRenderContext::BindLightmapTexture( ITexture *pLightmapTexture )
  2283. {
  2284. if ( ( m_lightmapPageID == MATERIAL_SYSTEM_LIGHTMAP_PAGE_USER_DEFINED ) && ( m_pUserDefinedLightmap == pLightmapTexture ) )
  2285. return;
  2286. if ( pLightmapTexture )
  2287. {
  2288. pLightmapTexture->IncrementReferenceCount();
  2289. }
  2290. if ( m_pUserDefinedLightmap )
  2291. {
  2292. m_pUserDefinedLightmap->DecrementReferenceCount();
  2293. }
  2294. m_pUserDefinedLightmap = static_cast<ITextureInternal*>( pLightmapTexture );
  2295. m_lightmapPageID = MATERIAL_SYSTEM_LIGHTMAP_PAGE_USER_DEFINED;
  2296. if ( g_pShaderDevice->IsUsingGraphics() )
  2297. {
  2298. g_pShaderAPI->SetStandardTextureHandle( TEXTURE_LIGHTMAP, GetLightmapTexture( m_lightmapPageID ) );
  2299. g_pShaderAPI->SetStandardTextureHandle( TEXTURE_PAINT, GetPaintmapTexture( m_lightmapPageID ) );
  2300. }
  2301. }
  2302. void CMatRenderContext::BindLightmap( Sampler_t sampler, TextureBindFlags_t nBindFlags )
  2303. {
  2304. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetLightmapTexture( m_lightmapPageID ) );
  2305. }
  2306. ShaderAPITextureHandle_t CMatRenderContext::GetPaintmapTexture( int nLightmapPage )
  2307. {
  2308. if( !GetPaintmaps()->IsEnabled() )
  2309. {
  2310. return GetBlackAlphaZeroTextureHandle();
  2311. }
  2312. switch ( nLightmapPage ) //paint map pages match lightmap pages
  2313. {
  2314. case MATERIAL_SYSTEM_LIGHTMAP_PAGE_USER_DEFINED:
  2315. case MATERIAL_SYSTEM_LIGHTMAP_PAGE_WHITE:
  2316. case MATERIAL_SYSTEM_LIGHTMAP_PAGE_WHITE_BUMP:
  2317. break;
  2318. default:
  2319. {
  2320. int nNumLightmapPages = GetLightmaps()->GetNumLightmapPages();
  2321. Assert( ( nLightmapPage == 0 && nNumLightmapPages == 0 ) || ( nLightmapPage >= 0 && nLightmapPage < nNumLightmapPages ) );
  2322. if( nLightmapPage >= 0 && nLightmapPage < nNumLightmapPages )
  2323. return GetPaintmaps()->GetPaintmapPageTextureHandle( nLightmapPage );
  2324. }
  2325. break;
  2326. }
  2327. return GetBlackAlphaZeroTextureHandle();
  2328. }
  2329. void CMatRenderContext::BindPaintTexture( Sampler_t sampler, TextureBindFlags_t nBindFlags )
  2330. {
  2331. ShaderAPITextureHandle_t hPaintmap = GetPaintmapTexture( m_lightmapPageID );
  2332. g_pShaderAPI->BindTexture( sampler, nBindFlags, hPaintmap );
  2333. }
  2334. void CMatRenderContext::BindBumpLightmap( Sampler_t sampler, TextureBindFlags_t nBindFlags )
  2335. {
  2336. ShaderAPITextureHandle_t hLightmap = GetLightmapTexture( m_lightmapPageID );
  2337. g_pShaderAPI->BindTexture( sampler, nBindFlags, hLightmap );
  2338. g_pShaderAPI->BindTexture( (Sampler_t)(sampler+1), nBindFlags, hLightmap );
  2339. g_pShaderAPI->BindTexture( (Sampler_t)(sampler+2), nBindFlags, hLightmap );
  2340. }
  2341. void CMatRenderContext::BindFullbrightLightmap( Sampler_t sampler, TextureBindFlags_t nBindFlags )
  2342. {
  2343. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetFullbrightLightmapTextureHandle() );
  2344. }
  2345. void CMatRenderContext::BindBumpedFullbrightLightmap( Sampler_t sampler, TextureBindFlags_t nBindFlags )
  2346. {
  2347. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetFullbrightBumpedLightmapTextureHandle() );
  2348. }
  2349. static void SafeTextureBind( ITextureInternal *tex, Sampler_t sampler, TextureBindFlags_t nBindFlags )
  2350. {
  2351. AssertMsg( tex, "Tried to bind NULL texture.\n" );
  2352. if ( tex )
  2353. tex->Bind( sampler, nBindFlags );
  2354. }
  2355. //-----------------------------------------------------------------------------
  2356. // Bind standard textures
  2357. //-----------------------------------------------------------------------------
  2358. ShaderAPITextureHandle_t CMatRenderContext::GetStandardTexture( StandardTextureId_t id )
  2359. {
  2360. switch ( id )
  2361. {
  2362. case TEXTURE_PAINT:
  2363. return GetPaintmapTexture( m_lightmapPageID );
  2364. case TEXTURE_LIGHTMAP:
  2365. return GetLightmapTexture( m_lightmapPageID );
  2366. case TEXTURE_LIGHTMAP_BUMPED:
  2367. return GetLightmapTexture( m_lightmapPageID );
  2368. case TEXTURE_LIGHTMAP_FULLBRIGHT:
  2369. return GetFullbrightLightmapTextureHandle();
  2370. case TEXTURE_LIGHTMAP_BUMPED_FULLBRIGHT:
  2371. return GetFullbrightBumpedLightmapTextureHandle();
  2372. case TEXTURE_WHITE:
  2373. return GetWhiteTextureHandle();
  2374. case TEXTURE_BLACK:
  2375. return GetBlackTextureHandle();
  2376. case TEXTURE_BLACK_ALPHA_ZERO:
  2377. return GetBlackAlphaZeroTextureHandle();
  2378. case TEXTURE_GREY:
  2379. return GetGreyTextureHandle();
  2380. case TEXTURE_GREY_ALPHA_ZERO:
  2381. return GetGreyAlphaZeroTextureHandle();
  2382. case TEXTURE_NORMALMAP_FLAT:
  2383. return GetFlatNormalTextureHandle();
  2384. case TEXTURE_SSBUMP_FLAT:
  2385. return GetFlatSSBumpTextureHandle();
  2386. case TEXTURE_NORMALIZATION_CUBEMAP:
  2387. return TextureManager()->NormalizationCubemap()->GetTextureHandle(0);
  2388. case TEXTURE_NORMALIZATION_CUBEMAP_SIGNED:
  2389. return TextureManager()->SignedNormalizationCubemap()->GetTextureHandle(0);
  2390. case TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0:
  2391. case TEXTURE_FRAME_BUFFER_FULL_TEXTURE_1:
  2392. {
  2393. int nTextureIndex = id - TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0;
  2394. if( m_pCurrentFrameBufferCopyTexture[ nTextureIndex ] )
  2395. {
  2396. return ( ( ITextureInternal * )m_pCurrentFrameBufferCopyTexture[ nTextureIndex ] )->GetTextureHandle(0);
  2397. }
  2398. }
  2399. return INVALID_SHADERAPI_TEXTURE_HANDLE;
  2400. case TEXTURE_COLOR_CORRECTION_VOLUME_0:
  2401. case TEXTURE_COLOR_CORRECTION_VOLUME_1:
  2402. case TEXTURE_COLOR_CORRECTION_VOLUME_2:
  2403. case TEXTURE_COLOR_CORRECTION_VOLUME_3:
  2404. {
  2405. return TextureManager()->ColorCorrectionTexture( id - TEXTURE_COLOR_CORRECTION_VOLUME_0 )->GetTextureHandle(0);
  2406. }
  2407. case TEXTURE_SHADOW_NOISE_2D:
  2408. return TextureManager()->ShadowNoise2D()->GetTextureHandle(0);
  2409. case TEXTURE_SSAO_NOISE_2D:
  2410. return TextureManager()->SSAONoise2D()->GetTextureHandle(0);
  2411. case TEXTURE_IDENTITY_LIGHTWARP:
  2412. return TextureManager()->IdentityLightWarp()->GetTextureHandle(0);
  2413. case TEXTURE_MORPH_ACCUMULATOR:
  2414. return g_pMorphMgr->MorphAccumulator()->GetTextureHandle(0);
  2415. case TEXTURE_MORPH_WEIGHTS:
  2416. return g_pMorphMgr->MorphWeights()->GetTextureHandle(0);
  2417. case TEXTURE_FRAME_BUFFER_FULL_DEPTH:
  2418. if( m_bFullFrameDepthIsValid && TextureManager()->FullFrameDepthTexture() )
  2419. return TextureManager()->FullFrameDepthTexture()->GetTextureHandle(0);
  2420. else
  2421. return GetMaxDepthTextureHandle();
  2422. case TEXTURE_LOCAL_ENV_CUBEMAP:
  2423. {
  2424. ITextureInternal *pTextureInternal = static_cast<ITextureInternal*>( m_pLocalCubemapTexture );
  2425. return pTextureInternal->GetTextureHandle( 0 );
  2426. }
  2427. case TEXTURE_STEREO_PARAM_MAP:
  2428. {
  2429. return TextureManager()->StereoParamTexture()->GetTextureHandle( 0 );
  2430. }
  2431. default:
  2432. Assert(0);
  2433. }
  2434. return INVALID_SHADERAPI_TEXTURE_HANDLE;
  2435. }
  2436. void CMatRenderContext::BindStandardTexture( Sampler_t sampler, TextureBindFlags_t nBindFlags, StandardTextureId_t id )
  2437. {
  2438. switch ( id )
  2439. {
  2440. case TEXTURE_PAINT:
  2441. BindPaintTexture( sampler, nBindFlags );
  2442. break;
  2443. case TEXTURE_LIGHTMAP:
  2444. BindLightmap( sampler, nBindFlags );
  2445. return;
  2446. case TEXTURE_LIGHTMAP_BUMPED:
  2447. BindBumpLightmap( sampler, nBindFlags );
  2448. return;
  2449. case TEXTURE_LIGHTMAP_FULLBRIGHT:
  2450. BindFullbrightLightmap( sampler, nBindFlags );
  2451. return;
  2452. case TEXTURE_LIGHTMAP_BUMPED_FULLBRIGHT:
  2453. BindBumpedFullbrightLightmap( sampler, nBindFlags );
  2454. return;
  2455. case TEXTURE_WHITE:
  2456. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetWhiteTextureHandle() );
  2457. return;
  2458. case TEXTURE_BLACK:
  2459. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetBlackTextureHandle() );
  2460. return;
  2461. case TEXTURE_BLACK_ALPHA_ZERO:
  2462. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetBlackAlphaZeroTextureHandle() );
  2463. return;
  2464. case TEXTURE_GREY:
  2465. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetGreyTextureHandle() );
  2466. return;
  2467. case TEXTURE_GREY_ALPHA_ZERO:
  2468. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetGreyAlphaZeroTextureHandle() );
  2469. return;
  2470. case TEXTURE_NORMALMAP_FLAT:
  2471. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetFlatNormalTextureHandle() );
  2472. return;
  2473. case TEXTURE_SSBUMP_FLAT:
  2474. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetFlatSSBumpTextureHandle() );
  2475. return;
  2476. case TEXTURE_NORMALIZATION_CUBEMAP:
  2477. SafeTextureBind( TextureManager()->NormalizationCubemap(), sampler, nBindFlags );
  2478. return;
  2479. case TEXTURE_NORMALIZATION_CUBEMAP_SIGNED:
  2480. SafeTextureBind( TextureManager()->SignedNormalizationCubemap(), sampler, nBindFlags );
  2481. return;
  2482. case TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0:
  2483. case TEXTURE_FRAME_BUFFER_FULL_TEXTURE_1:
  2484. {
  2485. int nTextureIndex = id - TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0;
  2486. if( m_pCurrentFrameBufferCopyTexture[ nTextureIndex ] )
  2487. {
  2488. ( ( ITextureInternal * )m_pCurrentFrameBufferCopyTexture[ nTextureIndex ] )->Bind( sampler, nBindFlags );
  2489. }
  2490. }
  2491. return;
  2492. case TEXTURE_COLOR_CORRECTION_VOLUME_0:
  2493. case TEXTURE_COLOR_CORRECTION_VOLUME_1:
  2494. case TEXTURE_COLOR_CORRECTION_VOLUME_2:
  2495. case TEXTURE_COLOR_CORRECTION_VOLUME_3:
  2496. {
  2497. SafeTextureBind( TextureManager()->ColorCorrectionTexture( id - TEXTURE_COLOR_CORRECTION_VOLUME_0 ), sampler, nBindFlags );
  2498. }
  2499. return;
  2500. case TEXTURE_SHADOW_NOISE_2D:
  2501. SafeTextureBind( TextureManager()->ShadowNoise2D(), sampler, nBindFlags );
  2502. return;
  2503. case TEXTURE_SSAO_NOISE_2D:
  2504. SafeTextureBind( TextureManager()->SSAONoise2D(), sampler, nBindFlags );
  2505. return;
  2506. case TEXTURE_IDENTITY_LIGHTWARP:
  2507. SafeTextureBind( TextureManager()->IdentityLightWarp(), sampler, nBindFlags );
  2508. return;
  2509. case TEXTURE_MORPH_ACCUMULATOR:
  2510. SafeTextureBind( g_pMorphMgr->MorphAccumulator(), sampler, nBindFlags );
  2511. return;
  2512. case TEXTURE_MORPH_WEIGHTS:
  2513. SafeTextureBind( g_pMorphMgr->MorphWeights(), sampler, nBindFlags );
  2514. return;
  2515. case TEXTURE_FRAME_BUFFER_FULL_DEPTH:
  2516. if( m_bFullFrameDepthIsValid && TextureManager()->FullFrameDepthTexture() )
  2517. TextureManager()->FullFrameDepthTexture()->Bind( sampler, nBindFlags );
  2518. else
  2519. g_pShaderAPI->BindTexture( sampler, nBindFlags, GetMaxDepthTextureHandle() );
  2520. return;
  2521. case TEXTURE_LOCAL_ENV_CUBEMAP:
  2522. {
  2523. ITextureInternal *pTextureInternal = static_cast<ITextureInternal*>( m_pLocalCubemapTexture );
  2524. g_pShaderAPI->BindTexture( sampler, nBindFlags, pTextureInternal->GetTextureHandle( 0 ) );
  2525. }
  2526. return;
  2527. case TEXTURE_STEREO_PARAM_MAP:
  2528. {
  2529. SafeTextureBind( TextureManager()->StereoParamTexture(), sampler, nBindFlags );
  2530. }
  2531. return;
  2532. default:
  2533. Assert(0);
  2534. }
  2535. }
  2536. void CMatRenderContext::BindStandardVertexTexture( VertexTextureSampler_t vtSampler, StandardTextureId_t id )
  2537. {
  2538. switch ( id )
  2539. {
  2540. case TEXTURE_MORPH_ACCUMULATOR:
  2541. g_pMorphMgr->MorphAccumulator()->BindVertexTexture( vtSampler );
  2542. return;
  2543. case TEXTURE_MORPH_WEIGHTS:
  2544. g_pMorphMgr->MorphWeights()->BindVertexTexture( vtSampler );
  2545. return;
  2546. case TEXTURE_SUBDIVISION_PATCHES:
  2547. #if defined( FEATURE_SUBD_SUPPORT )
  2548. g_pShaderAPI->BindVertexTexture( vtSampler, g_pSubDMgr->SubDTexture() );
  2549. #else
  2550. // not supported
  2551. Assert( 0 );
  2552. #endif
  2553. return;
  2554. case TEXTURE_BLACK:
  2555. g_pShaderAPI->BindVertexTexture( vtSampler, GetBlackTextureHandle() );
  2556. return;
  2557. default:
  2558. Assert(0);
  2559. }
  2560. }
  2561. float CMatRenderContext::GetSubDHeight()
  2562. {
  2563. #if defined( FEATURE_SUBD_SUPPORT )
  2564. return (float)g_pSubDMgr->GetHeight();
  2565. #else
  2566. // not supported
  2567. Assert( 0 );
  2568. return 0;
  2569. #endif
  2570. }
  2571. void CMatRenderContext::GetStandardTextureDimensions( int *pWidth, int *pHeight, StandardTextureId_t id )
  2572. {
  2573. ITexture *pTexture = NULL;
  2574. switch ( id )
  2575. {
  2576. case TEXTURE_LIGHTMAP:
  2577. case TEXTURE_LIGHTMAP_BUMPED:
  2578. case TEXTURE_LIGHTMAP_FULLBRIGHT:
  2579. case TEXTURE_LIGHTMAP_BUMPED_FULLBRIGHT:
  2580. // NOTE: Doesn't exactly work since we may be in fullbright mode
  2581. // GetLightmapDimensions( pWidth, pHeight );
  2582. // break;
  2583. case TEXTURE_WHITE:
  2584. case TEXTURE_BLACK:
  2585. case TEXTURE_BLACK_ALPHA_ZERO:
  2586. case TEXTURE_GREY:
  2587. case TEXTURE_GREY_ALPHA_ZERO:
  2588. case TEXTURE_NORMALMAP_FLAT:
  2589. case TEXTURE_SSBUMP_FLAT:
  2590. default:
  2591. Assert( 0 );
  2592. Warning( "GetStandardTextureDimensions: still unimplemented for this type!\n" );
  2593. *pWidth = *pHeight = -1;
  2594. break;
  2595. case TEXTURE_NORMALIZATION_CUBEMAP:
  2596. pTexture = TextureManager()->NormalizationCubemap();
  2597. break;
  2598. case TEXTURE_NORMALIZATION_CUBEMAP_SIGNED:
  2599. pTexture = TextureManager()->SignedNormalizationCubemap();
  2600. break;
  2601. case TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0:
  2602. case TEXTURE_FRAME_BUFFER_FULL_TEXTURE_1:
  2603. {
  2604. int nTextureIndex = id - TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0;
  2605. pTexture = m_pCurrentFrameBufferCopyTexture[ nTextureIndex ];
  2606. }
  2607. break;
  2608. case TEXTURE_COLOR_CORRECTION_VOLUME_0:
  2609. case TEXTURE_COLOR_CORRECTION_VOLUME_1:
  2610. case TEXTURE_COLOR_CORRECTION_VOLUME_2:
  2611. case TEXTURE_COLOR_CORRECTION_VOLUME_3:
  2612. pTexture = TextureManager()->ColorCorrectionTexture( id - TEXTURE_COLOR_CORRECTION_VOLUME_0 );
  2613. break;
  2614. case TEXTURE_SHADOW_NOISE_2D:
  2615. pTexture = TextureManager()->ShadowNoise2D();
  2616. break;
  2617. case TEXTURE_SSAO_NOISE_2D:
  2618. pTexture = TextureManager()->SSAONoise2D();
  2619. break;
  2620. case TEXTURE_IDENTITY_LIGHTWARP:
  2621. pTexture = TextureManager()->IdentityLightWarp();
  2622. return;
  2623. case TEXTURE_MORPH_ACCUMULATOR:
  2624. pTexture = g_pMorphMgr->MorphAccumulator();
  2625. break;
  2626. case TEXTURE_MORPH_WEIGHTS:
  2627. pTexture = g_pMorphMgr->MorphWeights();
  2628. break;
  2629. case TEXTURE_STEREO_PARAM_MAP:
  2630. pTexture = TextureManager()->StereoParamTexture();
  2631. break;
  2632. }
  2633. if ( pTexture )
  2634. {
  2635. *pWidth = pTexture->GetActualWidth();
  2636. *pHeight = pTexture->GetActualHeight();
  2637. }
  2638. else
  2639. {
  2640. Warning( "GetStandardTextureDimensions: Couldn't find the texture to get the dimensions!\n" );
  2641. *pWidth = *pHeight = -1;
  2642. }
  2643. }
  2644. void CMatRenderContext::FogColor3f( float r, float g, float b )
  2645. {
  2646. unsigned char fogColor[3];
  2647. fogColor[0] = clamp( (int)(r * 255.0f), 0, 255 );
  2648. fogColor[1] = clamp( (int)(g * 255.0f), 0, 255 );
  2649. fogColor[2] = clamp( (int)(b * 255.0f), 0, 255 );
  2650. g_pShaderAPI->SceneFogColor3ub( fogColor[0], fogColor[1], fogColor[2] );
  2651. }
  2652. void CMatRenderContext::FogColor3fv( const float* rgb )
  2653. {
  2654. unsigned char fogColor[3];
  2655. fogColor[0] = clamp( (int)(rgb[0] * 255.0f), 0, 255 );
  2656. fogColor[1] = clamp( (int)(rgb[1] * 255.0f), 0, 255 );
  2657. fogColor[2] = clamp( (int)(rgb[2] * 255.0f), 0, 255 );
  2658. g_pShaderAPI->SceneFogColor3ub( fogColor[0], fogColor[1], fogColor[2] );
  2659. }
  2660. void CMatRenderContext::SetFlashlightMode( bool bEnable )
  2661. {
  2662. m_bFlashlightEnable = bEnable;
  2663. }
  2664. void CMatRenderContext::SetRenderingPaint( bool bEnable )
  2665. {
  2666. m_bRenderingPaint = bEnable;
  2667. }
  2668. bool CMatRenderContext::GetFlashlightMode( ) const
  2669. {
  2670. return m_bFlashlightEnable;
  2671. }
  2672. bool CMatRenderContext::IsCullingEnabledForSinglePassFlashlight() const
  2673. {
  2674. return m_bCullingEnabledForSinglePassFlashlight;
  2675. }
  2676. void CMatRenderContext::EnableCullingForSinglePassFlashlight( bool bEnable )
  2677. {
  2678. m_bCullingEnabledForSinglePassFlashlight = bEnable;
  2679. }
  2680. void CMatRenderContext::EnableSinglePassFlashlightMode( bool bEnable )
  2681. {
  2682. m_bSinglePassFlashlightMode = bEnable;
  2683. g_pShaderAPI->EnableSinglePassFlashlightMode( bEnable );
  2684. }
  2685. bool CMatRenderContext::SinglePassFlashlightModeEnabled() const
  2686. {
  2687. return m_bSinglePassFlashlightMode;
  2688. }
  2689. void CMatRenderContext::SetFlashlightStateEx( const FlashlightState_t &state, const VMatrix &worldToTexture, ITexture *pFlashlightDepthTexture )
  2690. {
  2691. g_pShaderAPI->SetFlashlightStateEx( state, worldToTexture, pFlashlightDepthTexture );
  2692. }
  2693. void CMatRenderContext::SetCascadedShadowMappingState( const CascadedShadowMappingState_t &state, ITexture *pDepthTextureAtlas )
  2694. {
  2695. g_pShaderAPI->SetCascadedShadowMappingState( state, pDepthTextureAtlas );
  2696. }
  2697. // This routine pushes a new scissor rect onto the top of the stack by intersecting with
  2698. // the current top before pushing. This means the top is always the intersection of all
  2699. // rects on the stack and it makes popping the stack trivial
  2700. void CMatRenderContext::PushScissorRect( const int nLeft, const int nTop, const int nRight, const int nBottom )
  2701. {
  2702. // Really deep stack, overflow?
  2703. if ( m_ScissorRectStack.Count() > 32 )
  2704. {
  2705. DevMsg( "Scissor Rect Stack overflow. Too many Pushes?\n" );
  2706. }
  2707. // Necessary to push the stack top onto itself; realloc could happen otherwise
  2708. m_ScissorRectStack.EnsureCapacity( m_ScissorRectStack.Count() + 1 );
  2709. int nNewLeft = nLeft;
  2710. int nNewTop = nTop;
  2711. int nNewRight = nRight;
  2712. int nNewBottom = nBottom;
  2713. // If there are already elements in the stack, intersect with them
  2714. if ( m_ScissorRectStack.Count() > 0 )
  2715. {
  2716. nNewLeft = MAX( m_ScissorRectStack.Top().nLeft, nLeft );
  2717. nNewTop = MAX( m_ScissorRectStack.Top().nTop, nTop );
  2718. nNewRight = MIN( m_ScissorRectStack.Top().nRight, nRight );
  2719. nNewBottom = MIN( m_ScissorRectStack.Top().nBottom, nBottom );
  2720. }
  2721. // If we have a negative width, just slam to a rect of zero width
  2722. if ( nNewLeft > nNewRight )
  2723. {
  2724. nNewLeft = nNewRight;
  2725. }
  2726. // If we have a negative height, just slam to a rect of zero height
  2727. if ( nNewTop > nNewBottom )
  2728. {
  2729. nNewTop = nNewBottom;
  2730. }
  2731. // Make sure we don't have a negative rect
  2732. Assert( nNewRight >= nNewLeft );
  2733. Assert( nNewBottom >= nNewTop );
  2734. // Make an element and push it
  2735. ScissorRectStackElement_t element = { nNewLeft, nNewTop, nNewRight, nNewBottom };
  2736. m_ScissorRectStack.Push( element );
  2737. g_pShaderAPI->SetScissorRect( element.nLeft, element.nTop, element.nRight, element.nBottom, true );
  2738. }
  2739. void CMatRenderContext::PopScissorRect( )
  2740. {
  2741. // Nothing on the stack. Just disable scissoring and bail
  2742. if ( m_ScissorRectStack.Count() <= 0 )
  2743. {
  2744. DevMsg( "Scissor Rect Stack underflow. Too many Pops?\n" );
  2745. g_pShaderAPI->SetScissorRect( -1, -1, -1, -1, false );
  2746. return;
  2747. }
  2748. m_ScissorRectStack.Pop();
  2749. // If there is anything left on the stack, set the ShaderAPI rect to the top
  2750. if ( m_ScissorRectStack.Count() > 0 )
  2751. {
  2752. g_pShaderAPI->SetScissorRect( m_ScissorRectStack.Top().nLeft,
  2753. m_ScissorRectStack.Top().nTop,
  2754. m_ScissorRectStack.Top().nRight,
  2755. m_ScissorRectStack.Top().nBottom, true );
  2756. }
  2757. else
  2758. {
  2759. // We popped the last element, turn off scissoring
  2760. g_pShaderAPI->SetScissorRect( -1, -1, -1, -1, false );
  2761. }
  2762. }
  2763. void CMatRenderContext::SetToneMappingScaleLinear( const Vector &vScale )
  2764. {
  2765. // Keep a copy in CMatRenderContext since CMatRenderContextBase::GetToneMappingScaleLinear() doesn't have access to ShaderAPI
  2766. m_LastSetToneMapScale = vScale;
  2767. // Call into ShaderAPI
  2768. g_pShaderAPI->SetToneMappingScaleLinear( vScale );
  2769. }
  2770. void CMatRenderContext::BeginBatch( IMesh* pIndices )
  2771. {
  2772. Assert( !m_pBatchMesh && !m_pBatchIndices);
  2773. m_pBatchIndices = pIndices;
  2774. }
  2775. void CMatRenderContext::BindBatch( IMesh* pVertices, IMaterial *pAutoBind )
  2776. {
  2777. m_pBatchMesh = GetDynamicMesh( false, pVertices, m_pBatchIndices, pAutoBind );
  2778. }
  2779. void CMatRenderContext::DrawBatch(MaterialPrimitiveType_t primType, int firstIndex, int numIndices )
  2780. {
  2781. Assert( m_pBatchMesh );
  2782. m_pBatchMesh->SetPrimitiveType( primType );
  2783. m_pBatchMesh->Draw( firstIndex, numIndices );
  2784. }
  2785. void CMatRenderContext::EndBatch()
  2786. {
  2787. m_pBatchIndices = NULL;
  2788. m_pBatchMesh = NULL;
  2789. }
  2790. bool CMatRenderContext::OnDrawMesh( IMesh *pMesh, int firstIndex, int numIndices )
  2791. {
  2792. SyncMatrices();
  2793. return true;
  2794. }
  2795. bool CMatRenderContext::OnDrawMesh( IMesh *pMesh, CPrimList *pLists, int nLists )
  2796. {
  2797. SyncMatrices();
  2798. return true;
  2799. }
  2800. bool CMatRenderContext::OnDrawMeshModulated( IMesh *pMesh, const Vector4D& vecDiffuseModulation, int firstIndex, int numIndices )
  2801. {
  2802. SyncMatrices();
  2803. return true;
  2804. }
  2805. //-----------------------------------------------------------------------------
  2806. // Methods related to morph accumulation
  2807. //-----------------------------------------------------------------------------
  2808. void CMatRenderContext::BeginMorphAccumulation()
  2809. {
  2810. g_pMorphMgr->BeginMorphAccumulation( m_pMorphRenderContext );
  2811. }
  2812. void CMatRenderContext::EndMorphAccumulation()
  2813. {
  2814. g_pMorphMgr->EndMorphAccumulation( m_pMorphRenderContext );
  2815. }
  2816. void CMatRenderContext::AccumulateMorph( IMorph* pMorph, int nMorphCount, const MorphWeight_t* pWeights )
  2817. {
  2818. g_pMorphMgr->AccumulateMorph( m_pMorphRenderContext, pMorph, nMorphCount, pWeights );
  2819. }
  2820. bool CMatRenderContext::GetMorphAccumulatorTexCoord( Vector2D *pTexCoord, IMorph *pMorph, int nVertex )
  2821. {
  2822. return g_pMorphMgr->GetMorphAccumulatorTexCoord( m_pMorphRenderContext, pTexCoord, pMorph, nVertex );
  2823. }
  2824. int CMatRenderContext::GetSubDBufferWidth()
  2825. {
  2826. #if defined( FEATURE_SUBD_SUPPORT )
  2827. return g_pSubDMgr->GetWidth();
  2828. #else
  2829. // not supported
  2830. Assert( 0 );
  2831. return 0;
  2832. #endif
  2833. }
  2834. float *CMatRenderContext::LockSubDBuffer( int nNumRows )
  2835. {
  2836. #if defined( FEATURE_SUBD_SUPPORT )
  2837. return g_pSubDMgr->Lock( nNumRows );
  2838. #else
  2839. // not supported
  2840. Assert( 0 );
  2841. return NULL;
  2842. #endif
  2843. }
  2844. void CMatRenderContext::UnlockSubDBuffer()
  2845. {
  2846. #if defined( FEATURE_SUBD_SUPPORT )
  2847. return g_pSubDMgr->Unlock();
  2848. #else
  2849. // not supported
  2850. Assert( 0 );
  2851. #endif
  2852. }
  2853. //-----------------------------------------------------------------------------
  2854. // Occlusion query support
  2855. //-----------------------------------------------------------------------------
  2856. OcclusionQueryObjectHandle_t CMatRenderContext::CreateOcclusionQueryObject()
  2857. {
  2858. OcclusionQueryObjectHandle_t h = g_pOcclusionQueryMgr->CreateOcclusionQueryObject();
  2859. g_pOcclusionQueryMgr->OnCreateOcclusionQueryObject( h );
  2860. return h;
  2861. }
  2862. int CMatRenderContext::OcclusionQuery_GetNumPixelsRendered( OcclusionQueryObjectHandle_t h )
  2863. {
  2864. return g_pOcclusionQueryMgr->OcclusionQuery_GetNumPixelsRendered( h, true );
  2865. }
  2866. void CMatRenderContext::SetFullScreenDepthTextureValidityFlag( bool bIsValid )
  2867. {
  2868. m_bFullFrameDepthIsValid = bIsValid;
  2869. }
  2870. //-----------------------------------------------------------------------------
  2871. // Debug logging
  2872. //-----------------------------------------------------------------------------
  2873. void CMatRenderContext::PrintfVA( char *fmt, va_list vargs )
  2874. {
  2875. #if GLMDEBUG
  2876. g_pShaderAPI->PrintfVA( fmt, vargs );
  2877. #endif
  2878. }
  2879. void CMatRenderContext::Printf( char *fmt, ... )
  2880. {
  2881. #if GLMDEBUG
  2882. va_list vargs;
  2883. va_start(vargs, fmt);
  2884. g_pShaderAPI->PrintfVA( fmt, vargs );
  2885. va_end( vargs );
  2886. #endif
  2887. }
  2888. float CMatRenderContext::Knob( char *knobname, float *setvalue )
  2889. {
  2890. #if GLMDEBUG
  2891. return g_pShaderAPI->Knob( knobname, setvalue );
  2892. #else
  2893. return 0.0f;
  2894. #endif
  2895. }