Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6845 lines
204 KiB

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