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.

6818 lines
205 KiB

  1. //================ Copyright (c) Valve Corporation. All Rights Reserved. =================
  2. //
  3. // dxabstract.cpp
  4. //
  5. //==================================================================================================
  6. #include "togl/rendermechanism.h"
  7. #include "tier0/dynfunction.h"
  8. #include "tier0/vprof_telemetry.h"
  9. #include "tier0/dbg.h"
  10. #include "tier0/threadtools.h"
  11. #include "tier0/vprof.h"
  12. #include "tier1/strtools.h"
  13. #include "tier1/utlbuffer.h"
  14. #include "dx9asmtogl2.h"
  15. #include "mathlib/vmatrix.h"
  16. #include "materialsystem/IShader.h"
  17. #if defined(OSX) || defined(LINUX) || (defined (WIN32) && defined( DX_TO_GL_ABSTRACTION ))
  18. #include "appframework/ilaunchermgr.h"
  19. extern ILauncherMgr *g_pLauncherMgr;
  20. #endif
  21. #include "tier0/icommandline.h"
  22. #include "tier0/memdbgon.h"
  23. #ifdef USE_ACTUAL_DX
  24. #pragma comment( lib, "../../dx9sdk/lib/d3d9.lib" )
  25. #pragma comment( lib, "../../dx9sdk/lib/d3dx9.lib" )
  26. #else
  27. #ifdef POSIX
  28. #define strcat_s( a, b, c) V_strcat( a, c, b )
  29. #endif
  30. #define D3D_DEVICE_VALID_MARKER 0x12EBC845
  31. #define GL_PUBLIC_ENTRYPOINT_CHECKS( dev ) Assert( dev->GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); Assert( dev->m_nValidMarker == D3D_DEVICE_VALID_MARKER );
  32. // ------------------------------------------------------------------------------------------------------------------------------ //
  33. bool g_bNullD3DDevice;
  34. static D3DToGL g_D3DToOpenGLTranslatorGLSL;
  35. static IDirect3DDevice9 *g_pD3D_Device;
  36. #if GL_BATCH_PERF_ANALYSIS
  37. #include "../../thirdparty/miniz/simple_bitmap.h"
  38. #include "../../thirdparty/miniz/miniz.c"
  39. ConVar gl_batch_vis_abs_scale( "gl_batch_vis_abs_scale", ".050" );
  40. ConVar gl_present_vis_abs_scale( "gl_present_vis_abs_scale", ".050" );
  41. //ConVar gl_batch_vis_y_scale( "gl_batch_vis_y_scale", "0.007" );
  42. ConVar gl_batch_vis_y_scale( "gl_batch_vis_y_scale", "0.0" );
  43. static double s_rdtsc_to_ms;
  44. uint64 g_nTotalD3DCycles;
  45. uint g_nTotalD3DCalls;
  46. class CGLBatchPerfCallTimer
  47. {
  48. public:
  49. inline CGLBatchPerfCallTimer() { g_nTotalD3DCalls++; g_nTotalD3DCycles -= TM_FAST_TIME(); }
  50. inline ~CGLBatchPerfCallTimer() { g_nTotalD3DCycles += TM_FAST_TIME(); }
  51. };
  52. #define GL_BATCH_PERF_CALL_TIMER CGLBatchPerfCallTimer scopedCallTimer;
  53. #else
  54. #define GL_BATCH_PERF_CALL_TIMER
  55. #endif // GL_BATCH_PERF_ANALYSIS
  56. ConVar gl_batch_vis( "gl_batch_vis", "0" );
  57. // ------------------------------------------------------------------------------------------------------------------------------ //
  58. // functions that are dependant on g_pLauncherMgr
  59. inline GLMDisplayDB *GetDisplayDB( void )
  60. {
  61. return g_pLauncherMgr->GetDisplayDB();
  62. }
  63. inline void RenderedSize( uint &width, uint &height, bool set )
  64. {
  65. g_pLauncherMgr->RenderedSize( width, height, set );
  66. }
  67. inline void GetStackCrawl( CStackCrawlParams *params )
  68. {
  69. g_pLauncherMgr->GetStackCrawl(params);
  70. }
  71. // ------------------------------------------------------------------------------------------------------------------------------ //
  72. #if defined( WIN32 )
  73. bool D3DMATRIX::operator == ( CONST D3DMATRIX& src) const
  74. {
  75. return V_memcmp( (void*)this, (void*)&src, sizeof(this) ) == 0;
  76. }
  77. D3DMATRIX::operator void* ()
  78. {
  79. return (void*)this;
  80. }
  81. #endif
  82. // ------------------------------------------------------------------------------------------------------------------------------ //
  83. #ifdef OSX
  84. #pragma mark ----- D3DXMATRIX operators
  85. #endif
  86. D3DXMATRIX D3DXMATRIX::operator*( const D3DXMATRIX &o ) const
  87. {
  88. D3DXMATRIX result;
  89. D3DXMatrixMultiply( &result, this, &o ); // this = lhs o = rhs result = this * o
  90. return result;
  91. }
  92. D3DXMATRIX::operator FLOAT* ()
  93. {
  94. return (float*)this;
  95. }
  96. float& D3DXMATRIX::operator()( int row, int column )
  97. {
  98. return m[row][column];
  99. }
  100. const float& D3DXMATRIX::operator()( int row, int column ) const
  101. {
  102. return m[row][column];
  103. }
  104. bool D3DXMATRIX::operator != ( CONST D3DXMATRIX& src ) const
  105. {
  106. return V_memcmp( (void*)this, (void*)&src, sizeof(this) ) != 0;
  107. }
  108. // ------------------------------------------------------------------------------------------------------------------------------ //
  109. #ifdef OSX
  110. #pragma mark ----- D3DXPLANE operators
  111. #endif
  112. float& D3DXPLANE::operator[]( int i )
  113. {
  114. return ((float*)this)[i];
  115. }
  116. bool D3DXPLANE::operator==( const D3DXPLANE &o )
  117. {
  118. return a == o.a && b == o.b && c == o.c && d == o.d;
  119. }
  120. bool D3DXPLANE::operator!=( const D3DXPLANE &o )
  121. {
  122. return !( *this == o );
  123. }
  124. D3DXPLANE::operator float*()
  125. {
  126. return (float*)this;
  127. }
  128. D3DXPLANE::operator const float*() const
  129. {
  130. return (const float*)this;
  131. }
  132. // ------------------------------------------------------------------------------------------------------------------------------ //
  133. #ifdef OSX
  134. #pragma mark ----- D3DXVECTOR2 operators
  135. #endif
  136. D3DXVECTOR2::operator FLOAT* ()
  137. {
  138. return (float*)this;
  139. }
  140. D3DXVECTOR2::operator CONST FLOAT* () const
  141. {
  142. return (const float*)this;
  143. }
  144. // ------------------------------------------------------------------------------------------------------------------------------ //
  145. #ifdef OSX
  146. #pragma mark ----- D3DXVECTOR3 operators
  147. #endif
  148. D3DXVECTOR3::D3DXVECTOR3( float a, float b, float c )
  149. {
  150. x = a;
  151. y = b;
  152. z = c;
  153. }
  154. D3DXVECTOR3::operator FLOAT* ()
  155. {
  156. return (float*)this;
  157. }
  158. D3DXVECTOR3::operator CONST FLOAT* () const
  159. {
  160. return (const float*)this;
  161. }
  162. // ------------------------------------------------------------------------------------------------------------------------------ //
  163. #ifdef OSX
  164. #pragma mark ----- D3DXVECTOR4 operators
  165. #endif
  166. D3DXVECTOR4::D3DXVECTOR4( float a, float b, float c, float d )
  167. {
  168. x = a;
  169. y = b;
  170. z = c;
  171. w = d;
  172. }
  173. // ------------------------------------------------------------------------------------------------------------------------------ //
  174. DWORD IDirect3DResource9::SetPriority(DWORD PriorityNew)
  175. {
  176. // DXABSTRACT_BREAK_ON_ERROR();
  177. // GLMPRINTF(( "-X- SetPriority" ));
  178. // no-op city
  179. return 0;
  180. }
  181. // ------------------------------------------------------------------------------------------------------------------------------ //
  182. #ifdef OSX
  183. #pragma mark ----- IDirect3DBaseTexture9
  184. #endif
  185. IDirect3DBaseTexture9::~IDirect3DBaseTexture9()
  186. {
  187. GL_BATCH_PERF_CALL_TIMER;
  188. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  189. GLMPRINTF(( ">-A- ~IDirect3DBaseTexture9" ));
  190. if (m_device)
  191. {
  192. Assert( m_device->m_ObjectStats.m_nTotalTextures >= 1 );
  193. m_device->m_ObjectStats.m_nTotalTextures--;
  194. GLMPRINTF(( "-A- ~IDirect3DBaseTexture9 taking normal delete path on %08x, device is %08x ", this, m_device ));
  195. m_device->ReleasedTexture( this );
  196. if (m_tex)
  197. {
  198. GLMPRINTF(("-A- ~IDirect3DBaseTexture9 deleted '%s' @ %08x (GLM %08x) %s",m_tex->m_layout->m_layoutSummary, this, m_tex, m_tex->m_debugLabel ? m_tex->m_debugLabel : "" ));
  199. m_device->ReleasedCGLMTex( m_tex );
  200. m_tex->m_ctx->DelTex( m_tex );
  201. m_tex = NULL;
  202. }
  203. else
  204. {
  205. GLMPRINTF(( "-A- ~IDirect3DBaseTexture9 : whoops, no tex to delete here ?" ));
  206. }
  207. m_device = NULL; // ** THIS ** is the only place to scrub this. Don't do it in the subclass destructors.
  208. }
  209. else
  210. {
  211. GLMPRINTF(( "-A- ~IDirect3DBaseTexture9 taking strange delete path on %08x, device is %08x ", this, m_device ));
  212. }
  213. GLMPRINTF(( "<-A- ~IDirect3DBaseTexture9" ));
  214. }
  215. D3DRESOURCETYPE IDirect3DBaseTexture9::GetType()
  216. {
  217. GL_BATCH_PERF_CALL_TIMER;
  218. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  219. return m_restype; //D3DRTYPE_TEXTURE;
  220. }
  221. DWORD IDirect3DBaseTexture9::GetLevelCount()
  222. {
  223. GL_BATCH_PERF_CALL_TIMER;
  224. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  225. return m_tex->m_layout->m_mipCount;
  226. }
  227. HRESULT IDirect3DBaseTexture9::GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc)
  228. {
  229. GL_BATCH_PERF_CALL_TIMER;
  230. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  231. Assert (Level < static_cast<uint>(m_tex->m_layout->m_mipCount));
  232. D3DSURFACE_DESC result = m_descZero;
  233. // then mutate it for the level of interest
  234. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( 0, Level ) ];
  235. result.Width = slice->m_xSize;
  236. result.Height = slice->m_ySize;
  237. *pDesc = result;
  238. return S_OK;
  239. }
  240. // ------------------------------------------------------------------------------------------------------------------------------ //
  241. #ifdef OSX
  242. #pragma mark ----- IDirect3DTexture9
  243. #endif
  244. HRESULT IDirect3DDevice9::CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,VD3DHANDLE* pSharedHandle, char *pDebugLabel )
  245. {
  246. GL_BATCH_PERF_CALL_TIMER;
  247. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  248. m_ObjectStats.m_nTotalTextures++;
  249. GLMPRINTF((">-A-IDirect3DDevice9::CreateTexture"));
  250. IDirect3DTexture9 *dxtex = new IDirect3DTexture9;
  251. dxtex->m_restype = D3DRTYPE_TEXTURE;
  252. dxtex->m_device = this;
  253. dxtex->m_descZero.Format = Format;
  254. dxtex->m_descZero.Type = D3DRTYPE_TEXTURE;
  255. dxtex->m_descZero.Usage = Usage;
  256. dxtex->m_descZero.Pool = Pool;
  257. dxtex->m_descZero.MultiSampleType = D3DMULTISAMPLE_NONE;
  258. dxtex->m_descZero.MultiSampleQuality = 0;
  259. dxtex->m_descZero.Width = Width;
  260. dxtex->m_descZero.Height = Height;
  261. GLMTexLayoutKey key;
  262. memset( &key, 0, sizeof(key) );
  263. key.m_texGLTarget = GL_TEXTURE_2D;
  264. key.m_texFormat = Format;
  265. if (Levels>1)
  266. {
  267. key.m_texFlags |= kGLMTexMipped;
  268. }
  269. // http://msdn.microsoft.com/en-us/library/bb172625(VS.85).aspx
  270. // complain if any usage bits come down that I don't know.
  271. uint knownUsageBits = (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_DYNAMIC | D3DUSAGE_TEXTURE_SRGB | D3DUSAGE_DEPTHSTENCIL);
  272. if ( (Usage & knownUsageBits) != Usage )
  273. {
  274. DXABSTRACT_BREAK_ON_ERROR();
  275. }
  276. if (Usage & D3DUSAGE_AUTOGENMIPMAP)
  277. {
  278. key.m_texFlags |= kGLMTexMipped | kGLMTexMippedAuto;
  279. }
  280. if (Usage & D3DUSAGE_DYNAMIC)
  281. {
  282. // GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME
  283. }
  284. if (Usage & D3DUSAGE_TEXTURE_SRGB)
  285. {
  286. key.m_texFlags |= kGLMTexSRGB;
  287. }
  288. if (Usage & D3DUSAGE_RENDERTARGET)
  289. {
  290. Assert( !(Usage & D3DUSAGE_DEPTHSTENCIL) );
  291. m_ObjectStats.m_nTotalRenderTargets++;
  292. key.m_texFlags |= kGLMTexRenderable;
  293. const GLMTexFormatDesc *pFmtDesc = GetFormatDesc( key.m_texFormat );
  294. if ( pFmtDesc->m_glIntFormatSRGB != 0 )
  295. {
  296. key.m_texFlags |= kGLMTexSRGB; // this catches callers of CreateTexture who set the "renderable" option - they get an SRGB tex
  297. }
  298. if (m_ctx->Caps().m_cantAttachSRGB)
  299. {
  300. // this config can't support SRGB render targets. quietly turn off the sRGB bit.
  301. key.m_texFlags &= ~kGLMTexSRGB;
  302. }
  303. }
  304. if ( ( Format == D3DFMT_D16 ) || ( Format == D3DFMT_D24X8 ) || ( Format == D3DFMT_D24S8 ) )
  305. {
  306. key.m_texFlags |= kGLMTexIsDepth;
  307. }
  308. if ( Format == D3DFMT_D24S8 )
  309. {
  310. key.m_texFlags |= kGLMTexIsStencil;
  311. }
  312. key.m_xSize = Width;
  313. key.m_ySize = Height;
  314. key.m_zSize = 1;
  315. CGLMTex *tex = m_ctx->NewTex( &key, Levels, pDebugLabel );
  316. if (!tex)
  317. {
  318. DXABSTRACT_BREAK_ON_ERROR();
  319. }
  320. dxtex->m_tex = tex;
  321. dxtex->m_tex->m_srgbFlipCount = 0;
  322. m_ObjectStats.m_nTotalSurfaces++;
  323. dxtex->m_surfZero = new IDirect3DSurface9;
  324. dxtex->m_surfZero->m_restype = (D3DRESOURCETYPE)0; // this is a ref to a tex, not the owner...
  325. // do not do an AddRef here.
  326. dxtex->m_surfZero->m_device = this;
  327. dxtex->m_surfZero->m_desc = dxtex->m_descZero;
  328. dxtex->m_surfZero->m_tex = tex;
  329. dxtex->m_surfZero->m_face = 0;
  330. dxtex->m_surfZero->m_mip = 0;
  331. GLMPRINTF(("-A- IDirect3DDevice9::CreateTexture created '%s' @ %08x (GLM %08x) %s",tex->m_layout->m_layoutSummary, dxtex, tex, pDebugLabel ? pDebugLabel : "" ));
  332. *ppTexture = dxtex;
  333. GLMPRINTF(("<-A-IDirect3DDevice9::CreateTexture"));
  334. return S_OK;
  335. }
  336. IDirect3DTexture9::~IDirect3DTexture9()
  337. {
  338. GL_BATCH_PERF_CALL_TIMER;
  339. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  340. GLMPRINTF(( ">-A- IDirect3DTexture9" ));
  341. // IDirect3DBaseTexture9::~IDirect3DBaseTexture9 frees up m_tex
  342. // we take care of surfZero
  343. if (m_device)
  344. {
  345. m_device->ReleasedTexture( this );
  346. if (m_surfZero)
  347. {
  348. ULONG refc = m_surfZero->Release( 0, "~IDirect3DTexture9 public release (surfZero)" ); (void)refc;
  349. Assert( !refc );
  350. m_surfZero = NULL;
  351. }
  352. // leave m_device alone!
  353. }
  354. GLMPRINTF(( "<-A- IDirect3DTexture9" ));
  355. }
  356. HRESULT IDirect3DTexture9::LockRect(UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags)
  357. {
  358. GL_BATCH_PERF_CALL_TIMER;
  359. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  360. DXABSTRACT_BREAK_ON_ERROR();
  361. return S_OK;
  362. }
  363. HRESULT IDirect3DTexture9::UnlockRect(UINT Level)
  364. {
  365. GL_BATCH_PERF_CALL_TIMER;
  366. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  367. DXABSTRACT_BREAK_ON_ERROR();
  368. return S_OK;
  369. }
  370. HRESULT IDirect3DTexture9::GetSurfaceLevel(UINT Level,IDirect3DSurface9** ppSurfaceLevel)
  371. {
  372. GL_BATCH_PERF_CALL_TIMER;
  373. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  374. // we create and pass back a surface, and the client is on the hook to release it. tidy.
  375. m_device->m_ObjectStats.m_nTotalSurfaces++;
  376. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  377. surf->m_restype = (D3DRESOURCETYPE)0; // 0 is special and means this 'surface' does not own its m_tex
  378. // Dicey...higher level code seems to want this and not want this. Are we missing some AddRef/Release behavior elsewhere?
  379. // trying to turn this off - experimental - 26Oct2010 surf->AddRef();
  380. surf->m_device = this->m_device;
  381. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( 0, Level ) ];
  382. surf->m_desc = m_descZero;
  383. surf->m_desc.Width = slice->m_xSize;
  384. surf->m_desc.Height = slice->m_ySize;
  385. surf->m_tex = m_tex;
  386. surf->m_face = 0;
  387. surf->m_mip = Level;
  388. *ppSurfaceLevel = surf;
  389. return S_OK;
  390. }
  391. // ------------------------------------------------------------------------------------------------------------------------------ //
  392. #ifdef OSX
  393. #pragma mark ----- IDirect3DCubeTexture9
  394. #endif
  395. HRESULT IDirect3DDevice9::CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,VD3DHANDLE* pSharedHandle, char *pDebugLabel)
  396. {
  397. GL_BATCH_PERF_CALL_TIMER;
  398. Assert( m_ctx->m_nCurOwnerThreadId == ThreadGetCurrentId() );
  399. GLMPRINTF((">-A- IDirect3DDevice9::CreateCubeTexture"));
  400. Assert( m_ctx->m_nCurOwnerThreadId == ThreadGetCurrentId() );
  401. m_ObjectStats.m_nTotalTextures++;
  402. IDirect3DCubeTexture9 *dxtex = new IDirect3DCubeTexture9;
  403. dxtex->m_restype = D3DRTYPE_CUBETEXTURE;
  404. dxtex->m_device = this;
  405. dxtex->m_descZero.Format = Format;
  406. dxtex->m_descZero.Type = D3DRTYPE_CUBETEXTURE;
  407. dxtex->m_descZero.Usage = Usage;
  408. dxtex->m_descZero.Pool = Pool;
  409. dxtex->m_descZero.MultiSampleType = D3DMULTISAMPLE_NONE;
  410. dxtex->m_descZero.MultiSampleQuality = 0;
  411. dxtex->m_descZero.Width = EdgeLength;
  412. dxtex->m_descZero.Height = EdgeLength;
  413. GLMTexLayoutKey key;
  414. memset( &key, 0, sizeof(key) );
  415. key.m_texGLTarget = GL_TEXTURE_CUBE_MAP;
  416. key.m_texFormat = Format;
  417. if (Levels>1)
  418. {
  419. key.m_texFlags |= kGLMTexMipped;
  420. }
  421. // http://msdn.microsoft.com/en-us/library/bb172625(VS.85).aspx
  422. // complain if any usage bits come down that I don't know.
  423. uint knownUsageBits = (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_DYNAMIC | D3DUSAGE_TEXTURE_SRGB);
  424. if ( (Usage & knownUsageBits) != Usage )
  425. {
  426. DXABSTRACT_BREAK_ON_ERROR();
  427. }
  428. if (Usage & D3DUSAGE_AUTOGENMIPMAP)
  429. {
  430. key.m_texFlags |= kGLMTexMipped | kGLMTexMippedAuto;
  431. }
  432. if (Usage & D3DUSAGE_RENDERTARGET)
  433. {
  434. key.m_texFlags |= kGLMTexRenderable;
  435. m_ObjectStats.m_nTotalRenderTargets++;
  436. }
  437. if (Usage & D3DUSAGE_DYNAMIC)
  438. {
  439. //GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME
  440. }
  441. if (Usage & D3DUSAGE_TEXTURE_SRGB)
  442. {
  443. key.m_texFlags |= kGLMTexSRGB;
  444. }
  445. key.m_xSize = EdgeLength;
  446. key.m_ySize = EdgeLength;
  447. key.m_zSize = 1;
  448. CGLMTex *tex = m_ctx->NewTex( &key, Levels, pDebugLabel );
  449. if (!tex)
  450. {
  451. DXABSTRACT_BREAK_ON_ERROR();
  452. }
  453. dxtex->m_tex = tex;
  454. dxtex->m_tex->m_srgbFlipCount = 0;
  455. for( int face = 0; face < 6; face ++)
  456. {
  457. m_ObjectStats.m_nTotalSurfaces++;
  458. dxtex->m_surfZero[face] = new IDirect3DSurface9;
  459. dxtex->m_surfZero[face]->m_restype = (D3DRESOURCETYPE)0; // 0 is special and means this 'surface' does not own its m_tex
  460. // do not do an AddRef here.
  461. dxtex->m_surfZero[face]->m_device = this;
  462. dxtex->m_surfZero[face]->m_desc = dxtex->m_descZero;
  463. dxtex->m_surfZero[face]->m_tex = tex;
  464. dxtex->m_surfZero[face]->m_face = face;
  465. dxtex->m_surfZero[face]->m_mip = 0;
  466. }
  467. GLMPRINTF(("-A- IDirect3DDevice9::CreateCubeTexture created '%s' @ %08x (GLM %08x)",tex->m_layout->m_layoutSummary, dxtex, tex ));
  468. *ppCubeTexture = dxtex;
  469. GLMPRINTF(("<-A- IDirect3DDevice9::CreateCubeTexture"));
  470. return S_OK;
  471. }
  472. IDirect3DCubeTexture9::~IDirect3DCubeTexture9()
  473. {
  474. GL_BATCH_PERF_CALL_TIMER;
  475. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  476. GLMPRINTF(( ">-A- ~IDirect3DCubeTexture9" ));
  477. if (m_device)
  478. {
  479. GLMPRINTF(( "-A- ~IDirect3DCubeTexture9 taking normal delete path on %08x, device is %08x, surfzero[0] is %08x ", this, m_device, m_surfZero[0] ));
  480. m_device->ReleasedTexture( this );
  481. // let IDirect3DBaseTexture9::~IDirect3DBaseTexture9 free up m_tex
  482. // we handle the surfZero array for the faces
  483. for( int face = 0; face < 6; face ++)
  484. {
  485. if (m_surfZero[face])
  486. {
  487. Assert( m_surfZero[face]->m_device == m_device );
  488. ULONG refc = m_surfZero[face]->Release( 0, "~IDirect3DCubeTexture9 public release (surfZero)");
  489. if ( refc!=0 )
  490. {
  491. GLMPRINTF(( "-A- ~IDirect3DCubeTexture9 seeing non zero refcount on surfzero[%d] => %d ", face, refc ));
  492. }
  493. m_surfZero[face] = NULL;
  494. }
  495. }
  496. // leave m_device alone!
  497. }
  498. else
  499. {
  500. GLMPRINTF(( "-A- ~IDirect3DCubeTexture9 taking strange delete path on %08x, device is %08x, surfzero[0] is %08x ", this, m_device, m_surfZero[0] ));
  501. }
  502. GLMPRINTF(( "<-A- ~IDirect3DCubeTexture9" ));
  503. }
  504. HRESULT IDirect3DCubeTexture9::GetCubeMapSurface(D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface)
  505. {
  506. GL_BATCH_PERF_CALL_TIMER;
  507. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  508. // we create and pass back a surface, and the client is on the hook to release it...
  509. m_device->m_ObjectStats.m_nTotalSurfaces++;
  510. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  511. surf->m_restype = (D3DRESOURCETYPE)0; // 0 is special and means this 'surface' does not own its m_tex
  512. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( FaceType, Level ) ];
  513. surf->m_device = this->m_device;
  514. surf->m_desc = m_descZero;
  515. surf->m_desc.Width = slice->m_xSize;
  516. surf->m_desc.Height = slice->m_ySize;
  517. surf->m_tex = m_tex;
  518. surf->m_face = FaceType;
  519. surf->m_mip = Level;
  520. *ppCubeMapSurface = surf;
  521. return S_OK;
  522. }
  523. HRESULT IDirect3DCubeTexture9::GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc)
  524. {
  525. GL_BATCH_PERF_CALL_TIMER;
  526. Assert (Level < static_cast<uint>(m_tex->m_layout->m_mipCount));
  527. D3DSURFACE_DESC result = m_descZero;
  528. // then mutate it for the level of interest
  529. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( 0, Level ) ];
  530. result.Width = slice->m_xSize;
  531. result.Height = slice->m_ySize;
  532. *pDesc = result;
  533. return S_OK;
  534. }
  535. // ------------------------------------------------------------------------------------------------------------------------------ //
  536. #ifdef OSX
  537. #pragma mark ----- IDirect3DVolumeTexture9
  538. #endif
  539. HRESULT IDirect3DDevice9::CreateVolumeTexture(UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,VD3DHANDLE* pSharedHandle, char *pDebugLabel)
  540. {
  541. GL_BATCH_PERF_CALL_TIMER;
  542. GLMPRINTF((">-A- IDirect3DDevice9::CreateVolumeTexture"));
  543. // set dxtex->m_restype to D3DRTYPE_VOLUMETEXTURE...
  544. Assert( m_ctx->m_nCurOwnerThreadId == ThreadGetCurrentId() );
  545. m_ObjectStats.m_nTotalTextures++;
  546. IDirect3DVolumeTexture9 *dxtex = new IDirect3DVolumeTexture9;
  547. dxtex->m_restype = D3DRTYPE_VOLUMETEXTURE;
  548. dxtex->m_device = this;
  549. dxtex->m_descZero.Format = Format;
  550. dxtex->m_descZero.Type = D3DRTYPE_VOLUMETEXTURE;
  551. dxtex->m_descZero.Usage = Usage;
  552. dxtex->m_descZero.Pool = Pool;
  553. dxtex->m_descZero.MultiSampleType = D3DMULTISAMPLE_NONE;
  554. dxtex->m_descZero.MultiSampleQuality = 0;
  555. dxtex->m_descZero.Width = Width;
  556. dxtex->m_descZero.Height = Height;
  557. // also a volume specific desc
  558. dxtex->m_volDescZero.Format = Format;
  559. dxtex->m_volDescZero.Type = D3DRTYPE_VOLUMETEXTURE;
  560. dxtex->m_volDescZero.Usage = Usage;
  561. dxtex->m_volDescZero.Pool = Pool;
  562. dxtex->m_volDescZero.Width = Width;
  563. dxtex->m_volDescZero.Height = Height;
  564. dxtex->m_volDescZero.Depth = Depth;
  565. GLMTexLayoutKey key;
  566. memset( &key, 0, sizeof(key) );
  567. key.m_texGLTarget = GL_TEXTURE_3D;
  568. key.m_texFormat = Format;
  569. if (Levels>1)
  570. {
  571. key.m_texFlags |= kGLMTexMipped;
  572. }
  573. // http://msdn.microsoft.com/en-us/library/bb172625(VS.85).aspx
  574. // complain if any usage bits come down that I don't know.
  575. uint knownUsageBits = (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_DYNAMIC | D3DUSAGE_TEXTURE_SRGB);
  576. if ( (Usage & knownUsageBits) != Usage )
  577. {
  578. DXABSTRACT_BREAK_ON_ERROR();
  579. }
  580. if (Usage & D3DUSAGE_AUTOGENMIPMAP)
  581. {
  582. key.m_texFlags |= kGLMTexMipped | kGLMTexMippedAuto;
  583. }
  584. if (Usage & D3DUSAGE_RENDERTARGET)
  585. {
  586. key.m_texFlags |= kGLMTexRenderable;
  587. m_ObjectStats.m_nTotalRenderTargets++;
  588. }
  589. if (Usage & D3DUSAGE_DYNAMIC)
  590. {
  591. GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME
  592. }
  593. if (Usage & D3DUSAGE_TEXTURE_SRGB)
  594. {
  595. key.m_texFlags |= kGLMTexSRGB;
  596. }
  597. key.m_xSize = Width;
  598. key.m_ySize = Height;
  599. key.m_zSize = Depth;
  600. CGLMTex *tex = m_ctx->NewTex( &key, Levels, pDebugLabel );
  601. if (!tex)
  602. {
  603. DXABSTRACT_BREAK_ON_ERROR();
  604. }
  605. dxtex->m_tex = tex;
  606. dxtex->m_tex->m_srgbFlipCount = 0;
  607. m_ObjectStats.m_nTotalSurfaces++;
  608. dxtex->m_surfZero = new IDirect3DSurface9;
  609. dxtex->m_surfZero->m_restype = (D3DRESOURCETYPE)0; // this is a ref to a tex, not the owner...
  610. // do not do an AddRef here.
  611. dxtex->m_surfZero->m_device = this;
  612. dxtex->m_surfZero->m_desc = dxtex->m_descZero;
  613. dxtex->m_surfZero->m_tex = tex;
  614. dxtex->m_surfZero->m_face = 0;
  615. dxtex->m_surfZero->m_mip = 0;
  616. GLMPRINTF(("-A- IDirect3DDevice9::CreateVolumeTexture created '%s' @ %08x (GLM %08x)",tex->m_layout->m_layoutSummary, dxtex, tex ));
  617. *ppVolumeTexture = dxtex;
  618. GLMPRINTF(("<-A- IDirect3DDevice9::CreateVolumeTexture"));
  619. return S_OK;
  620. }
  621. IDirect3DVolumeTexture9::~IDirect3DVolumeTexture9()
  622. {
  623. GL_BATCH_PERF_CALL_TIMER;
  624. GLMPRINTF((">-A- ~IDirect3DVolumeTexture9"));
  625. if (m_device)
  626. {
  627. m_device->ReleasedTexture( this );
  628. // let IDirect3DBaseTexture9::~IDirect3DBaseTexture9 free up m_tex
  629. // we handle m_surfZero
  630. if (m_surfZero)
  631. {
  632. ULONG refc = m_surfZero->Release( 0, "~IDirect3DVolumeTexture9 public release (surfZero)" ); (void)refc;
  633. Assert( !refc );
  634. m_surfZero = NULL;
  635. }
  636. // leave m_device alone!
  637. }
  638. GLMPRINTF(("<-A- ~IDirect3DVolumeTexture9"));
  639. }
  640. HRESULT IDirect3DVolumeTexture9::LockBox(UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags)
  641. {
  642. GL_BATCH_PERF_CALL_TIMER;
  643. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  644. GLMTexLockParams lockreq;
  645. memset( &lockreq, 0, sizeof(lockreq) );
  646. lockreq.m_tex = this->m_tex;
  647. lockreq.m_face = 0;
  648. lockreq.m_mip = Level;
  649. lockreq.m_region.xmin = pBox->Left;
  650. lockreq.m_region.ymin = pBox->Top;
  651. lockreq.m_region.zmin = pBox->Front;
  652. lockreq.m_region.xmax = pBox->Right;
  653. lockreq.m_region.ymax = pBox->Bottom;
  654. lockreq.m_region.zmax = pBox->Back;
  655. char *lockAddress;
  656. int yStride;
  657. int zStride;
  658. lockreq.m_tex->Lock( &lockreq, &lockAddress, &yStride, &zStride );
  659. pLockedVolume->RowPitch = yStride;
  660. pLockedVolume->SlicePitch = yStride;
  661. pLockedVolume->pBits = lockAddress;
  662. return S_OK;
  663. }
  664. HRESULT IDirect3DVolumeTexture9::UnlockBox(UINT Level)
  665. {
  666. GL_BATCH_PERF_CALL_TIMER;
  667. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  668. GLMTexLockParams lockreq;
  669. memset( &lockreq, 0, sizeof(lockreq) );
  670. lockreq.m_tex = this->m_tex;
  671. lockreq.m_face = 0;
  672. lockreq.m_mip = Level;
  673. this->m_tex->Unlock( &lockreq );
  674. return S_OK;
  675. }
  676. HRESULT IDirect3DVolumeTexture9::GetLevelDesc( UINT Level, D3DVOLUME_DESC *pDesc )
  677. {
  678. GL_BATCH_PERF_CALL_TIMER;
  679. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  680. if (Level > static_cast<uint>(m_tex->m_layout->m_mipCount))
  681. {
  682. DXABSTRACT_BREAK_ON_ERROR();
  683. }
  684. D3DVOLUME_DESC result = m_volDescZero;
  685. // then mutate it for the level of interest
  686. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( 0, Level ) ];
  687. result.Width = slice->m_xSize;
  688. result.Height = slice->m_ySize;
  689. result.Depth = slice->m_zSize;
  690. *pDesc = result;
  691. return S_OK;
  692. }
  693. // ------------------------------------------------------------------------------------------------------------------------------ //
  694. #ifdef OSX
  695. #pragma mark ----- IDirect3DSurface9
  696. #endif
  697. IDirect3DSurface9::~IDirect3DSurface9()
  698. {
  699. GL_BATCH_PERF_CALL_TIMER;
  700. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  701. // not much to do here, but good to verify that these things are being freed (and they are)
  702. //GLMPRINTF(("-A- ~IDirect3DSurface9 - signpost"));
  703. if (m_device)
  704. {
  705. GLMPRINTF(("-A- ~IDirect3DSurface9 - taking real delete path on %08x device %08x", this, m_device));
  706. m_device->ReleasedSurface( this );
  707. memset( &m_desc, 0, sizeof(m_desc) );
  708. if (m_restype != 0) // signal that we are a surface that owns this tex (render target)
  709. {
  710. if (m_tex)
  711. {
  712. GLMPRINTF(("-A- ~IDirect3DSurface9 deleted '%s' @ %08x (GLM %08x) %s",m_tex->m_layout->m_layoutSummary, this, m_tex, m_tex->m_debugLabel ? m_tex->m_debugLabel : "" ));
  713. m_device->ReleasedCGLMTex( m_tex );
  714. m_tex->m_ctx->DelTex( m_tex );
  715. m_tex = NULL;
  716. }
  717. else
  718. {
  719. GLMPRINTF(( "-A- ~IDirect3DSurface9 : whoops, no tex to delete here ?" ));
  720. }
  721. }
  722. else
  723. {
  724. m_tex = NULL; // we are just a view on the tex, we don't own the tex, do not delete it
  725. }
  726. m_face = m_mip = 0;
  727. m_device = NULL;
  728. }
  729. else
  730. {
  731. GLMPRINTF(("-A- ~IDirect3DSurface9 - taking strange delete path on %08x device %08x", this, m_device));
  732. }
  733. }
  734. HRESULT IDirect3DSurface9::LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags)
  735. {
  736. GL_BATCH_PERF_CALL_TIMER;
  737. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  738. GLMTexLockParams lockreq;
  739. memset( &lockreq, 0, sizeof(lockreq) );
  740. lockreq.m_tex = this->m_tex;
  741. lockreq.m_face = this->m_face;
  742. lockreq.m_mip = this->m_mip;
  743. lockreq.m_region.xmin = pRect->left;
  744. lockreq.m_region.ymin = pRect->top;
  745. lockreq.m_region.zmin = 0;
  746. lockreq.m_region.xmax = pRect->right;
  747. lockreq.m_region.ymax = pRect->bottom;
  748. lockreq.m_region.zmax = 1;
  749. if ((Flags & (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)) == (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK) )
  750. {
  751. // smells like readback, force texel readout
  752. lockreq.m_readback = true;
  753. }
  754. char *lockAddress;
  755. int yStride;
  756. int zStride;
  757. lockreq.m_tex->Lock( &lockreq, &lockAddress, &yStride, &zStride );
  758. pLockedRect->Pitch = yStride;
  759. pLockedRect->pBits = lockAddress;
  760. return S_OK;
  761. }
  762. HRESULT IDirect3DSurface9::UnlockRect()
  763. {
  764. GL_BATCH_PERF_CALL_TIMER;
  765. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  766. GLMTexLockParams lockreq;
  767. memset( &lockreq, 0, sizeof(lockreq) );
  768. lockreq.m_tex = this->m_tex;
  769. lockreq.m_face = this->m_face;
  770. lockreq.m_mip = this->m_mip;
  771. lockreq.m_tex->Unlock( &lockreq );
  772. return S_OK;
  773. }
  774. HRESULT IDirect3DSurface9::GetDesc(D3DSURFACE_DESC *pDesc)
  775. {
  776. GL_BATCH_PERF_CALL_TIMER;
  777. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  778. *pDesc = m_desc;
  779. return S_OK;
  780. }
  781. // ------------------------------------------------------------------------------------------------------------------------------ //
  782. #ifdef OSX
  783. #pragma mark ----- IDirect3D9 -------------------------------------------------------
  784. #endif
  785. IDirect3D9::~IDirect3D9()
  786. {
  787. GL_BATCH_PERF_CALL_TIMER;
  788. GLMPRINTF(("-A- ~IDirect3D9 - signpost"));
  789. }
  790. UINT IDirect3D9::GetAdapterCount()
  791. {
  792. GL_BATCH_PERF_CALL_TIMER;
  793. GLMgr::NewGLMgr(); // init GL manager
  794. GLMDisplayDB *db = GetDisplayDB();
  795. int dxAdapterCount = db->GetFakeAdapterCount();
  796. return dxAdapterCount;
  797. }
  798. static void FillD3DCaps9( const GLMRendererInfoFields &glmRendererInfo, D3DCAPS9* pCaps )
  799. {
  800. // fill in the pCaps record for adapter... we zero most of it and just fill in the fields that we think the caller wants.
  801. Q_memset( pCaps, 0, sizeof(*pCaps) );
  802. /* Device Info */
  803. pCaps->DeviceType = D3DDEVTYPE_HAL;
  804. /* Caps from DX7 Draw */
  805. pCaps->Caps = 0; // does anyone look at this ?
  806. pCaps->Caps2 = D3DCAPS2_DYNAMICTEXTURES;
  807. /* Cursor Caps */
  808. pCaps->CursorCaps = 0; // nobody looks at this
  809. /* 3D Device Caps */
  810. pCaps->DevCaps = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
  811. pCaps->TextureCaps = D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_MIPCUBEMAP | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PROJECTED;
  812. // D3DPTEXTURECAPS_NOPROJECTEDBUMPENV ?
  813. // D3DPTEXTURECAPS_POW2 ?
  814. // caller looks at POT support like this:
  815. // pCaps->m_SupportsNonPow2Textures =
  816. // ( !( caps.TextureCaps & D3DPTEXTURECAPS_POW2 ) ||
  817. // ( caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL ) );
  818. // so we should set D3DPTEXTURECAPS_NONPOW2CONDITIONAL bit ?
  819. pCaps->PrimitiveMiscCaps = 0; //only the HDR setup looks at this for D3DPMISCCAPS_SEPARATEALPHABLEND.
  820. // ? D3DPMISCCAPS_SEPARATEALPHABLEND
  821. // ? D3DPMISCCAPS_BLENDOP
  822. // ? D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
  823. // ? D3DPMISCCAPS_CLIPTLVERTS D3DPMISCCAPS_COLORWRITEENABLE D3DPMISCCAPS_MASKZ D3DPMISCCAPS_TSSARGTEMP
  824. pCaps->RasterCaps = D3DPRASTERCAPS_SCISSORTEST
  825. | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS // ref'd in CShaderDeviceMgrDx8::ComputeCapsFromD3D
  826. | D3DPRASTERCAPS_DEPTHBIAS // ref'd in CShaderDeviceMgrDx8::ComputeCapsFromD3D
  827. ;
  828. pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MAGFANISOTROPIC;
  829. pCaps->MaxTextureWidth = 4096;
  830. pCaps->MaxTextureHeight = 4096;
  831. pCaps->MaxVolumeExtent = 1024; //guesses
  832. pCaps->MaxTextureAspectRatio = 0; // imply no limit on AR
  833. pCaps->MaxAnisotropy = glmRendererInfo.m_maxAniso;
  834. pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_MODULATE2X; //guess
  835. //DWORD MaxTextureBlendStages;
  836. //DWORD MaxSimultaneousTextures;
  837. pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN_SPHEREMAP;
  838. pCaps->MaxActiveLights = 8; // guess
  839. // MaxUserClipPlanes. A bit complicated..
  840. // it's difficult to make this fluid without teaching the engine about a cap that could change during run.
  841. // start it out set to '2'.
  842. // turn it off, if we're in GLSL mode but do not have native clip plane capability.
  843. pCaps->MaxUserClipPlanes = 2; // assume good news
  844. // is user asking for it to be off ?
  845. if ( CommandLine()->CheckParm( "-nouserclip" ) ||
  846. ( !glmRendererInfo.m_hasNativeClipVertexMode ) )
  847. {
  848. pCaps->MaxUserClipPlanes = 0;
  849. }
  850. pCaps->MaxVertexBlendMatrices = 0; // see if anyone cares
  851. pCaps->MaxVertexBlendMatrixIndex = 0; // see if anyone cares
  852. pCaps->MaxPrimitiveCount = 32768; // guess
  853. pCaps->MaxStreams = D3D_MAX_STREAMS; // guess
  854. pCaps->VertexShaderVersion = 0x300; // model 3.0
  855. pCaps->MaxVertexShaderConst = DXABSTRACT_VS_PARAM_SLOTS; // number of vertex shader constant registers
  856. pCaps->PixelShaderVersion = 0x300; // model 3.0
  857. // Here are the DX9 specific ones
  858. pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET;
  859. pCaps->PS20Caps.NumInstructionSlots = 512; // guess
  860. // only examined once:
  861. // pCaps->m_SupportsPixelShaders_2_b = ( ( caps.PixelShaderVersion & 0xffff ) >= 0x0200) && (caps.PS20Caps.NumInstructionSlots >= 512);
  862. //pCaps->m_SupportsPixelShaders_2_b = 1;
  863. pCaps->NumSimultaneousRTs = 1; // Will be at least 1
  864. pCaps->MaxVertexShader30InstructionSlots = 0;
  865. pCaps->MaxPixelShader30InstructionSlots = 0;
  866. #if DX_TO_GL_ABSTRACTION
  867. pCaps->FakeSRGBWrite = !glmRendererInfo.m_hasGammaWrites;
  868. pCaps->CanDoSRGBReadFromRTs = !glmRendererInfo.m_cantAttachSRGB;
  869. pCaps->MixedSizeTargets = glmRendererInfo.m_hasMixedAttachmentSizes;
  870. #endif
  871. }
  872. HRESULT IDirect3D9::GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps)
  873. {
  874. GL_BATCH_PERF_CALL_TIMER;
  875. // Generally called from "CShaderDeviceMgrDx8::ComputeCapsFromD3D" in ShaderDeviceDX8.cpp
  876. // "Adapter" is used to index amongst the set of fake-adapters maintained in the display DB
  877. GLMDisplayDB *db = GetDisplayDB();
  878. int glmRendererIndex = -1;
  879. int glmDisplayIndex = -1;
  880. GLMRendererInfoFields glmRendererInfo;
  881. GLMDisplayInfoFields glmDisplayInfo;
  882. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo ); (void)result;
  883. Assert (!result);
  884. // just leave glmRendererInfo filled out for subsequent code to look at as needed.
  885. FillD3DCaps9( glmRendererInfo, pCaps );
  886. return S_OK;
  887. }
  888. HRESULT IDirect3D9::GetAdapterIdentifier( UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier )
  889. {
  890. GL_BATCH_PERF_CALL_TIMER;
  891. // Generally called from "CShaderDeviceMgrDx8::ComputeCapsFromD3D" in ShaderDeviceDX8.cpp
  892. Assert( Flags == D3DENUM_WHQL_LEVEL ); // we're not handling any other queries than this yet
  893. Q_memset( pIdentifier, 0, sizeof(*pIdentifier) );
  894. GLMDisplayDB *db = GetDisplayDB();
  895. int glmRendererIndex = -1;
  896. int glmDisplayIndex = -1;
  897. GLMRendererInfoFields glmRendererInfo;
  898. GLMDisplayInfoFields glmDisplayInfo;
  899. // the D3D "Adapter" number feeds the fake adapter index
  900. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo ); (void)result;
  901. Assert (!result);
  902. #ifndef OSX
  903. if( glmRendererInfo.m_rendererID )
  904. #endif
  905. {
  906. const char *pRenderer = GLMDecode( eGL_RENDERER, glmRendererInfo.m_rendererID & 0x00FFFF00 );
  907. Q_snprintf( pIdentifier->Driver, sizeof(pIdentifier->Driver), "OpenGL %s (%08x)",
  908. pRenderer, glmRendererInfo.m_rendererID );
  909. Q_snprintf( pIdentifier->Description, sizeof(pIdentifier->Description), "%s - %dx%d - %dMB VRAM",
  910. pRenderer,
  911. glmDisplayInfo.m_displayPixelWidth, glmDisplayInfo.m_displayPixelHeight,
  912. glmRendererInfo.m_vidMemory >> 20 );
  913. }
  914. #ifndef OSX
  915. else
  916. {
  917. static CDynamicFunctionOpenGL< true, const GLubyte *( APIENTRY *)(GLenum name), const GLubyte * > glGetString( NULL, "glGetString" );
  918. const char *pszStringVendor = ( const char * )glGetString( GL_VENDOR ); // NVIDIA Corporation
  919. const char *pszStringRenderer = ( const char * )glGetString( GL_RENDERER ); // GeForce GTX 680/PCIe/SSE2
  920. const char *pszStringVersion = ( const char * )glGetString( GL_VERSION ); // 4.2.0 NVIDIA 304.22
  921. Q_snprintf( pIdentifier->Driver, sizeof( pIdentifier->Driver ), "OpenGL %s (%s)",
  922. pszStringVendor, pszStringRenderer );
  923. Q_snprintf( pIdentifier->Description, sizeof( pIdentifier->Description ), "%s (%s) %s - %dx%d",
  924. pszStringVendor, pszStringRenderer, pszStringVersion,
  925. glmDisplayInfo.m_displayPixelWidth, glmDisplayInfo.m_displayPixelHeight );
  926. }
  927. #endif
  928. pIdentifier->VendorId = glmRendererInfo.m_pciVendorID; // 4318;
  929. pIdentifier->DeviceId = glmRendererInfo.m_pciDeviceID; // 401;
  930. pIdentifier->SubSysId = 0; // 3358668866;
  931. pIdentifier->Revision = 0; // 162;
  932. pIdentifier->VideoMemory = glmRendererInfo.m_vidMemory; // amount of video memory in bytes
  933. #if 0
  934. // this came from the shaderapigl effort
  935. Q_strncpy( pIdentifier->Driver, "Fake-Video-Card", MAX_DEVICE_IDENTIFIER_STRING );
  936. Q_strncpy( pIdentifier->Description, "Fake-Video-Card", MAX_DEVICE_IDENTIFIER_STRING );
  937. pIdentifier->VendorId = 4318;
  938. pIdentifier->DeviceId = 401;
  939. pIdentifier->SubSysId = 3358668866;
  940. pIdentifier->Revision = 162;
  941. #endif
  942. return S_OK;
  943. }
  944. HRESULT IDirect3D9::CheckDeviceFormat(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat)
  945. {
  946. GL_BATCH_PERF_CALL_TIMER;
  947. if (0) // hush for now, less spew
  948. {
  949. GLMPRINTF(("-X- ** IDirect3D9::CheckDeviceFormat: \n -- Adapter=%d || DeviceType=%4x:%s || AdapterFormat=%8x:%s\n -- RType %8x: %s\n -- CheckFormat %8x: %s\n -- Usage %8x: %s",
  950. Adapter,
  951. DeviceType, GLMDecode(eD3D_DEVTYPE, DeviceType),
  952. AdapterFormat, GLMDecode(eD3D_FORMAT, AdapterFormat),
  953. RType, GLMDecode(eD3D_RTYPE, RType),
  954. CheckFormat, GLMDecode(eD3D_FORMAT, CheckFormat),
  955. Usage, GLMDecodeMask( eD3D_USAGE, Usage ) ));
  956. }
  957. HRESULT result = D3DERR_NOTAVAILABLE; // failure
  958. DWORD knownUsageMask = D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP
  959. | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
  960. | D3DUSAGE_QUERY_VERTEXTEXTURE;
  961. (void)knownUsageMask;
  962. // FramebufferSRGB stuff.
  963. // basically a format is only allowed to have SRGB usage for writing, if you have the framebuffer SRGB extension.
  964. // so, check for that capability with GLM adapter db, and if it's not there, don't mark that bit as usable in any of our formats.
  965. GLMDisplayDB *db = GetDisplayDB();
  966. int glmRendererIndex = -1;
  967. int glmDisplayIndex = -1;
  968. GLMRendererInfoFields glmRendererInfo;
  969. GLMDisplayInfoFields glmDisplayInfo;
  970. bool dbresult = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo ); (void)dbresult;
  971. Assert (!dbresult);
  972. Assert ((Usage & knownUsageMask) == Usage);
  973. DWORD legalUsage = 0;
  974. switch( AdapterFormat )
  975. {
  976. case D3DFMT_X8R8G8B8:
  977. switch( RType )
  978. {
  979. case D3DRTYPE_TEXTURE:
  980. switch( CheckFormat )
  981. {
  982. case D3DFMT_DXT1:
  983. case D3DFMT_DXT3:
  984. case D3DFMT_DXT5:
  985. legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  986. legalUsage |= D3DUSAGE_QUERY_SRGBREAD;
  987. //open question: is auto gen of mipmaps is allowed or attempted on any DXT textures.
  988. break;
  989. case D3DFMT_A8R8G8B8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  990. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  991. break;
  992. case D3DFMT_A2R10G10B10: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  993. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  994. break;
  995. case D3DFMT_A2B10G10R10: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  996. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  997. break;
  998. case D3DFMT_R32F: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  999. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  1000. break;
  1001. case D3DFMT_A16B16G16R16:
  1002. legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1003. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  1004. break;
  1005. case D3DFMT_A16B16G16R16F: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE;
  1006. if ( !glmRendererInfo.m_atiR5xx )
  1007. {
  1008. legalUsage |= D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  1009. }
  1010. break;
  1011. case D3DFMT_A32B32G32R32F: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE;
  1012. if ( !glmRendererInfo.m_atiR5xx && !glmRendererInfo.m_nvG7x )
  1013. {
  1014. legalUsage |= D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  1015. }
  1016. break;
  1017. case D3DFMT_R5G6B5: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1018. break;
  1019. //-----------------------------------------------------------
  1020. // these come in from TestTextureFormat in ColorFormatDX8.cpp which is being driven by InitializeColorInformation...
  1021. // which is going to try all 8 combinations of (vertex texturable / render targetable / filterable ) on every image format it knows.
  1022. case D3DFMT_R8G8B8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1023. legalUsage |= D3DUSAGE_QUERY_SRGBREAD;
  1024. break;
  1025. case D3DFMT_X8R8G8B8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1026. legalUsage |= D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE;
  1027. break;
  1028. // one and two channel textures... we'll have to fake these as four channel tex if we want to support them
  1029. case D3DFMT_L8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1030. break;
  1031. case D3DFMT_A8L8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1032. break;
  1033. case D3DFMT_A8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1034. break;
  1035. // going to need to go back and double check all of these..
  1036. case D3DFMT_X1R5G5B5: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1037. break;
  1038. case D3DFMT_A4R4G4B4: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1039. break;
  1040. case D3DFMT_A1R5G5B5: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1041. break;
  1042. case D3DFMT_V8U8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1043. break;
  1044. case D3DFMT_Q8W8V8U8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1045. // what the heck is QWVU8 ... ?
  1046. break;
  1047. case D3DFMT_X8L8V8U8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  1048. // what the heck is XLVU8 ... ?
  1049. break;
  1050. // formats with depth...
  1051. case D3DFMT_D16: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL;
  1052. // just a guess on the legal usages
  1053. break;
  1054. case D3DFMT_D24S8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL;
  1055. // just a guess on the legal usages
  1056. break;
  1057. // vendor formats... try marking these all invalid for now
  1058. case D3DFMT_NV_INTZ:
  1059. case D3DFMT_NV_RAWZ:
  1060. case D3DFMT_NV_NULL:
  1061. case D3DFMT_ATI_D16:
  1062. case D3DFMT_ATI_D24S8:
  1063. case D3DFMT_ATI_2N:
  1064. case D3DFMT_ATI_1N:
  1065. legalUsage = 0;
  1066. break;
  1067. //-----------------------------------------------------------
  1068. default:
  1069. Assert(!"Unknown check format");
  1070. result = D3DERR_NOTAVAILABLE;
  1071. break;
  1072. }
  1073. if ((Usage & legalUsage) == Usage)
  1074. {
  1075. result = S_OK;
  1076. }
  1077. else
  1078. {
  1079. DWORD unsatBits = Usage & (~legalUsage); // clear the bits of the req that were legal, leaving the illegal ones
  1080. unsatBits;
  1081. GLMPRINTF(( "-X- --> NOT OK: flags %8x:%s", unsatBits,GLMDecodeMask( eD3D_USAGE, unsatBits ) ));
  1082. result = D3DERR_NOTAVAILABLE;
  1083. }
  1084. break;
  1085. case D3DRTYPE_SURFACE:
  1086. switch( static_cast<uint>(CheckFormat) )
  1087. {
  1088. case 0x434f5441:
  1089. case 0x41415353:
  1090. result = D3DERR_NOTAVAILABLE;
  1091. break;
  1092. case D3DFMT_D24S8:
  1093. result = S_OK;
  1094. break;
  1095. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=434f5441:UNKNOWN
  1096. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=41415353:UNKNOWN
  1097. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=434f5441:UNKNOWN
  1098. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=41415353:UNKNOWN
  1099. }
  1100. break;
  1101. default:
  1102. Assert(!"Unknown resource type");
  1103. result = D3DERR_NOTAVAILABLE;
  1104. break;
  1105. }
  1106. break;
  1107. default:
  1108. Assert(!"Unknown adapter format");
  1109. result = D3DERR_NOTAVAILABLE;
  1110. break;
  1111. }
  1112. return result;
  1113. }
  1114. UINT IDirect3D9::GetAdapterModeCount(UINT Adapter,D3DFORMAT Format)
  1115. {
  1116. GL_BATCH_PERF_CALL_TIMER;
  1117. GLMPRINTF(( "-X- IDirect3D9::GetAdapterModeCount: Adapter=%d || Format=%8x:%s", Adapter, Format, GLMDecode(eD3D_FORMAT, Format) ));
  1118. uint modeCount=0;
  1119. GLMDisplayDB *db = GetDisplayDB();
  1120. int glmRendererIndex = -1;
  1121. int glmDisplayIndex = -1;
  1122. GLMRendererInfoFields glmRendererInfo;
  1123. GLMDisplayInfoFields glmDisplayInfo;
  1124. // the D3D "Adapter" number feeds the fake adapter index
  1125. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo ); (void)result;
  1126. Assert (!result);
  1127. modeCount = db->GetModeCount( glmRendererIndex, glmDisplayIndex );
  1128. GLMPRINTF(( "-X- --> result is %d", modeCount ));
  1129. return modeCount;
  1130. }
  1131. HRESULT IDirect3D9::EnumAdapterModes(UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode)
  1132. {
  1133. GL_BATCH_PERF_CALL_TIMER;
  1134. GLMPRINTF(( "-X- IDirect3D9::EnumAdapterModes: Adapter=%d || Format=%8x:%s || Mode=%d", Adapter, Format, GLMDecode(eD3D_FORMAT, Format), Mode ));
  1135. Assert(Format==D3DFMT_X8R8G8B8);
  1136. GLMDisplayDB *db = GetDisplayDB();
  1137. int glmRendererIndex = -1;
  1138. int glmDisplayIndex = -1;
  1139. GLMRendererInfoFields glmRendererInfo;
  1140. GLMDisplayInfoFields glmDisplayInfo;
  1141. GLMDisplayModeInfoFields glmModeInfo;
  1142. // the D3D "Adapter" number feeds the fake adapter index
  1143. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  1144. Assert (!result);
  1145. if (result) return D3DERR_NOTAVAILABLE;
  1146. bool result2 = db->GetModeInfo( glmRendererIndex, glmDisplayIndex, Mode, &glmModeInfo );
  1147. Assert( !result2 );
  1148. if (result2) return D3DERR_NOTAVAILABLE;
  1149. pMode->Width = glmModeInfo.m_modePixelWidth;
  1150. pMode->Height = glmModeInfo.m_modePixelHeight;
  1151. pMode->RefreshRate = glmModeInfo.m_modeRefreshHz; // "adapter default"
  1152. pMode->Format = Format; // whatever you asked for ?
  1153. GLMPRINTF(( "-X- IDirect3D9::EnumAdapterModes returning mode size (%d,%d) and D3DFMT_X8R8G8B8",pMode->Width,pMode->Height ));
  1154. return S_OK;
  1155. }
  1156. HRESULT IDirect3D9::CheckDeviceType(UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed)
  1157. {
  1158. GL_BATCH_PERF_CALL_TIMER;
  1159. //FIXME: we just say "OK" on any query
  1160. GLMPRINTF(( "-X- IDirect3D9::CheckDeviceType: Adapter=%d || DevType=%d:%s || AdapterFormat=%d:%s || BackBufferFormat=%d:%s || bWindowed=%d",
  1161. Adapter,
  1162. DevType, GLMDecode(eD3D_DEVTYPE,DevType),
  1163. AdapterFormat, GLMDecode(eD3D_FORMAT, AdapterFormat),
  1164. BackBufferFormat, GLMDecode(eD3D_FORMAT, BackBufferFormat),
  1165. (int) bWindowed ));
  1166. return S_OK;
  1167. }
  1168. HRESULT IDirect3D9::GetAdapterDisplayMode(UINT Adapter,D3DDISPLAYMODE* pMode)
  1169. {
  1170. GL_BATCH_PERF_CALL_TIMER;
  1171. // asking what the current mode is
  1172. GLMPRINTF(("-X- IDirect3D9::GetAdapterDisplayMode: Adapter=%d", Adapter ));
  1173. GLMDisplayDB *db = GetDisplayDB();
  1174. int glmRendererIndex = -1;
  1175. int glmDisplayIndex = -1;
  1176. GLMRendererInfoFields glmRendererInfo;
  1177. GLMDisplayInfoFields glmDisplayInfo;
  1178. GLMDisplayModeInfoFields glmModeInfo;
  1179. // the D3D "Adapter" number feeds the fake adapter index
  1180. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  1181. Assert(!result);
  1182. if (result) return D3DERR_INVALIDCALL;
  1183. int modeIndex = -1; // pass -1 as a mode index to find out about whatever the current mode is on the selected display
  1184. bool modeResult = db->GetModeInfo( glmRendererIndex, glmDisplayIndex, modeIndex, &glmModeInfo );
  1185. Assert (!modeResult);
  1186. if (modeResult) return D3DERR_INVALIDCALL;
  1187. pMode->Width = glmModeInfo.m_modePixelWidth;
  1188. pMode->Height = glmModeInfo.m_modePixelHeight;
  1189. pMode->RefreshRate = glmModeInfo.m_modeRefreshHz; // "adapter default"
  1190. pMode->Format = D3DFMT_X8R8G8B8; //FIXME, this is a SWAG
  1191. return S_OK;
  1192. }
  1193. HRESULT IDirect3D9::CheckDepthStencilMatch(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat)
  1194. {
  1195. GL_BATCH_PERF_CALL_TIMER;
  1196. GLMPRINTF(("-X- IDirect3D9::CheckDepthStencilMatch: Adapter=%d || DevType=%d:%s || AdapterFormat=%d:%s || RenderTargetFormat=%d:%s || DepthStencilFormat=%d:%s",
  1197. Adapter,
  1198. DeviceType, GLMDecode(eD3D_DEVTYPE,DeviceType),
  1199. AdapterFormat, GLMDecode(eD3D_FORMAT, AdapterFormat),
  1200. RenderTargetFormat, GLMDecode(eD3D_FORMAT, RenderTargetFormat),
  1201. DepthStencilFormat, GLMDecode(eD3D_FORMAT, DepthStencilFormat) ));
  1202. // one known request looks like this:
  1203. // AdapterFormat=5:D3DFMT_X8R8G8B8 || RenderTargetFormat=3:D3DFMT_A8R8G8B8 || DepthStencilFormat=2:D3DFMT_D24S8
  1204. // return S_OK for that one combo, DXABSTRACT_BREAK_ON_ERROR() on anything else
  1205. HRESULT result = D3DERR_NOTAVAILABLE; // failure
  1206. switch( AdapterFormat )
  1207. {
  1208. case D3DFMT_X8R8G8B8:
  1209. {
  1210. if ( (RenderTargetFormat == D3DFMT_A8R8G8B8) && (DepthStencilFormat == D3DFMT_D24S8) )
  1211. {
  1212. result = S_OK;
  1213. }
  1214. }
  1215. break;
  1216. }
  1217. Assert( result == S_OK );
  1218. return result;
  1219. }
  1220. HRESULT IDirect3D9::CheckDeviceMultiSampleType( UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels )
  1221. {
  1222. GL_BATCH_PERF_CALL_TIMER;
  1223. GLMDisplayDB *db = GetDisplayDB();
  1224. int glmRendererIndex = -1;
  1225. int glmDisplayIndex = -1;
  1226. GLMRendererInfoFields glmRendererInfo;
  1227. GLMDisplayInfoFields glmDisplayInfo;
  1228. //GLMDisplayModeInfoFields glmModeInfo;
  1229. // the D3D "Adapter" number feeds the fake adapter index
  1230. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  1231. Assert( !result );
  1232. if ( result )
  1233. return D3DERR_INVALIDCALL;
  1234. if ( !CommandLine()->FindParm("-glmenabletrustmsaa") )
  1235. {
  1236. // These ghetto drivers don't get MSAA
  1237. if ( ( glmRendererInfo.m_nvG7x || glmRendererInfo.m_atiR5xx ) && ( MultiSampleType > D3DMULTISAMPLE_NONE ) )
  1238. {
  1239. if ( pQualityLevels )
  1240. {
  1241. *pQualityLevels = 0;
  1242. }
  1243. return D3DERR_NOTAVAILABLE;
  1244. }
  1245. }
  1246. switch ( MultiSampleType )
  1247. {
  1248. case D3DMULTISAMPLE_NONE: // always return true
  1249. if ( pQualityLevels )
  1250. {
  1251. *pQualityLevels = 1;
  1252. }
  1253. return S_OK;
  1254. break;
  1255. case D3DMULTISAMPLE_2_SAMPLES:
  1256. case D3DMULTISAMPLE_4_SAMPLES:
  1257. case D3DMULTISAMPLE_6_SAMPLES:
  1258. case D3DMULTISAMPLE_8_SAMPLES:
  1259. // note the fact that the d3d enums for 2, 4, 6, 8 samples are equal to 2,4,6,8...
  1260. if (glmRendererInfo.m_maxSamples >= (int)MultiSampleType )
  1261. {
  1262. if ( pQualityLevels )
  1263. {
  1264. *pQualityLevels = 1;
  1265. }
  1266. return S_OK;
  1267. }
  1268. else
  1269. {
  1270. return D3DERR_NOTAVAILABLE;
  1271. }
  1272. break;
  1273. default:
  1274. if ( pQualityLevels )
  1275. {
  1276. *pQualityLevels = 0;
  1277. }
  1278. return D3DERR_NOTAVAILABLE;
  1279. break;
  1280. }
  1281. return D3DERR_NOTAVAILABLE;
  1282. }
  1283. HRESULT IDirect3D9::CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,VD3DHWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface)
  1284. {
  1285. GL_BATCH_PERF_CALL_TIMER;
  1286. #if GLMDEBUG
  1287. Plat_DebugString( "WARNING: GLMEBUG is 1, perf. is going to be low!");
  1288. Warning( "WARNING: GLMEBUG is 1, perf. is going to be low!");
  1289. #endif
  1290. #if !TOGL_SUPPORT_NULL_DEVICE
  1291. if (DeviceType == D3DDEVTYPE_NULLREF)
  1292. {
  1293. Error("Must define TOGL_SUPPORT_NULL_DEVICE to use the NULL device");
  1294. DebuggerBreak();
  1295. return E_FAIL;
  1296. }
  1297. #endif
  1298. // constrain these inputs for the time being
  1299. // BackBufferFormat -> A8R8G8B8
  1300. // BackBufferCount -> 1;
  1301. // MultiSampleType -> D3DMULTISAMPLE_NONE
  1302. // AutoDepthStencilFormat -> D3DFMT_D24S8
  1303. // NULL out the return pointer so if we exit early it is not set
  1304. *ppReturnedDeviceInterface = NULL;
  1305. // assume success unless something is sour
  1306. HRESULT result = S_OK;
  1307. // relax this check for now
  1308. //if (pPresentationParameters->BackBufferFormat != D3DFMT_A8R8G8B8)
  1309. //{
  1310. // DXABSTRACT_BREAK_ON_ERROR();
  1311. // result = -1;
  1312. //}
  1313. //rbarris 24Aug10 - relaxing this check - we don't care if the game asks for two backbuffers, it's moot
  1314. //if ( pPresentationParameters->BackBufferCount != 1 )
  1315. //{
  1316. // DXABSTRACT_BREAK_ON_ERROR();
  1317. // result = D3DERR_NOTAVAILABLE;
  1318. //}
  1319. if ( pPresentationParameters->AutoDepthStencilFormat != D3DFMT_D24S8 )
  1320. {
  1321. DXABSTRACT_BREAK_ON_ERROR();
  1322. result = D3DERR_NOTAVAILABLE;
  1323. }
  1324. if ( result == S_OK )
  1325. {
  1326. // create an IDirect3DDevice9
  1327. // it will make a GLMContext and set up some drawables
  1328. IDirect3DDevice9Params devparams;
  1329. memset( &devparams, 0, sizeof(devparams) );
  1330. devparams.m_adapter = Adapter;
  1331. devparams.m_deviceType = DeviceType;
  1332. devparams.m_focusWindow = hFocusWindow; // is this meaningful? is this a WindowRef ? follow it up the chain..
  1333. devparams.m_behaviorFlags = BehaviorFlags;
  1334. devparams.m_presentationParameters = *pPresentationParameters;
  1335. IDirect3DDevice9 *dev = new IDirect3DDevice9;
  1336. result = dev->Create( &devparams );
  1337. if ( result == S_OK )
  1338. {
  1339. *ppReturnedDeviceInterface = dev;
  1340. }
  1341. g_bNullD3DDevice = ( DeviceType == D3DDEVTYPE_NULLREF );
  1342. }
  1343. return result;
  1344. }
  1345. // ------------------------------------------------------------------------------------------------------------------------------ //
  1346. #ifdef OSX
  1347. #pragma mark ----- IDirect3DQuery9
  1348. #endif
  1349. HRESULT IDirect3DQuery9::Issue(DWORD dwIssueFlags)
  1350. {
  1351. GL_BATCH_PERF_CALL_TIMER;
  1352. Assert( m_device->m_nValidMarker == D3D_DEVICE_VALID_MARKER );
  1353. // Flags field for Issue
  1354. // #define D3DISSUE_END (1 << 0) // Tells the runtime to issue the end of a query, changing it's state to "non-signaled".
  1355. // #define D3DISSUE_BEGIN (1 << 1) // Tells the runtime to issue the beginng of a query.
  1356. // Make sure calling thread owns the GL context.
  1357. Assert( m_ctx->m_nCurOwnerThreadId == ThreadGetCurrentId() );
  1358. if (dwIssueFlags & D3DISSUE_BEGIN)
  1359. {
  1360. m_nIssueStartThreadID = ThreadGetCurrentId();
  1361. m_nIssueStartDrawCallIndex = g_nTotalDrawsOrClears;
  1362. m_nIssueStartFrameIndex = m_ctx->m_nCurFrame;
  1363. m_nIssueStartQueryCreationCounter = CGLMQuery::s_nTotalOcclusionQueryCreatesOrDeletes;
  1364. switch( m_type )
  1365. {
  1366. case D3DQUERYTYPE_OCCLUSION:
  1367. m_query->Start(); // drop "start counter" call into stream
  1368. break;
  1369. default:
  1370. Assert(!"Can't use D3DISSUE_BEGIN on this query");
  1371. break;
  1372. }
  1373. }
  1374. if (dwIssueFlags & D3DISSUE_END)
  1375. {
  1376. m_nIssueEndThreadID = ThreadGetCurrentId();
  1377. m_nIssueEndDrawCallIndex = g_nTotalDrawsOrClears;
  1378. m_nIssueEndFrameIndex = m_ctx->m_nCurFrame;
  1379. m_nIssueEndQueryCreationCounter = CGLMQuery::s_nTotalOcclusionQueryCreatesOrDeletes;
  1380. switch( m_type )
  1381. {
  1382. case D3DQUERYTYPE_OCCLUSION:
  1383. m_query->Stop(); // drop "end counter" call into stream
  1384. break;
  1385. case D3DQUERYTYPE_EVENT:
  1386. m_nIssueStartThreadID = m_nIssueEndThreadID;
  1387. m_nIssueStartDrawCallIndex = m_nIssueEndDrawCallIndex;
  1388. m_nIssueStartFrameIndex = m_nIssueEndFrameIndex;
  1389. m_nIssueStartQueryCreationCounter = m_nIssueEndQueryCreationCounter;
  1390. // End is very weird with respect to Events (fences).
  1391. // DX9 docs say to use End to put the fence in the stream. So we map End to GLM's Start.
  1392. // http://msdn.microsoft.com/en-us/library/ee422167(VS.85).aspx
  1393. m_query->Start(); // drop "set fence" into stream
  1394. break;
  1395. }
  1396. }
  1397. return S_OK;
  1398. }
  1399. HRESULT IDirect3DQuery9::GetData(void* pData,DWORD dwSize,DWORD dwGetDataFlags)
  1400. {
  1401. GL_BATCH_PERF_CALL_TIMER;
  1402. Assert( m_device->m_nValidMarker == D3D_DEVICE_VALID_MARKER );
  1403. HRESULT result = S_FALSE ;
  1404. DWORD nCurThreadId = ThreadGetCurrentId();
  1405. // Make sure calling thread owns the GL context.
  1406. Assert( m_ctx->m_nCurOwnerThreadId == nCurThreadId );
  1407. if ( pData )
  1408. {
  1409. *(uint*)pData = 0;
  1410. }
  1411. if ( !m_query->IsStarted() || !m_query->IsStopped() )
  1412. {
  1413. Assert(!"Can't GetData before issue/start/stop");
  1414. printf("\n** IDirect3DQuery9::GetData: can't GetData before issue/start/stop");
  1415. return S_FALSE;
  1416. }
  1417. // GetData is not always called with the flush bit.
  1418. // if an answer is not yet available - return S_FALSE.
  1419. // if an answer is available - return S_OK and write the answer into *pData.
  1420. bool done = false;
  1421. bool flush = (dwGetDataFlags & D3DGETDATA_FLUSH) != 0; // aka spin until done
  1422. // hmmm both of these paths are the same, maybe we could fold them up
  1423. if ( m_type == D3DQUERYTYPE_OCCLUSION )
  1424. {
  1425. // Detect cases that are actually just not supported with the way we're using GL queries. (For example, beginning a query, then creating/deleting any query, the ending the same query is not supported.)
  1426. // Also extra paranoid to detect/work around various NV/AMD driver issues.
  1427. if ( ( ( m_nIssueStartThreadID != nCurThreadId ) || ( m_nIssueEndThreadID != nCurThreadId ) ) ||
  1428. ( m_nIssueStartDrawCallIndex == m_nIssueEndDrawCallIndex ) || ( m_nIssueStartFrameIndex != m_nIssueEndFrameIndex ) ||
  1429. ( m_nIssueStartQueryCreationCounter != m_nIssueEndQueryCreationCounter ) )
  1430. {
  1431. // The thread Issue() was called on differs from GetData() - NV's driver doesn't like this, not sure about AMD. Just fake the results if a flush is requested.
  1432. // There are various ways to properly handle this scenario, but in practice it only seems to occur in non-critical times (during shutdown or when mat_queue_mode is changed in L4D2).
  1433. if ( flush )
  1434. {
  1435. gGL->glFlush();
  1436. }
  1437. #if 0
  1438. if ( ( m_nIssueStartThreadID != nCurThreadId ) || ( m_nIssueEndThreadID != nCurThreadId ) )
  1439. {
  1440. GLMDebugPrintf( "IDirect3DQuery9::GetData: GetData() called from different thread verses the issueing thread()!\n" );
  1441. }
  1442. #endif
  1443. if ( m_nIssueStartQueryCreationCounter != m_nIssueEndQueryCreationCounter )
  1444. {
  1445. GLMDebugPrintf( "IDirect3DQuery9::GetData: One or more queries have been created or released while this query was still issued! This scenario is not supported in GL.\n");
  1446. }
  1447. // Return with a non-standard error code, so the caller has a chance to do something halfway intelligent.
  1448. return D3DERR_NOTAVAILABLE;
  1449. }
  1450. }
  1451. switch( m_type )
  1452. {
  1453. case D3DQUERYTYPE_OCCLUSION:
  1454. {
  1455. if ( flush )
  1456. {
  1457. uint oqValue = 0;
  1458. CFastTimer tm;
  1459. tm.Start();
  1460. // Is this flush actually necessary? According to the extension it's not.
  1461. // It doesn't seem to matter if this is a glFlush() or glFinish() with NVidia's driver (tested in MT mode - not sure if it matters), it still can take several calls to IsDone() before we can stop waiting for the query results.
  1462. // On AMD, this flush logic fails during shutdown (the query results never become available) - tried a bunch of experiments and checks with no luck.
  1463. m_query->Complete(&oqValue);
  1464. double flTotalTime = tm.GetDurationInProgress().GetSeconds() * 1000.0f;
  1465. if ( flTotalTime > .5f )
  1466. {
  1467. // Give up - something silly has obviously gone wrong in the driver, lying is better than stalling potentially forever.
  1468. // This occurs on AMD (single threaded driver) during shutdown, not sure why yet. It has nothing to do with threading. It may have to do with releasing queries or other objects.
  1469. // We must return a result otherwise the app itself could hang, waiting infinitely.
  1470. //Assert( 0 );
  1471. Warning( "IDirect3DQuery9::GetData(): Occlusion query flush took %3.3fms!\n", flTotalTime );
  1472. }
  1473. if (pData)
  1474. {
  1475. *(uint*)pData = oqValue;
  1476. }
  1477. result = S_OK;
  1478. }
  1479. else
  1480. {
  1481. done = m_query->IsDone();
  1482. if (done)
  1483. {
  1484. uint oqValue = 0; // or we could just pass pData directly to Complete...
  1485. m_query->Complete(&oqValue);
  1486. if (pData)
  1487. {
  1488. *(uint*)pData = oqValue;
  1489. }
  1490. result = S_OK;
  1491. }
  1492. else
  1493. {
  1494. result = S_FALSE;
  1495. Assert( !flush );
  1496. }
  1497. }
  1498. }
  1499. break;
  1500. case D3DQUERYTYPE_EVENT:
  1501. {
  1502. done = m_query->IsDone();
  1503. if ( ( done ) || ( flush ) )
  1504. {
  1505. m_query->Complete(NULL); // this will block on pre-SLGU
  1506. result = S_OK;
  1507. }
  1508. else
  1509. {
  1510. result = S_FALSE;
  1511. Assert( !flush );
  1512. }
  1513. }
  1514. break;
  1515. }
  1516. return result;
  1517. }
  1518. // ------------------------------------------------------------------------------------------------------------------------------ //
  1519. #ifdef OSX
  1520. #pragma mark ----- IDirect3DVertexBuffer9
  1521. #endif
  1522. HRESULT IDirect3DDevice9::CreateVertexBuffer(UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,VD3DHANDLE* pSharedHandle)
  1523. {
  1524. GL_BATCH_PERF_CALL_TIMER;
  1525. GLMPRINTF(( ">-A- IDirect3DDevice9::CreateVertexBuffer" ));
  1526. Assert( m_ctx->m_nCurOwnerThreadId == ThreadGetCurrentId() );
  1527. m_ObjectStats.m_nTotalVertexBuffers++;
  1528. IDirect3DVertexBuffer9 *newbuff = new IDirect3DVertexBuffer9;
  1529. newbuff->m_device = this;
  1530. newbuff->m_ctx = m_ctx;
  1531. // FIXME need to find home or use for the Usage, FVF, Pool values passed in
  1532. uint options = 0;
  1533. if (Usage&D3DUSAGE_DYNAMIC)
  1534. {
  1535. options |= GLMBufferOptionDynamic;
  1536. }
  1537. newbuff->m_vtxBuffer = m_ctx->NewBuffer( kGLMVertexBuffer, Length, options ) ;
  1538. newbuff->m_vtxDesc.Type = D3DRTYPE_VERTEXBUFFER;
  1539. newbuff->m_vtxDesc.Usage = Usage;
  1540. newbuff->m_vtxDesc.Pool = Pool;
  1541. newbuff->m_vtxDesc.Size = Length;
  1542. *ppVertexBuffer = newbuff;
  1543. GLMPRINTF(( "<-A- IDirect3DDevice9::CreateVertexBuffer" ));
  1544. return S_OK;
  1545. }
  1546. IDirect3DVertexBuffer9::~IDirect3DVertexBuffer9()
  1547. {
  1548. GL_BATCH_PERF_CALL_TIMER;
  1549. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  1550. GLMPRINTF(( ">-A- ~IDirect3DVertexBuffer9" ));
  1551. if (m_device)
  1552. {
  1553. m_device->ReleasedVertexBuffer( this );
  1554. if (m_ctx && m_vtxBuffer)
  1555. {
  1556. GLMPRINTF(( ">-A- ~IDirect3DVertexBuffer9 deleting m_vtxBuffer" ));
  1557. m_ctx->DelBuffer( m_vtxBuffer );
  1558. m_vtxBuffer = NULL;
  1559. GLMPRINTF(( "<-A- ~IDirect3DVertexBuffer9 deleting m_vtxBuffer - done" ));
  1560. }
  1561. m_device = NULL;
  1562. }
  1563. GLMPRINTF(( "<-A- ~IDirect3DVertexBuffer9" ));
  1564. }
  1565. HRESULT IDirect3DVertexBuffer9::Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags)
  1566. {
  1567. GL_BATCH_PERF_CALL_TIMER;
  1568. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  1569. tmZoneFiltered( TELEMETRY_LEVEL2, 25, TMZF_NONE, "VB Lock" );
  1570. // FIXME would be good to have "can't lock twice" logic
  1571. Assert( !(Flags & D3DLOCK_READONLY) ); // not impl'd
  1572. // Assert( !(Flags & D3DLOCK_NOSYSLOCK) ); // not impl'd - it triggers though
  1573. GLMBuffLockParams lockreq;
  1574. lockreq.m_nOffset = OffsetToLock;
  1575. lockreq.m_nSize = SizeToLock;
  1576. lockreq.m_bNoOverwrite = (Flags & D3DLOCK_NOOVERWRITE) != 0;
  1577. lockreq.m_bDiscard = (Flags & D3DLOCK_DISCARD) != 0;
  1578. m_vtxBuffer->Lock( &lockreq, (char**)ppbData );
  1579. GLMPRINTF(("-X- IDirect3DDevice9::Lock on D3D buf %p (GL name %d) offset %d, size %d => address %p", this, this->m_vtxBuffer->m_nHandle, OffsetToLock, SizeToLock, *ppbData));
  1580. return S_OK;
  1581. }
  1582. HRESULT IDirect3DVertexBuffer9::Unlock()
  1583. {
  1584. GL_BATCH_PERF_CALL_TIMER;
  1585. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  1586. tmZoneFiltered( TELEMETRY_LEVEL2, 25, TMZF_NONE, "VB Unlock" );
  1587. m_vtxBuffer->Unlock();
  1588. return S_OK;
  1589. }
  1590. void IDirect3DVertexBuffer9::UnlockActualSize( uint nActualSize, const void *pActualData )
  1591. {
  1592. GL_BATCH_PERF_CALL_TIMER;
  1593. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  1594. tmZoneFiltered( TELEMETRY_LEVEL2, 25, TMZF_NONE, "VB UnlockActualSize" );
  1595. m_vtxBuffer->Unlock( nActualSize, pActualData );
  1596. }
  1597. // ------------------------------------------------------------------------------------------------------------------------------ //
  1598. #ifdef OSX
  1599. #pragma mark ----- IDirect3DIndexBuffer9
  1600. #endif
  1601. HRESULT IDirect3DDevice9::CreateIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,VD3DHANDLE* pSharedHandle)
  1602. {
  1603. GL_BATCH_PERF_CALL_TIMER;
  1604. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  1605. GLMPRINTF(( ">-A- IDirect3DDevice9::CreateIndexBuffer" ));
  1606. // it is important to save all the create info, since GetDesc could get called later to query it
  1607. m_ObjectStats.m_nTotalIndexBuffers++;
  1608. IDirect3DIndexBuffer9 *newbuff = new IDirect3DIndexBuffer9;
  1609. newbuff->m_device = this;
  1610. newbuff->m_restype = D3DRTYPE_INDEXBUFFER; // hmmmmmmm why are we not derived from d3dresource..
  1611. newbuff->m_ctx = m_ctx;
  1612. // FIXME need to find home or use for the Usage, Format, Pool values passed in
  1613. uint options = 0;
  1614. if (Usage&D3DUSAGE_DYNAMIC)
  1615. {
  1616. options |= GLMBufferOptionDynamic;
  1617. }
  1618. newbuff->m_idxBuffer = m_ctx->NewBuffer( kGLMIndexBuffer, Length, options ) ;
  1619. newbuff->m_idxDesc.Format = Format;
  1620. newbuff->m_idxDesc.Type = D3DRTYPE_INDEXBUFFER;
  1621. newbuff->m_idxDesc.Usage = Usage;
  1622. newbuff->m_idxDesc.Pool = Pool;
  1623. newbuff->m_idxDesc.Size = Length;
  1624. *ppIndexBuffer = newbuff;
  1625. GLMPRINTF(( "<-A- IDirect3DDevice9::CreateIndexBuffer" ));
  1626. return S_OK;
  1627. }
  1628. IDirect3DIndexBuffer9::~IDirect3DIndexBuffer9()
  1629. {
  1630. GL_BATCH_PERF_CALL_TIMER;
  1631. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  1632. GLMPRINTF(( ">-A- ~IDirect3DIndexBuffer9" ));
  1633. if (m_device)
  1634. {
  1635. m_device->ReleasedIndexBuffer( this );
  1636. if (m_ctx && m_idxBuffer)
  1637. {
  1638. GLMPRINTF(( ">-A- ~IDirect3DIndexBuffer9 deleting m_idxBuffer" ));
  1639. m_ctx->DelBuffer( m_idxBuffer );
  1640. GLMPRINTF(( "<-A- ~IDirect3DIndexBuffer9 deleting m_idxBuffer - done" ));
  1641. }
  1642. m_device = NULL;
  1643. }
  1644. else
  1645. {
  1646. }
  1647. GLMPRINTF(( "<-A- ~IDirect3DIndexBuffer9" ));
  1648. }
  1649. HRESULT IDirect3DIndexBuffer9::Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags)
  1650. {
  1651. GL_BATCH_PERF_CALL_TIMER;
  1652. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  1653. // FIXME would be good to have "can't lock twice" logic
  1654. tmZoneFiltered( TELEMETRY_LEVEL2, 25, TMZF_NONE, "IB Lock" );
  1655. GLMBuffLockParams lockreq;
  1656. lockreq.m_nOffset = OffsetToLock;
  1657. lockreq.m_nSize = SizeToLock;
  1658. lockreq.m_bNoOverwrite = ( Flags & D3DLOCK_NOOVERWRITE ) != 0;
  1659. lockreq.m_bDiscard = ( Flags & D3DLOCK_DISCARD ) != 0;
  1660. m_idxBuffer->Lock( &lockreq, (char**)ppbData );
  1661. return S_OK;
  1662. }
  1663. HRESULT IDirect3DIndexBuffer9::Unlock()
  1664. {
  1665. GL_BATCH_PERF_CALL_TIMER;
  1666. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  1667. tmZoneFiltered( TELEMETRY_LEVEL2, 25, TMZF_NONE, "IB Unlock" );
  1668. m_idxBuffer->Unlock();
  1669. return S_OK;
  1670. }
  1671. void IDirect3DIndexBuffer9::UnlockActualSize( uint nActualSize, const void *pActualData )
  1672. {
  1673. GL_BATCH_PERF_CALL_TIMER;
  1674. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  1675. tmZoneFiltered( TELEMETRY_LEVEL2, 25, TMZF_NONE, "IB UnlockActualSize" );
  1676. m_idxBuffer->Unlock( nActualSize, pActualData );
  1677. }
  1678. HRESULT IDirect3DIndexBuffer9::GetDesc(D3DINDEXBUFFER_DESC *pDesc)
  1679. {
  1680. GL_BATCH_PERF_CALL_TIMER;
  1681. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  1682. *pDesc = m_idxDesc;
  1683. return S_OK;
  1684. }
  1685. // ------------------------------------------------------------------------------------------------------------------------------ //
  1686. #ifdef OSX
  1687. #pragma mark ----- IDirect3DDevice9 -------------------------------------------------
  1688. #endif
  1689. void ConvertPresentationParamsToGLMDisplayParams( D3DPRESENT_PARAMETERS *d3dp, GLMDisplayParams *gldp )
  1690. {
  1691. memset( gldp, 0, sizeof(*gldp) );
  1692. gldp->m_fsEnable = !d3dp->Windowed;
  1693. // see http://msdn.microsoft.com/en-us/library/ee416515(VS.85).aspx
  1694. // note that the values below are the only ones mentioned by Source engine; there are many others
  1695. switch(d3dp->PresentationInterval)
  1696. {
  1697. case D3DPRESENT_INTERVAL_ONE:
  1698. gldp->m_vsyncEnable = true; // "The driver will wait for the vertical retrace period (the runtime will beam-follow to prevent tearing)."
  1699. break;
  1700. case D3DPRESENT_INTERVAL_IMMEDIATE:
  1701. gldp->m_vsyncEnable = false; // "The runtime updates the window client area immediately and might do so more than once during the adapter refresh period."
  1702. break;
  1703. default:
  1704. gldp->m_vsyncEnable = true; // if I don't know it, you're getting vsync enabled.
  1705. break;
  1706. }
  1707. gldp->m_backBufferWidth = d3dp->BackBufferWidth;
  1708. gldp->m_backBufferHeight = d3dp->BackBufferHeight;
  1709. gldp->m_backBufferFormat = d3dp->BackBufferFormat;
  1710. gldp->m_multiSampleCount = d3dp->MultiSampleType; // it's a count really
  1711. gldp->m_enableAutoDepthStencil = d3dp->EnableAutoDepthStencil != 0;
  1712. gldp->m_autoDepthStencilFormat = d3dp->AutoDepthStencilFormat;
  1713. gldp->m_fsRefreshHz = d3dp->FullScreen_RefreshRateInHz;
  1714. // some fields in d3d PB we're not acting on yet...
  1715. // UINT BackBufferCount;
  1716. // DWORD MultiSampleQuality;
  1717. // D3DSWAPEFFECT SwapEffect;
  1718. // VD3DHWND hDeviceWindow;
  1719. // DWORD Flags;
  1720. }
  1721. void UnpackD3DRSITable( void );
  1722. HRESULT IDirect3DDevice9::Create( IDirect3DDevice9Params *params )
  1723. {
  1724. g_pD3D_Device = this;
  1725. GLMDebugPrintf( "IDirect3DDevice9::Create: BackBufWidth: %u, BackBufHeight: %u, D3DFMT: %u, BackBufCount: %u, MultisampleType: %u, MultisampleQuality: %u\n",
  1726. params->m_presentationParameters.BackBufferWidth,
  1727. params->m_presentationParameters.BackBufferHeight,
  1728. params->m_presentationParameters.BackBufferFormat,
  1729. params->m_presentationParameters.BackBufferCount,
  1730. params->m_presentationParameters.MultiSampleType,
  1731. params->m_presentationParameters.MultiSampleQuality );
  1732. UnpackD3DRSITable();
  1733. m_ObjectStats.clear();
  1734. m_PrevObjectStats.clear();
  1735. #if GL_BATCH_PERF_ANALYSIS && GL_BATCH_PERF_ANALYSIS_WRITE_PNGS
  1736. m_pBatch_vis_bitmap = NULL;
  1737. #endif
  1738. GL_BATCH_PERF_CALL_TIMER;
  1739. GLMPRINTF((">-X-IDirect3DDevice9::Create"));
  1740. HRESULT result = S_OK;
  1741. // create an IDirect3DDevice9
  1742. // make a GLMContext and set up some drawables
  1743. m_params = *params;
  1744. m_ctx = NULL;
  1745. V_memset( m_pRenderTargets, 0, sizeof( m_pRenderTargets ) );
  1746. m_pDepthStencil = NULL;
  1747. m_pDefaultColorSurface = NULL;
  1748. m_pDefaultDepthStencilSurface = NULL;
  1749. memset( m_streams, 0, sizeof(m_streams) );
  1750. memset( m_vtx_buffers, 0, sizeof( m_vtx_buffers ) );
  1751. memset( m_textures, 0, sizeof(m_textures) );
  1752. //memset( m_samplers, 0, sizeof(m_samplers) );
  1753. m_indices.m_idxBuffer = NULL;
  1754. m_vertexShader = NULL;
  1755. m_pixelShader = NULL;
  1756. m_pVertDecl = NULL;
  1757. //============================================================================
  1758. // param block for GLM context create
  1759. GLMDisplayParams glmParams;
  1760. ConvertPresentationParamsToGLMDisplayParams( &params->m_presentationParameters, &glmParams );
  1761. glmParams.m_mtgl = true; // forget this idea -> (params->m_behaviorFlags & D3DCREATE_MULTITHREADED) != 0;
  1762. // the call above fills in a bunch of things, but doesn't know about anything outside of the presentation params.
  1763. // those tend to be the things that do not change after create, so we do those here in Create.
  1764. glmParams.m_focusWindow = params->m_focusWindow;
  1765. #if 0 //FIXME-HACK
  1766. // map the D3D "adapter" to a renderer/display pair
  1767. // (that GPU will have to stay set as-is for any subsequent mode changes)
  1768. int glmRendererIndex = -1;
  1769. int glmDisplayIndex = -1;
  1770. GLMRendererInfoFields glmRendererInfo;
  1771. GLMDisplayInfoFields glmDisplayInfo;
  1772. // the D3D "Adapter" number feeds the fake adapter index
  1773. bool adaptResult = GLMgr::aGLMgr()->GetDisplayDB()->GetFakeAdapterInfo( params->m_adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  1774. Assert(!adaptResult);
  1775. glmParams.m_rendererIndex = glmRendererIndex;
  1776. glmParams.m_displayIndex = glmDisplayIndex;
  1777. // glmParams.m_modeIndex hmmmmm, client doesn't give us a mode number, just a resolution..
  1778. #endif
  1779. m_ctx = GLMgr::aGLMgr()->NewContext( this, &glmParams );
  1780. if (!m_ctx)
  1781. {
  1782. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1783. return (HRESULT) -1;
  1784. }
  1785. // make an FBO to draw into and activate it.
  1786. m_ctx->m_drawingFBO = m_ctx->NewFBO();
  1787. // bind it to context. will receive attachments shortly.
  1788. m_ctx->BindFBOToCtx( m_ctx->m_drawingFBO, GL_FRAMEBUFFER_EXT );
  1789. m_bFBODirty = false;
  1790. m_pFBOs = new CGLMFBOMap();
  1791. m_pFBOs->SetLessFunc( RenderTargetState_t::LessFunc );
  1792. // we create two IDirect3DSurface9's. These will be known as the internal render target 0 and the depthstencil.
  1793. GLMPRINTF(("-X- IDirect3DDevice9::Create making color render target..."));
  1794. // color surface
  1795. result = this->CreateRenderTarget(
  1796. m_params.m_presentationParameters.BackBufferWidth, // width
  1797. m_params.m_presentationParameters.BackBufferHeight, // height
  1798. m_params.m_presentationParameters.BackBufferFormat, // format
  1799. m_params.m_presentationParameters.MultiSampleType, // MSAA depth
  1800. m_params.m_presentationParameters.MultiSampleQuality, // MSAA quality
  1801. true, // lockable
  1802. &m_pDefaultColorSurface, // ppSurface
  1803. NULL, // shared handle
  1804. "InternalRT0"
  1805. );
  1806. if (result != S_OK)
  1807. {
  1808. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1809. return result;
  1810. }
  1811. // do not do an AddRef..
  1812. GLMPRINTF(("-X- IDirect3DDevice9::Create making color render target complete -> %08x", m_pDefaultColorSurface ));
  1813. GLMPRINTF(("-X- IDirect3DDevice9::Create setting color render target..."));
  1814. result = this->SetRenderTarget(0, m_pDefaultColorSurface);
  1815. if (result != S_OK)
  1816. {
  1817. GLMPRINTF(("< IDirect3DDevice9::Create (error out)"));
  1818. return result;
  1819. }
  1820. GLMPRINTF(("-X- IDirect3DDevice9::Create setting color render target complete."));
  1821. Assert (m_params.m_presentationParameters.EnableAutoDepthStencil);
  1822. GLMPRINTF(("-X- IDirect3DDevice9::Create making depth-stencil..."));
  1823. result = CreateDepthStencilSurface(
  1824. m_params.m_presentationParameters.BackBufferWidth, // width
  1825. m_params.m_presentationParameters.BackBufferHeight, // height
  1826. m_params.m_presentationParameters.AutoDepthStencilFormat, // format
  1827. m_params.m_presentationParameters.MultiSampleType, // MSAA depth
  1828. m_params.m_presentationParameters.MultiSampleQuality, // MSAA quality
  1829. TRUE, // enable z-buffer discard ????
  1830. &m_pDefaultDepthStencilSurface, // ppSurface
  1831. NULL // shared handle
  1832. );
  1833. if (result != S_OK)
  1834. {
  1835. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1836. return result;
  1837. }
  1838. // do not do an AddRef here..
  1839. GLMPRINTF(("-X- IDirect3DDevice9::Create making depth-stencil complete -> %08x", m_pDefaultDepthStencilSurface));
  1840. GLMPRINTF(("-X- Direct3DDevice9::Create setting depth-stencil render target..."));
  1841. result = this->SetDepthStencilSurface(m_pDefaultDepthStencilSurface);
  1842. if (result != S_OK)
  1843. {
  1844. DXABSTRACT_BREAK_ON_ERROR();
  1845. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1846. return result;
  1847. }
  1848. GLMPRINTF(("-X- IDirect3DDevice9::Create setting depth-stencil render target complete."));
  1849. UpdateBoundFBO();
  1850. bool ready = m_ctx->m_drawingFBO->IsReady();
  1851. if (!ready)
  1852. {
  1853. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1854. return (HRESULT)-1;
  1855. }
  1856. // this next part really needs to be inside GLMContext.. or replaced with D3D style viewport setup calls.
  1857. m_ctx->GenDebugFontTex();
  1858. // blast the gl state mirror...
  1859. memset( &this->gl, 0, sizeof( this->gl ) );
  1860. InitStates();
  1861. GLScissorEnable_t defScissorEnable = { true };
  1862. GLScissorBox_t defScissorBox = { 0,0, m_params.m_presentationParameters.BackBufferWidth,m_params.m_presentationParameters.BackBufferHeight };
  1863. GLViewportBox_t defViewportBox = { 0,0, m_params.m_presentationParameters.BackBufferWidth,m_params.m_presentationParameters.BackBufferHeight, m_params.m_presentationParameters.BackBufferWidth | ( m_params.m_presentationParameters.BackBufferHeight << 16 ) };
  1864. GLViewportDepthRange_t defViewportDepthRange = { 0.1, 1000.0 };
  1865. GLCullFaceEnable_t defCullFaceEnable = { true };
  1866. GLCullFrontFace_t defCullFrontFace = { GL_CCW };
  1867. gl.m_ScissorEnable = defScissorEnable;
  1868. gl.m_ScissorBox = defScissorBox;
  1869. gl.m_ViewportBox = defViewportBox;
  1870. gl.m_ViewportDepthRange = defViewportDepthRange;
  1871. gl.m_CullFaceEnable = defCullFaceEnable;
  1872. gl.m_CullFrontFace = defCullFrontFace;
  1873. FullFlushStates();
  1874. GLMPRINTF(("<-X- IDirect3DDevice9::Create complete"));
  1875. // so GetClientRect can return sane answers
  1876. //uint width, height;
  1877. RenderedSize( m_params.m_presentationParameters.BackBufferWidth, m_params.m_presentationParameters.BackBufferHeight, true ); // true = set
  1878. #if GL_TELEMETRY_GPU_ZONES
  1879. g_TelemetryGPUStats.Clear();
  1880. #endif
  1881. GL_BATCH_PERF(
  1882. g_nTotalD3DCalls = 0, g_nTotalD3DCycles = 0, m_nBatchVisY = 0, m_nBatchVisFrameIndex = 0, m_nBatchVisFileIdx = 0, m_nNumProgramChanges = 0, m_flTotalD3DTime = 0, m_nTotalD3DCalls = 0,
  1883. m_flTotalD3DTime = 0, m_nTotalGLCalls = 0, m_flTotalGLTime = 0, m_nOverallDraws = 0, m_nOverallPrims = 0, m_nOverallD3DCalls = 0, m_flOverallD3DTime = 0, m_nOverallGLCalls = 0, m_flOverallGLTime = 0, m_nOverallProgramChanges = 0,
  1884. m_flOverallPresentTime = 0, m_flOverallPresentTimeSquared = 0, m_nOverallPresents = 0, m_flOverallSwapWindowTime = 0, m_flOverallSwapWindowTimeSquared = 0, m_nTotalPrims = 0; );
  1885. g_nTotalDrawsOrClears = 0;
  1886. gGL->m_nTotalGLCycles = 0;
  1887. gGL->m_nTotalGLCalls = 0;
  1888. m_pDummy_vtx_buffer = new CGLMBuffer( m_ctx, kGLMVertexBuffer, 4096, 0 );
  1889. m_vtx_buffers[0] = m_pDummy_vtx_buffer;
  1890. m_vtx_buffers[1] = m_pDummy_vtx_buffer;
  1891. m_vtx_buffers[2] = m_pDummy_vtx_buffer;
  1892. m_vtx_buffers[3] = m_pDummy_vtx_buffer;
  1893. return result;
  1894. }
  1895. IDirect3DDevice9::IDirect3DDevice9() :
  1896. m_nValidMarker( D3D_DEVICE_VALID_MARKER )
  1897. {
  1898. }
  1899. IDirect3DDevice9::~IDirect3DDevice9()
  1900. {
  1901. Assert( m_nValidMarker == D3D_DEVICE_VALID_MARKER );
  1902. #if GL_BATCH_PERF_ANALYSIS && GL_BATCH_PERF_ANALYSIS_WRITE_PNGS
  1903. delete m_pBatch_vis_bitmap;
  1904. #endif
  1905. delete m_pDummy_vtx_buffer;
  1906. for ( int i = 0; i < 4; i++ )
  1907. SetRenderTarget( i, NULL );
  1908. SetDepthStencilSurface( NULL );
  1909. if ( m_pDefaultColorSurface )
  1910. {
  1911. m_pDefaultColorSurface->Release( 0, "IDirect3DDevice9::~IDirect3DDevice9 release color surface" );
  1912. m_pDefaultColorSurface = NULL;
  1913. }
  1914. if ( m_pDefaultDepthStencilSurface )
  1915. {
  1916. m_pDefaultDepthStencilSurface->Release( 0, "IDirect3DDevice9::~IDirect3DDevice9 release depth surface" );
  1917. m_pDefaultDepthStencilSurface = NULL;
  1918. }
  1919. if ( m_pFBOs )
  1920. {
  1921. ResetFBOMap();
  1922. }
  1923. GLMPRINTF(( "-D- IDirect3DDevice9::~IDirect3DDevice9 signpost" )); // want to know when this is called, if ever
  1924. g_pD3D_Device = NULL;
  1925. if ( m_ObjectStats.m_nTotalFBOs ) GLMDebugPrintf( "Leaking %i FBOs\n", m_ObjectStats.m_nTotalFBOs );
  1926. if ( m_ObjectStats.m_nTotalVertexShaders ) ConMsg( "Leaking %i vertex shaders\n", m_ObjectStats.m_nTotalVertexShaders );
  1927. if ( m_ObjectStats.m_nTotalPixelShaders ) ConMsg( "Leaking %i pixel shaders\n", m_ObjectStats.m_nTotalPixelShaders );
  1928. if ( m_ObjectStats.m_nTotalVertexDecls ) ConMsg( "Leaking %i vertex decls\n", m_ObjectStats.m_nTotalVertexDecls );
  1929. if ( m_ObjectStats.m_nTotalIndexBuffers ) ConMsg( "Leaking %i index buffers\n", m_ObjectStats.m_nTotalIndexBuffers );
  1930. if ( m_ObjectStats.m_nTotalVertexBuffers ) ConMsg( "Leaking %i vertex buffers\n", m_ObjectStats.m_nTotalVertexBuffers );
  1931. if ( m_ObjectStats.m_nTotalTextures ) ConMsg( "Leaking %i textures\n", m_ObjectStats.m_nTotalTextures );
  1932. if ( m_ObjectStats.m_nTotalSurfaces ) ConMsg( "Leaking %i surfaces\n", m_ObjectStats.m_nTotalSurfaces );
  1933. if ( m_ObjectStats.m_nTotalQueries ) ConMsg( "Leaking %i queries\n", m_ObjectStats.m_nTotalQueries );
  1934. if ( m_ObjectStats.m_nTotalRenderTargets ) ConMsg( "Leaking %i render targets\n", m_ObjectStats.m_nTotalRenderTargets );
  1935. GLMgr::aGLMgr()->DelContext( m_ctx );
  1936. m_ctx = NULL;
  1937. m_nValidMarker = 0xDEADBEEF;
  1938. }
  1939. #ifdef OSX
  1940. #pragma mark ----- Basics - (IDirect3DDevice9)
  1941. #endif
  1942. HRESULT IDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPresentationParameters)
  1943. {
  1944. GL_BATCH_PERF_CALL_TIMER;
  1945. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  1946. Assert( m_nValidMarker == D3D_DEVICE_VALID_MARKER );
  1947. HRESULT result = S_OK;
  1948. // define the task of reset as:
  1949. // provide new drawable RT's for the backbuffer (color and depthstencil).
  1950. // fix up viewport / scissor..
  1951. // then pass the new presentation parameters through to GLM.
  1952. // (it will in turn notify appframework on the next present... which may be very soon, as mode changes are usually spotted inside Present() ).
  1953. // so some of this looks a lot like Create - we're just a subset of what it does.
  1954. // with a little work you could refactor this to be common code.
  1955. GLMDebugPrintf( "IDirect3DDevice9::Reset: BackBufWidth: %u, BackBufHeight: %u, D3DFMT: %u, BackBufCount: %u, MultisampleType: %u, MultisampleQuality: %u\n",
  1956. pPresentationParameters->BackBufferWidth,
  1957. pPresentationParameters->BackBufferHeight,
  1958. pPresentationParameters->BackBufferFormat,
  1959. pPresentationParameters->BackBufferCount,
  1960. pPresentationParameters->MultiSampleType,
  1961. pPresentationParameters->MultiSampleQuality );
  1962. //------------------------------------------------------------------------------- absorb new presentation params..
  1963. m_params.m_presentationParameters = *pPresentationParameters;
  1964. //------------------------------------------------------------------------------- color buffer..
  1965. // release old color surface if it's there..
  1966. if ( m_pDefaultColorSurface )
  1967. {
  1968. ULONG refc = m_pDefaultColorSurface->Release( 0, "IDirect3DDevice9::Reset public release color surface" ); (void)refc;
  1969. Assert( !refc );
  1970. m_pDefaultColorSurface = NULL;
  1971. }
  1972. GLMPRINTF(("-X- IDirect3DDevice9::Reset making new color render target..."));
  1973. // color surface
  1974. result = this->CreateRenderTarget(
  1975. m_params.m_presentationParameters.BackBufferWidth, // width
  1976. m_params.m_presentationParameters.BackBufferHeight, // height
  1977. m_params.m_presentationParameters.BackBufferFormat, // format
  1978. m_params.m_presentationParameters.MultiSampleType, // MSAA depth
  1979. m_params.m_presentationParameters.MultiSampleQuality, // MSAA quality
  1980. true, // lockable
  1981. &m_pDefaultColorSurface, // ppSurface
  1982. NULL // shared handle
  1983. );
  1984. if ( result != S_OK )
  1985. {
  1986. GLMPRINTF(("<-X- IDirect3DDevice9::Reset (error out)"));
  1987. return result;
  1988. }
  1989. // do not do an AddRef here..
  1990. GLMPRINTF(("-X- IDirect3DDevice9::Reset making color render target complete -> %08x", m_pDefaultColorSurface ));
  1991. GLMPRINTF(("-X- IDirect3DDevice9::Reset setting color render target..."));
  1992. result = this->SetDepthStencilSurface( NULL );
  1993. result = this->SetRenderTarget( 0, m_pDefaultColorSurface );
  1994. if (result != S_OK)
  1995. {
  1996. GLMPRINTF(("< IDirect3DDevice9::Reset (error out)"));
  1997. return result;
  1998. }
  1999. GLMPRINTF(("-X- IDirect3DDevice9::Reset setting color render target complete."));
  2000. //-------------------------------------------------------------------------------depth stencil buffer
  2001. // release old depthstencil surface if it's there..
  2002. if ( m_pDefaultDepthStencilSurface )
  2003. {
  2004. ULONG refc = m_pDefaultDepthStencilSurface->Release( 0, "IDirect3DDevice9::Reset public release depthstencil surface" ); (void)refc;
  2005. Assert(!refc);
  2006. m_pDefaultDepthStencilSurface = NULL;
  2007. }
  2008. Assert (m_params.m_presentationParameters.EnableAutoDepthStencil);
  2009. GLMPRINTF(("-X- IDirect3DDevice9::Reset making depth-stencil..."));
  2010. result = CreateDepthStencilSurface(
  2011. m_params.m_presentationParameters.BackBufferWidth, // width
  2012. m_params.m_presentationParameters.BackBufferHeight, // height
  2013. m_params.m_presentationParameters.AutoDepthStencilFormat, // format
  2014. m_params.m_presentationParameters.MultiSampleType, // MSAA depth
  2015. m_params.m_presentationParameters.MultiSampleQuality, // MSAA quality
  2016. TRUE, // enable z-buffer discard ????
  2017. &m_pDefaultDepthStencilSurface, // ppSurface
  2018. NULL // shared handle
  2019. );
  2020. if (result != S_OK)
  2021. {
  2022. GLMPRINTF(("<-X- IDirect3DDevice9::Reset (error out)"));
  2023. return result;
  2024. }
  2025. // do not do an AddRef here..
  2026. GLMPRINTF(("-X- IDirect3DDevice9::Reset making depth-stencil complete -> %08x", m_pDefaultDepthStencilSurface));
  2027. GLMPRINTF(("-X- IDirect3DDevice9::Reset setting depth-stencil render target..."));
  2028. result = this->SetDepthStencilSurface(m_pDefaultDepthStencilSurface);
  2029. if (result != S_OK)
  2030. {
  2031. GLMPRINTF(("<-X- IDirect3DDevice9::Reset (error out)"));
  2032. return result;
  2033. }
  2034. GLMPRINTF(("-X- IDirect3DDevice9::Reset setting depth-stencil render target complete."));
  2035. UpdateBoundFBO();
  2036. bool ready = m_ctx->m_drawingFBO->IsReady();
  2037. if (!ready)
  2038. {
  2039. GLMPRINTF(("<-X- IDirect3DDevice9::Reset (error out)"));
  2040. return D3DERR_DEVICELOST;
  2041. }
  2042. //-------------------------------------------------------------------------------zap viewport and scissor to new backbuffer size
  2043. InitStates();
  2044. GLScissorEnable_t defScissorEnable = { true };
  2045. GLScissorBox_t defScissorBox = { 0,0, m_params.m_presentationParameters.BackBufferWidth,m_params.m_presentationParameters.BackBufferHeight };
  2046. GLViewportBox_t defViewportBox = { 0,0, m_params.m_presentationParameters.BackBufferWidth,m_params.m_presentationParameters.BackBufferHeight, m_params.m_presentationParameters.BackBufferWidth | ( m_params.m_presentationParameters.BackBufferHeight << 16 ) };
  2047. GLViewportDepthRange_t defViewportDepthRange = { 0.1, 1000.0 };
  2048. GLCullFaceEnable_t defCullFaceEnable = { true };
  2049. GLCullFrontFace_t defCullFrontFace = { GL_CCW };
  2050. gl.m_ScissorEnable = defScissorEnable;
  2051. gl.m_ScissorBox = defScissorBox;
  2052. gl.m_ViewportBox = defViewportBox;
  2053. gl.m_ViewportDepthRange = defViewportDepthRange;
  2054. gl.m_CullFaceEnable = defCullFaceEnable;
  2055. gl.m_CullFrontFace = defCullFrontFace;
  2056. FullFlushStates();
  2057. //-------------------------------------------------------------------------------finally, propagate new display params to GLM context
  2058. GLMDisplayParams glmParams;
  2059. ConvertPresentationParamsToGLMDisplayParams( pPresentationParameters, &glmParams );
  2060. // steal back previously sent focus window...
  2061. glmParams.m_focusWindow = m_ctx->m_displayParams.m_focusWindow;
  2062. Assert( glmParams.m_focusWindow != NULL );
  2063. // so GetClientRect can return sane answers
  2064. //uint width, height;
  2065. RenderedSize( pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight, true ); // true = set
  2066. m_ctx->Reset();
  2067. m_ctx->SetDisplayParams( &glmParams );
  2068. return S_OK;
  2069. }
  2070. HRESULT IDirect3DDevice9::SetViewport(CONST D3DVIEWPORT9* pViewport)
  2071. {
  2072. GL_BATCH_PERF_CALL_TIMER;
  2073. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2074. GLMPRINTF(("-X- IDirect3DDevice9::SetViewport : minZ %f, maxZ %f",pViewport->MinZ, pViewport->MaxZ ));
  2075. gl.m_ViewportBox.x = pViewport->X;
  2076. gl.m_ViewportBox.width = pViewport->Width;
  2077. gl.m_ViewportBox.y = pViewport->Y;
  2078. gl.m_ViewportBox.height = pViewport->Height;
  2079. gl.m_ViewportBox.widthheight = pViewport->Width | ( pViewport->Height << 16 );
  2080. m_ctx->WriteViewportBox( &gl.m_ViewportBox );
  2081. gl.m_ViewportDepthRange.flNear = pViewport->MinZ;
  2082. gl.m_ViewportDepthRange.flFar = pViewport->MaxZ;
  2083. m_ctx->WriteViewportDepthRange( &gl.m_ViewportDepthRange );
  2084. return S_OK;
  2085. }
  2086. HRESULT IDirect3DDevice9::GetViewport( D3DVIEWPORT9* pViewport )
  2087. {
  2088. // TODO - GetViewport() only used in scaleformuirenderimpl.cpp where only width and height required - unfinished otherwise.
  2089. GL_BATCH_PERF_CALL_TIMER;
  2090. Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() );
  2091. GLMPRINTF(("-X- IDirect3DDevice9::GetViewport " ));
  2092. pViewport->X = gl.m_ViewportBox.x;
  2093. pViewport->Width = gl.m_ViewportBox.width;
  2094. pViewport->Y = gl.m_ViewportBox.y;
  2095. pViewport->Height = gl.m_ViewportBox.height;
  2096. pViewport->MinZ = gl.m_ViewportDepthRange.flNear;
  2097. pViewport->MaxZ = gl.m_ViewportDepthRange.flFar;
  2098. return S_OK;
  2099. }
  2100. HRESULT IDirect3DDevice9::BeginScene()
  2101. {
  2102. GL_BATCH_PERF_CALL_TIMER;
  2103. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2104. m_ctx->BeginFrame();
  2105. return S_OK;
  2106. }
  2107. HRESULT IDirect3DDevice9::EndScene()
  2108. {
  2109. GL_BATCH_PERF_CALL_TIMER;
  2110. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2111. m_ctx->EndFrame();
  2112. return S_OK;
  2113. }
  2114. // stolen from glmgrbasics.cpp
  2115. enum ECarbonModKeyIndex
  2116. {
  2117. EcmdKeyBit = 8, /* command key down?*/
  2118. EshiftKeyBit = 9, /* shift key down?*/
  2119. EalphaLockBit = 10, /* alpha lock down?*/
  2120. EoptionKeyBit = 11, /* option key down?*/
  2121. EcontrolKeyBit = 12 /* control key down?*/
  2122. };
  2123. enum ECarbonModKeyMask
  2124. {
  2125. EcmdKey = 1 << EcmdKeyBit,
  2126. EshiftKey = 1 << EshiftKeyBit,
  2127. EalphaLock = 1 << EalphaLockBit,
  2128. EoptionKey = 1 << EoptionKeyBit,
  2129. EcontrolKey = 1 << EcontrolKeyBit
  2130. };
  2131. void IDirect3DDevice9::PrintObjectStats( const ObjectStats_t &stats )
  2132. {
  2133. ConMsg( "Total FBOs: %i\n", stats.m_nTotalFBOs );
  2134. ConMsg( "Total vertex shaders: %i\n", stats.m_nTotalVertexShaders );
  2135. ConMsg( "Total pixel shaders: %i\n", stats.m_nTotalPixelShaders );
  2136. ConMsg( "Total vertex decls: %i\n", stats.m_nTotalVertexDecls );
  2137. ConMsg( "Total index buffers: %i\n", stats.m_nTotalIndexBuffers );
  2138. ConMsg( "Total vertex buffers: %i\n", stats.m_nTotalVertexBuffers );
  2139. ConMsg( "Total textures: %i\n", stats.m_nTotalTextures );
  2140. ConMsg( "Total surfaces: %i\n", stats.m_nTotalSurfaces );
  2141. ConMsg( "Total queries: %i\n", stats.m_nTotalQueries );
  2142. ConMsg( "Total render targets: %i\n", stats.m_nTotalRenderTargets );
  2143. }
  2144. void IDirect3DDevice9::DumpStatsToConsole( const CCommand *pArgs )
  2145. {
  2146. #if GL_BATCH_PERF_ANALYSIS
  2147. ConMsg( "Overall: Batches: %u, Prims: %u, Program Changes: %u\n", m_nOverallDraws, m_nOverallPrims, m_nOverallProgramChanges );
  2148. ConMsg( "Overall: D3D Calls: %u D3D Time: %4.3fms, Avg D3D Time Per Call: %4.9fms\n", m_nOverallD3DCalls, m_flOverallD3DTime, m_nOverallD3DCalls ? ( m_flOverallD3DTime / m_nOverallD3DCalls ) : 0.0f );
  2149. ConMsg( "Overall: GL Calls: %u GL Time: %4.3fms, Avg GL Time Per Call: %4.9fms\n", m_nOverallGLCalls, m_flOverallGLTime, m_nOverallGLCalls ? ( m_flOverallGLTime / m_nOverallGLCalls ) : 0.0f );
  2150. ConMsg( "D3DPresent: %u, Overall Time: %4.3fms, Avg: %4.6fms, Std Dev: %4.6fms\n",
  2151. m_nOverallPresents,
  2152. m_flOverallPresentTime, m_nOverallPresents ? ( m_flOverallPresentTime / m_nOverallPresents ) : 0.0f,
  2153. m_nOverallPresents ? ( sqrt( ( m_flOverallPresentTimeSquared / m_nOverallPresents ) - ( m_flOverallPresentTime / m_nOverallPresents ) * ( m_flOverallPresentTime / m_nOverallPresents ) ) ) : 0.0f );
  2154. ConMsg( "GL SwapWindow(): Overall Time: %4.3fms, Avg: %4.6fms, Std Dev: %4.6fms\n",
  2155. m_flOverallSwapWindowTime, m_nOverallPresents ? ( m_flOverallSwapWindowTime / m_nOverallPresents ) : 0.0f,
  2156. m_nOverallPresents ? ( sqrt( ( m_flOverallSwapWindowTimeSquared / m_nOverallPresents ) - ( m_flOverallSwapWindowTime / m_nOverallPresents ) * ( m_flOverallSwapWindowTime / m_nOverallPresents ) ) ) : 0.0f );
  2157. if ( ( pArgs ) && ( pArgs->ArgC() == 2 ) && (pArgs->Arg(1)[0] != '0') )
  2158. {
  2159. m_nOverallDraws = 0;
  2160. m_nOverallPrims = 0;
  2161. m_nOverallProgramChanges = 0;
  2162. m_nOverallD3DCalls = 0;
  2163. m_flOverallD3DTime = 0;
  2164. m_nOverallGLCalls = 0;
  2165. m_flOverallGLTime = 0;
  2166. m_flOverallPresentTime = 0;
  2167. m_flOverallPresentTimeSquared = 0;
  2168. m_flOverallSwapWindowTime = 0;
  2169. m_flOverallSwapWindowTimeSquared = 0;
  2170. m_nOverallPresents = 0;
  2171. }
  2172. #endif
  2173. ConMsg( "Totals:\n" );
  2174. m_ObjectStats.m_nTotalFBOs = m_pFBOs->Count();
  2175. PrintObjectStats( m_ObjectStats );
  2176. ObjectStats_t delta( m_ObjectStats );
  2177. delta -= m_PrevObjectStats;
  2178. ConMsg( "Delta:\n" );
  2179. PrintObjectStats( delta );
  2180. m_PrevObjectStats = m_ObjectStats;
  2181. }
  2182. static void gl_dump_stats_func( const CCommand &args )
  2183. {
  2184. if ( g_pD3D_Device )
  2185. {
  2186. g_pD3D_Device->DumpStatsToConsole( &args );
  2187. }
  2188. }
  2189. static ConCommand gl_dump_stats( "gl_dump_stats", gl_dump_stats_func );
  2190. #if GLMDEBUG
  2191. void IDirect3DDevice9::DumpTextures( const CCommand *pArgs )
  2192. {
  2193. Assert( m_nValidMarker == D3D_DEVICE_VALID_MARKER );
  2194. (void)pArgs;
  2195. CGLMTex *pCurTex = g_pFirstCGMLTex;
  2196. if ( pCurTex )
  2197. {
  2198. Assert( pCurTex->m_pPrevTex == NULL );
  2199. }
  2200. ConMsg( "--- Internal CGLMTex's:\n" );
  2201. uint nNumFound = 0;
  2202. while ( pCurTex )
  2203. {
  2204. nNumFound++;
  2205. ConMsg( "Tex \"%s\", Layout: \"%s\", Size: %u, RT: %u, Depth: %u, Stencil: %u, MSAA: %u\n",
  2206. pCurTex->m_debugLabel ? pCurTex->m_debugLabel : "?",
  2207. pCurTex->m_layout->m_layoutSummary,
  2208. pCurTex->m_layout->m_storageTotalSize,
  2209. ( pCurTex->m_layout->m_key.m_texFlags & kGLMTexRenderable ) ? 1 : 0,
  2210. ( pCurTex->m_layout->m_key.m_texFlags & kGLMTexIsDepth ) ? 1 : 0,
  2211. ( pCurTex->m_layout->m_key.m_texFlags & kGLMTexIsStencil ) ? 1 : 0,
  2212. ( pCurTex->m_layout->m_key.m_texFlags & kGLMTexMultisampled ) ? 1 : 0 );
  2213. CGLMTex *pNextTex = pCurTex->m_pNextTex;
  2214. if ( pNextTex )
  2215. {
  2216. Assert( pNextTex->m_pPrevTex == pCurTex );
  2217. }
  2218. pCurTex = pNextTex;
  2219. }
  2220. ConMsg( "--- Found %u total CGLMTex's\n", nNumFound );
  2221. }
  2222. static void gl_dump_textures_func( const CCommand &args )
  2223. {
  2224. if ( g_pD3D_Device )
  2225. {
  2226. g_pD3D_Device->DumpTextures( &args );
  2227. }
  2228. }
  2229. static ConCommand gl_dump_textures( "gl_dump_textures", gl_dump_textures_func );
  2230. #endif
  2231. ConVar gl_blitmode( "gl_blitmode", "1" );
  2232. ConVar dxa_nullrefresh_capslock( "dxa_nullrefresh_capslock", "0" );
  2233. HRESULT IDirect3DDevice9::Present(CONST RECT* pSourceRect,CONST RECT* pDestRect,VD3DHWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion)
  2234. {
  2235. GL_BATCH_PERF( g_nTotalD3DCalls++; )
  2236. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2237. TOGL_NULL_DEVICE_CHECK;
  2238. if ( m_bFBODirty )
  2239. {
  2240. UpdateBoundFBO();
  2241. }
  2242. // before attempting to present a tex, make sure it's been resolved if it was MSAA.
  2243. // if we push that responsibility down to m_ctx->Present, it could probably do it without an extra copy.
  2244. // i.e. anticipate the blit from the resolvedtex to GL_BACK, and just do that instead.
  2245. // no explicit ResolveTex call first - that got pushed down into GLMContext::Present
  2246. #if GL_BATCH_PERF_ANALYSIS
  2247. uint64 nStartGLCycles = gGL->m_nTotalGLCycles;
  2248. nStartGLCycles;
  2249. CFastTimer tm;
  2250. tm.Start();
  2251. #endif
  2252. m_ctx->Present( m_pDefaultColorSurface->m_tex );
  2253. #if GL_BATCH_PERF_ANALYSIS
  2254. double flPresentTime = tm.GetDurationInProgress().GetMillisecondsF();
  2255. double flGLSwapWindowTime = g_pLauncherMgr->GetPrevGLSwapWindowTime();
  2256. m_flOverallPresentTime += flPresentTime;
  2257. m_flOverallPresentTimeSquared += flPresentTime * flPresentTime;
  2258. m_flOverallSwapWindowTime += flGLSwapWindowTime;
  2259. m_flOverallSwapWindowTimeSquared += flGLSwapWindowTime * flGLSwapWindowTime;
  2260. m_nOverallPresents++;
  2261. uint64 nEndGLCycles = gGL->m_nTotalGLCycles;
  2262. nEndGLCycles;
  2263. m_flTotalD3DTime += flPresentTime + g_nTotalD3DCycles * s_rdtsc_to_ms;
  2264. m_nTotalD3DCalls += g_nTotalD3DCalls;
  2265. m_flTotalGLTime += gGL->m_nTotalGLCycles * s_rdtsc_to_ms;
  2266. m_nTotalGLCalls += gGL->m_nTotalGLCalls;
  2267. m_nOverallProgramChanges += m_nNumProgramChanges;
  2268. m_nOverallDraws += g_nTotalDrawsOrClears;
  2269. m_nOverallPrims += m_nTotalPrims;
  2270. m_nOverallD3DCalls += m_nTotalD3DCalls;
  2271. m_flOverallD3DTime += m_flTotalD3DTime;
  2272. m_nOverallGLCalls += m_nTotalGLCalls;
  2273. m_flOverallGLTime += m_flTotalGLTime;
  2274. static int nPrevBatchVis = -1;
  2275. #if GL_BATCH_PERF_ANALYSIS_WRITE_PNGS
  2276. if ((nPrevBatchVis == 1) && m_pBatch_vis_bitmap && m_pBatch_vis_bitmap->is_valid())
  2277. {
  2278. double flTotalGLPresentTime = ( nEndGLCycles - nStartGLCycles ) * s_rdtsc_to_ms;
  2279. m_pBatch_vis_bitmap->fill_box(0, m_nBatchVisY, (uint)(.5f + flPresentTime / gl_present_vis_abs_scale.GetFloat() * m_pBatch_vis_bitmap->width()), 10, 255, 16, 128);
  2280. m_pBatch_vis_bitmap->additive_fill_box(0, m_nBatchVisY, (uint)(.5f + flTotalGLPresentTime / gl_present_vis_abs_scale.GetFloat() * m_pBatch_vis_bitmap->width()), 10, 0, 255, 128);
  2281. m_nBatchVisY += 10;
  2282. uint y = MAX(m_nBatchVisY + 20, 600), l = 0;
  2283. m_pBatch_vis_bitmap->draw_formatted_text(0, y+8*(l++), 1, 255, 255, 255, "OpenGL Frame: %u, Batches+Clears: %u, Prims: %u, Program Changes: %u", m_nOverallPresents, g_nTotalDrawsOrClears, m_nTotalPrims, m_nNumProgramChanges );
  2284. m_pBatch_vis_bitmap->draw_formatted_text(0, y+8*(l++), 1, 255, 255, 255, "Frame: D3D Calls: %u, D3D Time: %3.3fms", m_nTotalD3DCalls, m_flTotalD3DTime);
  2285. m_pBatch_vis_bitmap->draw_formatted_text(0, y+8*(l++), 1, 255, 255, 255, "Frame: GL Calls: %u, GL Time: %3.3fms", m_nTotalGLCalls, m_flTotalGLTime);
  2286. l++;
  2287. m_pBatch_vis_bitmap->draw_formatted_text(0, y+8*(l++), 1, 255, 255, 255, "Overall: Batches: %u, Prims: %u, Program Changes: %u", m_nOverallDraws, m_nOverallPrims, m_nOverallProgramChanges );
  2288. m_pBatch_vis_bitmap->draw_formatted_text(0, y+8*(l++), 1, 255, 255, 255, "Overall: D3D Calls: %u D3D Time: %4.3fms", m_nOverallD3DCalls, m_flOverallD3DTime );
  2289. m_pBatch_vis_bitmap->draw_formatted_text(0, y+8*(l++), 1, 255, 255, 255, "Overall: GL Calls: %u GL Time: %4.3fms", m_nOverallGLCalls, m_flOverallGLTime );
  2290. size_t png_size = 0;
  2291. void *pPNG_data = tdefl_write_image_to_png_file_in_memory(m_pBatch_vis_bitmap->get_ptr(), m_pBatch_vis_bitmap->width(), m_pBatch_vis_bitmap->height(), 3, &png_size, true);
  2292. if (pPNG_data)
  2293. {
  2294. char filename[256];
  2295. V_snprintf(filename, sizeof(filename), "left4dead2/batchvis_%u_%u.png", m_nBatchVisFileIdx, m_nBatchVisFrameIndex);
  2296. FILE* pFile = fopen(filename, "wb");
  2297. if (pFile)
  2298. {
  2299. fwrite(pPNG_data, png_size, 1, pFile);
  2300. fclose(pFile);
  2301. }
  2302. free(pPNG_data);
  2303. }
  2304. m_nBatchVisFrameIndex++;
  2305. m_nBatchVisY = 0;
  2306. m_pBatch_vis_bitmap->cls();
  2307. }
  2308. #endif
  2309. if (nPrevBatchVis != (int)gl_batch_vis.GetBool())
  2310. {
  2311. if ( !m_pBatch_vis_bitmap )
  2312. m_pBatch_vis_bitmap = new simple_bitmap;
  2313. nPrevBatchVis = gl_batch_vis.GetBool();
  2314. if (!nPrevBatchVis)
  2315. {
  2316. DumpStatsToConsole( NULL );
  2317. m_pBatch_vis_bitmap->clear();
  2318. }
  2319. else
  2320. {
  2321. m_pBatch_vis_bitmap->init(768, 1024);
  2322. }
  2323. m_nBatchVisY = 0;
  2324. m_nBatchVisFrameIndex = 0;
  2325. m_nBatchVisFileIdx = (uint)time(NULL); //rand();
  2326. m_nOverallProgramChanges = 0;
  2327. m_nOverallDraws = 0;
  2328. m_nOverallD3DCalls = 0;
  2329. m_flOverallD3DTime = 0;
  2330. m_nOverallGLCalls = 0;
  2331. m_flOverallGLTime = 0;
  2332. m_flOverallPresentTime = 0;
  2333. m_flOverallPresentTimeSquared = 0;
  2334. m_flOverallSwapWindowTime = 0;
  2335. m_flOverallSwapWindowTimeSquared = 0;
  2336. m_nOverallPresents = 0;
  2337. }
  2338. g_nTotalD3DCycles = 0;
  2339. g_nTotalD3DCalls = 0;
  2340. gGL->m_nTotalGLCycles = 0;
  2341. gGL->m_nTotalGLCalls = 0;
  2342. m_nNumProgramChanges = 0;
  2343. m_flTotalD3DTime = 0;
  2344. m_nTotalD3DCalls = 0;
  2345. m_flTotalGLTime = 0;
  2346. m_nTotalGLCalls = 0;
  2347. m_nTotalPrims = 0;
  2348. #else
  2349. if ( gl_batch_vis.GetBool() )
  2350. {
  2351. gl_batch_vis.SetValue( false );
  2352. ConMsg( "Must define GL_BATCH_PERF_ANALYSIS to use this feature" );
  2353. }
  2354. #endif
  2355. g_nTotalDrawsOrClears = 0;
  2356. #if GL_TELEMETRY_GPU_ZONES
  2357. g_TelemetryGPUStats.Clear();
  2358. #endif
  2359. return S_OK;
  2360. }
  2361. #ifdef OSX
  2362. #pragma mark ----- Textures - (IDirect3DDevice9)
  2363. #pragma mark ( create functions for each texture are now adjacent to the rest of the methods for each texture class)
  2364. #endif
  2365. HRESULT IDirect3DDevice9::GetTexture(DWORD Stage,IDirect3DBaseTexture9** ppTexture)
  2366. {
  2367. GL_BATCH_PERF_CALL_TIMER;
  2368. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2369. // if implemented, should it increase the ref count ??
  2370. DXABSTRACT_BREAK_ON_ERROR();
  2371. return S_OK;
  2372. }
  2373. #ifdef OSX
  2374. #pragma mark ----- RTs and Surfaces - (IDirect3DDevice9)
  2375. #endif
  2376. HRESULT IDirect3DDevice9::CreateRenderTarget(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle, char *pDebugLabel)
  2377. {
  2378. GL_BATCH_PERF_CALL_TIMER;
  2379. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2380. HRESULT result = S_OK;
  2381. m_ObjectStats.m_nTotalSurfaces++;
  2382. m_ObjectStats.m_nTotalRenderTargets++;
  2383. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  2384. surf->m_restype = D3DRTYPE_SURFACE;
  2385. surf->m_device = this; // always set device on creations!
  2386. GLMTexLayoutKey rtkey;
  2387. memset( &rtkey, 0, sizeof(rtkey) );
  2388. rtkey.m_texGLTarget = GL_TEXTURE_2D;
  2389. rtkey.m_xSize = Width;
  2390. rtkey.m_ySize = Height;
  2391. rtkey.m_zSize = 1;
  2392. rtkey.m_texFormat = Format;
  2393. rtkey.m_texFlags = kGLMTexRenderable;
  2394. rtkey.m_texFlags |= kGLMTexSRGB; // all render target tex are SRGB mode
  2395. if (m_ctx->Caps().m_cantAttachSRGB)
  2396. {
  2397. // this config can't support SRGB render targets. quietly turn off the sRGB bit.
  2398. rtkey.m_texFlags &= ~kGLMTexSRGB;
  2399. }
  2400. if ( (MultiSample !=0) && (!m_ctx->Caps().m_nvG7x) )
  2401. {
  2402. rtkey.m_texFlags |= kGLMTexMultisampled;
  2403. rtkey.m_texSamples = MultiSample;
  2404. // FIXME no support for "MS quality" yet
  2405. }
  2406. surf->m_tex = m_ctx->NewTex( &rtkey, 1, pDebugLabel );
  2407. surf->m_face = 0;
  2408. surf->m_mip = 0;
  2409. //desc
  2410. surf->m_desc.Format = Format;
  2411. surf->m_desc.Type = D3DRTYPE_SURFACE;
  2412. surf->m_desc.Usage = 0; //FIXME ???????????
  2413. surf->m_desc.Pool = D3DPOOL_DEFAULT; //FIXME ???????????
  2414. surf->m_desc.MultiSampleType = MultiSample;
  2415. surf->m_desc.MultiSampleQuality = MultisampleQuality;
  2416. surf->m_desc.Width = Width;
  2417. surf->m_desc.Height = Height;
  2418. *ppSurface = (result==S_OK) ? surf : NULL;
  2419. #if IUNKNOWN_ALLOC_SPEW
  2420. char scratch[1024];
  2421. sprintf(scratch,"RT %s", surf->m_tex->m_layout->m_layoutSummary );
  2422. surf->SetMark( true, scratch );
  2423. #endif
  2424. return result;
  2425. }
  2426. void IDirect3DDevice9::UpdateBoundFBO()
  2427. {
  2428. RenderTargetState_t renderTargetState;
  2429. for ( uint i = 0; i < 4; i++ )
  2430. {
  2431. renderTargetState.m_pRenderTargets[i] = m_pRenderTargets[i] ? m_pRenderTargets[i]->m_tex : NULL;
  2432. }
  2433. renderTargetState.m_pDepthStencil = m_pDepthStencil ? m_pDepthStencil->m_tex : NULL;
  2434. CUtlMap < RenderTargetState_t, CGLMFBO * >::IndexType_t index = m_pFBOs->Find( renderTargetState );
  2435. if ( m_pFBOs->IsValidIndex( index ) )
  2436. {
  2437. Assert( (*m_pFBOs)[index] );
  2438. m_ctx->m_drawingFBO = (*m_pFBOs)[index];
  2439. }
  2440. else
  2441. {
  2442. CGLMFBO *newFBO = m_ctx->NewFBO();
  2443. m_pFBOs->Insert( renderTargetState, newFBO );
  2444. uint nNumBound = 0;
  2445. for ( uint i = 0; i < 4; i++ )
  2446. {
  2447. if ( !m_pRenderTargets[i] )
  2448. continue;
  2449. GLMFBOTexAttachParams rtParams;
  2450. memset( &rtParams, 0, sizeof(rtParams) );
  2451. rtParams.m_tex = m_pRenderTargets[i]->m_tex;
  2452. rtParams.m_face = m_pRenderTargets[i]->m_face;
  2453. rtParams.m_mip = m_pRenderTargets[i]->m_mip;
  2454. rtParams.m_zslice = 0;
  2455. newFBO->TexAttach( &rtParams, (EGLMFBOAttachment)(kAttColor0 + i) );
  2456. nNumBound++;
  2457. }
  2458. if ( m_pDepthStencil )
  2459. {
  2460. GLMFBOTexAttachParams depthParams;
  2461. memset( &depthParams, 0, sizeof(depthParams) );
  2462. depthParams.m_tex = m_pDepthStencil->m_tex;
  2463. EGLMFBOAttachment destAttach = (depthParams.m_tex->m_layout->m_format->m_glDataFormat != 34041) ? kAttDepth : kAttDepthStencil;
  2464. newFBO->TexAttach( &depthParams, destAttach );
  2465. nNumBound++;
  2466. }
  2467. (void)nNumBound;
  2468. Assert( nNumBound );
  2469. #if GLMDEBUG
  2470. Assert( newFBO->IsReady() );
  2471. #endif
  2472. m_ctx->m_drawingFBO = newFBO;
  2473. }
  2474. m_ctx->BindFBOToCtx( m_ctx->m_drawingFBO, GL_FRAMEBUFFER_EXT );
  2475. m_bFBODirty = false;
  2476. }
  2477. void IDirect3DDevice9::ResetFBOMap()
  2478. {
  2479. if ( !m_pFBOs )
  2480. return;
  2481. FOR_EACH_MAP_FAST( (*m_pFBOs), i )
  2482. {
  2483. const RenderTargetState_t &rtState = m_pFBOs->Key( i ); (void)rtState;
  2484. CGLMFBO *pFBO = (*m_pFBOs)[i];
  2485. m_ctx->DelFBO( pFBO );
  2486. }
  2487. m_pFBOs->Purge();
  2488. m_bFBODirty = true;
  2489. }
  2490. void IDirect3DDevice9::ScrubFBOMap( CGLMTex *pTex )
  2491. {
  2492. Assert( pTex );
  2493. if ( !m_pFBOs )
  2494. return;
  2495. CUtlVectorFixed< RenderTargetState_t, 128 > fbosToRemove;
  2496. FOR_EACH_MAP_FAST( (*m_pFBOs), i )
  2497. {
  2498. const RenderTargetState_t &rtState = m_pFBOs->Key( i );
  2499. CGLMFBO *pFBO = (*m_pFBOs)[i]; (void)pFBO;
  2500. if ( rtState.RefersTo( pTex ) )
  2501. {
  2502. fbosToRemove.AddToTail( rtState );
  2503. }
  2504. }
  2505. for ( int i = 0; i < fbosToRemove.Count(); ++i )
  2506. {
  2507. const RenderTargetState_t &rtState = fbosToRemove[i];
  2508. CUtlMap < RenderTargetState_t, CGLMFBO * >::IndexType_t index = m_pFBOs->Find( rtState );
  2509. if ( !m_pFBOs->IsValidIndex( index ) )
  2510. {
  2511. Assert( 0 );
  2512. continue;
  2513. }
  2514. CGLMFBO *pFBO = (*m_pFBOs)[index];
  2515. m_ctx->DelFBO( pFBO );
  2516. m_pFBOs->RemoveAt( index );
  2517. m_bFBODirty = true;
  2518. }
  2519. //GLMDebugPrintf( "IDirect3DDevice9::ScrubFBOMap: Removed %u entries\n", fbosToRemove.Count() );
  2520. }
  2521. HRESULT IDirect3DDevice9::SetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget)
  2522. {
  2523. GL_BATCH_PERF_CALL_TIMER;
  2524. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2525. tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "%s", __FUNCTION__ );
  2526. Assert( RenderTargetIndex < 4 );
  2527. HRESULT result = S_OK;
  2528. GLMPRINTF(("-F- SetRenderTarget index=%d, surface=%8x (tex=%8x %s)",
  2529. RenderTargetIndex,
  2530. pRenderTarget,
  2531. pRenderTarget ? pRenderTarget->m_tex : NULL,
  2532. pRenderTarget ? pRenderTarget->m_tex->m_layout->m_layoutSummary : ""
  2533. ));
  2534. // note that it is OK to pass NULL for pRenderTarget, it implies that you would like to detach any color buffer from that target index
  2535. // behaviors...
  2536. // if new surf is same as old surf, no change in refcount, in fact, it's early exit
  2537. IDirect3DSurface9 *oldTarget = m_pRenderTargets[RenderTargetIndex];
  2538. if (pRenderTarget == oldTarget)
  2539. {
  2540. GLMPRINTF(("-F- --> no change",RenderTargetIndex));
  2541. return S_OK;
  2542. }
  2543. // Fix this if porting to x86_64
  2544. if ( m_pRenderTargets[RenderTargetIndex] )
  2545. {
  2546. // we now know that the new surf is not the same as the old surf.
  2547. // you can't assume either one is non NULL here though.
  2548. m_pRenderTargets[RenderTargetIndex]->Release( 1, "-A SetRenderTarget private release" );
  2549. }
  2550. if (pRenderTarget)
  2551. {
  2552. pRenderTarget->AddRef( 1, "+A SetRenderTarget private addref" ); // again, private refcount being raised
  2553. }
  2554. m_pRenderTargets[RenderTargetIndex] = pRenderTarget;
  2555. m_bFBODirty = true;
  2556. /*
  2557. if (!pRenderTarget)
  2558. {
  2559. GLMPRINTF(("-F- --> Setting NULL render target on index=%d ",RenderTargetIndex));
  2560. }
  2561. else
  2562. {
  2563. GLMPRINTF(("-F- --> attaching index=%d on drawing FBO (%8x)",RenderTargetIndex, m_drawableFBO));
  2564. // attach color to FBO
  2565. GLMFBOTexAttachParams rtParams;
  2566. memset( &rtParams, 0, sizeof(rtParams) );
  2567. rtParams.m_tex = pRenderTarget->m_tex;
  2568. rtParams.m_face = pRenderTarget->m_face;
  2569. rtParams.m_mip = pRenderTarget->m_mip;
  2570. rtParams.m_zslice = 0; // FIXME if you ever want to be able to render to slices of a 3D tex..
  2571. m_drawableFBO->TexAttach( &rtParams, (EGLMFBOAttachment)(kAttColor0 + RenderTargetIndex) );
  2572. }
  2573. */
  2574. #if GL_BATCH_PERF_ANALYSIS && GL_BATCH_PERF_ANALYSIS_WRITE_PNGS
  2575. if ( m_pBatch_vis_bitmap && m_pBatch_vis_bitmap->is_valid() && !RenderTargetIndex )
  2576. {
  2577. m_pBatch_vis_bitmap->fill_box(0, m_nBatchVisY, m_pBatch_vis_bitmap->width(), 1, 30, 20, 20);
  2578. m_nBatchVisY += 1;
  2579. }
  2580. #endif
  2581. return result;
  2582. }
  2583. HRESULT IDirect3DDevice9::GetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget)
  2584. {
  2585. GL_BATCH_PERF_CALL_TIMER;
  2586. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2587. if ( !m_pRenderTargets[ RenderTargetIndex ] )
  2588. return D3DERR_NOTFOUND;
  2589. if ( ( RenderTargetIndex > 4 ) || !ppRenderTarget )
  2590. return D3DERR_INVALIDCALL;
  2591. // safe because of early exit on NULL above
  2592. m_pRenderTargets[ RenderTargetIndex ]->AddRef(0, "+B GetRenderTarget public addref"); // per http://msdn.microsoft.com/en-us/library/bb174404(VS.85).aspx
  2593. *ppRenderTarget = m_pRenderTargets[ RenderTargetIndex ];
  2594. return S_OK;
  2595. }
  2596. HRESULT IDirect3DDevice9::CreateOffscreenPlainSurface( UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle )
  2597. {
  2598. GL_BATCH_PERF_CALL_TIMER;
  2599. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2600. // set surf->m_restype to D3DRTYPE_SURFACE...
  2601. // this is almost identical to CreateRenderTarget..
  2602. HRESULT result = S_OK;
  2603. m_ObjectStats.m_nTotalSurfaces++;
  2604. m_ObjectStats.m_nTotalRenderTargets++;
  2605. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  2606. surf->m_restype = D3DRTYPE_SURFACE;
  2607. surf->m_device = this; // always set device on creations!
  2608. GLMTexLayoutKey rtkey;
  2609. memset( &rtkey, 0, sizeof(rtkey) );
  2610. rtkey.m_texGLTarget = GL_TEXTURE_2D;
  2611. rtkey.m_xSize = Width;
  2612. rtkey.m_ySize = Height;
  2613. rtkey.m_zSize = 1;
  2614. rtkey.m_texFormat = Format;
  2615. rtkey.m_texFlags = kGLMTexRenderable;
  2616. surf->m_tex = m_ctx->NewTex( &rtkey, 1, "offscreen plain surface" );
  2617. surf->m_face = 0;
  2618. surf->m_mip = 0;
  2619. //desc
  2620. surf->m_desc.Format = Format;
  2621. surf->m_desc.Type = D3DRTYPE_SURFACE;
  2622. surf->m_desc.Usage = 0;
  2623. surf->m_desc.Pool = D3DPOOL_DEFAULT;
  2624. surf->m_desc.MultiSampleType = D3DMULTISAMPLE_NONE;
  2625. surf->m_desc.MultiSampleQuality = 0;
  2626. surf->m_desc.Width = Width;
  2627. surf->m_desc.Height = Height;
  2628. *ppSurface = (result==S_OK) ? surf : NULL;
  2629. return result;
  2630. }
  2631. HRESULT IDirect3DDevice9::CreateDepthStencilSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle)
  2632. {
  2633. GL_BATCH_PERF_CALL_TIMER;
  2634. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2635. Assert( ( Format == D3DFMT_D16 ) || ( Format == D3DFMT_D24X8 ) || ( Format == D3DFMT_D24S8 ) );
  2636. HRESULT result = S_OK;
  2637. m_ObjectStats.m_nTotalSurfaces++;
  2638. m_ObjectStats.m_nTotalRenderTargets++;
  2639. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  2640. surf->m_restype = D3DRTYPE_SURFACE;
  2641. surf->m_device = this; // always set device on creations!
  2642. GLMTexLayoutKey depthkey;
  2643. memset( &depthkey, 0, sizeof(depthkey) );
  2644. depthkey.m_texGLTarget = GL_TEXTURE_2D;
  2645. depthkey.m_xSize = Width;
  2646. depthkey.m_ySize = Height;
  2647. depthkey.m_zSize = 1;
  2648. depthkey.m_texFormat = Format;
  2649. depthkey.m_texFlags = kGLMTexRenderable | kGLMTexIsDepth;
  2650. if ( Format == D3DFMT_D24S8 )
  2651. {
  2652. depthkey.m_texFlags |= kGLMTexIsStencil;
  2653. }
  2654. if ( (MultiSample !=0) && (!m_ctx->Caps().m_nvG7x) )
  2655. {
  2656. depthkey.m_texFlags |= kGLMTexMultisampled;
  2657. depthkey.m_texSamples = MultiSample;
  2658. // FIXME no support for "MS quality" yet
  2659. }
  2660. surf->m_tex = m_ctx->NewTex( &depthkey, 1, "depth-stencil surface" );
  2661. surf->m_face = 0;
  2662. surf->m_mip = 0;
  2663. //desc
  2664. surf->m_desc.Format = Format;
  2665. surf->m_desc.Type = D3DRTYPE_SURFACE;
  2666. surf->m_desc.Usage = 0; //FIXME ???????????
  2667. surf->m_desc.Pool = D3DPOOL_DEFAULT; //FIXME ???????????
  2668. surf->m_desc.MultiSampleType = MultiSample;
  2669. surf->m_desc.MultiSampleQuality = MultisampleQuality;
  2670. surf->m_desc.Width = Width;
  2671. surf->m_desc.Height = Height;
  2672. *ppSurface = (result==S_OK) ? surf : NULL;
  2673. return result;
  2674. }
  2675. HRESULT IDirect3DDevice9::SetDepthStencilSurface( IDirect3DSurface9* pNewZStencil )
  2676. {
  2677. GL_BATCH_PERF_CALL_TIMER;
  2678. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2679. HRESULT result = S_OK;
  2680. GLMPRINTF(("-F- SetDepthStencilSurface, surface=%8x (tex=%8x %s)",
  2681. pNewZStencil,
  2682. pNewZStencil ? pNewZStencil->m_tex : NULL,
  2683. pNewZStencil ? pNewZStencil->m_tex->m_layout->m_layoutSummary : ""
  2684. ));
  2685. if ( pNewZStencil == m_pDepthStencil )
  2686. {
  2687. GLMPRINTF(("-F- --> no change"));
  2688. return S_OK;
  2689. }
  2690. if ( pNewZStencil )
  2691. {
  2692. pNewZStencil->AddRef(1, "+A SetDepthStencilSurface private addref");
  2693. }
  2694. if ( m_pDepthStencil )
  2695. {
  2696. // Note this Release() could cause the surface to be deleted!
  2697. m_pDepthStencil->Release(1, "-A SetDepthStencilSurface private release");
  2698. }
  2699. m_pDepthStencil = pNewZStencil;
  2700. m_bFBODirty = true;
  2701. return result;
  2702. }
  2703. HRESULT IDirect3DDevice9::GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface)
  2704. {
  2705. GL_BATCH_PERF_CALL_TIMER;
  2706. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2707. if ( !ppZStencilSurface )
  2708. {
  2709. return D3DERR_INVALIDCALL;
  2710. }
  2711. if ( !m_pDepthStencil )
  2712. {
  2713. *ppZStencilSurface = NULL;
  2714. return D3DERR_NOTFOUND;
  2715. }
  2716. m_pDepthStencil->AddRef(0, "+B GetDepthStencilSurface public addref"); // per http://msdn.microsoft.com/en-us/library/bb174384(VS.85).aspx
  2717. *ppZStencilSurface = m_pDepthStencil;
  2718. return S_OK;
  2719. }
  2720. HRESULT IDirect3DDevice9::GetRenderTargetData(IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface)
  2721. {
  2722. GL_BATCH_PERF_CALL_TIMER;
  2723. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2724. // is it just a blit ?
  2725. this->StretchRect( pRenderTarget, NULL, pDestSurface, NULL, D3DTEXF_NONE ); // is this good enough ???
  2726. return S_OK;
  2727. }
  2728. HRESULT IDirect3DDevice9::GetFrontBufferData(UINT iSwapChain,IDirect3DSurface9* pDestSurface)
  2729. {
  2730. GL_BATCH_PERF_CALL_TIMER;
  2731. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2732. DXABSTRACT_BREAK_ON_ERROR();
  2733. return S_OK;
  2734. }
  2735. HRESULT IDirect3DDevice9::StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter)
  2736. {
  2737. GL_BATCH_PERF_CALL_TIMER;
  2738. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2739. // find relevant slices in GLM tex
  2740. if ( m_bFBODirty )
  2741. {
  2742. UpdateBoundFBO();
  2743. }
  2744. CGLMTex *srcTex = pSourceSurface->m_tex;
  2745. int srcSliceIndex = srcTex->CalcSliceIndex( pSourceSurface->m_face, pSourceSurface->m_mip );
  2746. GLMTexLayoutSlice *srcSlice = &srcTex->m_layout->m_slices[ srcSliceIndex ];
  2747. CGLMTex *dstTex = pDestSurface->m_tex;
  2748. int dstSliceIndex = dstTex->CalcSliceIndex( pDestSurface->m_face, pDestSurface->m_mip );
  2749. GLMTexLayoutSlice *dstSlice = &dstTex->m_layout->m_slices[ dstSliceIndex ];
  2750. if ( dstTex->m_rboName != 0 )
  2751. {
  2752. Assert(!"No path yet for blitting into an MSAA tex");
  2753. return S_OK;
  2754. }
  2755. bool useFastBlit = (gl_blitmode.GetInt() != 0);
  2756. if ( !useFastBlit && (srcTex->m_rboName !=0)) // old way, we do a resolve to scratch tex first (necessitating two step blit)
  2757. {
  2758. m_ctx->ResolveTex( srcTex, true );
  2759. }
  2760. // set up source/dest rect in GLM form
  2761. GLMRect srcRect, dstRect;
  2762. // d3d nomenclature:
  2763. // Y=0 is the visual top and also aligned with V=0.
  2764. srcRect.xmin = pSourceRect ? pSourceRect->left : 0;
  2765. srcRect.xmax = pSourceRect ? pSourceRect->right : srcSlice->m_xSize;
  2766. srcRect.ymin = pSourceRect ? pSourceRect->top : 0;
  2767. srcRect.ymax = pSourceRect ? pSourceRect->bottom : srcSlice->m_ySize;
  2768. dstRect.xmin = pDestRect ? pDestRect->left : 0;
  2769. dstRect.xmax = pDestRect ? pDestRect->right : dstSlice->m_xSize;
  2770. dstRect.ymin = pDestRect ? pDestRect->top : 0;
  2771. dstRect.ymax = pDestRect ? pDestRect->bottom : dstSlice->m_ySize;
  2772. GLenum filterGL = 0;
  2773. switch(Filter)
  2774. {
  2775. case D3DTEXF_NONE:
  2776. case D3DTEXF_POINT:
  2777. filterGL = GL_NEAREST;
  2778. break;
  2779. case D3DTEXF_LINEAR:
  2780. filterGL = GL_LINEAR;
  2781. break;
  2782. default: // D3DTEXF_ANISOTROPIC
  2783. Assert(!"Impl aniso stretch");
  2784. break;
  2785. }
  2786. if (useFastBlit)
  2787. {
  2788. m_ctx->Blit2( srcTex, &srcRect, pSourceSurface->m_face, pSourceSurface->m_mip,
  2789. dstTex, &dstRect, pDestSurface->m_face, pDestSurface->m_mip,
  2790. filterGL
  2791. );
  2792. }
  2793. else
  2794. {
  2795. m_ctx->BlitTex( srcTex, &srcRect, pSourceSurface->m_face, pSourceSurface->m_mip,
  2796. dstTex, &dstRect, pDestSurface->m_face, pDestSurface->m_mip,
  2797. filterGL
  2798. );
  2799. }
  2800. return S_OK;
  2801. }
  2802. // This totally sucks, but this information can't be gleaned any
  2803. // other way when translating from D3D to GL at this level
  2804. //
  2805. // This returns a mask, since multiple GLSL "varyings" can be tagged with centroid
  2806. static uint32 CentroidMaskFromName( bool bPixelShader, const char *pName )
  2807. {
  2808. if ( !pName )
  2809. return 0;
  2810. // Important: The centroid bitflags must match between all linked vertex/pixel shaders!
  2811. if ( bPixelShader )
  2812. {
  2813. if ( V_stristr( pName, "lightmappedgeneric_ps" ) || V_strstr( pName, "worldtwotextureblend_ps" ) )
  2814. {
  2815. return (0x01 << 2) | (0x01 << 3); // iterators 2 and 3
  2816. }
  2817. else if ( V_stristr( pName, "lightmappedreflective_ps" ) )
  2818. {
  2819. return (0x01 << 6) | (0x01 << 7); // iterators 6 and 7
  2820. }
  2821. else if ( V_stristr( pName, "water_ps" ) )
  2822. {
  2823. return 0xE0;
  2824. }
  2825. else if ( V_stristr( pName, "shadow_ps" ) )
  2826. {
  2827. return 0xE;
  2828. }
  2829. else if ( V_stristr( pName, "ShatteredGlass_ps" ) )
  2830. {
  2831. return 0xC;
  2832. }
  2833. else if ( V_stristr( pName, "WorldVertexAlpha_ps" ) || V_stristr( pName, "WorldVertexTransition_ps" ) )
  2834. {
  2835. // These pixel shaders want centroid but shouldn't be used
  2836. Assert(0);
  2837. return 0;
  2838. }
  2839. else if ( V_stristr( pName, "flashlight_ps" ) )
  2840. {
  2841. return 0xC;
  2842. }
  2843. }
  2844. else // vertex shader
  2845. {
  2846. // Vertex shaders also
  2847. if ( V_stristr( pName, "lightmappedgeneric_vs" ) )
  2848. {
  2849. return (0x01 << 2) | (0x01 << 3); // iterators 2 and 3
  2850. }
  2851. else if ( V_stristr( pName, "lightmappedreflective_vs" ) )
  2852. {
  2853. return (0x01 << 6) | (0x01 << 7); // iterators 6 and 7
  2854. }
  2855. else if ( V_stristr( pName, "water_vs" ) )
  2856. {
  2857. return 0xE0;
  2858. }
  2859. else if ( V_stristr( pName, "shadow_vs" ) )
  2860. {
  2861. return 0xE;
  2862. }
  2863. else if ( V_stristr( pName, "ShatteredGlass_vs" ) )
  2864. {
  2865. return 0xC;
  2866. }
  2867. else if ( V_stristr( pName, "flashlight_vs" ) )
  2868. {
  2869. return 0xC;
  2870. }
  2871. }
  2872. // This shader doesn't have any centroid iterators
  2873. return 0;
  2874. }
  2875. // This totally sucks, but this information can't be gleaned any
  2876. // other way when translating from D3D to GL at this level
  2877. static int ShadowDepthSamplerMaskFromName( const char *pName )
  2878. {
  2879. if ( !pName )
  2880. return 0;
  2881. if ( V_stristr( pName, "water_ps" ) )
  2882. {
  2883. return (1<<7);
  2884. }
  2885. else if ( V_stristr( pName, "infected_ps" ) )
  2886. {
  2887. return (1<<1);
  2888. }
  2889. else if ( V_stristr( pName, "phong_ps" ) )
  2890. {
  2891. return (1<<4) | (1<<15);
  2892. }
  2893. else if ( V_stristr( pName, "vertexlit_and_unlit_generic_bump_ps" ) )
  2894. {
  2895. return (1<<8) | (1<<15);
  2896. }
  2897. else if ( V_stristr( pName, "vertexlit_and_unlit_generic_ps" ) )
  2898. {
  2899. return (1<<8) | (1<<15);
  2900. }
  2901. else if ( V_stristr( pName, "eye_refract_ps" ) )
  2902. {
  2903. return (1<<6);
  2904. }
  2905. else if ( V_stristr( pName, "eyes_flashlight_ps" ) )
  2906. {
  2907. return (1<<4);
  2908. }
  2909. else if ( V_stristr( pName, "worldtwotextureblend_ps" ) )
  2910. {
  2911. return (1<<7);
  2912. }
  2913. else if ( V_stristr( pName, "teeth_flashlight_ps" ) )
  2914. {
  2915. return (1<<2);
  2916. }
  2917. else if ( V_stristr( pName, "flashlight_ps" ) ) // substring of above, make sure this comes last!!
  2918. {
  2919. return (1<<7);
  2920. }
  2921. else if ( V_stristr( pName, "lightmappedgeneric_ps" ) )
  2922. {
  2923. return (1<<15);
  2924. }
  2925. else if ( V_stristr( pName, "character_ps" ) )
  2926. {
  2927. return (1 << 8);
  2928. }
  2929. // This shader doesn't have a shadow depth map sampler
  2930. return 0;
  2931. }
  2932. #ifdef OSX
  2933. #pragma mark ----- Pixel Shaders - (IDirect3DDevice9)
  2934. #endif
  2935. HRESULT IDirect3DDevice9::CreatePixelShader(CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader, const char *pShaderName, char *pDebugLabel, const uint32 *pCentroidMask )
  2936. {
  2937. GL_BATCH_PERF_CALL_TIMER;
  2938. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  2939. HRESULT result = D3DERR_INVALIDCALL;
  2940. *ppShader = NULL;
  2941. int nShadowDepthSamplerMask = ShadowDepthSamplerMaskFromName( pShaderName );
  2942. uint nCentroidMask = CentroidMaskFromName( true, pShaderName );
  2943. if ( pCentroidMask )
  2944. {
  2945. if ( *pCentroidMask != nCentroidMask )
  2946. {
  2947. char buf[256];
  2948. V_snprintf( buf, sizeof( buf ), "IDirect3DDevice9::CreatePixelShader: shaderapi's centroid mask (0x%08X) differs from mask derived from shader name (0x%08X) for shader %s\n", *pCentroidMask, nCentroidMask, pDebugLabel );
  2949. Plat_DebugString( buf );
  2950. }
  2951. // It would be great if we could use these centroid masks passed in from shaderapi - but unfortunately they're only available for pixel shaders, and we also need to compute matching masks for vertex shaders!
  2952. //nCentroidMask = *pCentroidMask;
  2953. }
  2954. {
  2955. int numTranslations = 1;
  2956. bool bVertexShader = false;
  2957. // we can do one or two translated forms. they go together in a single buffer with some markers to allow GLM to break it up.
  2958. // this also lets us mirror each set of translations to disk with a single file making it easier to view and edit side by side.
  2959. int maxTranslationSize = 50000; // size of any one translation
  2960. CUtlBuffer transbuf( 3000, numTranslations * maxTranslationSize, CUtlBuffer::TEXT_BUFFER );
  2961. CUtlBuffer tempbuf( 3000, maxTranslationSize, CUtlBuffer::TEXT_BUFFER );
  2962. transbuf.PutString( "//GLSLfp\n" ); // this is required so GLM can crack the text apart
  2963. // note the GLSL translator wants its own buffer
  2964. tempbuf.EnsureCapacity( maxTranslationSize );
  2965. uint glslPixelShaderOptions = D3DToGL_OptionUseEnvParams;// | D3DToGL_OptionAllowStaticControlFlow;
  2966. // Fake SRGB mode - needed on R500, probably indefinitely.
  2967. // Do this stuff if caps show m_needsFakeSRGB=true and the sRGBWrite state is true
  2968. // (but not if it's engine_post which is special)
  2969. if (!m_ctx->Caps().m_hasGammaWrites)
  2970. {
  2971. if ( pShaderName )
  2972. {
  2973. if ( !V_stristr( pShaderName, "engine_post" ) )
  2974. {
  2975. glslPixelShaderOptions |= D3DToGL_OptionSRGBWriteSuffix;
  2976. }
  2977. }
  2978. }
  2979. g_D3DToOpenGLTranslatorGLSL.TranslateShader( (uint32 *) pFunction, &tempbuf, &bVertexShader, glslPixelShaderOptions, nShadowDepthSamplerMask, nCentroidMask, pDebugLabel );
  2980. transbuf.PutString( (char*)tempbuf.Base() );
  2981. transbuf.PutString( "\n\n" ); // whitespace
  2982. if ( bVertexShader )
  2983. {
  2984. // don't cross the streams
  2985. Assert(!"Can't accept vertex shader in CreatePixelShader");
  2986. result = D3DERR_INVALIDCALL;
  2987. }
  2988. else
  2989. {
  2990. m_ObjectStats.m_nTotalPixelShaders++;
  2991. IDirect3DPixelShader9 *newprog = new IDirect3DPixelShader9;
  2992. newprog->m_pixHighWater = 0;
  2993. newprog->m_pixSamplerMask = 0;
  2994. newprog->m_pixSamplerTypes = 0;
  2995. newprog->m_pixProgram = m_ctx->NewProgram( kGLMFragmentProgram, (char *)transbuf.Base(), pShaderName ? pShaderName : "?" ) ;
  2996. newprog->m_pixProgram->m_nCentroidMask = nCentroidMask;
  2997. newprog->m_pixProgram->m_nShadowDepthSamplerMask = nShadowDepthSamplerMask;
  2998. newprog->m_pixProgram->m_bTranslatedProgram = true;
  2999. newprog->m_pixProgram->m_maxVertexAttrs = 0;
  3000. newprog->m_device = this;
  3001. //------ find the frag program metadata and extract it..
  3002. {
  3003. // find the highwater mark
  3004. char *highWaterPrefix = "//HIGHWATER-"; // try to arrange this so it can work with pure GLSL if needed
  3005. char *highWaterStr = strstr( (char *)transbuf.Base(), highWaterPrefix );
  3006. if (highWaterStr)
  3007. {
  3008. char *highWaterActualData = highWaterStr + strlen( highWaterPrefix );
  3009. int value = -1;
  3010. sscanf( highWaterActualData, "%d", &value );
  3011. newprog->m_pixHighWater = value;
  3012. newprog->m_pixProgram->m_descs[kGLMGLSL].m_highWater = value;
  3013. }
  3014. else
  3015. {
  3016. Assert(!"couldn't find sampler map in pixel shader");
  3017. }
  3018. }
  3019. {
  3020. // find the sampler map
  3021. char *samplerMaskPrefix = "//SAMPLERMASK-"; // try to arrange this so it can work with pure GLSL if needed
  3022. char *samplerMaskStr = strstr( (char *)transbuf.Base(), samplerMaskPrefix );
  3023. if (samplerMaskStr)
  3024. {
  3025. char *samplerMaskActualData = samplerMaskStr + strlen( samplerMaskPrefix );
  3026. int value = -1;
  3027. sscanf( samplerMaskActualData, "%04x", &value );
  3028. newprog->m_pixSamplerMask = value;
  3029. newprog->m_pixProgram->m_samplerMask = value; // helps GLM maintain a better linked pair cache even when SRGB sampler state changes
  3030. int nMaxReg;
  3031. for ( nMaxReg = 31; nMaxReg >= 0; --nMaxReg )
  3032. if ( value & ( 1 << nMaxReg ) )
  3033. break;
  3034. newprog->m_pixProgram->m_maxSamplers = nMaxReg + 1;
  3035. int nNumUsedSamplers = 0;
  3036. for ( int i = 31; i >= 0; --i)
  3037. if ( value & ( 1 << i ) )
  3038. nNumUsedSamplers++;
  3039. newprog->m_pixProgram->m_nNumUsedSamplers = nNumUsedSamplers;
  3040. }
  3041. else
  3042. {
  3043. Assert(!"couldn't find sampler map in pixel shader");
  3044. }
  3045. }
  3046. {
  3047. // find the sampler map
  3048. char *samplerTypesPrefix = "//SAMPLERTYPES-"; // try to arrange this so it can work with pure GLSL if needed
  3049. char *samplerTypesStr = strstr( (char *)transbuf.Base(), samplerTypesPrefix );
  3050. if (samplerTypesStr)
  3051. {
  3052. char *samplerTypesActualData = samplerTypesStr + strlen( samplerTypesPrefix );
  3053. int value = -1;
  3054. sscanf( samplerTypesActualData, "%08x", &value );
  3055. newprog->m_pixSamplerTypes = value;
  3056. newprog->m_pixProgram->m_samplerTypes = value; // helps GLM maintain a better linked pair cache even when SRGB sampler state changes
  3057. }
  3058. else
  3059. {
  3060. Assert(!"couldn't find sampler types in pixel shader");
  3061. }
  3062. }
  3063. {
  3064. // find the fb outputs used by this shader/combo
  3065. const GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT };
  3066. char *fragDataMaskPrefix = "//FRAGDATAMASK-";
  3067. char *fragDataMaskStr = strstr( (char *)transbuf.Base(), fragDataMaskPrefix );
  3068. if ( fragDataMaskStr )
  3069. {
  3070. char *fragDataActualData = fragDataMaskStr + strlen( fragDataMaskPrefix );
  3071. int value = -1;
  3072. sscanf( fragDataActualData, "%04x", &value );
  3073. newprog->m_pixFragDataMask = value;
  3074. newprog->m_pixProgram->m_fragDataMask = value;
  3075. newprog->m_pixProgram->m_numDrawBuffers = 0;
  3076. for( int i = 0; i < 4; i++ )
  3077. {
  3078. if( newprog->m_pixProgram->m_fragDataMask & ( 1 << i ) )
  3079. {
  3080. newprog->m_pixProgram->m_drawBuffers[ newprog->m_pixProgram->m_numDrawBuffers ] = buffers[ i ];
  3081. newprog->m_pixProgram->m_numDrawBuffers++;
  3082. }
  3083. }
  3084. if( newprog->m_pixProgram->m_numDrawBuffers == 0 )
  3085. {
  3086. Assert(!"couldn't find fragment output in pixel shader");
  3087. newprog->m_pixProgram->m_drawBuffers[ 0 ] = buffers[ 0 ];
  3088. newprog->m_pixProgram->m_numDrawBuffers = 1;
  3089. }
  3090. }
  3091. else
  3092. {
  3093. newprog->m_pixFragDataMask = 0;
  3094. newprog->m_pixProgram->m_fragDataMask = 0;
  3095. }
  3096. }
  3097. *ppShader = newprog;
  3098. result = S_OK;
  3099. }
  3100. }
  3101. return result;
  3102. }
  3103. IDirect3DPixelShader9::~IDirect3DPixelShader9()
  3104. {
  3105. GL_BATCH_PERF_CALL_TIMER;
  3106. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  3107. GLMPRINTF(( ">-A- ~IDirect3DPixelShader9" ));
  3108. if (m_device)
  3109. {
  3110. m_device->ReleasedPixelShader( this );
  3111. if (m_pixProgram)
  3112. {
  3113. m_pixProgram->m_ctx->DelProgram( m_pixProgram );
  3114. m_pixProgram = NULL;
  3115. }
  3116. m_device = NULL;
  3117. }
  3118. GLMPRINTF(( "<-A- ~IDirect3DPixelShader9" ));
  3119. }
  3120. HRESULT IDirect3DDevice9::SetPixelShaderNonInline(IDirect3DPixelShader9* pShader)
  3121. {
  3122. GL_BATCH_PERF_CALL_TIMER;
  3123. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3124. m_ctx->SetFragmentProgram( pShader ? pShader->m_pixProgram : NULL );
  3125. m_pixelShader = pShader;
  3126. return S_OK;
  3127. }
  3128. HRESULT IDirect3DDevice9::SetPixelShaderConstantFNonInline(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount)
  3129. {
  3130. GL_BATCH_PERF_CALL_TIMER;
  3131. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3132. TOGL_NULL_DEVICE_CHECK;
  3133. #if 0
  3134. const uint nRegToWatch = 3;
  3135. if ( ( ( StartRegister + Vector4fCount ) > nRegToWatch ) && ( StartRegister <= nRegToWatch ) )
  3136. {
  3137. char buf[256];
  3138. V_snprintf( buf, sizeof(buf ), "-- %f %f %f %f\n", pConstantData[(nRegToWatch - StartRegister)*4+0], pConstantData[(nRegToWatch - StartRegister)*4+1], pConstantData[(nRegToWatch - StartRegister)*4+2], pConstantData[(nRegToWatch - StartRegister)*4+3] );
  3139. Plat_DebugString( buf );
  3140. }
  3141. #endif
  3142. m_ctx->SetProgramParametersF( kGLMFragmentProgram, StartRegister, (float *)pConstantData, Vector4fCount );
  3143. return S_OK;
  3144. }
  3145. HRESULT IDirect3DDevice9::SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount)
  3146. {
  3147. GL_BATCH_PERF_CALL_TIMER;
  3148. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3149. TOGL_NULL_DEVICE_CHECK;
  3150. m_ctx->SetProgramParametersB( kGLMFragmentProgram, StartRegister, (int *)pConstantData, BoolCount );
  3151. return S_OK;
  3152. }
  3153. HRESULT IDirect3DDevice9::SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount)
  3154. {
  3155. GL_BATCH_PERF_CALL_TIMER;
  3156. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3157. TOGL_NULL_DEVICE_CHECK;
  3158. GLMPRINTF(("-X- Ignoring IDirect3DDevice9::SetPixelShaderConstantI call, count was %d", Vector4iCount ));
  3159. // m_ctx->SetProgramParametersI( kGLMFragmentProgram, StartRegister, pConstantData, Vector4iCount );
  3160. return S_OK;
  3161. }
  3162. #ifdef OSX
  3163. #pragma mark ----- Vertex Shaders - (IDirect3DDevice9)
  3164. #endif
  3165. HRESULT IDirect3DDevice9::CreateVertexShader(CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader, const char *pShaderName, char *pDebugLabel)
  3166. {
  3167. GL_BATCH_PERF_CALL_TIMER;
  3168. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3169. HRESULT result = D3DERR_INVALIDCALL;
  3170. *ppShader = NULL;
  3171. uint32 nCentroidMask = CentroidMaskFromName( false, pShaderName );
  3172. {
  3173. int numTranslations = 1;
  3174. bool bVertexShader = false;
  3175. // we can do one or two translated forms. they go together in a single buffer with some markers to allow GLM to break it up.
  3176. // this also lets us mirror each set of translations to disk with a single file making it easier to view and edit side by side.
  3177. int maxTranslationSize = 500000; // size of any one translation
  3178. CUtlBuffer transbuf( 1000, numTranslations * maxTranslationSize, CUtlBuffer::TEXT_BUFFER );
  3179. CUtlBuffer tempbuf( 1000, maxTranslationSize, CUtlBuffer::TEXT_BUFFER );
  3180. transbuf.PutString( "//GLSLvp\n" ); // this is required so GLM can crack the text apart
  3181. // note the GLSL translator wants its own buffer
  3182. tempbuf.EnsureCapacity( maxTranslationSize );
  3183. uint glslVertexShaderOptions = D3DToGL_OptionUseEnvParams | D3DToGL_OptionDoFixupZ | D3DToGL_OptionDoFixupY;
  3184. if ( m_ctx->Caps().m_hasNativeClipVertexMode )
  3185. {
  3186. // note the matched trickery over in IDirect3DDevice9::FlushStates -
  3187. // if on a chipset that does no have native gl_ClipVertex support, then
  3188. // omit writes to gl_ClipVertex, and instead submit plane equations that have been altered,
  3189. // and clipping will take place in GL space using gl_Position instead of gl_ClipVertex.
  3190. // note that this is very much a hack to mate up with ATI R5xx hardware constraints, and with older
  3191. // drivers even for later ATI parts like r6xx/r7xx. And it doesn't work on NV parts, so you really
  3192. // do have to choose the right way to go.
  3193. glslVertexShaderOptions |= D3DToGL_OptionDoUserClipPlanes;
  3194. }
  3195. if ( !CommandLine()->CheckParm("-disableboneuniformbuffers") )
  3196. {
  3197. // If using GLSL, enabling a uniform buffer specifically for bone registers. (Not currently supported with ARB shaders, which are not optimized at all anyway.)
  3198. glslVertexShaderOptions |= D3DToGL_OptionGenerateBoneUniformBuffer;
  3199. }
  3200. g_D3DToOpenGLTranslatorGLSL.TranslateShader( (uint32 *) pFunction, &tempbuf, &bVertexShader, glslVertexShaderOptions, -1, nCentroidMask, pDebugLabel );
  3201. transbuf.PutString( (char*)tempbuf.Base() );
  3202. transbuf.PutString( "\n\n" ); // whitespace
  3203. if ( !bVertexShader )
  3204. {
  3205. // don't cross the streams
  3206. Assert(!"Can't accept pixel shader in CreateVertexShader");
  3207. result = D3DERR_INVALIDCALL;
  3208. }
  3209. else
  3210. {
  3211. m_ObjectStats.m_nTotalVertexShaders++;
  3212. IDirect3DVertexShader9 *newprog = new IDirect3DVertexShader9;
  3213. newprog->m_device = this;
  3214. newprog->m_vtxProgram = m_ctx->NewProgram( kGLMVertexProgram, (char *)transbuf.Base(), pShaderName ? pShaderName : "?" ) ;
  3215. newprog->m_vtxProgram->m_nCentroidMask = nCentroidMask;
  3216. newprog->m_vtxProgram->m_bTranslatedProgram = true;
  3217. newprog->m_vtxProgram->m_maxVertexAttrs = 0;
  3218. newprog->m_maxVertexAttrs = 0;
  3219. // find the highwater mark..
  3220. char *highWaterPrefix = "//HIGHWATER-"; // try to arrange this so it can work with pure GLSL if needed
  3221. char *highWaterStr = strstr( (char *)transbuf.Base(), highWaterPrefix );
  3222. if (highWaterStr)
  3223. {
  3224. char *highWaterActualData = highWaterStr + strlen( highWaterPrefix );
  3225. int value = -1;
  3226. sscanf( highWaterActualData, "%d", &value );
  3227. newprog->m_vtxHighWater = value;
  3228. newprog->m_vtxProgram->m_descs[kGLMGLSL].m_highWater = value;
  3229. }
  3230. else
  3231. {
  3232. Assert(!"couldn't find highwater mark in vertex shader");
  3233. }
  3234. char *highWaterBonePrefix = "//HIGHWATERBONE-"; // try to arrange this so it can work with pure GLSL if needed
  3235. char *highWaterBoneStr = strstr( (char *)transbuf.Base(), highWaterBonePrefix );
  3236. if (highWaterBoneStr)
  3237. {
  3238. char *highWaterActualData = highWaterBoneStr + strlen( highWaterBonePrefix );
  3239. int value = -1;
  3240. sscanf( highWaterActualData, "%d", &value );
  3241. newprog->m_vtxHighWaterBone = value;
  3242. newprog->m_vtxProgram->m_descs[kGLMGLSL].m_VSHighWaterBone = value;
  3243. }
  3244. else
  3245. {
  3246. newprog->m_vtxHighWaterBone = 0;
  3247. newprog->m_vtxProgram->m_descs[kGLMGLSL].m_VSHighWaterBone = 0;
  3248. }
  3249. // find the attrib map..
  3250. char *attribMapPrefix = "//ATTRIBMAP-"; // try to arrange this so it can work with pure GLSL if needed
  3251. char *attribMapStr = strstr( (char *)transbuf.Base(), attribMapPrefix );
  3252. if (attribMapStr)
  3253. {
  3254. char *attribMapActualData = attribMapStr + strlen( attribMapPrefix );
  3255. uint nMaxVertexAttribs = 0;
  3256. for( int i=0; i<16; i++)
  3257. {
  3258. int value = -1;
  3259. char *dataItem = attribMapActualData + (i*3);
  3260. sscanf( dataItem, "%02x", &value );
  3261. if (value >=0)
  3262. {
  3263. // make sure it's not a terminator
  3264. if (value == 0xBB)
  3265. {
  3266. DXABSTRACT_BREAK_ON_ERROR();
  3267. }
  3268. }
  3269. else
  3270. {
  3271. // probably an 'xx'... check
  3272. if ( (dataItem[0] != 'x') || (dataItem[1] != 'x') )
  3273. {
  3274. DXABSTRACT_BREAK_ON_ERROR(); // bad news
  3275. }
  3276. else
  3277. {
  3278. value = 0xBB; // not likely to see one of these... "fog with usage index 11"
  3279. }
  3280. }
  3281. if ( value != 0xBB )
  3282. nMaxVertexAttribs = i;
  3283. newprog->m_vtxAttribMap[i] = value;
  3284. }
  3285. newprog->m_vtxProgram->m_maxVertexAttrs = nMaxVertexAttribs + 1;
  3286. newprog->m_maxVertexAttrs = nMaxVertexAttribs + 1;
  3287. }
  3288. else
  3289. {
  3290. DXABSTRACT_BREAK_ON_ERROR(); // that's bad...
  3291. }
  3292. *ppShader = newprog;
  3293. result = S_OK;
  3294. }
  3295. }
  3296. return result;
  3297. }
  3298. IDirect3DVertexShader9::~IDirect3DVertexShader9()
  3299. {
  3300. GL_BATCH_PERF_CALL_TIMER;
  3301. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  3302. GLMPRINTF(( ">-A- ~IDirect3DVertexShader9" ));
  3303. if (m_device)
  3304. {
  3305. m_device->ReleasedVertexShader( this );
  3306. if (m_vtxProgram)
  3307. {
  3308. m_vtxProgram->m_ctx->DelProgram( m_vtxProgram );
  3309. m_vtxProgram = NULL;
  3310. }
  3311. m_device = NULL;
  3312. }
  3313. else
  3314. {
  3315. }
  3316. GLMPRINTF(( "<-A- ~IDirect3DVertexShader9" ));
  3317. }
  3318. HRESULT IDirect3DDevice9::SetVertexShaderNonInline(IDirect3DVertexShader9* pShader)
  3319. {
  3320. GL_BATCH_PERF_CALL_TIMER;
  3321. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3322. m_ctx->SetVertexProgram( pShader ? pShader->m_vtxProgram : NULL );
  3323. m_vertexShader = pShader;
  3324. return S_OK;
  3325. }
  3326. HRESULT IDirect3DDevice9::SetVertexShaderConstantFNonInline(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) // groups of 4 floats!
  3327. {
  3328. GL_BATCH_PERF_CALL_TIMER;
  3329. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3330. TOGL_NULL_DEVICE_CHECK;
  3331. m_ctx->SetProgramParametersF( kGLMVertexProgram, StartRegister, (float *)pConstantData, Vector4fCount );
  3332. return S_OK;
  3333. }
  3334. HRESULT IDirect3DDevice9::SetVertexShaderConstantBNonInline(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) // individual bool count!
  3335. {
  3336. GL_BATCH_PERF_CALL_TIMER;
  3337. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3338. TOGL_NULL_DEVICE_CHECK;
  3339. m_ctx->SetProgramParametersB( kGLMVertexProgram, StartRegister, (int *)pConstantData, BoolCount );
  3340. return S_OK;
  3341. }
  3342. HRESULT IDirect3DDevice9::SetVertexShaderConstantINonInline(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) // groups of 4 ints!
  3343. {
  3344. GL_BATCH_PERF_CALL_TIMER;
  3345. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3346. TOGL_NULL_DEVICE_CHECK;
  3347. m_ctx->SetProgramParametersI( kGLMVertexProgram, StartRegister, (int *)pConstantData, Vector4iCount );
  3348. return S_OK;
  3349. }
  3350. #ifdef OSX
  3351. #pragma mark ----- Shader Pairs - (IDirect3DDevice9)
  3352. #endif
  3353. // callers need to ifdef POSIX this, because this method does not exist on real DX9
  3354. HRESULT IDirect3DDevice9::LinkShaderPair( IDirect3DVertexShader9* vs, IDirect3DPixelShader9* ps )
  3355. {
  3356. GL_BATCH_PERF_CALL_TIMER;
  3357. // these are really GLSL "shaders" not "programs" but the old reference to "program" persists due to the assembler heritage
  3358. if (vs->m_vtxProgram && ps->m_pixProgram)
  3359. {
  3360. m_ctx->LinkShaderPair( vs->m_vtxProgram, ps->m_pixProgram );
  3361. }
  3362. return S_OK;
  3363. }
  3364. HRESULT IDirect3DDevice9::ValidateShaderPair( IDirect3DVertexShader9* vs, IDirect3DPixelShader9* ps )
  3365. {
  3366. GL_BATCH_PERF_CALL_TIMER;
  3367. // these are really GLSL "shaders" not "programs" but the old reference to "program" persists due to the assembler heritage
  3368. if (vs->m_vtxProgram && ps->m_pixProgram)
  3369. {
  3370. m_ctx->ValidateShaderPair( vs->m_vtxProgram, ps->m_pixProgram );
  3371. }
  3372. return S_OK;
  3373. }
  3374. // callers need to ifdef POSIX this, because this method does not exist on real DX9
  3375. //
  3376. HRESULT IDirect3DDevice9::QueryShaderPair( int index, GLMShaderPairInfo *infoOut )
  3377. {
  3378. GL_BATCH_PERF_CALL_TIMER;
  3379. // these are really GLSL "shaders" not "programs" ...
  3380. m_ctx->QueryShaderPair( index, infoOut );
  3381. return S_OK;
  3382. }
  3383. #ifdef OSX
  3384. #pragma mark ----- Vertex Buffers and Vertex Declarations - (IDirect3DDevice9)
  3385. #endif
  3386. HRESULT IDirect3DDevice9::CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl)
  3387. {
  3388. GL_BATCH_PERF_CALL_TIMER;
  3389. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3390. *ppDecl = NULL;
  3391. // the goal here is to arrive at something which lets us quickly generate GLMVertexSetups.
  3392. // the information we don't have, that must be inferred from the decls, is:
  3393. // -> how many unique streams (buffers) are used - pure curiosity
  3394. // -> what the stride and offset is for each decl. Size you can figure out on the spot, stride requires surveying all the components in each stream first.
  3395. // so init an array of per-stream offsets to 0.
  3396. // each one is a cursor that gets bumped by decls.
  3397. uint streamOffsets[ D3D_MAX_STREAMS ];
  3398. uint streamCount = 0;
  3399. uint attribMap[16];
  3400. uint attribMapIndex = 0;
  3401. memset( attribMap, 0xFF, sizeof( attribMap ) );
  3402. memset( streamOffsets, 0, sizeof( streamOffsets ) );
  3403. m_ObjectStats.m_nTotalVertexDecls++;
  3404. IDirect3DVertexDeclaration9 *decl9 = new IDirect3DVertexDeclaration9;
  3405. decl9->m_device = this;
  3406. decl9->m_elemCount = 0;
  3407. for (const D3DVERTEXELEMENT9 *src = pVertexElements; (src->Stream != 0xFF); src++)
  3408. {
  3409. // element
  3410. D3DVERTEXELEMENT9_GL *elem = &decl9->m_elements[ decl9->m_elemCount++ ];
  3411. // copy the D3D decl wholesale.
  3412. elem->m_dxdecl = *src;
  3413. // latch current offset in this stream.
  3414. elem->m_gldecl.m_offset = streamOffsets[ elem->m_dxdecl.Stream ];
  3415. // figure out size of this attr and move the cursor
  3416. // if cursor was on zero, bump the active stream count
  3417. if (!streamOffsets[ elem->m_dxdecl.Stream ])
  3418. streamCount++;
  3419. int bytes = 0;
  3420. switch( elem->m_dxdecl.Type )
  3421. {
  3422. case D3DDECLTYPE_FLOAT1: elem->m_gldecl.m_nCompCount = 1; elem->m_gldecl.m_datatype = GL_FLOAT; elem->m_gldecl.m_normalized=0; bytes = 4; break;
  3423. case D3DDECLTYPE_FLOAT2: elem->m_gldecl.m_nCompCount = 2; elem->m_gldecl.m_datatype = GL_FLOAT; elem->m_gldecl.m_normalized=0; bytes = 8; break;
  3424. //case D3DVSDT_FLOAT3:
  3425. case D3DDECLTYPE_FLOAT3: elem->m_gldecl.m_nCompCount = 3; elem->m_gldecl.m_datatype = GL_FLOAT; elem->m_gldecl.m_normalized=0; bytes = 12; break;
  3426. //case D3DVSDT_FLOAT4:
  3427. case D3DDECLTYPE_FLOAT4: elem->m_gldecl.m_nCompCount = 4; elem->m_gldecl.m_datatype = GL_FLOAT; elem->m_gldecl.m_normalized=0; bytes = 16; break;
  3428. // case D3DVSDT_UBYTE4:
  3429. case D3DDECLTYPE_D3DCOLOR:
  3430. case D3DDECLTYPE_UBYTE4:
  3431. case D3DDECLTYPE_UBYTE4N:
  3432. // Force this path since we're on 10.6.2 and can't rely on EXT_vertex_array_bgra
  3433. if ( 1 )
  3434. {
  3435. // pass 4 UB's but we know this is out of order compared to D3DCOLOR data
  3436. elem->m_gldecl.m_nCompCount = 4; elem->m_gldecl.m_datatype = GL_UNSIGNED_BYTE;
  3437. }
  3438. else
  3439. {
  3440. // pass a GL BGRA color courtesy of http://www.opengl.org/registry/specs/ARB/vertex_array_bgra.txt
  3441. elem->m_gldecl.m_nCompCount = GL_BGRA; elem->m_gldecl.m_datatype = GL_UNSIGNED_BYTE;
  3442. }
  3443. elem->m_gldecl.m_normalized = ( (elem->m_dxdecl.Type == D3DDECLTYPE_D3DCOLOR) ||
  3444. (elem->m_dxdecl.Type == D3DDECLTYPE_UBYTE4N) );
  3445. bytes = 4;
  3446. break;
  3447. case D3DDECLTYPE_SHORT2:
  3448. // pass 2 US's but we know this is out of order compared to D3DCOLOR data
  3449. elem->m_gldecl.m_nCompCount = 2; elem->m_gldecl.m_datatype = GL_SHORT;
  3450. elem->m_gldecl.m_normalized = 0;
  3451. bytes = 4;
  3452. break;
  3453. default: DXABSTRACT_BREAK_ON_ERROR(); return D3DERR_INVALIDCALL; break;
  3454. /*
  3455. typedef enum _D3DDECLTYPE
  3456. {
  3457. D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.)
  3458. D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.)
  3459. D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.)
  3460. D3DDECLTYPE_FLOAT4 = 3, // 4D float
  3461. D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range
  3462. // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
  3463. D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte
  3464. D3DDECLTYPE_SHORT2 = 6, // 2D signed short expanded to (value, value, 0., 1.)
  3465. D3DDECLTYPE_SHORT4 = 7, // 4D signed short
  3466. // The following types are valid only with vertex shaders >= 2.0
  3467. D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0
  3468. D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
  3469. D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
  3470. D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
  3471. D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
  3472. D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
  3473. D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
  3474. D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1)
  3475. D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values
  3476. D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused.
  3477. } D3DDECLTYPE;
  3478. */
  3479. }
  3480. // write the offset and move the cursor
  3481. elem->m_gldecl.m_offset = streamOffsets[elem->m_dxdecl.Stream];
  3482. streamOffsets[ elem->m_dxdecl.Stream ] += bytes;
  3483. // cannot write m_stride yet, so zero it
  3484. elem->m_gldecl.m_stride = 0;
  3485. elem->m_gldecl.m_pBuffer = NULL; // must be filled in at draw time..
  3486. // elem count was already bumped.
  3487. // update attrib map
  3488. attribMap[ attribMapIndex++ ] = (elem->m_dxdecl.Usage << 4) | (elem->m_dxdecl.UsageIndex);
  3489. }
  3490. // the loop is done, we now know how many active streams there are, how many atribs are active in the declaration,
  3491. // and how big each one is in terms of stride.
  3492. // all that is left is to go back and write the strides - the stride comes from the stream offset cursors accumulated earlier.
  3493. for( uint j=0; j< decl9->m_elemCount; j++)
  3494. {
  3495. D3DVERTEXELEMENT9_GL *elem = &decl9->m_elements[ j ];
  3496. elem->m_gldecl.m_stride = streamOffsets[ elem->m_dxdecl.Stream ];
  3497. }
  3498. memset( decl9->m_VertexAttribDescToStreamIndex, 0xFF, sizeof( decl9->m_VertexAttribDescToStreamIndex ) );
  3499. D3DVERTEXELEMENT9_GL *pDeclElem = decl9->m_elements;
  3500. for( uint j = 0; j < decl9->m_elemCount; j++, pDeclElem++)
  3501. {
  3502. uint nPackedVertexAttribDesc = ( pDeclElem->m_dxdecl.Usage << 4 ) | pDeclElem->m_dxdecl.UsageIndex;
  3503. if ( nPackedVertexAttribDesc == 0xBB )
  3504. {
  3505. // 0xBB is a reserved packed vertex attrib value - shouldn't encounter in practice
  3506. DXABSTRACT_BREAK_ON_ERROR();
  3507. }
  3508. decl9->m_VertexAttribDescToStreamIndex[ nPackedVertexAttribDesc ] = j;
  3509. }
  3510. *ppDecl = decl9;
  3511. return S_OK;
  3512. }
  3513. IDirect3DVertexDeclaration9::~IDirect3DVertexDeclaration9()
  3514. {
  3515. GL_BATCH_PERF_CALL_TIMER;
  3516. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  3517. GLMPRINTF(("-A- ~IDirect3DVertexDeclaration9 signpost"));
  3518. m_device->ReleasedVertexDeclaration( this );
  3519. }
  3520. HRESULT IDirect3DDevice9::SetVertexDeclarationNonInline(IDirect3DVertexDeclaration9* pDecl)
  3521. {
  3522. GL_BATCH_PERF_CALL_TIMER;
  3523. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3524. m_pVertDecl = pDecl;
  3525. return S_OK;
  3526. }
  3527. HRESULT IDirect3DDevice9::SetFVF(DWORD FVF)
  3528. {
  3529. GL_BATCH_PERF_CALL_TIMER;
  3530. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3531. DXABSTRACT_BREAK_ON_ERROR();
  3532. return S_OK;
  3533. }
  3534. HRESULT IDirect3DDevice9::GetFVF(DWORD* pFVF)
  3535. {
  3536. GL_BATCH_PERF_CALL_TIMER;
  3537. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3538. DXABSTRACT_BREAK_ON_ERROR();
  3539. return S_OK;
  3540. }
  3541. #ifdef OSX
  3542. #pragma mark ----- Vertex Buffers and Streams - (IDirect3DDevice9)
  3543. #pragma mark ----- Create function moved to be adjacent to other buffer methods
  3544. #endif
  3545. HRESULT IDirect3DDevice9::SetStreamSourceNonInline(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
  3546. {
  3547. GL_BATCH_PERF_CALL_TIMER;
  3548. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3549. Assert( StreamNumber < D3D_MAX_STREAMS );
  3550. Assert( ( Stride & 3 ) == 0 ); // we support non-DWORD aligned strides, but on some drivers (like AMD's) perf goes off a cliff
  3551. // perfectly legal to see a vertex buffer of NULL get passed in here.
  3552. // so we need an array to track these.
  3553. // OK, we are being given the stride, we don't need to calc it..
  3554. GLMPRINTF(("-X- IDirect3DDevice9::SetStreamSource setting stream #%d to D3D buf %p (GL name %d); offset %d, stride %d", StreamNumber, pStreamData, (pStreamData) ? pStreamData->m_vtxBuffer->m_nHandle: -1, OffsetInBytes, Stride));
  3555. if ( !pStreamData )
  3556. {
  3557. OffsetInBytes = 0;
  3558. Stride = 0;
  3559. m_vtx_buffers[ StreamNumber ] = m_pDummy_vtx_buffer;
  3560. }
  3561. else
  3562. {
  3563. // We do not support strides of 0
  3564. Assert( Stride > 0 );
  3565. m_vtx_buffers[ StreamNumber ] = pStreamData->m_vtxBuffer;
  3566. }
  3567. m_streams[ StreamNumber ].m_vtxBuffer = pStreamData;
  3568. m_streams[ StreamNumber ].m_offset = OffsetInBytes;
  3569. m_streams[ StreamNumber ].m_stride = Stride;
  3570. return S_OK;
  3571. }
  3572. #ifdef OSX
  3573. #pragma mark ----- Index Buffers - (IDirect3DDevice9)
  3574. #pragma mark ----- Creatue function relocated to be adjacent to the rest of the index buffer methods
  3575. #endif
  3576. HRESULT IDirect3DDevice9::SetIndicesNonInline(IDirect3DIndexBuffer9* pIndexData)
  3577. {
  3578. GL_BATCH_PERF_CALL_TIMER;
  3579. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3580. // just latch it.
  3581. m_indices.m_idxBuffer = pIndexData;
  3582. return S_OK;
  3583. }
  3584. #ifdef OSX
  3585. #pragma mark ----- Release Handlers - (IDirect3DDevice9)
  3586. #endif
  3587. void IDirect3DDevice9::ReleasedVertexDeclaration( IDirect3DVertexDeclaration9 *pDecl )
  3588. {
  3589. m_ctx->ClearCurAttribs();
  3590. Assert( m_ObjectStats.m_nTotalVertexDecls >= 1 );
  3591. m_ObjectStats.m_nTotalVertexDecls--;
  3592. }
  3593. void IDirect3DDevice9::ReleasedTexture( IDirect3DBaseTexture9 *baseTex )
  3594. {
  3595. GL_BATCH_PERF_CALL_TIMER;
  3596. TOGL_NULL_DEVICE_CHECK_RET_VOID;
  3597. // see if this texture is referenced in any of the texture units and scrub it if so.
  3598. for( int i=0; i< GLM_SAMPLER_COUNT; i++)
  3599. {
  3600. if (m_textures[i] == baseTex)
  3601. {
  3602. m_textures[i] = NULL;
  3603. m_ctx->SetSamplerTex( i, NULL ); // texture sets go straight through to GLM, no dirty bit
  3604. }
  3605. }
  3606. }
  3607. void IDirect3DDevice9::ReleasedCGLMTex( CGLMTex *pTex)
  3608. {
  3609. GL_BATCH_PERF_CALL_TIMER;
  3610. TOGL_NULL_DEVICE_CHECK_RET_VOID;
  3611. ScrubFBOMap( pTex );
  3612. if ( pTex->m_layout )
  3613. {
  3614. if ( pTex->m_layout->m_key.m_texFlags & kGLMTexRenderable )
  3615. {
  3616. Assert( m_ObjectStats.m_nTotalRenderTargets >= 1 );
  3617. m_ObjectStats.m_nTotalRenderTargets--;
  3618. }
  3619. }
  3620. }
  3621. void IDirect3DDevice9::ReleasedSurface( IDirect3DSurface9 *pSurface )
  3622. {
  3623. for( int i = 0; i < 4; i++ )
  3624. {
  3625. if ( m_pRenderTargets[i] == pSurface )
  3626. {
  3627. // this was a surprise release... scrub it
  3628. m_pRenderTargets[i] = NULL;
  3629. m_bFBODirty = true;
  3630. GLMPRINTF(( "-A- Scrubbed pSurface %08x from m_pRenderTargets[%d]", pSurface, i ));
  3631. }
  3632. }
  3633. if ( m_pDepthStencil == pSurface )
  3634. {
  3635. m_pDepthStencil = NULL;
  3636. m_bFBODirty = true;
  3637. GLMPRINTF(( "-A- Scrubbed pSurface %08x from m_pDepthStencil", pSurface ));
  3638. }
  3639. if ( m_pDefaultColorSurface == pSurface )
  3640. {
  3641. m_pDefaultColorSurface = NULL;
  3642. GLMPRINTF(( "-A- Scrubbed pSurface %08x from m_pDefaultColorSurface", pSurface ));
  3643. }
  3644. if ( m_pDefaultDepthStencilSurface == pSurface )
  3645. {
  3646. m_pDefaultDepthStencilSurface = NULL;
  3647. GLMPRINTF(( "-A- Scrubbed pSurface %08x from m_pDefaultDepthStencilSurface", pSurface ));
  3648. }
  3649. Assert( m_ObjectStats.m_nTotalSurfaces >= 1 );
  3650. m_ObjectStats.m_nTotalSurfaces--;
  3651. }
  3652. void IDirect3DDevice9::ReleasedPixelShader( IDirect3DPixelShader9 *pixelShader )
  3653. {
  3654. if ( m_pixelShader == pixelShader )
  3655. {
  3656. m_pixelShader = NULL;
  3657. GLMPRINTF(( "-A- Scrubbed pixel shader %08x from m_pixelShader", pixelShader ));
  3658. }
  3659. m_ctx->ReleasedShader();
  3660. Assert( m_ObjectStats.m_nTotalPixelShaders >= 1 );
  3661. m_ObjectStats.m_nTotalPixelShaders--;
  3662. }
  3663. void IDirect3DDevice9::ReleasedVertexShader( IDirect3DVertexShader9 *vertexShader )
  3664. {
  3665. if ( m_vertexShader == vertexShader )
  3666. {
  3667. m_vertexShader = NULL;
  3668. GLMPRINTF(( "-A- Scrubbed vertex shader %08x from m_vertexShader", vertexShader ));
  3669. }
  3670. m_ctx->ClearCurAttribs();
  3671. m_ctx->ReleasedShader();
  3672. Assert( m_ObjectStats.m_nTotalVertexShaders >= 1 );
  3673. m_ObjectStats.m_nTotalVertexShaders--;
  3674. }
  3675. void IDirect3DDevice9::ReleasedVertexBuffer( IDirect3DVertexBuffer9 *vertexBuffer )
  3676. {
  3677. for (int i=0; i< D3D_MAX_STREAMS; i++)
  3678. {
  3679. if ( m_streams[i].m_vtxBuffer == vertexBuffer )
  3680. {
  3681. m_streams[i].m_vtxBuffer = NULL;
  3682. m_vtx_buffers[i] = m_pDummy_vtx_buffer;
  3683. GLMPRINTF(( "-A- Scrubbed vertex buffer %08x from m_streams[%d]", vertexBuffer, i ));
  3684. }
  3685. }
  3686. m_ctx->ClearCurAttribs();
  3687. Assert( m_ObjectStats.m_nTotalVertexBuffers >= 1 );
  3688. m_ObjectStats.m_nTotalVertexBuffers--;
  3689. }
  3690. void IDirect3DDevice9::ReleasedIndexBuffer( IDirect3DIndexBuffer9 *indexBuffer )
  3691. {
  3692. if ( m_indices.m_idxBuffer == indexBuffer )
  3693. {
  3694. m_indices.m_idxBuffer = NULL;
  3695. GLMPRINTF(( "-A- Scrubbed index buffer %08x from m_indices", indexBuffer ));
  3696. }
  3697. Assert( m_ObjectStats.m_nTotalIndexBuffers >= 1 );
  3698. m_ObjectStats.m_nTotalIndexBuffers--;
  3699. }
  3700. void IDirect3DDevice9::ReleasedQuery( IDirect3DQuery9 *query )
  3701. {
  3702. Assert( m_ObjectStats.m_nTotalQueries >= 1 );
  3703. m_ObjectStats.m_nTotalQueries--;
  3704. }
  3705. #ifdef OSX
  3706. #pragma mark ----- Queries - (IDirect3DDevice9)
  3707. #endif
  3708. // note that detection of whether queries are supported is done by trying to create one.
  3709. // so for GL, be observant here of whether we have that capability or not.
  3710. // pretty much have this everywhere but i950.
  3711. HRESULT IDirect3DDevice9::CreateQuery(D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery)
  3712. {
  3713. GL_BATCH_PERF_CALL_TIMER;
  3714. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  3715. if (m_ctx->Caps().m_hasOcclusionQuery)
  3716. {
  3717. m_ObjectStats.m_nTotalQueries++;
  3718. IDirect3DQuery9 *newquery = new IDirect3DQuery9;
  3719. newquery->m_device = this;
  3720. newquery->m_type = Type;
  3721. newquery->m_ctx = m_ctx;
  3722. newquery->m_nIssueStartThreadID = 0;
  3723. newquery->m_nIssueEndThreadID = 0;
  3724. newquery->m_nIssueStartDrawCallIndex = 0;
  3725. newquery->m_nIssueEndDrawCallIndex = 0;
  3726. GLMQueryParams params;
  3727. memset( &params, 0, sizeof(params) );
  3728. //bool known = false;
  3729. switch(newquery->m_type)
  3730. {
  3731. case D3DQUERYTYPE_OCCLUSION: /* D3DISSUE_BEGIN, D3DISSUE_END */
  3732. // create an occlusion query
  3733. params.m_type = EOcclusion;
  3734. break;
  3735. case D3DQUERYTYPE_EVENT: /* D3DISSUE_END */
  3736. params.m_type = EFence;
  3737. break;
  3738. case D3DQUERYTYPE_RESOURCEMANAGER: /* D3DISSUE_END */
  3739. case D3DQUERYTYPE_TIMESTAMP: /* D3DISSUE_END */
  3740. case D3DQUERYTYPE_TIMESTAMPFREQ: /* D3DISSUE_END */
  3741. case D3DQUERYTYPE_INTERFACETIMINGS: /* D3DISSUE_BEGIN, D3DISSUE_END */
  3742. case D3DQUERYTYPE_PIXELTIMINGS: /* D3DISSUE_BEGIN, D3DISSUE_END */
  3743. case D3DQUERYTYPE_CACHEUTILIZATION: /* D3DISSUE_BEGIN, D3DISSUE_END */
  3744. Assert( !"Un-implemented query type" );
  3745. break;
  3746. default:
  3747. Assert( !"Unknown query type" );
  3748. break;
  3749. }
  3750. newquery->m_query = m_ctx->NewQuery( &params );
  3751. *ppQuery = newquery;
  3752. return S_OK;
  3753. }
  3754. else
  3755. {
  3756. *ppQuery = NULL;
  3757. return -1; // failed
  3758. }
  3759. }
  3760. IDirect3DQuery9::~IDirect3DQuery9()
  3761. {
  3762. GL_BATCH_PERF_CALL_TIMER;
  3763. GL_PUBLIC_ENTRYPOINT_CHECKS( m_device );
  3764. GLMPRINTF((">-A- ~IDirect3DQuery9"));
  3765. if (m_device)
  3766. {
  3767. m_device->ReleasedQuery( this );
  3768. if (m_query)
  3769. {
  3770. GLMPRINTF((">-A- ~IDirect3DQuery9 freeing m_query"));
  3771. m_query->m_ctx->DelQuery( m_query );
  3772. m_query = NULL;
  3773. GLMPRINTF(("<-A- ~IDirect3DQuery9 freeing m_query done"));
  3774. }
  3775. m_device = NULL;
  3776. }
  3777. GLMPRINTF(("<-A- ~IDirect3DQuery9"));
  3778. }
  3779. #ifdef OSX
  3780. #pragma mark ----- Render States - (IDirect3DDevice9)
  3781. #endif
  3782. #define D3DRS_VALUE_LIMIT 210
  3783. struct D3D_RSINFO
  3784. {
  3785. int m_class;
  3786. D3DRENDERSTATETYPE m_state;
  3787. DWORD m_defval;
  3788. // m_class runs 0-3.
  3789. // 3 = must implement - fully general - "obey"
  3790. // 2 = implement setup to the default value (it has a GL effect but does not change later) "obey once"
  3791. // 1 = "fake implement" setup to the default value no GL effect, debug break if anything but default value comes through - "ignore"
  3792. // 0 = game never ever sets this one, break if someone even tries. "complain"
  3793. };
  3794. D3D_RSINFO g_D3DRS_INFO_unpacked[ D3DRS_VALUE_LIMIT+1 ];
  3795. #ifdef D3D_RSI
  3796. #error macro collision... rename this
  3797. #else
  3798. #define D3D_RSI(nclass,nstate,ndefval) { nclass, nstate, ndefval }
  3799. #endif
  3800. // FP conversions to hex courtesy of http://babbage.cs.qc.cuny.edu/IEEE-754/Decimal.html
  3801. #define CONST_DZERO 0x00000000
  3802. #define CONST_DONE 0x3F800000
  3803. #define CONST_D64 0x42800000
  3804. #define DONT_KNOW_YET 0x31415926
  3805. // see http://www.toymaker.info/Games/html/render_states.html
  3806. D3D_RSINFO g_D3DRS_INFO_packed[] =
  3807. {
  3808. // these do not have to be in any particular order. they get unpacked into the empty array above for direct indexing.
  3809. D3D_RSI( 3, D3DRS_ZENABLE, DONT_KNOW_YET ), // enable Z test (or W buffering)
  3810. D3D_RSI( 3, D3DRS_ZWRITEENABLE, DONT_KNOW_YET ), // enable Z write
  3811. D3D_RSI( 3, D3DRS_ZFUNC, DONT_KNOW_YET ), // select Z func
  3812. D3D_RSI( 3, D3DRS_COLORWRITEENABLE, TRUE ), // see transitiontable.cpp "APPLY_RENDER_STATE_FUNC( D3DRS_COLORWRITEENABLE, ColorWriteEnable )"
  3813. D3D_RSI( 3, D3DRS_CULLMODE, D3DCULL_CCW ), // backface cull control
  3814. D3D_RSI( 3, D3DRS_ALPHABLENDENABLE, DONT_KNOW_YET ), // ->CTransitionTable::ApplySeparateAlphaBlend and ApplyAlphaBlend
  3815. D3D_RSI( 3, D3DRS_BLENDOP, D3DBLENDOP_ADD ),
  3816. D3D_RSI( 3, D3DRS_SRCBLEND, DONT_KNOW_YET ),
  3817. D3D_RSI( 3, D3DRS_DESTBLEND, DONT_KNOW_YET ),
  3818. D3D_RSI( 1, D3DRS_SEPARATEALPHABLENDENABLE, FALSE ), // hit in CTransitionTable::ApplySeparateAlphaBlend
  3819. D3D_RSI( 1, D3DRS_SRCBLENDALPHA, D3DBLEND_ONE ), // going to demote these to class 1 until I figure out if they are implementable
  3820. D3D_RSI( 1, D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO ),
  3821. D3D_RSI( 1, D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD ),
  3822. // what is the deal with alpha test... looks like it is inited to off.
  3823. D3D_RSI( 3, D3DRS_ALPHATESTENABLE, 0 ),
  3824. D3D_RSI( 3, D3DRS_ALPHAREF, 0 ),
  3825. D3D_RSI( 3, D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL ),
  3826. D3D_RSI( 3, D3DRS_STENCILENABLE, FALSE ),
  3827. D3D_RSI( 3, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP ),
  3828. D3D_RSI( 3, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP ),
  3829. D3D_RSI( 3, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP ),
  3830. D3D_RSI( 3, D3DRS_STENCILFUNC, D3DCMP_ALWAYS ),
  3831. D3D_RSI( 3, D3DRS_STENCILREF, 0 ),
  3832. D3D_RSI( 3, D3DRS_STENCILMASK, 0xFFFFFFFF ),
  3833. D3D_RSI( 3, D3DRS_STENCILWRITEMASK, 0xFFFFFFFF ),
  3834. D3D_RSI( 3, D3DRS_TWOSIDEDSTENCILMODE, FALSE ),
  3835. D3D_RSI( 3, D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP ),
  3836. D3D_RSI( 3, D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP ),
  3837. D3D_RSI( 3, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP ),
  3838. D3D_RSI( 3, D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS ),
  3839. D3D_RSI( 3, D3DRS_FOGENABLE, FALSE ), // see CShaderAPIDx8::FogMode and friends - be ready to do the ARB fog linear option madness
  3840. D3D_RSI( 3, D3DRS_FOGCOLOR, 0 ),
  3841. D3D_RSI( 3, D3DRS_FOGTABLEMODE, D3DFOG_NONE ),
  3842. D3D_RSI( 3, D3DRS_FOGSTART, CONST_DZERO ),
  3843. D3D_RSI( 3, D3DRS_FOGEND, CONST_DONE ),
  3844. D3D_RSI( 3, D3DRS_FOGDENSITY, CONST_DZERO ),
  3845. D3D_RSI( 3, D3DRS_RANGEFOGENABLE, FALSE ),
  3846. D3D_RSI( 3, D3DRS_FOGVERTEXMODE, D3DFOG_NONE ), // watch out for CShaderAPIDx8::CommitPerPassFogMode....
  3847. D3D_RSI( 3, D3DRS_MULTISAMPLEANTIALIAS, TRUE ),
  3848. D3D_RSI( 3, D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF ),
  3849. D3D_RSI( 3, D3DRS_SCISSORTESTENABLE, FALSE ), // heed IDirect3DDevice9::SetScissorRect
  3850. D3D_RSI( 3, D3DRS_DEPTHBIAS, CONST_DZERO ),
  3851. D3D_RSI( 3, D3DRS_SLOPESCALEDEPTHBIAS, CONST_DZERO ),
  3852. D3D_RSI( 3, D3DRS_COLORWRITEENABLE1, 0x0000000f ),
  3853. D3D_RSI( 3, D3DRS_COLORWRITEENABLE2, 0x0000000f ),
  3854. D3D_RSI( 3, D3DRS_COLORWRITEENABLE3, 0x0000000f ),
  3855. D3D_RSI( 3, D3DRS_SRGBWRITEENABLE, 0 ), // heeded but ignored..
  3856. D3D_RSI( 2, D3DRS_CLIPPING, TRUE ), // um, yeah, clipping is enabled (?)
  3857. D3D_RSI( 3, D3DRS_CLIPPLANEENABLE, 0 ), // mask 1<<n of active user clip planes.
  3858. D3D_RSI( 0, D3DRS_LIGHTING, 0 ), // strange, someone turns it on then off again. move to class 0 and just ignore it (lie)?
  3859. D3D_RSI( 3, D3DRS_FILLMODE, D3DFILL_SOLID ),
  3860. D3D_RSI( 1, D3DRS_SHADEMODE, D3DSHADE_GOURAUD ),
  3861. D3D_RSI( 1, D3DRS_LASTPIXEL, TRUE ),
  3862. D3D_RSI( 1, D3DRS_DITHERENABLE, 0 ), //set to false by game, no one sets it to true
  3863. D3D_RSI( 1, D3DRS_SPECULARENABLE, FALSE ),
  3864. D3D_RSI( 1, D3DRS_TEXTUREFACTOR, 0xFFFFFFFF ), // watch out for CShaderAPIDx8::Color3f et al.
  3865. D3D_RSI( 1, D3DRS_WRAP0, 0 ),
  3866. D3D_RSI( 1, D3DRS_WRAP1, 0 ),
  3867. D3D_RSI( 1, D3DRS_WRAP2, 0 ),
  3868. D3D_RSI( 1, D3DRS_WRAP3, 0 ),
  3869. D3D_RSI( 1, D3DRS_WRAP4, 0 ),
  3870. D3D_RSI( 1, D3DRS_WRAP5, 0 ),
  3871. D3D_RSI( 1, D3DRS_WRAP6, 0 ),
  3872. D3D_RSI( 1, D3DRS_WRAP7, 0 ),
  3873. D3D_RSI( 1, D3DRS_AMBIENT, 0 ), // FF lighting, no
  3874. D3D_RSI( 1, D3DRS_COLORVERTEX, TRUE ), // FF lighing again
  3875. D3D_RSI( 1, D3DRS_LOCALVIEWER, TRUE ), // FF lighting
  3876. D3D_RSI( 1, D3DRS_NORMALIZENORMALS, FALSE ), // FF mode I think. CShaderAPIDx8::SetVertexBlendState says it might switch this on when skinning is in play
  3877. D3D_RSI( 1, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL ), // hit only in CShaderAPIDx8::ResetRenderState
  3878. D3D_RSI( 1, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2 ),
  3879. D3D_RSI( 1, D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL ),
  3880. D3D_RSI( 1, D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL ),
  3881. D3D_RSI( 1, D3DRS_VERTEXBLEND, D3DVBF_DISABLE ), // also being set by CShaderAPIDx8::SetVertexBlendState, so might be FF
  3882. D3D_RSI( 1, D3DRS_POINTSIZE, CONST_DONE ),
  3883. D3D_RSI( 1, D3DRS_POINTSIZE_MIN, CONST_DONE ),
  3884. D3D_RSI( 1, D3DRS_POINTSPRITEENABLE, FALSE ),
  3885. D3D_RSI( 1, D3DRS_POINTSCALEENABLE, FALSE ),
  3886. D3D_RSI( 1, D3DRS_POINTSCALE_A, CONST_DONE ),
  3887. D3D_RSI( 1, D3DRS_POINTSCALE_B, CONST_DZERO ),
  3888. D3D_RSI( 1, D3DRS_POINTSCALE_C, CONST_DZERO ),
  3889. D3D_RSI( 1, D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE ),
  3890. D3D_RSI( 1, D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE ),
  3891. D3D_RSI( 1, D3DRS_POINTSIZE_MAX, CONST_D64 ),
  3892. D3D_RSI( 1, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE ),
  3893. D3D_RSI( 1, D3DRS_TWEENFACTOR, CONST_DZERO ),
  3894. D3D_RSI( 1, D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC ),
  3895. D3D_RSI( 1, D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR ),
  3896. D3D_RSI( 1, D3DRS_ANTIALIASEDLINEENABLE, FALSE ), // just ignore it
  3897. D3D_RSI( 1, D3DRS_MINTESSELLATIONLEVEL, CONST_DONE ),
  3898. D3D_RSI( 1, D3DRS_MAXTESSELLATIONLEVEL, CONST_DONE ),
  3899. D3D_RSI( 1, D3DRS_ADAPTIVETESS_X, CONST_DZERO ),
  3900. D3D_RSI( 1, D3DRS_ADAPTIVETESS_Y, CONST_DZERO ), // Overridden as Alpha-to-coverage contrl
  3901. D3D_RSI( 1, D3DRS_ADAPTIVETESS_Z, CONST_DONE ),
  3902. D3D_RSI( 1, D3DRS_ADAPTIVETESS_W, CONST_DZERO ),
  3903. D3D_RSI( 1, D3DRS_ENABLEADAPTIVETESSELLATION, FALSE ),
  3904. D3D_RSI( 1, D3DRS_BLENDFACTOR, 0xffffffff ),
  3905. D3D_RSI( 1, D3DRS_WRAP8, 0 ),
  3906. D3D_RSI( 1, D3DRS_WRAP9, 0 ),
  3907. D3D_RSI( 1, D3DRS_WRAP10, 0 ),
  3908. D3D_RSI( 1, D3DRS_WRAP11, 0 ),
  3909. D3D_RSI( 1, D3DRS_WRAP12, 0 ),
  3910. D3D_RSI( 1, D3DRS_WRAP13, 0 ),
  3911. D3D_RSI( 1, D3DRS_WRAP14, 0 ),
  3912. D3D_RSI( 1, D3DRS_WRAP15, 0 ),
  3913. D3D_RSI( -1, (D3DRENDERSTATETYPE)0, 0 ) // terminator
  3914. };
  3915. void UnpackD3DRSITable( void )
  3916. {
  3917. memset (g_D3DRS_INFO_unpacked, 0, sizeof(g_D3DRS_INFO_unpacked) );
  3918. for( D3D_RSINFO *packed = g_D3DRS_INFO_packed; packed->m_class >= 0; packed++ )
  3919. {
  3920. if ( (packed->m_state <0) || (packed->m_state >= D3DRS_VALUE_LIMIT) )
  3921. {
  3922. // bad
  3923. DXABSTRACT_BREAK_ON_ERROR();
  3924. }
  3925. else
  3926. {
  3927. // dispatch it to the unpacked array
  3928. g_D3DRS_INFO_unpacked[ packed->m_state ] = *packed;
  3929. }
  3930. }
  3931. }
  3932. // convenience functions
  3933. #ifdef OSX
  3934. #pragma mark ----- Sampler States - (IDirect3DDevice9)
  3935. #endif
  3936. void IDirect3DDevice9::FlushClipPlaneEquation()
  3937. {
  3938. for( int x=0; x<kGLMUserClipPlanes; x++)
  3939. {
  3940. GLClipPlaneEquation_t temp1; // Antonio's way
  3941. GLClipPlaneEquation_t temp2; // our way
  3942. // if we don't have native clip vertex support. then munge the plane coeffs
  3943. // this should engage on ALL ATI PARTS < 10.6.4
  3944. // and should continue to engage on R5xx forever.
  3945. if ( !m_ctx->Caps().m_hasNativeClipVertexMode )
  3946. {
  3947. // hacked coeffs = { src->x, -src->y, 0.5f * src->z, src->w + (0.5f * src->z) };
  3948. // Antonio's trick - so we can use gl_Position as the clippee, not gl_ClipVertex.
  3949. GLClipPlaneEquation_t *equ = &gl.m_ClipPlaneEquation[x];
  3950. ///////////////// temp1
  3951. temp1.x = equ->x;
  3952. temp1.y = equ->y * -1.0;
  3953. temp1.z = equ->z * 0.5;
  3954. temp1.w = equ->w + (equ->z * 0.5);
  3955. //////////////// temp2
  3956. VMatrix mat1( 1, 0, 0, 0,
  3957. 0, -1, 0, 0,
  3958. 0, 0, 2, -1,
  3959. 0, 0, 0, 1
  3960. );
  3961. //mat1 = mat1.Transpose();
  3962. VMatrix mat2;
  3963. bool success = mat1.InverseGeneral( mat2 );
  3964. if (success)
  3965. {
  3966. VMatrix mat3;
  3967. mat3 = mat2.Transpose();
  3968. VPlane origPlane( Vector( equ->x, equ->y, equ->z ), equ->w );
  3969. VPlane newPlane;
  3970. newPlane = mat3 * origPlane /* * mat3 */;
  3971. VPlane finalPlane = newPlane;
  3972. temp2.x = newPlane.m_Normal.x;
  3973. temp2.y = newPlane.m_Normal.y;
  3974. temp2.z = newPlane.m_Normal.z;
  3975. temp2.w = newPlane.m_Dist;
  3976. }
  3977. else
  3978. {
  3979. temp2.x = 0;
  3980. temp2.y = 0;
  3981. temp2.z = 0;
  3982. temp2.w = 0;
  3983. }
  3984. }
  3985. else
  3986. {
  3987. temp1 = temp2 = gl.m_ClipPlaneEquation[x];
  3988. }
  3989. if (1) //GLMKnob("caps-key",NULL)==0.0)
  3990. {
  3991. m_ctx->WriteClipPlaneEquation( &temp1, x ); // no caps lock = Antonio or classic
  3992. /*
  3993. if (x<1)
  3994. {
  3995. GLMPRINTF(( " plane %d √vers1[ %5.2f %5.2f %5.2f %5.2f ] vers2[ %5.2f %5.2f %5.2f %5.2f ]",
  3996. x,
  3997. temp1.x,temp1.y,temp1.z,temp1.w,
  3998. temp2.x,temp2.y,temp2.z,temp2.w
  3999. ));
  4000. }
  4001. */
  4002. }
  4003. else
  4004. {
  4005. m_ctx->WriteClipPlaneEquation( &temp2, x ); // caps = our way or classic
  4006. /*
  4007. if (x<1)
  4008. {
  4009. GLMPRINTF(( " plane %d vers1[ %5.2f %5.2f %5.2f %5.2f ] √vers2[ %5.2f %5.2f %5.2f %5.2f ]",
  4010. x,
  4011. temp1.x,temp1.y,temp1.z,temp1.w,
  4012. temp2.x,temp2.y,temp2.z,temp2.w
  4013. ));
  4014. }
  4015. */
  4016. }
  4017. }
  4018. }
  4019. void IDirect3DDevice9::InitStates()
  4020. {
  4021. m_ctx->m_AlphaTestEnable.Read( &gl.m_AlphaTestEnable, 0 );
  4022. m_ctx->m_AlphaTestFunc.Read( &gl.m_AlphaTestFunc, 0 );
  4023. m_ctx->m_CullFaceEnable.Read( &gl.m_CullFaceEnable, 0 );
  4024. m_ctx->m_DepthBias.Read( &gl.m_DepthBias, 0 );
  4025. m_ctx->m_ScissorEnable.Read( &gl.m_ScissorEnable, 0 );
  4026. m_ctx->m_ScissorBox.Read( &gl.m_ScissorBox, 0 );
  4027. m_ctx->m_ViewportBox.Read( &gl.m_ViewportBox, 0 );
  4028. m_ctx->m_ViewportDepthRange.Read( &gl.m_ViewportDepthRange, 0 );
  4029. for( int x=0; x<kGLMUserClipPlanes; x++)
  4030. m_ctx->m_ClipPlaneEnable.ReadIndex( &gl.m_ClipPlaneEnable[x], x, 0 );
  4031. m_ctx->m_PolygonMode.Read( &gl.m_PolygonMode, 0 );
  4032. m_ctx->m_CullFrontFace.Read( &gl.m_CullFrontFace, 0 );
  4033. m_ctx->m_AlphaToCoverageEnable.Read( &gl.m_AlphaToCoverageEnable, 0 );
  4034. m_ctx->m_BlendEquation.Read( &gl.m_BlendEquation, 0 );
  4035. m_ctx->m_BlendColor.Read( &gl.m_BlendColor, 0 );
  4036. for( int x=0; x<kGLMUserClipPlanes; x++)
  4037. m_ctx->m_ClipPlaneEquation.ReadIndex( &gl.m_ClipPlaneEquation[x], x, 0 );
  4038. m_ctx->m_ColorMaskSingle.Read( &gl.m_ColorMaskSingle, 0 );
  4039. m_ctx->m_BlendEnable.Read( &gl.m_BlendEnable, 0 );
  4040. m_ctx->m_BlendFactor.Read( &gl.m_BlendFactor, 0 );
  4041. m_ctx->m_BlendEnableSRGB.Read( &gl.m_BlendEnableSRGB, 0 );
  4042. m_ctx->m_DepthTestEnable.Read( &gl.m_DepthTestEnable, 0 );
  4043. m_ctx->m_DepthFunc.Read( &gl.m_DepthFunc, 0 );
  4044. m_ctx->m_DepthMask.Read( &gl.m_DepthMask, 0 );
  4045. m_ctx->m_StencilTestEnable.Read( &gl.m_StencilTestEnable, 0 );
  4046. m_ctx->m_StencilFunc.Read( &gl.m_StencilFunc, 0 );
  4047. m_ctx->m_StencilOp.ReadIndex( &gl.m_StencilOp, 0, 0 );
  4048. m_ctx->m_StencilOp.ReadIndex( &gl.m_StencilOp, 1, 0 );
  4049. m_ctx->m_StencilWriteMask.Read( &gl.m_StencilWriteMask, 0 );
  4050. m_ctx->m_ClearColor.Read( &gl.m_ClearColor, 0 );
  4051. m_ctx->m_ClearDepth.Read( &gl.m_ClearDepth, 0 );
  4052. m_ctx->m_ClearStencil.Read( &gl.m_ClearStencil, 0 );
  4053. }
  4054. void IDirect3DDevice9::FullFlushStates()
  4055. {
  4056. m_ctx->WriteAlphaTestEnable( &gl.m_AlphaTestEnable );
  4057. m_ctx->WriteAlphaTestFunc( &gl.m_AlphaTestFunc );
  4058. m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable );
  4059. m_ctx->WriteDepthBias( &gl.m_DepthBias );
  4060. m_ctx->WriteScissorEnable( &gl.m_ScissorEnable );
  4061. m_ctx->WriteScissorBox( &gl.m_ScissorBox );
  4062. m_ctx->WriteViewportBox( &gl.m_ViewportBox );
  4063. m_ctx->WriteViewportDepthRange( &gl.m_ViewportDepthRange );
  4064. for( int x=0; x<kGLMUserClipPlanes; x++)
  4065. m_ctx->WriteClipPlaneEnable( &gl.m_ClipPlaneEnable[x], x );
  4066. m_ctx->WritePolygonMode( &gl.m_PolygonMode );
  4067. m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace );
  4068. m_ctx->WriteAlphaToCoverageEnable( &gl.m_AlphaToCoverageEnable );
  4069. m_ctx->WriteBlendEquation( &gl.m_BlendEquation );
  4070. m_ctx->WriteBlendColor( &gl.m_BlendColor );
  4071. FlushClipPlaneEquation();
  4072. m_ctx->WriteColorMaskSingle( &gl.m_ColorMaskSingle );
  4073. m_ctx->WriteBlendEnable( &gl.m_BlendEnable );
  4074. m_ctx->WriteBlendFactor( &gl.m_BlendFactor );
  4075. m_ctx->WriteBlendEnableSRGB( &gl.m_BlendEnableSRGB );
  4076. m_ctx->WriteDepthTestEnable( &gl.m_DepthTestEnable );
  4077. m_ctx->WriteDepthFunc( &gl.m_DepthFunc );
  4078. m_ctx->WriteDepthMask( &gl.m_DepthMask );
  4079. m_ctx->WriteStencilTestEnable( &gl.m_StencilTestEnable );
  4080. m_ctx->WriteStencilFunc( &gl.m_StencilFunc );
  4081. m_ctx->WriteStencilOp( &gl.m_StencilOp,0 );
  4082. m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this
  4083. m_ctx->WriteStencilWriteMask( &gl.m_StencilWriteMask );
  4084. m_ctx->WriteClearColor( &gl.m_ClearColor );
  4085. m_ctx->WriteClearDepth( &gl.m_ClearDepth );
  4086. m_ctx->WriteClearStencil( &gl.m_ClearStencil );
  4087. }
  4088. HRESULT IDirect3DDevice9::DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount)
  4089. {
  4090. GL_BATCH_PERF_CALL_TIMER;
  4091. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4092. DXABSTRACT_BREAK_ON_ERROR();
  4093. return S_OK;
  4094. }
  4095. #ifndef DX_TO_GL_ABSTRACTION
  4096. HRESULT IDirect3DDevice9::DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCountx,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride)
  4097. {
  4098. GL_BATCH_PERF_CALL_TIMER;
  4099. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4100. DXABSTRACT_BREAK_ON_ERROR();
  4101. return S_OK;
  4102. }
  4103. #endif
  4104. // Type
  4105. // [in] Member of the D3DPRIMITIVETYPE enumerated type, describing the type of primitive to render. D3DPT_POINTLIST is not supported with this method. See Remarks.
  4106. // BaseVertexIndex
  4107. // [in] Offset from the start of the vertex buffer to the first vertex. See Scenario 4.
  4108. // MinIndex
  4109. // [in] Minimum vertex index for vertices used during this call. This is a zero based index relative to BaseVertexIndex.
  4110. // NumVertices
  4111. // [in] Number of vertices used during this call. The first vertex is located at index: BaseVertexIndex + MinIndex.
  4112. // StartIndex
  4113. // [in] Index of the first index to use when accessing the index buffer.
  4114. // PrimitiveCount
  4115. // [in] Number of primitives to render. The number of vertices used is a function of the primitive count and the primitive type. The maximum number of primitives allowed is determined by checking the MaxPrimitiveCount member of the D3DCAPS9 structure.
  4116. #include "glmgr_flush.inl"
  4117. // BE VERY CAREFUL what you do in this function. It's extremely hot, and calling the wrong GL API's in here will crush perf. on NVidia threaded drivers.
  4118. #ifndef OSX
  4119. HRESULT IDirect3DDevice9::DrawIndexedPrimitive( D3DPRIMITIVETYPE Type, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount )
  4120. {
  4121. tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "%s", __FUNCTION__ );
  4122. Assert( m_ctx->m_nCurOwnerThreadId == ThreadGetCurrentId() );
  4123. TOGL_NULL_DEVICE_CHECK;
  4124. if ( m_bFBODirty )
  4125. {
  4126. UpdateBoundFBO();
  4127. }
  4128. g_nTotalDrawsOrClears++;
  4129. #if GL_BATCH_PERF_ANALYSIS
  4130. m_nTotalPrims += primCount;
  4131. CFastTimer tm;
  4132. CFlushDrawStatesStats& flushStats = m_ctx->m_FlushStats;
  4133. tm.Start();
  4134. flushStats.Clear();
  4135. #endif
  4136. #if GLMDEBUG
  4137. if ( gl.m_FogEnable )
  4138. {
  4139. GLMPRINTF(("-D- IDirect3DDevice9::DrawIndexedPrimitive is seeing enabled fog..."));
  4140. }
  4141. #endif
  4142. if ( ( !m_indices.m_idxBuffer ) || ( !m_vertexShader ) )
  4143. goto draw_failed;
  4144. {
  4145. GL_BATCH_PERF_CALL_TIMER;
  4146. m_ctx->FlushDrawStates( MinVertexIndex, MinVertexIndex + NumVertices - 1, BaseVertexIndex );
  4147. {
  4148. #if !GL_TELEMETRY_ZONES && GL_BATCH_TELEMETRY_ZONES
  4149. tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "glDrawRangeElements %u", primCount );
  4150. #endif
  4151. Assert( ( D3DPT_LINELIST == 2 ) && ( D3DPT_TRIANGLELIST == 4 ) && ( D3DPT_TRIANGLESTRIP == 5 ) );
  4152. static const struct prim_t
  4153. {
  4154. GLenum m_nType;
  4155. uint m_nPrimMul;
  4156. uint m_nPrimAdd;
  4157. } s_primTypes[6] =
  4158. {
  4159. { 0, 0, 0 }, // 0
  4160. { 0, 0, 0 }, // 1
  4161. { GL_LINES, 2, 0 }, // 2 D3DPT_LINELIST
  4162. { 0, 0, 0 }, // 3
  4163. { GL_TRIANGLES, 3, 0 }, // 4 D3DPT_TRIANGLELIST
  4164. { GL_TRIANGLE_STRIP, 1, 2 } // 5 D3DPT_TRIANGLESTRIP
  4165. };
  4166. if ( Type <= D3DPT_TRIANGLESTRIP )
  4167. {
  4168. const prim_t& p = s_primTypes[Type];
  4169. Assert( p.m_nType );
  4170. Assert( NumVertices >= 1 );
  4171. m_ctx->DrawRangeElements( p.m_nType, (GLuint)MinVertexIndex, (GLuint)( MinVertexIndex + NumVertices - 1 ), (GLsizei)p.m_nPrimAdd + primCount * p.m_nPrimMul, (GLenum)GL_UNSIGNED_SHORT, (const GLvoid *)( startIndex * sizeof(short) ), BaseVertexIndex, m_indices.m_idxBuffer->m_idxBuffer );
  4172. }
  4173. }
  4174. }
  4175. #if GL_BATCH_PERF_ANALYSIS
  4176. if ( s_rdtsc_to_ms == 0.0f )
  4177. {
  4178. TmU64 t0 = Plat_Rdtsc();
  4179. double d0 = Plat_FloatTime();
  4180. ThreadSleep( 1000 );
  4181. TmU64 t1 = Plat_Rdtsc();
  4182. double d1 = Plat_FloatTime();
  4183. s_rdtsc_to_ms = ( 1000.0f * ( d1 - d0 ) ) / ( t1 - t0 );
  4184. }
  4185. #if GL_BATCH_PERF_ANALYSIS_WRITE_PNGS
  4186. if ( m_pBatch_vis_bitmap && m_pBatch_vis_bitmap->is_valid() )
  4187. {
  4188. double t = tm.GetDurationInProgress().GetMillisecondsF();
  4189. uint h = 1;
  4190. if ( gl_batch_vis_y_scale.GetFloat() > 0.0f)
  4191. {
  4192. h = ceil( t / gl_batch_vis_y_scale.GetFloat() );
  4193. h = MAX(h, 1);
  4194. }
  4195. // Total time spent inside any and all our "D3D9" calls
  4196. double flTotalD3DTime = g_nTotalD3DCycles * s_rdtsc_to_ms;
  4197. m_pBatch_vis_bitmap->fill_box(0, m_nBatchVisY, (uint)(.5f + flTotalD3DTime / gl_batch_vis_abs_scale.GetFloat() * m_pBatch_vis_bitmap->width()), h, 150, 150, 150);
  4198. // Total total spent processing just DrawIndexedPrimitive() for this batch.
  4199. m_pBatch_vis_bitmap->fill_box(0, m_nBatchVisY, (uint)(.5f + t / gl_batch_vis_abs_scale.GetFloat() * m_pBatch_vis_bitmap->width()), h, 70, 70, 70);
  4200. double flTotalGLMS = gGL->m_nTotalGLCycles * s_rdtsc_to_ms;
  4201. // Total time spent inside of all OpenGL calls
  4202. m_pBatch_vis_bitmap->additive_fill_box(0, m_nBatchVisY, (uint)(.5f + flTotalGLMS / gl_batch_vis_abs_scale.GetFloat() * m_pBatch_vis_bitmap->width()), h, 0, 0, 64);
  4203. if (flushStats.m_nNewVS) m_pBatch_vis_bitmap->additive_fill_box(80-16, m_nBatchVisY, 8, h, 0, 110, 0);
  4204. if (flushStats.m_nNewPS) m_pBatch_vis_bitmap->additive_fill_box(80-8, m_nBatchVisY, 8, h, 110, 0, 110);
  4205. int lm = 80;
  4206. m_pBatch_vis_bitmap->fill_box(lm+0+flushStats.m_nFirstVSConstant, m_nBatchVisY, flushStats.m_nNumVSConstants, h, 64, 255, 255);
  4207. m_pBatch_vis_bitmap->fill_box(lm+64, m_nBatchVisY, flushStats.m_nNumVSBoneConstants, h, 255, 64, 64);
  4208. m_pBatch_vis_bitmap->fill_box(lm+64+256+flushStats.m_nFirstPSConstant, m_nBatchVisY, flushStats.m_nNumPSConstants, h, 64, 64, 255);
  4209. m_pBatch_vis_bitmap->fill_box(lm+64+256+32, m_nBatchVisY, flushStats.m_nNumChangedSamplers, h, 255, 255, 255);
  4210. m_pBatch_vis_bitmap->fill_box(lm+64+256+32+16, m_nBatchVisY, flushStats.m_nNumSamplingParamsChanged, h, 92, 128, 255);
  4211. if ( flushStats.m_nVertexBufferChanged ) m_pBatch_vis_bitmap->fill_box(lm+64+256+32+16+64, m_nBatchVisY, 16, h, 128, 128, 128);
  4212. if ( flushStats.m_nIndexBufferChanged ) m_pBatch_vis_bitmap->fill_box(lm+64+256+32+16+64+16, m_nBatchVisY, 16, h, 128, 128, 255);
  4213. m_pBatch_vis_bitmap->fill_box(lm+64+256+32+16+64+16+16, m_nBatchVisY, ( ( g_nTotalVBLockBytes + g_nTotalIBLockBytes ) * 64 + 2047 ) / 2048, h, 120, 120, 120 );
  4214. m_pBatch_vis_bitmap->additive_fill_box(lm+64+256+32+16+64+16+16, m_nBatchVisY, ( g_nTotalVBLockBytes * 64 + 2047 ) / 2048, h, 120, 0, 0);
  4215. m_nBatchVisY += h;
  4216. }
  4217. #endif
  4218. m_nNumProgramChanges += ((flushStats.m_nNewVS + flushStats.m_nNewPS) != 0);
  4219. m_flTotalD3DTime += g_nTotalD3DCycles * s_rdtsc_to_ms;
  4220. m_nTotalD3DCalls += g_nTotalD3DCalls;
  4221. g_nTotalD3DCycles = 0;
  4222. g_nTotalD3DCalls = 0;
  4223. m_flTotalGLTime += gGL->m_nTotalGLCycles * s_rdtsc_to_ms;
  4224. m_nTotalGLCalls += gGL->m_nTotalGLCalls;
  4225. gGL->m_nTotalGLCycles = 0;
  4226. gGL->m_nTotalGLCalls = 0;
  4227. g_nTotalVBLockBytes = 0;
  4228. g_nTotalIBLockBytes = 0;
  4229. #endif
  4230. return S_OK;
  4231. draw_failed:
  4232. Assert( 0 );
  4233. return E_FAIL;
  4234. }
  4235. #else
  4236. // legacy (10.6) path that we're re-enabling for all OSX users as a result of perf regressions
  4237. HRESULT IDirect3DDevice9::FlushIndexBindings( void )
  4238. {
  4239. // push index buffer state
  4240. m_ctx->SetIndexBuffer( m_indices.m_idxBuffer->m_idxBuffer );
  4241. return S_OK;
  4242. }
  4243. HRESULT IDirect3DDevice9::FlushVertexBindings( uint baseVertexIndex )
  4244. {
  4245. // push vertex buffer state for the current vertex decl
  4246. // in this variant we just walk the attrib map in the VS and do a pull for each one.
  4247. // if we can't find a match in the vertex decl, we may fall back to the secret 'dummy' VBO that GLM maintains
  4248. GLMVertexSetup setup;
  4249. memset( &setup, 0, sizeof( setup ) );
  4250. IDirect3DVertexDeclaration9 *vxdecl = m_pVertDecl;
  4251. unsigned char *vshAttribMap = m_vertexShader->m_vtxAttribMap;
  4252. // this loop could be tightened if we knew the number of live entries in the shader attrib map.
  4253. // which of course would be easy to do in the create shader function or even in the translator.
  4254. GLMVertexAttributeDesc *dstAttr = setup.m_attrs;
  4255. for( int i=0; i<16; i++,dstAttr++ )
  4256. {
  4257. unsigned char vshattrib = vshAttribMap[ i ];
  4258. if (vshattrib != 0xBB)
  4259. {
  4260. // try to find the match in the decl.
  4261. // idea: put some inverse table in the decl which could accelerate this search.
  4262. D3DVERTEXELEMENT9_GL *elem = m_pVertDecl->m_elements;
  4263. for( int j=0; j< m_pVertDecl->m_elemCount; j++,elem++)
  4264. {
  4265. // if it matches, install it, change vshattrib so the code below does not trigger, then end the loop
  4266. if ( ((vshattrib>>4) == elem->m_dxdecl.Usage) && ((vshattrib & 0x0F) == elem->m_dxdecl.UsageIndex) )
  4267. {
  4268. // targeting attribute #i in the setup with element data #j from the decl
  4269. *dstAttr = elem->m_gldecl;
  4270. // then fix buffer, stride, offset - note that we honor the base vertex index here by fiddling the offset
  4271. int streamIndex = elem->m_dxdecl.Stream;
  4272. dstAttr->m_pBuffer = m_streams[ streamIndex ].m_vtxBuffer->m_vtxBuffer;
  4273. dstAttr->m_stride = m_streams[ streamIndex ].m_stride;
  4274. dstAttr->m_offset += m_streams[ streamIndex ].m_offset + (baseVertexIndex * dstAttr->m_stride);
  4275. // set mask
  4276. setup.m_attrMask |= (1 << i);
  4277. // end loop
  4278. vshattrib = 0xBB;
  4279. j = 999;
  4280. }
  4281. }
  4282. // if vshattrib is not 0xBB here, that means we could not find a source in the decl for it
  4283. if (vshattrib != 0xBB)
  4284. {
  4285. // fill out attr the same way as usual, we just pass NULL for the buffer and ask GLM to have mercy on us
  4286. dstAttr->m_pBuffer = NULL;
  4287. dstAttr->m_stride = 0;
  4288. dstAttr->m_offset = 0;
  4289. // only implement certain usages... if we haven't seen it before, stop.
  4290. switch (vshattrib >> 4) // aka usage
  4291. {
  4292. case D3DDECLUSAGE_POSITION:
  4293. case D3DDECLUSAGE_BLENDWEIGHT:
  4294. case D3DDECLUSAGE_BLENDINDICES:
  4295. Debugger();
  4296. break;
  4297. case D3DDECLUSAGE_NORMAL:
  4298. dstAttr->m_nCompCount = 3;
  4299. dstAttr->m_datatype = GL_FLOAT;
  4300. dstAttr->m_normalized = false;
  4301. break;
  4302. case D3DDECLUSAGE_PSIZE:
  4303. Debugger();
  4304. break;
  4305. case D3DDECLUSAGE_TEXCOORD:
  4306. dstAttr->m_nCompCount = 3;
  4307. dstAttr->m_datatype = GL_FLOAT;
  4308. dstAttr->m_normalized = false;
  4309. break;
  4310. case D3DDECLUSAGE_TANGENT:
  4311. case D3DDECLUSAGE_BINORMAL:
  4312. case D3DDECLUSAGE_TESSFACTOR:
  4313. case D3DDECLUSAGE_PLUGH:
  4314. Debugger();
  4315. break;
  4316. case D3DDECLUSAGE_COLOR:
  4317. dstAttr->m_nCompCount = 4;
  4318. dstAttr->m_datatype = GL_UNSIGNED_BYTE;
  4319. dstAttr->m_normalized = true;
  4320. break;
  4321. case D3DDECLUSAGE_FOG:
  4322. case D3DDECLUSAGE_DEPTH:
  4323. case D3DDECLUSAGE_SAMPLE:
  4324. Debugger();
  4325. break;
  4326. }
  4327. }
  4328. }
  4329. }
  4330. // copy active program's vertex attrib map into the vert setup info
  4331. memcpy(&setup.m_vtxAttribMap, m_vertexShader->m_vtxAttribMap, sizeof(m_vertexShader->m_vtxAttribMap));
  4332. m_ctx->SetVertexAttributes(&setup);
  4333. return S_OK;
  4334. }
  4335. // OSX path offering support for 10.6 (we do not have support for glDrawRangeElementsBaseVertex)
  4336. HRESULT IDirect3DDevice9::DrawIndexedPrimitive( D3DPRIMITIVETYPE Type,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount )
  4337. {
  4338. Assert( m_ctx->m_nCurOwnerThreadId == ThreadGetCurrentId() );
  4339. TOGL_NULL_DEVICE_CHECK;
  4340. if ( m_bFBODirty )
  4341. {
  4342. UpdateBoundFBO();
  4343. }
  4344. g_nTotalDrawsOrClears++;
  4345. #if GL_BATCH_PERF_ANALYSIS
  4346. m_nTotalPrims += primCount;
  4347. CFastTimer tm;
  4348. CFlushDrawStatesStats& flushStats = m_ctx->m_FlushStats;
  4349. tm.Start();
  4350. flushStats.Clear();
  4351. #endif
  4352. #if GLMDEBUG
  4353. if ( gl.m_FogEnable )
  4354. {
  4355. GLMPRINTF(("-D- IDirect3DDevice9::DrawIndexedPrimitive is seeing enabled fog..."));
  4356. }
  4357. #endif
  4358. if ( ( !m_indices.m_idxBuffer ) || ( !m_vertexShader ) )
  4359. goto draw_failed;
  4360. this->FlushIndexBindings( );
  4361. this->FlushVertexBindings( BaseVertexIndex );
  4362. m_ctx->FlushDrawStates( MinVertexIndex, MinVertexIndex + NumVertices - 1, 0 );
  4363. if (gl.m_FogEnable)
  4364. {
  4365. GLMPRINTF(("-D- IDirect3DDevice9::DrawIndexedPrimitive is seeing enabled fog..."));
  4366. }
  4367. switch(Type)
  4368. {
  4369. case D3DPT_POINTLIST:
  4370. Debugger();
  4371. break;
  4372. case D3DPT_LINELIST:
  4373. GLMPRINTF(("-X- IDirect3DDevice9::DrawIndexedPrimitive( D3DPT_LINELIST ) - ignored."));
  4374. // Debugger();
  4375. m_ctx->DrawRangeElements( (GLenum)GL_LINES, (GLuint)MinVertexIndex, (GLuint)(MinVertexIndex + NumVertices), (GLsizei)primCount*2, (GLenum)GL_UNSIGNED_SHORT, (const GLvoid *)(startIndex * sizeof(short)), m_indices.m_idxBuffer->m_idxBuffer );
  4376. break;
  4377. case D3DPT_TRIANGLELIST:
  4378. m_ctx->DrawRangeElements(GL_TRIANGLES, (GLuint)MinVertexIndex, (GLuint)(MinVertexIndex + NumVertices), (GLsizei)primCount*3, (GLenum)GL_UNSIGNED_SHORT, (const GLvoid *)(startIndex * sizeof(short)), m_indices.m_idxBuffer->m_idxBuffer );
  4379. break;
  4380. case D3DPT_TRIANGLESTRIP:
  4381. // enabled... Debugger();
  4382. m_ctx->DrawRangeElements(GL_TRIANGLE_STRIP, (GLuint)MinVertexIndex, (GLuint)(MinVertexIndex + NumVertices), (GLsizei)(2+primCount), (GLenum)GL_UNSIGNED_SHORT, (const GLvoid *)(startIndex * sizeof(short)), m_indices.m_idxBuffer->m_idxBuffer );
  4383. break;
  4384. }
  4385. return S_OK;
  4386. draw_failed:
  4387. Assert( 0 );
  4388. return E_FAIL;
  4389. }
  4390. #endif // #ifndef OSX
  4391. HRESULT IDirect3DDevice9::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride)
  4392. {
  4393. GL_BATCH_PERF_CALL_TIMER;
  4394. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4395. DXABSTRACT_BREAK_ON_ERROR();
  4396. return S_OK;
  4397. }
  4398. BOOL IDirect3DDevice9::ShowCursor(BOOL bShow)
  4399. {
  4400. // FIXME NOP
  4401. //DXABSTRACT_BREAK_ON_ERROR();
  4402. return TRUE;
  4403. }
  4404. void d3drect_to_glmbox( D3DRECT *src, GLScissorBox_t *dst )
  4405. {
  4406. // to convert from a d3d rect to a GL rect you have to fix up the vertical axis, since D3D Y=0 is the top, but GL Y=0 is the bottom.
  4407. // you can't fix it without knowing the height.
  4408. dst->width = src->x2 - src->x1;
  4409. dst->x = src->x1; // left edge
  4410. dst->height = src->y2 - src->y1;
  4411. dst->y = src->y1; // bottom edge - take large Y from d3d and subtract from surf height.
  4412. }
  4413. HRESULT IDirect3DDevice9::Clear(DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil)
  4414. {
  4415. GL_BATCH_PERF_CALL_TIMER;
  4416. if ( m_bFBODirty )
  4417. {
  4418. UpdateBoundFBO();
  4419. }
  4420. g_nTotalDrawsOrClears++;
  4421. m_ctx->FlushDrawStatesNoShaders();
  4422. //debugging Color = (rand() | 0xFF0000FF) & 0xFF3F3FFF;
  4423. if (!Count)
  4424. {
  4425. // run clear with no added rectangle
  4426. m_ctx->Clear( (Flags&D3DCLEAR_TARGET)!=0, Color,
  4427. (Flags&D3DCLEAR_ZBUFFER)!=0, Z,
  4428. (Flags&D3DCLEAR_STENCIL)!=0, Stencil,
  4429. NULL
  4430. );
  4431. }
  4432. else
  4433. {
  4434. GLScissorBox_t tempbox;
  4435. // do the rects one by one and convert each one to GL form
  4436. for( uint i=0; i<Count; i++)
  4437. {
  4438. D3DRECT d3dtempbox = pRects[i];
  4439. d3drect_to_glmbox( &d3dtempbox, &tempbox );
  4440. m_ctx->Clear( (Flags&D3DCLEAR_TARGET)!=0, Color,
  4441. (Flags&D3DCLEAR_ZBUFFER)!=0, Z,
  4442. (Flags&D3DCLEAR_STENCIL)!=0, Stencil,
  4443. &tempbox
  4444. );
  4445. }
  4446. }
  4447. return S_OK;
  4448. }
  4449. HRESULT IDirect3DDevice9::SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix)
  4450. {
  4451. GL_BATCH_PERF_CALL_TIMER;
  4452. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4453. DXABSTRACT_BREAK_ON_ERROR();
  4454. return S_OK;
  4455. }
  4456. HRESULT IDirect3DDevice9::SetTextureStageState(DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value)
  4457. {
  4458. GL_BATCH_PERF_CALL_TIMER;
  4459. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4460. DXABSTRACT_BREAK_ON_ERROR();
  4461. return S_OK;
  4462. }
  4463. HRESULT IDirect3DDevice9::ValidateDevice(DWORD* pNumPasses)
  4464. {
  4465. GL_BATCH_PERF_CALL_TIMER;
  4466. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4467. DXABSTRACT_BREAK_ON_ERROR();
  4468. return S_OK;
  4469. }
  4470. HRESULT IDirect3DDevice9::SetMaterial(CONST D3DMATERIAL9* pMaterial)
  4471. {
  4472. GL_BATCH_PERF_CALL_TIMER;
  4473. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4474. GLMPRINTF(("-X- IDirect3DDevice9::SetMaterial - ignored."));
  4475. // DXABSTRACT_BREAK_ON_ERROR();
  4476. return S_OK;
  4477. }
  4478. HRESULT IDirect3DDevice9::LightEnable(DWORD Index,BOOL Enable)
  4479. {
  4480. GL_BATCH_PERF_CALL_TIMER;
  4481. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4482. DXABSTRACT_BREAK_ON_ERROR();
  4483. return S_OK;
  4484. }
  4485. HRESULT IDirect3DDevice9::SetScissorRect(CONST RECT* pRect)
  4486. {
  4487. GL_BATCH_PERF_CALL_TIMER;
  4488. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4489. //int nSurfaceHeight = m_ctx->m_drawingFBO->m_attach[ kAttColor0 ].m_tex->m_layout->m_key.m_ySize;
  4490. GLScissorBox_t newScissorBox = { pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top };
  4491. gl.m_ScissorBox = newScissorBox;
  4492. m_ctx->WriteScissorBox( &gl.m_ScissorBox );
  4493. return S_OK;
  4494. }
  4495. HRESULT IDirect3DDevice9::GetDeviceCaps(D3DCAPS9* pCaps)
  4496. {
  4497. GL_BATCH_PERF_CALL_TIMER;
  4498. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4499. // "Adapter" is used to index amongst the set of fake-adapters maintained in the display DB
  4500. GLMDisplayDB *db = GetDisplayDB();
  4501. int glmRendererIndex = -1;
  4502. int glmDisplayIndex = -1;
  4503. GLMRendererInfoFields glmRendererInfo;
  4504. GLMDisplayInfoFields glmDisplayInfo;
  4505. bool result = db->GetFakeAdapterInfo( m_params.m_adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo ); (void)result;
  4506. Assert (!result);
  4507. // just leave glmRendererInfo filled out for subsequent code to look at as needed.
  4508. FillD3DCaps9( glmRendererInfo, pCaps );
  4509. return S_OK;
  4510. }
  4511. HRESULT IDirect3DDevice9::TestCooperativeLevel()
  4512. {
  4513. GL_BATCH_PERF_CALL_TIMER;
  4514. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4515. // game calls this to see if device was lost.
  4516. // last I checked the device was still attached to the computer.
  4517. // so, return OK.
  4518. return S_OK;
  4519. }
  4520. HRESULT IDirect3DDevice9::SetClipPlane(DWORD Index,CONST float* pPlane)
  4521. {
  4522. GL_BATCH_PERF_CALL_TIMER;
  4523. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4524. Assert(Index<2);
  4525. // We actually push the clip plane coeffs to two places
  4526. // - into a shader param for ARB mode
  4527. // - and into the API defined clip plane slots for GLSL mode.
  4528. // if ARB mode... THIS NEEDS TO GO... it's messing up the dirty ranges..
  4529. {
  4530. // this->SetVertexShaderConstantF( DXABSTRACT_VS_CLIP_PLANE_BASE+Index, pPlane, 1 ); // stash the clip plane values into shader param - translator knows where to look
  4531. }
  4532. // if GLSL mode... latch it and let FlushStates push it out
  4533. {
  4534. GLClipPlaneEquation_t peq;
  4535. peq.x = pPlane[0];
  4536. peq.y = pPlane[1];
  4537. peq.z = pPlane[2];
  4538. peq.w = pPlane[3];
  4539. gl.m_ClipPlaneEquation[ Index ] = peq;
  4540. FlushClipPlaneEquation();
  4541. // m_ctx->WriteClipPlaneEquation( &peq, Index );
  4542. }
  4543. return S_OK;
  4544. }
  4545. HRESULT IDirect3DDevice9::EvictManagedResources()
  4546. {
  4547. GL_BATCH_PERF_CALL_TIMER;
  4548. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4549. GLMPRINTF(("-X- IDirect3DDevice9::EvictManagedResources --> IGNORED"));
  4550. return S_OK;
  4551. }
  4552. HRESULT IDirect3DDevice9::SetLight(DWORD Index,CONST D3DLIGHT9*)
  4553. {
  4554. GL_BATCH_PERF_CALL_TIMER;
  4555. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4556. DXABSTRACT_BREAK_ON_ERROR();
  4557. return S_OK;
  4558. }
  4559. void IDirect3DDevice9::SetGammaRamp(UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp)
  4560. {
  4561. GL_BATCH_PERF_CALL_TIMER;
  4562. Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() );
  4563. #ifdef OSX
  4564. // just slam it directly for the time being
  4565. // this code is OS X specific
  4566. CGDisplayErr cgErr;
  4567. CGGammaValue redt[256];
  4568. CGGammaValue grnt[256];
  4569. CGGammaValue blut[256];
  4570. for( int i=0; i<256; i++)
  4571. {
  4572. redt[i] = ((float)pRamp->red[i]) / 65535.0f;
  4573. grnt[i] = ((float)pRamp->green[i]) / 65535.0f;
  4574. blut[i] = ((float)pRamp->blue[i]) / 65535.0f;
  4575. }
  4576. cgErr = CGSetDisplayTransferByTable( 0, 256, redt, grnt, blut );
  4577. #else
  4578. if ( g_pLauncherMgr )
  4579. {
  4580. g_pLauncherMgr->SetGammaRamp( pRamp->red, pRamp->green, pRamp->blue );
  4581. }
  4582. #endif
  4583. }
  4584. void TOGLMETHODCALLTYPE IDirect3DDevice9::SaveGLState()
  4585. {
  4586. }
  4587. void TOGLMETHODCALLTYPE IDirect3DDevice9::RestoreGLState()
  4588. {
  4589. m_ctx->ForceFlushStates();
  4590. m_bFBODirty = true;
  4591. }
  4592. void IDirect3DDevice9::AcquireThreadOwnership( )
  4593. {
  4594. GL_BATCH_PERF_CALL_TIMER;
  4595. m_ctx->MakeCurrent( true );
  4596. }
  4597. void IDirect3DDevice9::ReleaseThreadOwnership( )
  4598. {
  4599. GL_BATCH_PERF_CALL_TIMER;
  4600. m_ctx->ReleaseCurrent( true );
  4601. }
  4602. void IDirect3DDevice9::SetMaxUsedVertexShaderConstantsHintNonInline( uint nMaxReg )
  4603. {
  4604. GL_BATCH_PERF_CALL_TIMER;
  4605. m_ctx->SetMaxUsedVertexShaderConstantsHint( nMaxReg );
  4606. }
  4607. HRESULT IDirect3DDevice9::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value )
  4608. {
  4609. GL_BATCH_PERF_CALL_TIMER;
  4610. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4611. TOGL_NULL_DEVICE_CHECK;
  4612. #if GLMDEBUG
  4613. // None of this is needed normally.
  4614. char rsSpew = 1;
  4615. char ignored = 0;
  4616. if (State >= D3DRS_VALUE_LIMIT)
  4617. {
  4618. DXABSTRACT_BREAK_ON_ERROR(); // bad
  4619. return S_OK;
  4620. }
  4621. const D3D_RSINFO *info = &g_D3DRS_INFO_unpacked[ State ];
  4622. if (info->m_state != State)
  4623. {
  4624. DXABSTRACT_BREAK_ON_ERROR(); // bad - we never set up that state in our list
  4625. return S_OK;
  4626. }
  4627. if (rsSpew)
  4628. {
  4629. GLMPRINTF(("-X- IDirect3DDevice9::SetRenderState: set %s(%d) to %d(0x%08x) ( class %d, defval is %d(0x%08x) )", GLMDecode( eD3D_RSTATE,State),State, Value,Value, info->m_class, info->m_defval,info->m_defval ));
  4630. }
  4631. switch( info->m_class )
  4632. {
  4633. case 0: // just ignore quietly. example: D3DRS_LIGHTING
  4634. ignored = 1;
  4635. break;
  4636. case 1:
  4637. {
  4638. // no GL response - and no error as long as the write value matches the default
  4639. if (Value != info->m_defval)
  4640. {
  4641. static char stop_here_1 = 0;
  4642. if (stop_here_1)
  4643. DXABSTRACT_BREAK_ON_ERROR();
  4644. }
  4645. break;
  4646. }
  4647. case 2:
  4648. {
  4649. // provide GL response, but only support known default value
  4650. if (Value != info->m_defval)
  4651. {
  4652. static char stop_here_2 = 0;
  4653. if (stop_here_2)
  4654. DXABSTRACT_BREAK_ON_ERROR();
  4655. }
  4656. // fall through to mode 3
  4657. }
  4658. case 3:
  4659. // normal case - the switch statement below will handle this
  4660. break;
  4661. }
  4662. #endif
  4663. switch (State)
  4664. {
  4665. case D3DRS_ZENABLE: // kGLDepthTestEnable
  4666. {
  4667. gl.m_DepthTestEnable.enable = Value;
  4668. m_ctx->WriteDepthTestEnable( &gl.m_DepthTestEnable );
  4669. break;
  4670. }
  4671. case D3DRS_ZWRITEENABLE: // kGLDepthMask
  4672. {
  4673. gl.m_DepthMask.mask = Value;
  4674. m_ctx->WriteDepthMask( &gl.m_DepthMask );
  4675. break;
  4676. }
  4677. case D3DRS_ZFUNC:
  4678. {
  4679. // kGLDepthFunc
  4680. GLenum func = D3DCompareFuncToGL( Value );
  4681. gl.m_DepthFunc.func = func;
  4682. m_ctx->WriteDepthFunc( &gl.m_DepthFunc );
  4683. break;
  4684. }
  4685. case D3DRS_COLORWRITEENABLE: // kGLColorMaskSingle
  4686. {
  4687. gl.m_ColorMaskSingle.r = ((Value & D3DCOLORWRITEENABLE_RED) != 0) ? 0xFF : 0x00;
  4688. gl.m_ColorMaskSingle.g = ((Value & D3DCOLORWRITEENABLE_GREEN)!= 0) ? 0xFF : 0x00;
  4689. gl.m_ColorMaskSingle.b = ((Value & D3DCOLORWRITEENABLE_BLUE) != 0) ? 0xFF : 0x00;
  4690. gl.m_ColorMaskSingle.a = ((Value & D3DCOLORWRITEENABLE_ALPHA)!= 0) ? 0xFF : 0x00;
  4691. m_ctx->WriteColorMaskSingle( &gl.m_ColorMaskSingle );
  4692. break;
  4693. }
  4694. case D3DRS_CULLMODE: // kGLCullFaceEnable / kGLCullFrontFace
  4695. {
  4696. switch (Value)
  4697. {
  4698. case D3DCULL_NONE:
  4699. {
  4700. gl.m_CullFaceEnable.enable = false;
  4701. gl.m_CullFrontFace.value = GL_CCW; //doesn't matter
  4702. m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable );
  4703. m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace );
  4704. break;
  4705. }
  4706. case D3DCULL_CW:
  4707. {
  4708. gl.m_CullFaceEnable.enable = true;
  4709. gl.m_CullFrontFace.value = GL_CW; //origGL_CCW;
  4710. m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable );
  4711. m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace );
  4712. break;
  4713. }
  4714. case D3DCULL_CCW:
  4715. {
  4716. gl.m_CullFaceEnable.enable = true;
  4717. gl.m_CullFrontFace.value = GL_CCW; //origGL_CW;
  4718. m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable );
  4719. m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace );
  4720. break;
  4721. }
  4722. default:
  4723. {
  4724. DXABSTRACT_BREAK_ON_ERROR();
  4725. break;
  4726. }
  4727. }
  4728. break;
  4729. }
  4730. //-------------------------------------------------------------------------------------------- alphablend stuff
  4731. case D3DRS_ALPHABLENDENABLE: // kGLBlendEnable
  4732. {
  4733. gl.m_BlendEnable.enable = Value;
  4734. m_ctx->WriteBlendEnable( &gl.m_BlendEnable );
  4735. break;
  4736. }
  4737. case D3DRS_BLENDOP: // kGLBlendEquation // D3D blend-op ==> GL blend equation
  4738. {
  4739. GLenum equation = D3DBlendOperationToGL( Value );
  4740. gl.m_BlendEquation.equation = equation;
  4741. m_ctx->WriteBlendEquation( &gl.m_BlendEquation );
  4742. break;
  4743. }
  4744. case D3DRS_SRCBLEND: // kGLBlendFactor // D3D blend-factor ==> GL blend factor
  4745. case D3DRS_DESTBLEND: // kGLBlendFactor
  4746. {
  4747. GLenum factor = D3DBlendFactorToGL( Value );
  4748. if (State==D3DRS_SRCBLEND)
  4749. {
  4750. gl.m_BlendFactor.srcfactor = factor;
  4751. }
  4752. else
  4753. {
  4754. gl.m_BlendFactor.dstfactor = factor;
  4755. }
  4756. m_ctx->WriteBlendFactor( &gl.m_BlendFactor );
  4757. break;
  4758. }
  4759. case D3DRS_SRGBWRITEENABLE: // kGLBlendEnableSRGB
  4760. {
  4761. gl.m_BlendEnableSRGB.enable = Value;
  4762. m_ctx->WriteBlendEnableSRGB( &gl.m_BlendEnableSRGB );
  4763. break;
  4764. }
  4765. //-------------------------------------------------------------------------------------------- alphatest stuff
  4766. case D3DRS_ALPHATESTENABLE:
  4767. {
  4768. gl.m_AlphaTestEnable.enable = Value;
  4769. m_ctx->WriteAlphaTestEnable( &gl.m_AlphaTestEnable );
  4770. break;
  4771. }
  4772. case D3DRS_ALPHAREF:
  4773. {
  4774. gl.m_AlphaTestFunc.ref = Value / 255.0f;
  4775. m_ctx->WriteAlphaTestFunc( &gl.m_AlphaTestFunc );
  4776. break;
  4777. }
  4778. case D3DRS_ALPHAFUNC:
  4779. {
  4780. GLenum func = D3DCompareFuncToGL( Value );;
  4781. gl.m_AlphaTestFunc.func = func;
  4782. m_ctx->WriteAlphaTestFunc( &gl.m_AlphaTestFunc );
  4783. break;
  4784. }
  4785. //-------------------------------------------------------------------------------------------- stencil stuff
  4786. case D3DRS_STENCILENABLE: // GLStencilTestEnable_t
  4787. {
  4788. gl.m_StencilTestEnable.enable = Value;
  4789. m_ctx->WriteStencilTestEnable( &gl.m_StencilTestEnable );
  4790. break;
  4791. }
  4792. case D3DRS_STENCILFAIL: // GLStencilOp_t "what do you do if stencil test fails"
  4793. {
  4794. GLenum stencilop = D3DStencilOpToGL( Value );
  4795. gl.m_StencilOp.sfail = stencilop;
  4796. m_ctx->WriteStencilOp( &gl.m_StencilOp,0 );
  4797. m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this
  4798. break;
  4799. }
  4800. case D3DRS_STENCILZFAIL: // GLStencilOp_t "what do you do if stencil test passes *but* depth test fails, if depth test happened"
  4801. {
  4802. GLenum stencilop = D3DStencilOpToGL( Value );
  4803. gl.m_StencilOp.dpfail = stencilop;
  4804. m_ctx->WriteStencilOp( &gl.m_StencilOp,0 );
  4805. m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this
  4806. break;
  4807. }
  4808. case D3DRS_STENCILPASS: // GLStencilOp_t "what do you do if stencil test and depth test both pass"
  4809. {
  4810. GLenum stencilop = D3DStencilOpToGL( Value );
  4811. gl.m_StencilOp.dppass = stencilop;
  4812. m_ctx->WriteStencilOp( &gl.m_StencilOp,0 );
  4813. m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this
  4814. break;
  4815. }
  4816. case D3DRS_STENCILFUNC: // GLStencilFunc_t
  4817. {
  4818. GLenum stencilfunc = D3DCompareFuncToGL( Value );
  4819. gl.m_StencilFunc.frontfunc = gl.m_StencilFunc.backfunc = stencilfunc;
  4820. m_ctx->WriteStencilFunc( &gl.m_StencilFunc );
  4821. break;
  4822. }
  4823. case D3DRS_STENCILREF: // GLStencilFunc_t
  4824. {
  4825. gl.m_StencilFunc.ref = Value;
  4826. m_ctx->WriteStencilFunc( &gl.m_StencilFunc );
  4827. break;
  4828. }
  4829. case D3DRS_STENCILMASK: // GLStencilFunc_t
  4830. {
  4831. gl.m_StencilFunc.mask = Value;
  4832. m_ctx->WriteStencilFunc( &gl.m_StencilFunc );
  4833. break;
  4834. }
  4835. case D3DRS_STENCILWRITEMASK: // GLStencilWriteMask_t
  4836. {
  4837. gl.m_StencilWriteMask.mask = Value;
  4838. m_ctx->WriteStencilWriteMask( &gl.m_StencilWriteMask );
  4839. break;
  4840. }
  4841. case D3DRS_FOGENABLE: // none of these are implemented yet... erk
  4842. {
  4843. gl.m_FogEnable = (Value != 0);
  4844. GLMPRINTF(("-D- fogenable = %d",Value ));
  4845. break;
  4846. }
  4847. case D3DRS_SCISSORTESTENABLE: // kGLScissorEnable
  4848. {
  4849. gl.m_ScissorEnable.enable = Value;
  4850. m_ctx->WriteScissorEnable( &gl.m_ScissorEnable );
  4851. break;
  4852. }
  4853. case D3DRS_DEPTHBIAS: // kGLDepthBias
  4854. {
  4855. // the value in the dword is actually a float
  4856. float fvalue = *(float*)&Value;
  4857. gl.m_DepthBias.units = fvalue;
  4858. m_ctx->WriteDepthBias( &gl.m_DepthBias );
  4859. break;
  4860. }
  4861. // good ref on these: http://aras-p.info/blog/2008/06/12/depth-bias-and-the-power-of-deceiving-yourself/
  4862. case D3DRS_SLOPESCALEDEPTHBIAS:
  4863. {
  4864. // the value in the dword is actually a float
  4865. float fvalue = *(float*)&Value;
  4866. gl.m_DepthBias.factor = fvalue;
  4867. m_ctx->WriteDepthBias( &gl.m_DepthBias );
  4868. break;
  4869. }
  4870. // Alpha to coverage
  4871. case D3DRS_ADAPTIVETESS_Y:
  4872. {
  4873. gl.m_AlphaToCoverageEnable.enable = Value;
  4874. m_ctx->WriteAlphaToCoverageEnable( &gl.m_AlphaToCoverageEnable );
  4875. break;
  4876. }
  4877. case D3DRS_CLIPPLANEENABLE: // kGLClipPlaneEnable
  4878. {
  4879. // d3d packs all the enables into one word.
  4880. // we break that out so we don't do N glEnable calls to sync -
  4881. // GLM is tracking one unique enable per plane.
  4882. for( int i=0; i<kGLMUserClipPlanes; i++)
  4883. {
  4884. gl.m_ClipPlaneEnable[i].enable = (Value & (1<<i)) != 0;
  4885. }
  4886. for( int x=0; x<kGLMUserClipPlanes; x++)
  4887. m_ctx->WriteClipPlaneEnable( &gl.m_ClipPlaneEnable[x], x );
  4888. break;
  4889. }
  4890. //-------------------------------------------------------------------------------------------- polygon/fill mode
  4891. case D3DRS_FILLMODE:
  4892. {
  4893. GLuint mode = 0;
  4894. switch(Value)
  4895. {
  4896. case D3DFILL_POINT: mode = GL_POINT; break;
  4897. case D3DFILL_WIREFRAME: mode = GL_LINE; break;
  4898. case D3DFILL_SOLID: mode = GL_FILL; break;
  4899. default: DXABSTRACT_BREAK_ON_ERROR(); break;
  4900. }
  4901. gl.m_PolygonMode.values[0] = gl.m_PolygonMode.values[1] = mode;
  4902. m_ctx->WritePolygonMode( &gl.m_PolygonMode );
  4903. break;
  4904. }
  4905. #if GLMDEBUG
  4906. case D3DRS_MULTISAMPLEANTIALIAS:
  4907. case D3DRS_MULTISAMPLEMASK:
  4908. case D3DRS_FOGCOLOR:
  4909. case D3DRS_FOGTABLEMODE:
  4910. case D3DRS_FOGSTART:
  4911. case D3DRS_FOGEND:
  4912. case D3DRS_FOGDENSITY:
  4913. case D3DRS_RANGEFOGENABLE:
  4914. case D3DRS_FOGVERTEXMODE:
  4915. case D3DRS_COLORWRITEENABLE1: // kGLColorMaskMultiple
  4916. case D3DRS_COLORWRITEENABLE2: // kGLColorMaskMultiple
  4917. case D3DRS_COLORWRITEENABLE3: // kGLColorMaskMultiple
  4918. case D3DRS_SEPARATEALPHABLENDENABLE:
  4919. case D3DRS_BLENDOPALPHA:
  4920. case D3DRS_SRCBLENDALPHA:
  4921. case D3DRS_DESTBLENDALPHA:
  4922. case D3DRS_TWOSIDEDSTENCILMODE: // -> GL_STENCIL_TEST_TWO_SIDE_EXT... not yet implemented ?
  4923. case D3DRS_CCW_STENCILFAIL: // GLStencilOp_t
  4924. case D3DRS_CCW_STENCILZFAIL: // GLStencilOp_t
  4925. case D3DRS_CCW_STENCILPASS: // GLStencilOp_t
  4926. case D3DRS_CCW_STENCILFUNC: // GLStencilFunc_t
  4927. case D3DRS_CLIPPING: // ???? is clipping ever turned off ??
  4928. case D3DRS_LASTPIXEL:
  4929. case D3DRS_DITHERENABLE:
  4930. case D3DRS_SHADEMODE:
  4931. default:
  4932. ignored = 1;
  4933. break;
  4934. #endif
  4935. }
  4936. #if GLMDEBUG
  4937. if (rsSpew && ignored)
  4938. {
  4939. GLMPRINTF(("-X- (ignored)"));
  4940. }
  4941. #endif
  4942. return S_OK;
  4943. }
  4944. HRESULT IDirect3DDevice9::SetSamplerStateNonInline( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value )
  4945. {
  4946. GL_BATCH_PERF_CALL_TIMER;
  4947. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4948. Assert( Sampler < GLM_SAMPLER_COUNT );
  4949. m_ctx->SetSamplerDirty( Sampler );
  4950. switch( Type )
  4951. {
  4952. case D3DSAMP_ADDRESSU:
  4953. m_ctx->SetSamplerAddressU( Sampler, Value );
  4954. break;
  4955. case D3DSAMP_ADDRESSV:
  4956. m_ctx->SetSamplerAddressV( Sampler, Value );
  4957. break;
  4958. case D3DSAMP_ADDRESSW:
  4959. m_ctx->SetSamplerAddressW( Sampler, Value );
  4960. break;
  4961. case D3DSAMP_BORDERCOLOR:
  4962. m_ctx->SetSamplerBorderColor( Sampler, Value );
  4963. break;
  4964. case D3DSAMP_MAGFILTER:
  4965. m_ctx->SetSamplerMagFilter( Sampler, Value );
  4966. break;
  4967. case D3DSAMP_MIPFILTER:
  4968. m_ctx->SetSamplerMipFilter( Sampler, Value );
  4969. break;
  4970. case D3DSAMP_MINFILTER:
  4971. m_ctx->SetSamplerMinFilter( Sampler, Value );
  4972. break;
  4973. case D3DSAMP_MIPMAPLODBIAS:
  4974. m_ctx->SetSamplerMipMapLODBias( Sampler, Value );
  4975. break;
  4976. case D3DSAMP_MAXMIPLEVEL:
  4977. m_ctx->SetSamplerMaxMipLevel( Sampler, Value);
  4978. break;
  4979. case D3DSAMP_MAXANISOTROPY:
  4980. m_ctx->SetSamplerMaxAnisotropy( Sampler, Value);
  4981. break;
  4982. case D3DSAMP_SRGBTEXTURE:
  4983. //m_samplers[ Sampler ].m_srgb = Value;
  4984. m_ctx->SetSamplerSRGBTexture(Sampler, Value);
  4985. break;
  4986. case D3DSAMP_SHADOWFILTER:
  4987. m_ctx->SetShadowFilter(Sampler, Value);
  4988. break;
  4989. default: DXABSTRACT_BREAK_ON_ERROR(); break;
  4990. }
  4991. return S_OK;
  4992. }
  4993. void IDirect3DDevice9::SetSamplerStatesNonInline(
  4994. DWORD Sampler, DWORD AddressU, DWORD AddressV, DWORD AddressW,
  4995. DWORD MinFilter, DWORD MagFilter, DWORD MipFilter )
  4996. {
  4997. GL_BATCH_PERF_CALL_TIMER;
  4998. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  4999. Assert( Sampler < GLM_SAMPLER_COUNT);
  5000. m_ctx->SetSamplerDirty( Sampler );
  5001. m_ctx->SetSamplerStates( Sampler, AddressU, AddressV, AddressW, MinFilter, MagFilter, MipFilter );
  5002. }
  5003. HRESULT IDirect3DDevice9::SetTextureNonInline(DWORD Stage,IDirect3DBaseTexture9* pTexture)
  5004. {
  5005. GL_BATCH_PERF_CALL_TIMER;
  5006. GL_PUBLIC_ENTRYPOINT_CHECKS( this );
  5007. Assert( Stage < GLM_SAMPLER_COUNT );
  5008. m_textures[Stage] = pTexture;
  5009. m_ctx->SetSamplerTex( Stage, pTexture ? pTexture->m_tex : NULL );
  5010. return S_OK;
  5011. }
  5012. // ------------------------------------------------------------------------------------------------------------------------------ //
  5013. void* ID3DXBuffer::GetBufferPointer()
  5014. {
  5015. GL_BATCH_PERF_CALL_TIMER;
  5016. DXABSTRACT_BREAK_ON_ERROR();
  5017. return NULL;
  5018. }
  5019. DWORD ID3DXBuffer::GetBufferSize()
  5020. {
  5021. GL_BATCH_PERF_CALL_TIMER;
  5022. DXABSTRACT_BREAK_ON_ERROR();
  5023. return 0;
  5024. }
  5025. #ifndef _MSC_VER
  5026. #pragma mark ----- More D3DX stuff
  5027. #endif
  5028. // ------------------------------------------------------------------------------------------------------------------------------ //
  5029. // D3DX stuff.
  5030. // ------------------------------------------------------------------------------------------------------------------------------ //
  5031. // matrix stack...
  5032. HRESULT D3DXCreateMatrixStack( DWORD Flags, LPD3DXMATRIXSTACK* ppStack)
  5033. {
  5034. *ppStack = new ID3DXMatrixStack;
  5035. (*ppStack)->Create();
  5036. return S_OK;
  5037. }
  5038. ID3DXMatrixStack::ID3DXMatrixStack( void )
  5039. {
  5040. m_refcount[0] = 1;
  5041. m_refcount[1] = 0;
  5042. };
  5043. void ID3DXMatrixStack::AddRef( int which, char *comment )
  5044. {
  5045. Assert( which >= 0 );
  5046. Assert( which < 2 );
  5047. m_refcount[which]++;
  5048. };
  5049. ULONG ID3DXMatrixStack::Release( int which, char *comment )
  5050. {
  5051. Assert( which >= 0 );
  5052. Assert( which < 2 );
  5053. bool deleting = false;
  5054. m_refcount[which]--;
  5055. if ( (!m_refcount[0]) && (!m_refcount[1]) )
  5056. {
  5057. deleting = true;
  5058. }
  5059. if (deleting)
  5060. {
  5061. if (m_mark)
  5062. {
  5063. GLMPRINTF(("")) ; // place to hang a breakpoint
  5064. }
  5065. delete this;
  5066. return 0;
  5067. }
  5068. else
  5069. {
  5070. return m_refcount[0];
  5071. }
  5072. };
  5073. HRESULT ID3DXMatrixStack::Create()
  5074. {
  5075. m_stack.EnsureCapacity( 16 ); // 1KB ish
  5076. m_stack.AddToTail();
  5077. m_stackTop = 0; // top of stack is at index 0 currently
  5078. LoadIdentity();
  5079. return S_OK;
  5080. }
  5081. D3DXMATRIX* ID3DXMatrixStack::GetTop()
  5082. {
  5083. return (D3DXMATRIX*)&m_stack[ m_stackTop ];
  5084. }
  5085. void ID3DXMatrixStack::Push()
  5086. {
  5087. D3DMATRIX temp = m_stack[ m_stackTop ];
  5088. m_stack.AddToTail( temp );
  5089. m_stackTop ++;
  5090. }
  5091. void ID3DXMatrixStack::Pop()
  5092. {
  5093. int elem = m_stackTop--;
  5094. m_stack.Remove( elem );
  5095. }
  5096. void ID3DXMatrixStack::LoadIdentity()
  5097. {
  5098. D3DXMATRIX *mat = GetTop();
  5099. D3DXMatrixIdentity( mat );
  5100. }
  5101. void ID3DXMatrixStack::LoadMatrix( const D3DXMATRIX *pMat )
  5102. {
  5103. *(GetTop()) = *pMat;
  5104. }
  5105. void ID3DXMatrixStack::MultMatrix( const D3DXMATRIX *pMat )
  5106. {
  5107. // http://msdn.microsoft.com/en-us/library/bb174057(VS.85).aspx
  5108. // This method right-multiplies the given matrix to the current matrix
  5109. // (transformation is about the current world origin).
  5110. // m_pstack[m_currentPos] = m_pstack[m_currentPos] * (*pMat);
  5111. // This method does not add an item to the stack, it replaces the current
  5112. // matrix with the product of the current matrix and the given matrix.
  5113. DXABSTRACT_BREAK_ON_ERROR();
  5114. }
  5115. void ID3DXMatrixStack::MultMatrixLocal( const D3DXMATRIX *pMat )
  5116. {
  5117. // http://msdn.microsoft.com/en-us/library/bb174058(VS.85).aspx
  5118. // This method left-multiplies the given matrix to the current matrix
  5119. // (transformation is about the local origin of the object).
  5120. // m_pstack[m_currentPos] = (*pMat) * m_pstack[m_currentPos];
  5121. // This method does not add an item to the stack, it replaces the current
  5122. // matrix with the product of the given matrix and the current matrix.
  5123. DXABSTRACT_BREAK_ON_ERROR();
  5124. }
  5125. HRESULT ID3DXMatrixStack::ScaleLocal(FLOAT x, FLOAT y, FLOAT z)
  5126. {
  5127. // http://msdn.microsoft.com/en-us/library/bb174066(VS.85).aspx
  5128. // Scale the current matrix about the object origin.
  5129. // This method left-multiplies the current matrix with the computed
  5130. // scale matrix. The transformation is about the local origin of the object.
  5131. //
  5132. // D3DXMATRIX tmp;
  5133. // D3DXMatrixScaling(&tmp, x, y, z);
  5134. // m_stack[m_currentPos] = tmp * m_stack[m_currentPos];
  5135. DXABSTRACT_BREAK_ON_ERROR();
  5136. return S_OK;
  5137. }
  5138. HRESULT ID3DXMatrixStack::RotateAxisLocal(CONST D3DXVECTOR3* pV, FLOAT Angle)
  5139. {
  5140. // http://msdn.microsoft.com/en-us/library/bb174062(VS.85).aspx
  5141. // Left multiply the current matrix with the computed rotation
  5142. // matrix, counterclockwise about the given axis with the given angle.
  5143. // (rotation is about the local origin of the object)
  5144. // D3DXMATRIX tmp;
  5145. // D3DXMatrixRotationAxis( &tmp, pV, angle );
  5146. // m_stack[m_currentPos] = tmp * m_stack[m_currentPos];
  5147. // Because the rotation is left-multiplied to the matrix stack, the rotation
  5148. // is relative to the object's local coordinate space.
  5149. DXABSTRACT_BREAK_ON_ERROR();
  5150. return S_OK;
  5151. }
  5152. HRESULT ID3DXMatrixStack::TranslateLocal(FLOAT x, FLOAT y, FLOAT z)
  5153. {
  5154. // http://msdn.microsoft.com/en-us/library/bb174068(VS.85).aspx
  5155. // Left multiply the current matrix with the computed translation
  5156. // matrix. (transformation is about the local origin of the object)
  5157. // D3DXMATRIX tmp;
  5158. // D3DXMatrixTranslation( &tmp, x, y, z );
  5159. // m_stack[m_currentPos] = tmp * m_stack[m_currentPos];
  5160. DXABSTRACT_BREAK_ON_ERROR();
  5161. return S_OK;
  5162. }
  5163. const char* D3DXGetPixelShaderProfile( IDirect3DDevice9 *pDevice )
  5164. {
  5165. DXABSTRACT_BREAK_ON_ERROR();
  5166. return "";
  5167. }
  5168. #ifdef _MSC_VER
  5169. #pragma warning (push)
  5170. #pragma warning (disable:4701) // potentially uninitialized local variable 'temp' used
  5171. #endif
  5172. D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 )
  5173. {
  5174. D3DXMATRIX temp;
  5175. for( int i=0; i<4; i++)
  5176. {
  5177. for( int j=0; j<4; j++)
  5178. {
  5179. temp.m[i][j] = (pM1->m[ i ][ 0 ] * pM2->m[ 0 ][ j ])
  5180. + (pM1->m[ i ][ 1 ] * pM2->m[ 1 ][ j ])
  5181. + (pM1->m[ i ][ 2 ] * pM2->m[ 2 ][ j ])
  5182. + (pM1->m[ i ][ 3 ] * pM2->m[ 3 ][ j ]);
  5183. }
  5184. }
  5185. *pOut = temp;
  5186. return pOut;
  5187. }
  5188. #ifdef _MSC_VER
  5189. #pragma warning(pop)
  5190. #endif
  5191. // Transform a 3D vector by a given matrix, projecting the result back into w = 1
  5192. // http://msdn.microsoft.com/en-us/library/ee417622(VS.85).aspx
  5193. D3DXVECTOR3* D3DXVec3TransformCoord(D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM)
  5194. {
  5195. D3DXVECTOR3 vOut;
  5196. vOut.x = vOut.y = vOut.z = 0.0f;
  5197. float norm = (pM->m[0][3] * pV->x) + (pM->m[1][3] * pV->y) + (pM->m[2][3] *pV->z) + pM->m[3][3];
  5198. if ( norm )
  5199. {
  5200. vOut.x = (pM->m[0][0] * pV->x + pM->m[1][0] * pV->y + pM->m[2][0] * pV->z + pM->m[3][0]) / norm;
  5201. vOut.y = (pM->m[0][1] * pV->x + pM->m[1][1] * pV->y + pM->m[2][1] * pV->z + pM->m[3][1]) / norm;
  5202. vOut.z = (pM->m[0][2] * pV->x + pM->m[1][2] * pV->y + pM->m[2][2] * pV->z + pM->m[3][2]) / norm;
  5203. }
  5204. *pOut = vOut;
  5205. return pOut;
  5206. }
  5207. void D3DXMatrixIdentity( D3DXMATRIX *mat )
  5208. {
  5209. for( int i=0; i<4; i++)
  5210. {
  5211. for( int j=0; j<4; j++)
  5212. {
  5213. mat->m[i][j] = (i==j) ? 1.0f : 0.0f; // 1's on the diagonal.
  5214. }
  5215. }
  5216. }
  5217. D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z )
  5218. {
  5219. D3DXMatrixIdentity( pOut );
  5220. pOut->m[3][0] = x;
  5221. pOut->m[3][1] = y;
  5222. pOut->m[3][2] = z;
  5223. return pOut;
  5224. }
  5225. D3DXMATRIX* D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM )
  5226. {
  5227. Assert( sizeof( D3DXMATRIX ) == (16 * sizeof(float) ) );
  5228. Assert( sizeof( VMatrix ) == (16 * sizeof(float) ) );
  5229. Assert( pDeterminant == NULL ); // homey don't play that
  5230. VMatrix *origM = (VMatrix*)pM;
  5231. VMatrix *destM = (VMatrix*)pOut;
  5232. bool success = MatrixInverseGeneral( *origM, *destM ); (void)success;
  5233. Assert( success );
  5234. return pOut;
  5235. }
  5236. D3DXMATRIX* D3DXMatrixTranspose( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM )
  5237. {
  5238. if (pOut != pM)
  5239. {
  5240. for( int i=0; i<4; i++)
  5241. {
  5242. for( int j=0; j<4; j++)
  5243. {
  5244. pOut->m[i][j] = pM->m[j][i];
  5245. }
  5246. }
  5247. }
  5248. else
  5249. {
  5250. D3DXMATRIX temp = *pM;
  5251. D3DXMatrixTranspose( pOut, &temp );
  5252. }
  5253. return NULL;
  5254. }
  5255. D3DXPLANE* D3DXPlaneNormalize( D3DXPLANE *pOut, CONST D3DXPLANE *pP)
  5256. {
  5257. // not very different from normalizing a vector.
  5258. // figure out the square root of the sum-of-squares of the x,y,z components
  5259. // make sure that's non zero
  5260. // then divide all four components by that value
  5261. // or return some dummy plane like 0,0,1,0 if it fails
  5262. float len = sqrt( (pP->a * pP->a) + (pP->b * pP->b) + (pP->c * pP->c) );
  5263. if (len > 1e-10) //FIXME need a real epsilon here ?
  5264. {
  5265. pOut->a = pP->a / len; pOut->b = pP->b / len; pOut->c = pP->c / len; pOut->d = pP->d / len;
  5266. }
  5267. else
  5268. {
  5269. pOut->a = 0.0f; pOut->b = 0.0f; pOut->c = 1.0f; pOut->d = 0.0f;
  5270. }
  5271. return pOut;
  5272. }
  5273. D3DXVECTOR4* D3DXVec4Transform( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM )
  5274. {
  5275. VMatrix *mat = (VMatrix*)pM;
  5276. Vector4D *vIn = (Vector4D*)pV;
  5277. Vector4D *vOut = (Vector4D*)pOut;
  5278. Vector4DMultiplyTranspose( *mat, *vIn, *vOut );
  5279. return pOut;
  5280. }
  5281. D3DXVECTOR4* D3DXVec4Normalize( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV )
  5282. {
  5283. Vector4D *vIn = (Vector4D*) pV;
  5284. Vector4D *vOut = (Vector4D*) pOut;
  5285. *vOut = *vIn;
  5286. Vector4DNormalize( *vOut );
  5287. return pOut;
  5288. }
  5289. D3DXMATRIX* D3DXMatrixOrthoOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn,FLOAT zf )
  5290. {
  5291. DXABSTRACT_BREAK_ON_ERROR();
  5292. return NULL;
  5293. }
  5294. D3DXMATRIX* D3DXMatrixPerspectiveRH( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf )
  5295. {
  5296. DXABSTRACT_BREAK_ON_ERROR();
  5297. return NULL;
  5298. }
  5299. D3DXMATRIX* D3DXMatrixPerspectiveOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf )
  5300. {
  5301. DXABSTRACT_BREAK_ON_ERROR();
  5302. return NULL;
  5303. }
  5304. D3DXPLANE* D3DXPlaneTransform( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM )
  5305. {
  5306. float *out = &pOut->a;
  5307. // dot dot dot
  5308. for( int x=0; x<4; x++ )
  5309. {
  5310. out[x] = (pM->m[0][x] * pP->a)
  5311. + (pM->m[1][x] * pP->b)
  5312. + (pM->m[2][x] * pP->c)
  5313. + (pM->m[3][x] * pP->d);
  5314. }
  5315. return pOut;
  5316. }
  5317. // ------------------------------------------------------------------------------------------------------------------------------ //
  5318. IDirect3D9 *Direct3DCreate9(UINT SDKVersion)
  5319. {
  5320. GLMPRINTF(( "-X- Direct3DCreate9: %d", SDKVersion ));
  5321. return new IDirect3D9;
  5322. }
  5323. // ------------------------------------------------------------------------------------------------------------------------------ //
  5324. void D3DPERF_SetOptions( DWORD dwOptions )
  5325. {
  5326. }
  5327. HRESULT D3DXCompileShader(
  5328. LPCSTR pSrcData,
  5329. UINT SrcDataLen,
  5330. CONST D3DXMACRO* pDefines,
  5331. LPD3DXINCLUDE pInclude,
  5332. LPCSTR pFunctionName,
  5333. LPCSTR pProfile,
  5334. DWORD Flags,
  5335. LPD3DXBUFFER* ppShader,
  5336. LPD3DXBUFFER* ppErrorMsgs,
  5337. LPD3DXCONSTANTTABLE* ppConstantTable)
  5338. {
  5339. DXABSTRACT_BREAK_ON_ERROR(); // is anyone calling this ?
  5340. return S_OK;
  5341. }
  5342. #if defined(DX_TO_GL_ABSTRACTION)
  5343. void toglGetClientRect( void *hWnd, RECT *destRect )
  5344. {
  5345. // the only useful answer this call can offer, is the size of the canvas.
  5346. // actually getting the window bounds is not useful.
  5347. // so, see if a D3D device is up and running, and if so,
  5348. // dig in and find out its backbuffer size and use that.
  5349. uint width, height;
  5350. g_pLauncherMgr->RenderedSize( width, height, false ); // false = get them, don't set them
  5351. Assert( width!=0 && height!=0 );
  5352. destRect->left = 0;
  5353. destRect->top = 0;
  5354. destRect->right = width;
  5355. destRect->bottom = height;
  5356. //GLMPRINTF(( "-D- GetClientRect returning rect of (0,0, %d,%d)",width,height ));
  5357. return;
  5358. }
  5359. #endif
  5360. #endif