Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5762 lines
183 KiB

  1. //================ Copyright (c) 1996-2009 Valve Corporation. All Rights Reserved. =================
  2. //
  3. //
  4. //
  5. //==================================================================================================
  6. #include "dxabstract.h"
  7. #include "tier0/platform.h"
  8. #include "tier0/dbg.h"
  9. #include "tier0/threadtools.h"
  10. #include <stdarg.h>
  11. #include "tier1/strtools.h"
  12. #include "tier1/utlbuffer.h"
  13. //#include "dx9asmtogl.h"
  14. #include "dx9asmtogl2.h"
  15. #include "mathlib/vmatrix.h"
  16. #ifdef OSX
  17. #include "glmgr/glmgr.h"
  18. #include "appframework/icocoamgr.h"
  19. extern ICocoaMgr *g_extCocoaMgr;
  20. #include <Carbon/Carbon.h>
  21. #endif
  22. #include "tier0/icommandline.h"
  23. #include "tier0/memdbgon.h"
  24. #ifdef USE_ACTUAL_DX
  25. #pragma comment( lib, "../../dx9sdk/lib/d3d9.lib" )
  26. #pragma comment( lib, "../../dx9sdk/lib/d3dx9.lib" )
  27. #else
  28. #ifdef POSIX
  29. #define strcat_s( a, b, c) V_strcat( a, c, b )
  30. #endif
  31. // ------------------------------------------------------------------------------------------------------------------------------ //
  32. bool g_useASMTranslations = true;
  33. //static D3DToGL_ASM g_D3DToOpenGLTranslatorASM; // old translator retired
  34. static D3DToGL g_D3DToOpenGLTranslatorASM; // same class as the GLSL one, just invoked with different options
  35. bool g_useGLSLTranslations = true;
  36. static D3DToGL g_D3DToOpenGLTranslatorGLSL;
  37. bool g_bUseControlFlow = false;
  38. // ------------------------------------------------------------------------------------------------------------------------------ //
  39. void GlobalMemoryStatus( MEMORYSTATUS *pOut )
  40. {
  41. //cheese: return 2GB physical
  42. pOut->dwTotalPhys = (1<<31);
  43. }
  44. void Sleep( unsigned int ms )
  45. {
  46. Debugger();
  47. ThreadSleep( ms );
  48. }
  49. bool IsIconic( VD3DHWND hWnd )
  50. {
  51. // FIXME for now just act non-minimized all the time
  52. //Debugger();
  53. return false;
  54. }
  55. void GetClientRect( void *hWnd, RECT *destRect )
  56. {
  57. // the only useful answer this call can offer, is the size of the canvas.
  58. // actually getting the window bounds is not useful.
  59. // so, see if a D3D device is up and running, and if so,
  60. // dig in and find out its backbuffer size and use that.
  61. uint width, height;
  62. g_extCocoaMgr->RenderedSize( width, height, false ); // false = get them, don't set them
  63. Assert( width!=0 && height!=0 );
  64. destRect->left = 0;
  65. destRect->top = 0;
  66. destRect->right = width;
  67. destRect->bottom = height;
  68. //GLMPRINTF(( "-D- GetClientRect returning rect of (0,0, %d,%d)",width,height ));
  69. return;
  70. }
  71. BOOL ClientToScreen( VD3DHWND hWnd, LPPOINT pPoint )
  72. {
  73. Debugger();
  74. return true;
  75. }
  76. void* GetCurrentThread()
  77. {
  78. Debugger();
  79. return 0;
  80. }
  81. void SetThreadAffinityMask( void *hThread, int nMask )
  82. {
  83. Debugger();
  84. }
  85. bool GUID::operator==( const struct _GUID &other ) const
  86. {
  87. Debugger();
  88. return memcmp( this, &other, sizeof( GUID ) ) == 0;
  89. }
  90. // ------------------------------------------------------------------------------------------------------------------------------ //
  91. #pragma mark ----- D3DXMATRIX operators
  92. D3DXMATRIX D3DXMATRIX::operator*( const D3DXMATRIX &o ) const
  93. {
  94. D3DXMATRIX result;
  95. D3DXMatrixMultiply( &result, this, &o ); // this = lhs o = rhs result = this * o
  96. return result;
  97. }
  98. D3DXMATRIX::operator FLOAT* ()
  99. {
  100. return (float*)this;
  101. }
  102. float& D3DXMATRIX::operator()( int row, int column )
  103. {
  104. return m[row][column];
  105. }
  106. const float& D3DXMATRIX::operator()( int row, int column ) const
  107. {
  108. return m[row][column];
  109. }
  110. // ------------------------------------------------------------------------------------------------------------------------------ //
  111. #pragma mark ----- D3DXPLANE operators
  112. float& D3DXPLANE::operator[]( int i )
  113. {
  114. return ((float*)this)[i];
  115. }
  116. bool D3DXPLANE::operator==( const D3DXPLANE &o )
  117. {
  118. return a == o.a && b == o.b && c == o.c && d == o.d;
  119. }
  120. bool D3DXPLANE::operator!=( const D3DXPLANE &o )
  121. {
  122. return !( *this == o );
  123. }
  124. D3DXPLANE::operator float*()
  125. {
  126. return (float*)this;
  127. }
  128. D3DXPLANE::operator const float*() const
  129. {
  130. return (const float*)this;
  131. }
  132. // ------------------------------------------------------------------------------------------------------------------------------ //
  133. #pragma mark ----- D3DXVECTOR2 operators
  134. D3DXVECTOR2::operator FLOAT* ()
  135. {
  136. return (float*)this;
  137. }
  138. D3DXVECTOR2::operator CONST FLOAT* () const
  139. {
  140. return (const float*)this;
  141. }
  142. // ------------------------------------------------------------------------------------------------------------------------------ //
  143. #pragma mark ----- D3DXVECTOR3 operators
  144. D3DXVECTOR3::D3DXVECTOR3( float a, float b, float c )
  145. {
  146. x = a;
  147. y = b;
  148. z = c;
  149. }
  150. D3DXVECTOR3::operator FLOAT* ()
  151. {
  152. return (float*)this;
  153. }
  154. D3DXVECTOR3::operator CONST FLOAT* () const
  155. {
  156. return (const float*)this;
  157. }
  158. // ------------------------------------------------------------------------------------------------------------------------------ //
  159. #pragma mark ----- D3DXVECTOR4 operators
  160. D3DXVECTOR4::D3DXVECTOR4( float a, float b, float c, float d )
  161. {
  162. x = a;
  163. y = b;
  164. z = c;
  165. w = d;
  166. }
  167. // ------------------------------------------------------------------------------------------------------------------------------ //
  168. DWORD IDirect3DResource9::SetPriority(DWORD PriorityNew)
  169. {
  170. // Debugger();
  171. // GLMPRINTF(( "-X- SetPriority" ));
  172. // no-op city
  173. return 0;
  174. }
  175. // ------------------------------------------------------------------------------------------------------------------------------ //
  176. #pragma mark ----- IDirect3DBaseTexture9
  177. IDirect3DBaseTexture9::~IDirect3DBaseTexture9()
  178. {
  179. GLMPRINTF(( ">-A- ~IDirect3DBaseTexture9" ));
  180. if (m_device)
  181. {
  182. GLMPRINTF(( "-A- ~IDirect3DBaseTexture9 taking normal delete path on %08x, device is %08x ", this, m_device ));
  183. m_device->ReleasedTexture( this );
  184. if (m_tex)
  185. {
  186. 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 : "" ));
  187. m_tex->m_ctx->DelTex( m_tex );
  188. m_tex = NULL;
  189. }
  190. else
  191. {
  192. GLMPRINTF(( "-A- ~IDirect3DBaseTexture9 : whoops, no tex to delete here ?" ));
  193. }
  194. m_device = NULL; // ** THIS ** is the only place to scrub this. Don't do it in the subclass destructors.
  195. }
  196. else
  197. {
  198. GLMPRINTF(( "-A- ~IDirect3DBaseTexture9 taking strange delete path on %08x, device is %08x ", this, m_device ));
  199. }
  200. GLMPRINTF(( "<-A- ~IDirect3DBaseTexture9" ));
  201. }
  202. D3DRESOURCETYPE IDirect3DBaseTexture9::GetType()
  203. {
  204. return m_restype; //D3DRTYPE_TEXTURE;
  205. }
  206. DWORD IDirect3DBaseTexture9::GetLevelCount()
  207. {
  208. return m_tex->m_layout->m_mipCount;
  209. }
  210. HRESULT IDirect3DBaseTexture9::GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc)
  211. {
  212. Assert (Level < m_tex->m_layout->m_mipCount);
  213. D3DSURFACE_DESC result = m_descZero;
  214. // then mutate it for the level of interest
  215. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( 0, Level ) ];
  216. result.Width = slice->m_xSize;
  217. result.Height = slice->m_ySize;
  218. *pDesc = result;
  219. return S_OK;
  220. }
  221. // ------------------------------------------------------------------------------------------------------------------------------ //
  222. #pragma mark ----- IDirect3DTexture9
  223. HRESULT IDirect3DDevice9::CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,VD3DHANDLE* pSharedHandle, char *pDebugLabel )
  224. {
  225. GLMPRINTF((">-A-IDirect3DDevice9::CreateTexture"));
  226. IDirect3DTexture9 *dxtex = new IDirect3DTexture9;
  227. dxtex->m_restype = D3DRTYPE_TEXTURE;
  228. dxtex->m_device = this;
  229. dxtex->m_descZero.Format = Format;
  230. dxtex->m_descZero.Type = D3DRTYPE_TEXTURE;
  231. dxtex->m_descZero.Usage = Usage;
  232. dxtex->m_descZero.Pool = Pool;
  233. dxtex->m_descZero.MultiSampleType = D3DMULTISAMPLE_NONE;
  234. dxtex->m_descZero.MultiSampleQuality = 0;
  235. dxtex->m_descZero.Width = Width;
  236. dxtex->m_descZero.Height = Height;
  237. GLMTexLayoutKey key;
  238. memset( &key, 0, sizeof(key) );
  239. key.m_texGLTarget = GL_TEXTURE_2D;
  240. key.m_texFormat = Format;
  241. if (Levels>1)
  242. {
  243. key.m_texFlags |= kGLMTexMipped;
  244. }
  245. // http://msdn.microsoft.com/en-us/library/bb172625(VS.85).aspx
  246. // complain if any usage bits come down that I don't know.
  247. uint knownUsageBits = (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_DYNAMIC | D3DUSAGE_TEXTURE_SRGB | D3DUSAGE_DEPTHSTENCIL);
  248. if ( ( Usage & knownUsageBits ) != Usage )
  249. {
  250. GLMDebugger();
  251. }
  252. if ( Usage & D3DUSAGE_AUTOGENMIPMAP )
  253. {
  254. key.m_texFlags |= kGLMTexMipped | kGLMTexMippedAuto;
  255. }
  256. if ( Usage & D3DUSAGE_DYNAMIC )
  257. {
  258. // GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME
  259. }
  260. if ( Usage & D3DUSAGE_TEXTURE_SRGB )
  261. {
  262. key.m_texFlags |= kGLMTexSRGB;
  263. }
  264. if ( Usage & D3DUSAGE_RENDERTARGET )
  265. {
  266. Assert( !(Usage & D3DUSAGE_DEPTHSTENCIL) );
  267. key.m_texFlags |= kGLMTexRenderable;
  268. key.m_texFlags |= kGLMTexSRGB; // this catches callers of CreateTexture who set the "renderable" option - they get an SRGB tex
  269. if (m_ctx->Caps().m_cantAttachSRGB)
  270. {
  271. // this config can't support SRGB render targets. quietly turn off the sRGB bit.
  272. key.m_texFlags &= ~kGLMTexSRGB;
  273. }
  274. }
  275. key.m_xSize = Width;
  276. key.m_ySize = Height;
  277. key.m_zSize = 1;
  278. CGLMTex *tex = m_ctx->NewTex( &key, pDebugLabel );
  279. if ( !tex )
  280. {
  281. GLMDebugger();
  282. }
  283. dxtex->m_tex = tex;
  284. dxtex->m_srgbFlipCount = 0;
  285. dxtex->m_surfZero = new IDirect3DSurface9;
  286. dxtex->m_surfZero->m_restype = (D3DRESOURCETYPE)0; // this is a ref to a tex, not the owner...
  287. // do not do an AddRef here.
  288. dxtex->m_surfZero->m_device = this;
  289. dxtex->m_surfZero->m_desc = dxtex->m_descZero;
  290. dxtex->m_surfZero->m_tex = tex;
  291. dxtex->m_surfZero->m_face = 0;
  292. dxtex->m_surfZero->m_mip = 0;
  293. GLMPRINTF(("-A- IDirect3DDevice9::CreateTexture created '%s' @ %08x (GLM %08x) %s",tex->m_layout->m_layoutSummary, dxtex, tex, pDebugLabel ? pDebugLabel : "" ));
  294. *ppTexture = dxtex;
  295. GLMPRINTF(("<-A-IDirect3DDevice9::CreateTexture"));
  296. return S_OK;
  297. }
  298. IDirect3DTexture9::~IDirect3DTexture9()
  299. {
  300. GLMPRINTF(( ">-A- IDirect3DTexture9" ));
  301. // IDirect3DBaseTexture9::~IDirect3DBaseTexture9 frees up m_tex
  302. // we take care of surfZero
  303. if (m_device)
  304. {
  305. m_device->ReleasedTexture( this );
  306. if (m_surfZero)
  307. {
  308. ULONG refc = m_surfZero->Release( 0, "~IDirect3DTexture9 public release (surfZero)" );
  309. Assert( !refc );
  310. m_surfZero = NULL;
  311. }
  312. // leave m_device alone!
  313. }
  314. GLMPRINTF(( "<-A- IDirect3DTexture9" ));
  315. }
  316. HRESULT IDirect3DTexture9::LockRect(UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags)
  317. {
  318. Debugger();
  319. return S_OK;
  320. }
  321. HRESULT IDirect3DTexture9::UnlockRect(UINT Level)
  322. {
  323. Debugger();
  324. return S_OK;
  325. }
  326. HRESULT IDirect3DTexture9::GetSurfaceLevel(UINT Level,IDirect3DSurface9** ppSurfaceLevel)
  327. {
  328. // we create and pass back a surface, and the client is on the hook to release it. tidy.
  329. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  330. surf->m_restype = (D3DRESOURCETYPE)0; // 0 is special and means this 'surface' does not own its m_tex
  331. // Dicey...higher level code seems to want this and not want this. Are we missing some AddRef/Release behavior elsewhere?
  332. // surf->AddRef();
  333. surf->m_device = this->m_device;
  334. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( 0, Level ) ];
  335. surf->m_desc = m_descZero;
  336. surf->m_desc.Width = slice->m_xSize;
  337. surf->m_desc.Height = slice->m_ySize;
  338. surf->m_tex = m_tex;
  339. surf->m_face = 0;
  340. surf->m_mip = Level;
  341. *ppSurfaceLevel = surf;
  342. return S_OK;
  343. }
  344. // ------------------------------------------------------------------------------------------------------------------------------ //
  345. #pragma mark ----- IDirect3DCubeTexture9
  346. HRESULT IDirect3DDevice9::CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,VD3DHANDLE* pSharedHandle, char *pDebugLabel)
  347. {
  348. GLMPRINTF((">-A- IDirect3DDevice9::CreateCubeTexture"));
  349. IDirect3DCubeTexture9 *dxtex = new IDirect3DCubeTexture9;
  350. dxtex->m_restype = D3DRTYPE_CUBETEXTURE;
  351. dxtex->m_device = this;
  352. dxtex->m_descZero.Format = Format;
  353. dxtex->m_descZero.Type = D3DRTYPE_CUBETEXTURE;
  354. dxtex->m_descZero.Usage = Usage;
  355. dxtex->m_descZero.Pool = Pool;
  356. dxtex->m_descZero.MultiSampleType = D3DMULTISAMPLE_NONE;
  357. dxtex->m_descZero.MultiSampleQuality = 0;
  358. dxtex->m_descZero.Width = EdgeLength;
  359. dxtex->m_descZero.Height = EdgeLength;
  360. GLMTexLayoutKey key;
  361. memset( &key, 0, sizeof(key) );
  362. key.m_texGLTarget = GL_TEXTURE_CUBE_MAP;
  363. key.m_texFormat = Format;
  364. if (Levels>1)
  365. {
  366. key.m_texFlags |= kGLMTexMipped;
  367. }
  368. // http://msdn.microsoft.com/en-us/library/bb172625(VS.85).aspx
  369. // complain if any usage bits come down that I don't know.
  370. uint knownUsageBits = (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_DYNAMIC | D3DUSAGE_TEXTURE_SRGB);
  371. if ( (Usage & knownUsageBits) != Usage )
  372. {
  373. GLMDebugger();
  374. }
  375. if (Usage & D3DUSAGE_AUTOGENMIPMAP)
  376. {
  377. key.m_texFlags |= kGLMTexMipped | kGLMTexMippedAuto;
  378. }
  379. if (Usage & D3DUSAGE_RENDERTARGET)
  380. {
  381. key.m_texFlags |= kGLMTexRenderable;
  382. }
  383. if (Usage & D3DUSAGE_DYNAMIC)
  384. {
  385. //GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME
  386. }
  387. if (Usage & D3DUSAGE_TEXTURE_SRGB)
  388. {
  389. key.m_texFlags |= kGLMTexSRGB;
  390. }
  391. key.m_xSize = EdgeLength;
  392. key.m_ySize = EdgeLength;
  393. key.m_zSize = 1;
  394. CGLMTex *tex = m_ctx->NewTex( &key, pDebugLabel );
  395. if (!tex)
  396. {
  397. GLMDebugger();
  398. }
  399. dxtex->m_tex = tex;
  400. dxtex->m_srgbFlipCount = 0;
  401. for( int face = 0; face < 6; face ++)
  402. {
  403. dxtex->m_surfZero[face] = new IDirect3DSurface9;
  404. dxtex->m_surfZero[face]->m_restype = (D3DRESOURCETYPE)0; // 0 is special and means this 'surface' does not own its m_tex
  405. // do not do an AddRef here.
  406. dxtex->m_surfZero[face]->m_device = this;
  407. dxtex->m_surfZero[face]->m_desc = dxtex->m_descZero;
  408. dxtex->m_surfZero[face]->m_tex = tex;
  409. dxtex->m_surfZero[face]->m_face = face;
  410. dxtex->m_surfZero[face]->m_mip = 0;
  411. }
  412. GLMPRINTF(("-A- IDirect3DDevice9::CreateCubeTexture created '%s' @ %08x (GLM %08x)",tex->m_layout->m_layoutSummary, dxtex, tex ));
  413. *ppCubeTexture = dxtex;
  414. GLMPRINTF(("<-A- IDirect3DDevice9::CreateCubeTexture"));
  415. return S_OK;
  416. }
  417. IDirect3DCubeTexture9::~IDirect3DCubeTexture9()
  418. {
  419. GLMPRINTF(( ">-A- ~IDirect3DCubeTexture9" ));
  420. if (m_device)
  421. {
  422. GLMPRINTF(( "-A- ~IDirect3DCubeTexture9 taking normal delete path on %08x, device is %08x, surfzero[0] is %08x ", this, m_device, m_surfZero[0] ));
  423. m_device->ReleasedTexture( this );
  424. // let IDirect3DBaseTexture9::~IDirect3DBaseTexture9 free up m_tex
  425. // we handle the surfZero array for the faces
  426. for( int face = 0; face < 6; face ++)
  427. {
  428. if (m_surfZero[face])
  429. {
  430. Assert( m_surfZero[face]->m_device = m_device );
  431. ULONG refc = m_surfZero[face]->Release( 0, "~IDirect3DCubeTexture9 public release (surfZero)");
  432. if ( refc!=0 )
  433. {
  434. GLMPRINTF(( "-A- ~IDirect3DCubeTexture9 seeing non zero refcount on surfzero[%d] => %d ", face, refc ));
  435. }
  436. m_surfZero[face] = NULL;
  437. }
  438. }
  439. // leave m_device alone!
  440. }
  441. else
  442. {
  443. GLMPRINTF(( "-A- ~IDirect3DCubeTexture9 taking strange delete path on %08x, device is %08x, surfzero[0] is %08x ", this, m_device, m_surfZero[0] ));
  444. }
  445. GLMPRINTF(( "<-A- ~IDirect3DCubeTexture9" ));
  446. }
  447. HRESULT IDirect3DCubeTexture9::GetCubeMapSurface(D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface)
  448. {
  449. // we create and pass back a surface, and the client is on the hook to release it...
  450. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  451. surf->m_restype = (D3DRESOURCETYPE)0; // 0 is special and means this 'surface' does not own its m_tex
  452. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( FaceType, Level ) ];
  453. surf->m_device = this->m_device;
  454. surf->m_desc = m_descZero;
  455. surf->m_desc.Width = slice->m_xSize;
  456. surf->m_desc.Height = slice->m_ySize;
  457. surf->m_tex = m_tex;
  458. surf->m_face = FaceType;
  459. surf->m_mip = Level;
  460. *ppCubeMapSurface = surf;
  461. return S_OK;
  462. }
  463. HRESULT IDirect3DCubeTexture9::GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc)
  464. {
  465. Assert (Level < m_tex->m_layout->m_mipCount);
  466. D3DSURFACE_DESC result = m_descZero;
  467. // then mutate it for the level of interest
  468. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( 0, Level ) ];
  469. result.Width = slice->m_xSize;
  470. result.Height = slice->m_ySize;
  471. *pDesc = result;
  472. return S_OK;
  473. }
  474. // ------------------------------------------------------------------------------------------------------------------------------ //
  475. #pragma mark ----- IDirect3DVolumeTexture9
  476. HRESULT IDirect3DDevice9::CreateVolumeTexture(UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,VD3DHANDLE* pSharedHandle, char *pDebugLabel)
  477. {
  478. GLMPRINTF((">-A- IDirect3DDevice9::CreateVolumeTexture"));
  479. // set dxtex->m_restype to D3DRTYPE_VOLUMETEXTURE...
  480. IDirect3DVolumeTexture9 *dxtex = new IDirect3DVolumeTexture9;
  481. dxtex->m_restype = D3DRTYPE_VOLUMETEXTURE;
  482. dxtex->m_device = this;
  483. dxtex->m_descZero.Format = Format;
  484. dxtex->m_descZero.Type = D3DRTYPE_VOLUMETEXTURE;
  485. dxtex->m_descZero.Usage = Usage;
  486. dxtex->m_descZero.Pool = Pool;
  487. dxtex->m_descZero.MultiSampleType = D3DMULTISAMPLE_NONE;
  488. dxtex->m_descZero.MultiSampleQuality = 0;
  489. dxtex->m_descZero.Width = Width;
  490. dxtex->m_descZero.Height = Height;
  491. // also a volume specific desc
  492. dxtex->m_volDescZero.Format = Format;
  493. dxtex->m_volDescZero.Type = D3DRTYPE_VOLUMETEXTURE;
  494. dxtex->m_volDescZero.Usage = Usage;
  495. dxtex->m_volDescZero.Pool = Pool;
  496. dxtex->m_volDescZero.Width = Width;
  497. dxtex->m_volDescZero.Height = Height;
  498. dxtex->m_volDescZero.Depth = Depth;
  499. GLMTexLayoutKey key;
  500. memset( &key, 0, sizeof(key) );
  501. key.m_texGLTarget = GL_TEXTURE_3D;
  502. key.m_texFormat = Format;
  503. if (Levels>1)
  504. {
  505. key.m_texFlags |= kGLMTexMipped;
  506. }
  507. // http://msdn.microsoft.com/en-us/library/bb172625(VS.85).aspx
  508. // complain if any usage bits come down that I don't know.
  509. uint knownUsageBits = (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_DYNAMIC | D3DUSAGE_TEXTURE_SRGB);
  510. if ( (Usage & knownUsageBits) != Usage )
  511. {
  512. Debugger();
  513. }
  514. if (Usage & D3DUSAGE_AUTOGENMIPMAP)
  515. {
  516. key.m_texFlags |= kGLMTexMipped | kGLMTexMippedAuto;
  517. }
  518. if (Usage & D3DUSAGE_RENDERTARGET)
  519. {
  520. key.m_texFlags |= kGLMTexRenderable;
  521. }
  522. if (Usage & D3DUSAGE_DYNAMIC)
  523. {
  524. GLMPRINTF(("-X- DYNAMIC tex usage ignored..")); //FIXME
  525. }
  526. if (Usage & D3DUSAGE_TEXTURE_SRGB)
  527. {
  528. key.m_texFlags |= kGLMTexSRGB;
  529. }
  530. key.m_xSize = Width;
  531. key.m_ySize = Height;
  532. key.m_zSize = Depth;
  533. CGLMTex *tex = m_ctx->NewTex( &key, pDebugLabel );
  534. if (!tex)
  535. {
  536. Debugger();
  537. }
  538. dxtex->m_tex = tex;
  539. dxtex->m_srgbFlipCount = 0;
  540. dxtex->m_surfZero = new IDirect3DSurface9;
  541. dxtex->m_surfZero->m_restype = (D3DRESOURCETYPE)0; // this is a ref to a tex, not the owner...
  542. // do not do an AddRef here.
  543. dxtex->m_surfZero->m_device = this;
  544. dxtex->m_surfZero->m_desc = dxtex->m_descZero;
  545. dxtex->m_surfZero->m_tex = tex;
  546. dxtex->m_surfZero->m_face = 0;
  547. dxtex->m_surfZero->m_mip = 0;
  548. GLMPRINTF(("-A- IDirect3DDevice9::CreateVolumeTexture created '%s' @ %08x (GLM %08x)",tex->m_layout->m_layoutSummary, dxtex, tex ));
  549. *ppVolumeTexture = dxtex;
  550. GLMPRINTF(("<-A- IDirect3DDevice9::CreateVolumeTexture"));
  551. return S_OK;
  552. }
  553. IDirect3DVolumeTexture9::~IDirect3DVolumeTexture9()
  554. {
  555. GLMPRINTF((">-A- ~IDirect3DVolumeTexture9"));
  556. if (m_device)
  557. {
  558. m_device->ReleasedTexture( this );
  559. // let IDirect3DBaseTexture9::~IDirect3DBaseTexture9 free up m_tex
  560. // we handle m_surfZero
  561. if (m_surfZero)
  562. {
  563. ULONG refc = m_surfZero->Release( 0, "~IDirect3DVolumeTexture9 public release (surfZero)" );
  564. Assert( !refc );
  565. m_surfZero = NULL;
  566. }
  567. // leave m_device alone!
  568. }
  569. GLMPRINTF(("<-A- ~IDirect3DVolumeTexture9"));
  570. }
  571. HRESULT IDirect3DVolumeTexture9::LockBox(UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags)
  572. {
  573. GLMTexLockParams lockreq;
  574. memset( &lockreq, 0, sizeof(lockreq) );
  575. lockreq.m_tex = this->m_tex;
  576. lockreq.m_face = 0;
  577. lockreq.m_mip = Level;
  578. lockreq.m_region.xmin = pBox->Left;
  579. lockreq.m_region.ymin = pBox->Top;
  580. lockreq.m_region.zmin = pBox->Front;
  581. lockreq.m_region.xmax = pBox->Right;
  582. lockreq.m_region.ymax = pBox->Bottom;
  583. lockreq.m_region.zmax = pBox->Back;
  584. char *lockAddress;
  585. int yStride;
  586. int zStride;
  587. lockreq.m_tex->Lock( &lockreq, &lockAddress, &yStride, &zStride );
  588. pLockedVolume->RowPitch = yStride;
  589. pLockedVolume->SlicePitch = yStride;
  590. pLockedVolume->pBits = lockAddress;
  591. return S_OK;
  592. }
  593. HRESULT IDirect3DVolumeTexture9::UnlockBox(UINT Level)
  594. {
  595. GLMTexLockParams lockreq;
  596. memset( &lockreq, 0, sizeof(lockreq) );
  597. lockreq.m_tex = this->m_tex;
  598. lockreq.m_face = 0;
  599. lockreq.m_mip = Level;
  600. this->m_tex->Unlock( &lockreq );
  601. return S_OK;
  602. }
  603. HRESULT IDirect3DVolumeTexture9::GetLevelDesc( UINT Level, D3DVOLUME_DESC *pDesc )
  604. {
  605. if (Level > m_tex->m_layout->m_mipCount)
  606. {
  607. Debugger();
  608. }
  609. D3DVOLUME_DESC result = m_volDescZero;
  610. // then mutate it for the level of interest
  611. GLMTexLayoutSlice *slice = &m_tex->m_layout->m_slices[ m_tex->CalcSliceIndex( 0, Level ) ];
  612. result.Width = slice->m_xSize;
  613. result.Height = slice->m_ySize;
  614. result.Depth = slice->m_zSize;
  615. *pDesc = result;
  616. return S_OK;
  617. }
  618. // ------------------------------------------------------------------------------------------------------------------------------ //
  619. #pragma mark ----- IDirect3DSurface9
  620. IDirect3DSurface9::~IDirect3DSurface9()
  621. {
  622. // not much to do here, but good to verify that these things are being freed (and they are)
  623. //GLMPRINTF(("-A- ~IDirect3DSurface9 - signpost"));
  624. if (m_device)
  625. {
  626. GLMPRINTF(("-A- ~IDirect3DSurface9 - taking real delete path on %08x device %08x", this, m_device));
  627. m_device->ReleasedSurface( this );
  628. memset( &m_desc, 0, sizeof(m_desc) );
  629. if (m_restype != 0) // signal that we are a surface that owns this tex (render target)
  630. {
  631. if (m_tex)
  632. {
  633. 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 : "" ));
  634. m_tex->m_ctx->DelTex( m_tex );
  635. m_tex = NULL;
  636. }
  637. else
  638. {
  639. GLMPRINTF(( "-A- ~IDirect3DSurface9 : whoops, no tex to delete here ?" ));
  640. }
  641. }
  642. else
  643. {
  644. m_tex = NULL; // we are just a view on the tex, we don't own the tex, do not delete it
  645. }
  646. m_face = m_mip = 0;
  647. m_device = NULL;
  648. }
  649. else
  650. {
  651. GLMPRINTF(("-A- ~IDirect3DSurface9 - taking strange delete path on %08x device %08x", this, m_device));
  652. }
  653. }
  654. HRESULT IDirect3DSurface9::LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags)
  655. {
  656. GLMTexLockParams lockreq;
  657. memset( &lockreq, 0, sizeof(lockreq) );
  658. lockreq.m_tex = this->m_tex;
  659. lockreq.m_face = this->m_face;
  660. lockreq.m_mip = this->m_mip;
  661. lockreq.m_region.xmin = pRect->left;
  662. lockreq.m_region.ymin = pRect->top;
  663. lockreq.m_region.zmin = 0;
  664. lockreq.m_region.xmax = pRect->right;
  665. lockreq.m_region.ymax = pRect->bottom;
  666. lockreq.m_region.zmax = 1;
  667. if ((Flags & (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)) == (D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK) )
  668. {
  669. // smells like readback, force texel readout
  670. lockreq.m_readback = true;
  671. }
  672. char *lockAddress;
  673. int yStride;
  674. int zStride;
  675. lockreq.m_tex->Lock( &lockreq, &lockAddress, &yStride, &zStride );
  676. pLockedRect->Pitch = yStride;
  677. pLockedRect->pBits = lockAddress;
  678. return S_OK;
  679. }
  680. HRESULT IDirect3DSurface9::UnlockRect()
  681. {
  682. GLMTexLockParams lockreq;
  683. memset( &lockreq, 0, sizeof(lockreq) );
  684. lockreq.m_tex = this->m_tex;
  685. lockreq.m_face = this->m_face;
  686. lockreq.m_mip = this->m_mip;
  687. lockreq.m_tex->Unlock( &lockreq );
  688. return S_OK;
  689. }
  690. HRESULT IDirect3DSurface9::GetDesc(D3DSURFACE_DESC *pDesc)
  691. {
  692. *pDesc = m_desc;
  693. return S_OK;
  694. }
  695. // ------------------------------------------------------------------------------------------------------------------------------ //
  696. #pragma mark ----- IDirect3D9 -------------------------------------------------------
  697. IDirect3D9::~IDirect3D9()
  698. {
  699. GLMPRINTF(("-A- ~IDirect3D9 - signpost"));
  700. }
  701. UINT IDirect3D9::GetAdapterCount()
  702. {
  703. GLMgr::NewGLMgr(); // init GL manager
  704. GLMDisplayDB *db = g_extCocoaMgr->GetDisplayDB();
  705. int dxAdapterCount = db->GetFakeAdapterCount();
  706. return dxAdapterCount;
  707. }
  708. HRESULT IDirect3D9::GetDeviceCaps(UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps)
  709. {
  710. // Generally called from "CShaderDeviceMgrDx8::ComputeCapsFromD3D" in ShaderDeviceDX8.cpp
  711. // "Adapter" is used to index amongst the set of fake-adapters maintained in the display DB
  712. GLMDisplayDB *db = g_extCocoaMgr->GetDisplayDB();
  713. int glmRendererIndex = -1;
  714. int glmDisplayIndex = -1;
  715. GLMRendererInfoFields glmRendererInfo;
  716. GLMDisplayInfoFields glmDisplayInfo;
  717. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  718. Assert (!result);
  719. // just leave glmRendererInfo filled out for subsequent code to look at as needed.
  720. // fill in the pCaps record for adapter... we zero most of it and just fill in the fields that we think the caller wants.
  721. Q_memset( pCaps, 0, sizeof(*pCaps) );
  722. /* Device Info */
  723. pCaps->DeviceType = D3DDEVTYPE_HAL;
  724. /* Caps from DX7 Draw */
  725. pCaps->Caps = 0; // does anyone look at this ?
  726. pCaps->Caps2 = D3DCAPS2_DYNAMICTEXTURES;
  727. /* Cursor Caps */
  728. pCaps->CursorCaps = 0; // nobody looks at this
  729. /* 3D Device Caps */
  730. pCaps->DevCaps = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
  731. pCaps->TextureCaps = D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_MIPCUBEMAP | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PROJECTED;
  732. // D3DPTEXTURECAPS_NOPROJECTEDBUMPENV ?
  733. // D3DPTEXTURECAPS_POW2 ?
  734. // caller looks at POT support like this:
  735. // pCaps->m_SupportsNonPow2Textures =
  736. // ( !( caps.TextureCaps & D3DPTEXTURECAPS_POW2 ) ||
  737. // ( caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL ) );
  738. // so we should set D3DPTEXTURECAPS_NONPOW2CONDITIONAL bit ?
  739. pCaps->PrimitiveMiscCaps = 0; //only the HDR setup looks at this for D3DPMISCCAPS_SEPARATEALPHABLEND.
  740. // ? D3DPMISCCAPS_SEPARATEALPHABLEND
  741. // ? D3DPMISCCAPS_BLENDOP
  742. // ? D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
  743. // ? D3DPMISCCAPS_CLIPTLVERTS D3DPMISCCAPS_COLORWRITEENABLE D3DPMISCCAPS_MASKZ D3DPMISCCAPS_TSSARGTEMP
  744. pCaps->RasterCaps = D3DPRASTERCAPS_SCISSORTEST
  745. | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS // ref'd in CShaderDeviceMgrDx8::ComputeCapsFromD3D
  746. | D3DPRASTERCAPS_DEPTHBIAS // ref'd in CShaderDeviceMgrDx8::ComputeCapsFromD3D
  747. ;
  748. pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MAGFANISOTROPIC;
  749. pCaps->MaxTextureWidth = 4096;
  750. pCaps->MaxTextureHeight = 4096;
  751. pCaps->MaxVolumeExtent = 1024; //guesses
  752. pCaps->MaxTextureAspectRatio = 0; // imply no limit on AR
  753. pCaps->MaxAnisotropy = glmRendererInfo.m_maxAniso;
  754. pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_MODULATE2X; //guess
  755. DWORD MaxTextureBlendStages;
  756. DWORD MaxSimultaneousTextures;
  757. pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN_SPHEREMAP;
  758. pCaps->MaxActiveLights = 8; // guess
  759. // MaxUserClipPlanes. A bit complicated..
  760. // it's difficult to make this fluid without teaching the engine about a cap that could change during run.
  761. // start it out set to '2'.
  762. // turn it off, if we're in GLSL mode but do not have native clip plane capability.
  763. pCaps->MaxUserClipPlanes = 2; // assume good news
  764. // is user asking for it to be off ?
  765. if ( CommandLine()->CheckParm( "-nouserclip" ) )
  766. {
  767. pCaps->MaxUserClipPlanes = 0;
  768. }
  769. g_bUseControlFlow = CommandLine()->CheckParm( "-glslcontrolflow" );
  770. // are we ARB mode and not forcing GLSL control flow mode?
  771. if ( CommandLine()->CheckParm( "-arbmode" ) && !g_bUseControlFlow )
  772. {
  773. pCaps->MaxUserClipPlanes = 0;
  774. }
  775. pCaps->MaxVertexBlendMatrices = 0; // see if anyone cares
  776. pCaps->MaxVertexBlendMatrixIndex = 0; // see if anyone cares
  777. pCaps->MaxPrimitiveCount = 32768; // guess
  778. pCaps->MaxStreams = 4; // guess
  779. pCaps->VertexShaderVersion = 0x200; // model 2.0
  780. pCaps->MaxVertexShaderConst = DXABSTRACT_VS_PARAM_SLOTS; // number of vertex shader constant registers
  781. pCaps->PixelShaderVersion = 0x200; // model 2.0
  782. // Here are the DX9 specific ones
  783. pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET;
  784. pCaps->PS20Caps.NumInstructionSlots = 512; // guess
  785. // only examined once:
  786. // pCaps->m_SupportsPixelShaders_2_b = ( ( caps.PixelShaderVersion & 0xffff ) >= 0x0200) && (caps.PS20Caps.NumInstructionSlots >= 512);
  787. //pCaps->m_SupportsPixelShaders_2_b = 1;
  788. pCaps->NumSimultaneousRTs = 1; // Will be at least 1
  789. pCaps->MaxVertexShader30InstructionSlots = 0;
  790. pCaps->MaxPixelShader30InstructionSlots = 0;
  791. #if ( defined ( POSIX ) && !defined( _PS3 ) )
  792. pCaps->FakeSRGBWrite = !glmRendererInfo.m_hasGammaWrites;
  793. pCaps->CanDoSRGBReadFromRTs = !glmRendererInfo.m_cantAttachSRGB;
  794. pCaps->MixedSizeTargets = glmRendererInfo.m_hasMixedAttachmentSizes;
  795. pCaps->SRGBDecode = glmRendererInfo.m_hasSRGBDecode;
  796. #endif
  797. return S_OK;
  798. }
  799. HRESULT IDirect3D9::GetAdapterIdentifier( UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier )
  800. {
  801. // Generally called from "CShaderDeviceMgrDx8::ComputeCapsFromD3D" in ShaderDeviceDX8.cpp
  802. Assert( Flags == D3DENUM_WHQL_LEVEL ); // we're not handling any other queries than this yet
  803. Q_memset( pIdentifier, 0, sizeof(*pIdentifier) );
  804. GLMDisplayDB *db = g_extCocoaMgr->GetDisplayDB();
  805. int glmRendererIndex = -1;
  806. int glmDisplayIndex = -1;
  807. GLMRendererInfoFields glmRendererInfo;
  808. GLMDisplayInfoFields glmDisplayInfo;
  809. // the D3D "Adapter" number feeds the fake adapter index
  810. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  811. Assert (!result);
  812. Q_snprintf( pIdentifier->Driver, sizeof(pIdentifier->Driver), "OpenGL %s (%08x)",
  813. GLMDecode( eGL_RENDERER, glmRendererInfo.m_rendererID & 0x00FFFF00 ),
  814. glmRendererInfo.m_rendererID
  815. );
  816. Q_snprintf( pIdentifier->Description, sizeof(pIdentifier->Description), "%s - %dx%d - %dMB VRAM",
  817. GLMDecode( eGL_RENDERER, glmRendererInfo.m_rendererID & 0x00FFFF00 ),
  818. glmDisplayInfo.m_displayPixelWidth, glmDisplayInfo.m_displayPixelHeight,
  819. glmRendererInfo.m_vidMemory >> 20 );
  820. pIdentifier->VendorId = glmRendererInfo.m_pciVendorID; // 4318;
  821. pIdentifier->DeviceId = glmRendererInfo.m_pciDeviceID; // 401;
  822. pIdentifier->SubSysId = 0; // 3358668866;
  823. pIdentifier->Revision = 0; // 162;
  824. pIdentifier->VideoMemory = glmRendererInfo.m_vidMemory; // amount of video memory in bytes
  825. #if 0
  826. // this came from the shaderapigl effort
  827. Q_strncpy( pIdentifier->Driver, "Fake-Video-Card", MAX_DEVICE_IDENTIFIER_STRING );
  828. Q_strncpy( pIdentifier->Description, "Fake-Video-Card", MAX_DEVICE_IDENTIFIER_STRING );
  829. pIdentifier->VendorId = 4318;
  830. pIdentifier->DeviceId = 401;
  831. pIdentifier->SubSysId = 3358668866;
  832. pIdentifier->Revision = 162;
  833. #endif
  834. return S_OK;
  835. }
  836. HRESULT IDirect3D9::CheckDeviceFormat(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat)
  837. {
  838. if (0) // hush for now, less spew
  839. {
  840. 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",
  841. Adapter,
  842. DeviceType, GLMDecode(eD3D_DEVTYPE, DeviceType),
  843. AdapterFormat, GLMDecode(eD3D_FORMAT, AdapterFormat),
  844. RType, GLMDecode(eD3D_RTYPE, RType),
  845. CheckFormat, GLMDecode(eD3D_FORMAT, CheckFormat),
  846. Usage, GLMDecodeMask( eD3D_USAGE, Usage ) ));
  847. }
  848. HRESULT result = D3DERR_NOTAVAILABLE; // failure
  849. DWORD knownUsageMask = D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP
  850. | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
  851. | D3DUSAGE_QUERY_VERTEXTEXTURE;
  852. // FramebufferSRGB stuff.
  853. // basically a format is only allowed to have SRGB usage for writing, if you have the framebuffer SRGB extension.
  854. // 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.
  855. GLMDisplayDB *db = g_extCocoaMgr->GetDisplayDB();
  856. int glmRendererIndex = -1;
  857. int glmDisplayIndex = -1;
  858. GLMRendererInfoFields glmRendererInfo;
  859. GLMDisplayInfoFields glmDisplayInfo;
  860. bool dbresult = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  861. Assert (!dbresult);
  862. Assert ((Usage & knownUsageMask) == Usage);
  863. DWORD legalUsage = 0;
  864. switch( AdapterFormat )
  865. {
  866. case D3DFMT_X8R8G8B8:
  867. switch( RType )
  868. {
  869. case D3DRTYPE_TEXTURE:
  870. switch( CheckFormat )
  871. {
  872. case D3DFMT_DXT1:
  873. case D3DFMT_DXT3:
  874. case D3DFMT_DXT5:
  875. legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  876. legalUsage |= D3DUSAGE_QUERY_SRGBREAD;
  877. //open question: is auto gen of mipmaps is allowed or attempted on any DXT textures.
  878. break;
  879. case D3DFMT_A8R8G8B8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  880. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  881. break;
  882. case D3DFMT_R32F: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  883. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  884. break;
  885. case D3DFMT_A16B16G16R16:
  886. legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  887. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  888. break;
  889. case D3DFMT_A16B16G16R16F: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE;
  890. if ( !glmRendererInfo.m_atiR5xx )
  891. {
  892. legalUsage |= D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  893. }
  894. break;
  895. case D3DFMT_A32B32G32R32F: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE;
  896. if ( !glmRendererInfo.m_atiR5xx && !glmRendererInfo.m_nvG7x )
  897. {
  898. legalUsage |= D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  899. }
  900. break;
  901. case D3DFMT_R5G6B5: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  902. break;
  903. //-----------------------------------------------------------
  904. // these come in from TestTextureFormat in ColorFormatDX8.cpp which is being driven by InitializeColorInformation...
  905. // which is going to try all 8 combinations of (vertex texturable / render targetable / filterable ) on every image format it knows.
  906. case D3DFMT_R8G8B8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  907. legalUsage |= D3DUSAGE_QUERY_SRGBREAD;
  908. break;
  909. case D3DFMT_X8R8G8B8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  910. legalUsage |= D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE;
  911. break;
  912. // one and two channel textures... we'll have to fake these as four channel tex if we want to support them
  913. case D3DFMT_L8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  914. break;
  915. case D3DFMT_A8L8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  916. break;
  917. case D3DFMT_A8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  918. break;
  919. // going to need to go back and double check all of these..
  920. case D3DFMT_X1R5G5B5: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  921. break;
  922. case D3DFMT_A4R4G4B4: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  923. break;
  924. case D3DFMT_A1R5G5B5: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  925. break;
  926. case D3DFMT_V8U8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  927. break;
  928. case D3DFMT_Q8W8V8U8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  929. // what the heck is QWVU8 ... ?
  930. break;
  931. case D3DFMT_X8L8V8U8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  932. // what the heck is XLVU8 ... ?
  933. break;
  934. // formats with depth...
  935. case D3DFMT_D16: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL;
  936. // just a guess on the legal usages
  937. break;
  938. case D3DFMT_D24S8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL;
  939. // just a guess on the legal usages
  940. break;
  941. // vendor formats... try marking these all invalid for now
  942. case D3DFMT_NV_INTZ:
  943. case D3DFMT_NV_RAWZ:
  944. case D3DFMT_NV_NULL:
  945. case D3DFMT_ATI_D16:
  946. case D3DFMT_ATI_D24S8:
  947. case D3DFMT_ATI_2N:
  948. case D3DFMT_ATI_1N:
  949. legalUsage = 0;
  950. break;
  951. //-----------------------------------------------------------
  952. default:
  953. Assert(!"Unknown check format");
  954. result = D3DERR_NOTAVAILABLE;
  955. break;
  956. }
  957. if ((Usage & legalUsage) == Usage)
  958. {
  959. result = S_OK;
  960. }
  961. else
  962. {
  963. DWORD unsatBits = Usage & (~legalUsage); // clear the bits of the req that were legal, leaving the illegal ones
  964. GLMPRINTF(( "-X- --> NOT OK: flags %8x:%s", unsatBits,GLMDecodeMask( eD3D_USAGE, unsatBits ) ));
  965. result = D3DERR_NOTAVAILABLE;
  966. }
  967. break;
  968. case D3DRTYPE_SURFACE:
  969. switch( CheckFormat )
  970. {
  971. case 0x434f5441:
  972. case 0x41415353:
  973. result = D3DERR_NOTAVAILABLE;
  974. break;
  975. case D3DFMT_D24S8:
  976. result = S_OK;
  977. break;
  978. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=434f5441:UNKNOWN
  979. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=41415353:UNKNOWN
  980. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=434f5441:UNKNOWN
  981. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=41415353:UNKNOWN
  982. }
  983. break;
  984. default:
  985. Assert(!"Unknown resource type");
  986. result = D3DERR_NOTAVAILABLE;
  987. break;
  988. }
  989. break;
  990. default:
  991. Assert(!"Unknown adapter format");
  992. result = D3DERR_NOTAVAILABLE;
  993. break;
  994. }
  995. return result;
  996. }
  997. UINT IDirect3D9::GetAdapterModeCount(UINT Adapter,D3DFORMAT Format)
  998. {
  999. GLMPRINTF(( "-X- IDirect3D9::GetAdapterModeCount: Adapter=%d || Format=%8x:%s", Adapter, Format, GLMDecode(eD3D_FORMAT, Format) ));
  1000. uint modeCount=0;
  1001. GLMDisplayDB *db = g_extCocoaMgr->GetDisplayDB();
  1002. int glmRendererIndex = -1;
  1003. int glmDisplayIndex = -1;
  1004. GLMRendererInfoFields glmRendererInfo;
  1005. GLMDisplayInfoFields glmDisplayInfo;
  1006. // the D3D "Adapter" number feeds the fake adapter index
  1007. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  1008. Assert (!result);
  1009. modeCount = db->GetModeCount( glmRendererIndex, glmDisplayIndex );
  1010. GLMPRINTF(( "-X- --> result is %d", modeCount ));
  1011. return modeCount + 1; // Add one on for 800 x 500, which we'll tack on as mode 0 below
  1012. }
  1013. HRESULT IDirect3D9::EnumAdapterModes( UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode )
  1014. {
  1015. GLMPRINTF(( "-X- IDirect3D9::EnumAdapterModes: Adapter=%d || Format=%8x:%s || Mode=%d", Adapter, Format, GLMDecode(eD3D_FORMAT, Format), Mode ));
  1016. Assert(Format==D3DFMT_X8R8G8B8);
  1017. GLMDisplayDB *db = g_extCocoaMgr->GetDisplayDB();
  1018. int glmRendererIndex = -1;
  1019. int glmDisplayIndex = -1;
  1020. GLMRendererInfoFields glmRendererInfo;
  1021. GLMDisplayInfoFields glmDisplayInfo;
  1022. GLMDisplayModeInfoFields glmModeInfo;
  1023. // The D3D "Adapter" number feeds the fake adapter index
  1024. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  1025. Assert ( !result );
  1026. if ( result )
  1027. return D3DERR_NOTAVAILABLE;
  1028. bool result2 = db->GetModeInfo( glmRendererIndex, glmDisplayIndex, Mode == 0 ? 0 : Mode - 1, &glmModeInfo ); // End up asking Cocoa for mode zero twice
  1029. Assert( !result2 );
  1030. if ( result2 )
  1031. return D3DERR_NOTAVAILABLE;
  1032. pMode->Width = Mode == 0 ? 800 : glmModeInfo.m_modePixelWidth; // substitute in width of 800 on first "Mode zero"
  1033. pMode->Height = Mode == 0 ? 500 : glmModeInfo.m_modePixelHeight; // substitute in height of 500 on first "Mode zero"
  1034. pMode->RefreshRate = glmModeInfo.m_modeRefreshHz; // "adapter default"
  1035. pMode->Format = Format; // whatever you asked for ?
  1036. GLMPRINTF(( "-X- IDirect3D9::EnumAdapterModes returning mode size (%d,%d) and D3DFMT_X8R8G8B8", pMode->Width, pMode->Height ));
  1037. return S_OK;
  1038. }
  1039. HRESULT IDirect3D9::CheckDeviceType(UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed)
  1040. {
  1041. //FIXME: we just say "OK" on any query
  1042. GLMPRINTF(( "-X- IDirect3D9::CheckDeviceType: Adapter=%d || DevType=%d:%s || AdapterFormat=%d:%s || BackBufferFormat=%d:%s || bWindowed=%d",
  1043. Adapter,
  1044. DevType, GLMDecode(eD3D_DEVTYPE,DevType),
  1045. AdapterFormat, GLMDecode(eD3D_FORMAT, AdapterFormat),
  1046. BackBufferFormat, GLMDecode(eD3D_FORMAT, BackBufferFormat),
  1047. (int) bWindowed ));
  1048. return S_OK;
  1049. }
  1050. HRESULT IDirect3D9::GetAdapterDisplayMode(UINT Adapter,D3DDISPLAYMODE* pMode)
  1051. {
  1052. // asking what the current mode is
  1053. GLMPRINTF(("-X- IDirect3D9::GetAdapterDisplayMode: Adapter=%d", Adapter ));
  1054. GLMDisplayDB *db = g_extCocoaMgr->GetDisplayDB();
  1055. int glmRendererIndex = -1;
  1056. int glmDisplayIndex = -1;
  1057. GLMRendererInfoFields glmRendererInfo;
  1058. GLMDisplayInfoFields glmDisplayInfo;
  1059. GLMDisplayModeInfoFields glmModeInfo;
  1060. // the D3D "Adapter" number feeds the fake adapter index
  1061. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  1062. Assert(!result);
  1063. if (result) return D3DERR_INVALIDCALL;
  1064. int modeIndex = -1; // pass -1 as a mode index to find out about whatever the current mode is on the selected display
  1065. bool modeResult = db->GetModeInfo( glmRendererIndex, glmDisplayIndex, modeIndex, &glmModeInfo );
  1066. Assert (!modeResult);
  1067. if (modeResult) return D3DERR_INVALIDCALL;
  1068. pMode->Width = glmModeInfo.m_modePixelWidth;
  1069. pMode->Height = glmModeInfo.m_modePixelHeight;
  1070. pMode->RefreshRate = glmModeInfo.m_modeRefreshHz; // "adapter default"
  1071. pMode->Format = D3DFMT_X8R8G8B8; //FIXME, this is a SWAG
  1072. return S_OK;
  1073. }
  1074. HRESULT IDirect3D9::CheckDepthStencilMatch(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat)
  1075. {
  1076. GLMPRINTF(("-X- IDirect3D9::CheckDepthStencilMatch: Adapter=%d || DevType=%d:%s || AdapterFormat=%d:%s || RenderTargetFormat=%d:%s || DepthStencilFormat=%d:%s",
  1077. Adapter,
  1078. DeviceType, GLMDecode(eD3D_DEVTYPE,DeviceType),
  1079. AdapterFormat, GLMDecode(eD3D_FORMAT, AdapterFormat),
  1080. RenderTargetFormat, GLMDecode(eD3D_FORMAT, RenderTargetFormat),
  1081. DepthStencilFormat, GLMDecode(eD3D_FORMAT, DepthStencilFormat) ));
  1082. // one known request looks like this:
  1083. // AdapterFormat=5:D3DFMT_X8R8G8B8 || RenderTargetFormat=3:D3DFMT_A8R8G8B8 || DepthStencilFormat=2:D3DFMT_D24S8
  1084. // return S_OK for that one combo, Debugger() on anything else
  1085. HRESULT result = D3DERR_NOTAVAILABLE; // failure
  1086. switch( AdapterFormat )
  1087. {
  1088. case D3DFMT_X8R8G8B8:
  1089. {
  1090. if ( (RenderTargetFormat == D3DFMT_A8R8G8B8) && (DepthStencilFormat == D3DFMT_D24S8) )
  1091. {
  1092. result = S_OK;
  1093. }
  1094. }
  1095. break;
  1096. }
  1097. Assert( result == S_OK );
  1098. return result;
  1099. }
  1100. HRESULT IDirect3D9::CheckDeviceMultiSampleType( UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels )
  1101. {
  1102. GLMDisplayDB *db = g_extCocoaMgr->GetDisplayDB();
  1103. int glmRendererIndex = -1;
  1104. int glmDisplayIndex = -1;
  1105. GLMRendererInfoFields glmRendererInfo;
  1106. GLMDisplayInfoFields glmDisplayInfo;
  1107. GLMDisplayModeInfoFields glmModeInfo;
  1108. // the D3D "Adapter" number feeds the fake adapter index
  1109. bool result = db->GetFakeAdapterInfo( Adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  1110. Assert( !result );
  1111. if ( result )
  1112. return D3DERR_INVALIDCALL;
  1113. if ( !CommandLine()->FindParm("-glmenabletrustmsaa") )
  1114. {
  1115. // These ghetto drivers don't get MSAA
  1116. if ( ( glmRendererInfo.m_nvG7x || glmRendererInfo.m_atiR5xx ) && ( MultiSampleType > D3DMULTISAMPLE_NONE ) )
  1117. {
  1118. if ( pQualityLevels )
  1119. {
  1120. *pQualityLevels = 0;
  1121. }
  1122. return D3DERR_NOTAVAILABLE;
  1123. }
  1124. }
  1125. switch ( MultiSampleType )
  1126. {
  1127. case D3DMULTISAMPLE_NONE: // always return true
  1128. if ( pQualityLevels )
  1129. {
  1130. *pQualityLevels = 1;
  1131. }
  1132. return S_OK;
  1133. break;
  1134. case D3DMULTISAMPLE_2_SAMPLES:
  1135. case D3DMULTISAMPLE_4_SAMPLES:
  1136. case D3DMULTISAMPLE_6_SAMPLES:
  1137. case D3DMULTISAMPLE_8_SAMPLES:
  1138. // note the fact that the d3d enums for 2, 4, 6, 8 samples are equal to 2,4,6,8...
  1139. if (glmRendererInfo.m_maxSamples >= (int)MultiSampleType )
  1140. {
  1141. if ( pQualityLevels )
  1142. {
  1143. *pQualityLevels = 1;
  1144. }
  1145. return S_OK;
  1146. }
  1147. else
  1148. {
  1149. return D3DERR_NOTAVAILABLE;
  1150. }
  1151. break;
  1152. default:
  1153. if ( pQualityLevels )
  1154. {
  1155. *pQualityLevels = 0;
  1156. }
  1157. return D3DERR_NOTAVAILABLE;
  1158. break;
  1159. }
  1160. return D3DERR_NOTAVAILABLE;
  1161. }
  1162. HRESULT IDirect3D9::CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,VD3DHWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface)
  1163. {
  1164. // constrain these inputs for the time being
  1165. // BackBufferFormat -> A8R8G8B8
  1166. // BackBufferCount -> 1;
  1167. // MultiSampleType -> D3DMULTISAMPLE_NONE
  1168. // AutoDepthStencilFormat -> D3DFMT_D24S8
  1169. // NULL out the return pointer so if we exit early it is not set
  1170. *ppReturnedDeviceInterface = NULL;
  1171. // assume success unless something is sour
  1172. HRESULT result = S_OK;
  1173. // relax this check for now
  1174. //if (pPresentationParameters->BackBufferFormat != D3DFMT_A8R8G8B8)
  1175. //{
  1176. // Debugger();
  1177. // result = -1;
  1178. //}
  1179. //rbarris 24Aug10 - relaxing this check - we don't care if the game asks for two backbuffers, it's moot
  1180. //if ( pPresentationParameters->BackBufferCount != 1 )
  1181. //{
  1182. // Debugger();
  1183. // result = D3DERR_NOTAVAILABLE;
  1184. //}
  1185. if ( pPresentationParameters->AutoDepthStencilFormat != D3DFMT_D24S8 )
  1186. {
  1187. Debugger();
  1188. result = D3DERR_NOTAVAILABLE;
  1189. }
  1190. if ( result == S_OK )
  1191. {
  1192. // create an IDirect3DDevice9
  1193. // it will make a GLMContext and set up some drawables
  1194. IDirect3DDevice9Params devparams;
  1195. memset( &devparams, 0, sizeof(devparams) );
  1196. devparams.m_adapter = Adapter;
  1197. devparams.m_deviceType = DeviceType;
  1198. devparams.m_focusWindow = hFocusWindow; // is this meaningful? is this a WindowRef ? follow it up the chain..
  1199. devparams.m_behaviorFlags = BehaviorFlags;
  1200. devparams.m_presentationParameters = *pPresentationParameters;
  1201. IDirect3DDevice9 *dev = new IDirect3DDevice9;
  1202. result = dev->Create( &devparams );
  1203. if ( result == S_OK )
  1204. {
  1205. *ppReturnedDeviceInterface = dev;
  1206. }
  1207. }
  1208. return result;
  1209. }
  1210. // ------------------------------------------------------------------------------------------------------------------------------ //
  1211. #pragma mark ----- IDirect3DQuery9
  1212. HRESULT IDirect3DQuery9::Issue(DWORD dwIssueFlags)
  1213. {
  1214. // Flags field for Issue
  1215. // #define D3DISSUE_END (1 << 0) // Tells the runtime to issue the end of a query, changing it's state to "non-signaled".
  1216. // #define D3DISSUE_BEGIN (1 << 1) // Tells the runtime to issue the beginng of a query.
  1217. if (dwIssueFlags & D3DISSUE_BEGIN)
  1218. {
  1219. switch( m_type )
  1220. {
  1221. case D3DQUERYTYPE_OCCLUSION:
  1222. m_query->Start(); // drop "start counter" call into stream
  1223. break;
  1224. default:
  1225. Assert(!"Can't use D3DISSUE_BEGIN on this query");
  1226. break;
  1227. }
  1228. }
  1229. if (dwIssueFlags & D3DISSUE_END)
  1230. {
  1231. switch( m_type )
  1232. {
  1233. case D3DQUERYTYPE_OCCLUSION:
  1234. m_query->Stop(); // drop "end counter" call into stream
  1235. break;
  1236. case D3DQUERYTYPE_EVENT:
  1237. // End is very weird with respect to Events (fences).
  1238. // DX9 docs say to use End to put the fence in the stream. So we map End to GLM's Start.
  1239. // http://msdn.microsoft.com/en-us/library/ee422167(VS.85).aspx
  1240. m_query->Start(); // drop "set fence" into stream
  1241. break;
  1242. }
  1243. }
  1244. return S_OK;
  1245. }
  1246. HRESULT IDirect3DQuery9::GetData(void* pData,DWORD dwSize,DWORD dwGetDataFlags)
  1247. {
  1248. HRESULT result = -1;
  1249. // GetData is not always called with the flush bit.
  1250. // if an answer is not yet available - return S_FALSE.
  1251. // if an answer is available - return S_OK and write the answer into *pData.
  1252. bool done = false;
  1253. bool flush = (dwGetDataFlags & D3DGETDATA_FLUSH) != 0; // aka spin until done
  1254. // hmmm both of these paths are the same, maybe we could fold them up
  1255. if ( !m_query->IsStarted() )
  1256. {
  1257. Assert(!"Can't GetData before issue/start");
  1258. printf("\n** IDirect3DQuery9::GetData: can't GetData before issue/start");
  1259. result = -1;
  1260. }
  1261. else if ( !m_query->IsStopped() )
  1262. {
  1263. Assert(!"Can't GetData before issue-end/stop");
  1264. printf("\n** IDirect3DQuery9::GetData: can't GetData before issue-end/stop");
  1265. result = -1;
  1266. }
  1267. else
  1268. {
  1269. switch( m_type )
  1270. {
  1271. case D3DQUERYTYPE_OCCLUSION:
  1272. {
  1273. // expectation - caller already did an issue begin (start) and an issue end (stop).
  1274. // we can probe using IsDone.
  1275. if (flush && (!m_ctx->Caps().m_hasPerfPackage1) )
  1276. {
  1277. glFlush();
  1278. }
  1279. do
  1280. {
  1281. done = m_query->IsDone();
  1282. if (done)
  1283. {
  1284. uint oqValue = 0; // or we could just pass pData directly to Complete...
  1285. m_query->Complete(&oqValue);
  1286. if (pData)
  1287. {
  1288. *(uint*)pData = oqValue;
  1289. }
  1290. result = S_OK;
  1291. }
  1292. else
  1293. {
  1294. result = S_FALSE;
  1295. }
  1296. } while( flush && (!done) );
  1297. }
  1298. break;
  1299. case D3DQUERYTYPE_EVENT:
  1300. {
  1301. // expectation - caller already did an issue end (for fence => start) but has not done anything that would call Stop.
  1302. // that's ok because Stop is a no-op for fences.
  1303. if (flush && (!m_ctx->Caps().m_hasPerfPackage1) )
  1304. {
  1305. glFlush();
  1306. }
  1307. done = m_query->IsDone();
  1308. if (done)
  1309. {
  1310. m_query->Complete(NULL); // this will block on pre-SLGU
  1311. *(uint*)pData = 0;
  1312. result = S_OK;
  1313. }
  1314. else
  1315. {
  1316. result = S_FALSE;
  1317. }
  1318. }
  1319. break;
  1320. }
  1321. }
  1322. return result;
  1323. }
  1324. // ------------------------------------------------------------------------------------------------------------------------------ //
  1325. #pragma mark ----- IDirect3DVertexBuffer9
  1326. HRESULT IDirect3DDevice9::CreateVertexBuffer(UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,VD3DHANDLE* pSharedHandle)
  1327. {
  1328. GLMPRINTF(( ">-A- IDirect3DDevice9::CreateVertexBuffer" ));
  1329. IDirect3DVertexBuffer9 *newbuff = new IDirect3DVertexBuffer9;
  1330. newbuff->m_device = this;
  1331. newbuff->m_ctx = m_ctx;
  1332. // FIXME need to find home or use for the Usage, FVF, Pool values passed in
  1333. uint options = 0;
  1334. if (Usage&D3DUSAGE_DYNAMIC)
  1335. {
  1336. options |= GLMBufferOptionDynamic;
  1337. }
  1338. newbuff->m_vtxBuffer = m_ctx->NewBuffer( kGLMVertexBuffer, Length, options ) ;
  1339. newbuff->m_vtxDesc.Type = D3DRTYPE_VERTEXBUFFER;
  1340. newbuff->m_vtxDesc.Usage = Usage;
  1341. newbuff->m_vtxDesc.Pool = Pool;
  1342. newbuff->m_vtxDesc.Size = Length;
  1343. *ppVertexBuffer = newbuff;
  1344. GLMPRINTF(( "<-A- IDirect3DDevice9::CreateVertexBuffer" ));
  1345. return S_OK;
  1346. }
  1347. IDirect3DVertexBuffer9::~IDirect3DVertexBuffer9()
  1348. {
  1349. GLMPRINTF(( ">-A- ~IDirect3DVertexBuffer9" ));
  1350. if (m_device)
  1351. {
  1352. m_device->ReleasedVertexBuffer( this );
  1353. if (m_ctx && m_vtxBuffer)
  1354. {
  1355. GLMPRINTF(( ">-A- ~IDirect3DVertexBuffer9 deleting m_vtxBuffer" ));
  1356. m_ctx->DelBuffer( m_vtxBuffer );
  1357. m_vtxBuffer = NULL;
  1358. GLMPRINTF(( "<-A- ~IDirect3DVertexBuffer9 deleting m_vtxBuffer - done" ));
  1359. }
  1360. m_device = NULL;
  1361. }
  1362. GLMPRINTF(( "<-A- ~IDirect3DVertexBuffer9" ));
  1363. }
  1364. HRESULT IDirect3DVertexBuffer9::Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags)
  1365. {
  1366. // FIXME would be good to have "can't lock twice" logic
  1367. Assert( !(Flags & D3DLOCK_READONLY) ); // not impl'd
  1368. // Assert( !(Flags & D3DLOCK_NOSYSLOCK) ); // not impl'd - it triggers though
  1369. GLMBuffLockParams lockreq;
  1370. lockreq.m_offset = OffsetToLock;
  1371. lockreq.m_size = SizeToLock;
  1372. lockreq.m_discard = (Flags & D3DLOCK_DISCARD) != 0;
  1373. lockreq.m_nonblocking = ( (Flags & D3DLOCK_NOOVERWRITE) != 0 ) || lockreq.m_discard;
  1374. m_vtxBuffer->Lock( &lockreq, (char**)ppbData );
  1375. GLMPRINTF(("-X- IDirect3DDevice9::Lock on D3D buf %p (GL name %d) offset %d, size %d => address %p", this, this->m_vtxBuffer->m_name, OffsetToLock, SizeToLock, *ppbData));
  1376. return S_OK;
  1377. }
  1378. HRESULT IDirect3DVertexBuffer9::Unlock()
  1379. {
  1380. m_vtxBuffer->Unlock();
  1381. return S_OK;
  1382. }
  1383. // ------------------------------------------------------------------------------------------------------------------------------ //
  1384. #pragma mark ----- IDirect3DIndexBuffer9
  1385. HRESULT IDirect3DDevice9::CreateIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,VD3DHANDLE* pSharedHandle)
  1386. {
  1387. GLMPRINTF(( ">-A- IDirect3DDevice9::CreateIndexBuffer" ));
  1388. // it is important to save all the create info, since GetDesc could get called later to query it
  1389. IDirect3DIndexBuffer9 *newbuff = new IDirect3DIndexBuffer9;
  1390. newbuff->m_device = this;
  1391. newbuff->m_restype = D3DRTYPE_INDEXBUFFER; // hmmmmmmm why are we not derived from d3dresource..
  1392. newbuff->m_ctx = m_ctx;
  1393. // FIXME need to find home or use for the Usage, Format, Pool values passed in
  1394. uint options = 0;
  1395. if (Usage&D3DUSAGE_DYNAMIC)
  1396. {
  1397. options |= GLMBufferOptionDynamic;
  1398. }
  1399. newbuff->m_idxBuffer = m_ctx->NewBuffer( kGLMIndexBuffer, Length, options ) ;
  1400. newbuff->m_idxDesc.Format = Format;
  1401. newbuff->m_idxDesc.Type = D3DRTYPE_INDEXBUFFER;
  1402. newbuff->m_idxDesc.Usage = Usage;
  1403. newbuff->m_idxDesc.Pool = Pool;
  1404. newbuff->m_idxDesc.Size = Length;
  1405. *ppIndexBuffer = newbuff;
  1406. GLMPRINTF(( "<-A- IDirect3DDevice9::CreateIndexBuffer" ));
  1407. return S_OK;
  1408. }
  1409. IDirect3DIndexBuffer9::~IDirect3DIndexBuffer9()
  1410. {
  1411. GLMPRINTF(( ">-A- ~IDirect3DIndexBuffer9" ));
  1412. if (m_device)
  1413. {
  1414. m_device->ReleasedIndexBuffer( this );
  1415. if (m_ctx && m_idxBuffer)
  1416. {
  1417. GLMPRINTF(( ">-A- ~IDirect3DIndexBuffer9 deleting m_idxBuffer" ));
  1418. m_ctx->DelBuffer( m_idxBuffer );
  1419. GLMPRINTF(( "<-A- ~IDirect3DIndexBuffer9 deleting m_idxBuffer - done" ));
  1420. }
  1421. m_device = NULL;
  1422. }
  1423. else
  1424. {
  1425. }
  1426. GLMPRINTF(( "<-A- ~IDirect3DIndexBuffer9" ));
  1427. }
  1428. HRESULT IDirect3DIndexBuffer9::Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags)
  1429. {
  1430. // FIXME would be good to have "can't lock twice" logic
  1431. GLMBuffLockParams lockreq;
  1432. lockreq.m_offset = OffsetToLock;
  1433. lockreq.m_size = SizeToLock;
  1434. lockreq.m_discard = (Flags & D3DLOCK_DISCARD) != 0;
  1435. lockreq.m_nonblocking = ( (Flags & D3DLOCK_NOOVERWRITE) != 0 ) || lockreq.m_discard;
  1436. m_idxBuffer->Lock( &lockreq, (char**)ppbData );
  1437. return S_OK;
  1438. }
  1439. HRESULT IDirect3DIndexBuffer9::Unlock()
  1440. {
  1441. m_idxBuffer->Unlock();
  1442. return S_OK;
  1443. }
  1444. HRESULT IDirect3DIndexBuffer9::GetDesc(D3DINDEXBUFFER_DESC *pDesc)
  1445. {
  1446. *pDesc = m_idxDesc;
  1447. return S_OK;
  1448. }
  1449. // ------------------------------------------------------------------------------------------------------------------------------ //
  1450. #pragma mark ----- IDirect3DDevice9 -------------------------------------------------
  1451. void ConvertPresentationParamsToGLMDisplayParams( D3DPRESENT_PARAMETERS *d3dp, GLMDisplayParams *gldp )
  1452. {
  1453. memset( gldp, 0, sizeof(*gldp) );
  1454. gldp->m_fsEnable = !d3dp->Windowed;
  1455. // see http://msdn.microsoft.com/en-us/library/ee416515(VS.85).aspx
  1456. // note that the values below are the only ones mentioned by Source engine; there are many others
  1457. switch(d3dp->PresentationInterval)
  1458. {
  1459. case D3DPRESENT_INTERVAL_ONE:
  1460. gldp->m_vsyncEnable = true; // "The driver will wait for the vertical retrace period (the runtime will beam-follow to prevent tearing)."
  1461. break;
  1462. case D3DPRESENT_INTERVAL_IMMEDIATE:
  1463. gldp->m_vsyncEnable = false; // "The runtime updates the window client area immediately and might do so more than once during the adapter refresh period."
  1464. break;
  1465. default:
  1466. gldp->m_vsyncEnable = true; // if I don't know it, you're getting vsync enabled.
  1467. break;
  1468. }
  1469. gldp->m_backBufferWidth = d3dp->BackBufferWidth;
  1470. gldp->m_backBufferHeight = d3dp->BackBufferHeight;
  1471. gldp->m_backBufferFormat = d3dp->BackBufferFormat;
  1472. gldp->m_multiSampleCount = d3dp->MultiSampleType; // it's a count really
  1473. gldp->m_enableAutoDepthStencil = d3dp->EnableAutoDepthStencil;
  1474. gldp->m_autoDepthStencilFormat = d3dp->AutoDepthStencilFormat;
  1475. gldp->m_fsRefreshHz = d3dp->FullScreen_RefreshRateInHz;
  1476. // some fields in d3d PB we're not acting on yet...
  1477. // UINT BackBufferCount;
  1478. // DWORD MultiSampleQuality;
  1479. // D3DSWAPEFFECT SwapEffect;
  1480. // VD3DHWND hDeviceWindow;
  1481. // DWORD Flags;
  1482. }
  1483. HRESULT IDirect3DDevice9::Create( IDirect3DDevice9Params *params )
  1484. {
  1485. GLMPRINTF((">-X-IDirect3DDevice9::Create"));
  1486. HRESULT result = S_OK;
  1487. // create an IDirect3DDevice9
  1488. // make a GLMContext and set up some drawables
  1489. m_params = *params;
  1490. m_ctx = NULL;
  1491. m_drawableFBO = NULL;
  1492. memset( m_rtSurfaces, 0, sizeof(m_rtSurfaces) );
  1493. m_dsSurface = NULL;
  1494. m_defaultColorSurface = NULL;
  1495. m_defaultDepthStencilSurface = NULL;
  1496. memset( m_streams, 0, sizeof(m_streams) );
  1497. memset( m_textures, 0, sizeof(m_textures) );
  1498. memset( m_samplers, 0, sizeof(m_samplers) );
  1499. //============================================================================
  1500. // param block for GLM context create
  1501. GLMDisplayParams glmParams;
  1502. ConvertPresentationParamsToGLMDisplayParams( &params->m_presentationParameters, &glmParams );
  1503. glmParams.m_mtgl = true; // forget this idea -> (params->m_behaviorFlags & D3DCREATE_MULTITHREADED) != 0;
  1504. // the call above fills in a bunch of things, but doesn't know about anything outside of the presentation params.
  1505. // those tend to be the things that do not change after create, so we do those here in Create.
  1506. glmParams.m_focusWindow = params->m_focusWindow;
  1507. #if 0 //FIXME-HACK
  1508. // map the D3D "adapter" to a renderer/display pair
  1509. // (that GPU will have to stay set as-is for any subsequent mode changes)
  1510. int glmRendererIndex = -1;
  1511. int glmDisplayIndex = -1;
  1512. GLMRendererInfoFields glmRendererInfo;
  1513. GLMDisplayInfoFields glmDisplayInfo;
  1514. // the D3D "Adapter" number feeds the fake adapter index
  1515. bool adaptResult = GLMgr::aGLMgr()->GetDisplayDB()->GetFakeAdapterInfo( params->m_adapter, &glmRendererIndex, &glmDisplayIndex, &glmRendererInfo, &glmDisplayInfo );
  1516. Assert(!adaptResult);
  1517. glmParams.m_rendererIndex = glmRendererIndex;
  1518. glmParams.m_displayIndex = glmDisplayIndex;
  1519. // glmParams.m_modeIndex hmmmmm, client doesn't give us a mode number, just a resolution..
  1520. #endif
  1521. m_ctx = GLMgr::aGLMgr()->NewContext( &glmParams );
  1522. if (!m_ctx)
  1523. {
  1524. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1525. return (HRESULT) -1;
  1526. }
  1527. // make an FBO to draw into and activate it.
  1528. m_drawableFBO = m_ctx->NewFBO();
  1529. m_ctx->SetDrawingFBO( m_drawableFBO );
  1530. // bind it to context. will receive attachments shortly.
  1531. m_ctx->BindFBOToCtx( m_drawableFBO, GL_READ_FRAMEBUFFER_EXT );
  1532. m_ctx->BindFBOToCtx( m_drawableFBO, GL_DRAW_FRAMEBUFFER_EXT );
  1533. // we create two IDirect3DSurface9's. These will be known as the internal render target 0 and the depthstencil.
  1534. GLMPRINTF(("-X- IDirect3DDevice9::Create making color render target..."));
  1535. // color surface
  1536. result = this->CreateRenderTarget(
  1537. m_params.m_presentationParameters.BackBufferWidth, // width
  1538. m_params.m_presentationParameters.BackBufferHeight, // height
  1539. m_params.m_presentationParameters.BackBufferFormat, // format
  1540. m_params.m_presentationParameters.MultiSampleType, // MSAA depth
  1541. m_params.m_presentationParameters.MultiSampleQuality, // MSAA quality
  1542. true, // lockable
  1543. &m_defaultColorSurface, // ppSurface
  1544. NULL // shared handle
  1545. );
  1546. if (result != S_OK)
  1547. {
  1548. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1549. return result;
  1550. }
  1551. // do not do an AddRef..
  1552. GLMPRINTF(("-X- IDirect3DDevice9::Create making color render target complete -> %08x", m_defaultColorSurface ));
  1553. GLMPRINTF(("-X- IDirect3DDevice9::Create setting color render target..."));
  1554. result = this->SetRenderTarget(0, m_defaultColorSurface);
  1555. if (result != S_OK)
  1556. {
  1557. GLMPRINTF(("< IDirect3DDevice9::Create (error out)"));
  1558. return result;
  1559. }
  1560. GLMPRINTF(("-X- IDirect3DDevice9::Create setting color render target complete."));
  1561. Assert (m_params.m_presentationParameters.EnableAutoDepthStencil);
  1562. GLMPRINTF(("-X- IDirect3DDevice9::Create making depth-stencil..."));
  1563. result = CreateDepthStencilSurface(
  1564. m_params.m_presentationParameters.BackBufferWidth, // width
  1565. m_params.m_presentationParameters.BackBufferHeight, // height
  1566. m_params.m_presentationParameters.AutoDepthStencilFormat, // format
  1567. m_params.m_presentationParameters.MultiSampleType, // MSAA depth
  1568. m_params.m_presentationParameters.MultiSampleQuality, // MSAA quality
  1569. TRUE, // enable z-buffer discard ????
  1570. &m_defaultDepthStencilSurface, // ppSurface
  1571. NULL // shared handle
  1572. );
  1573. if (result != S_OK)
  1574. {
  1575. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1576. return result;
  1577. }
  1578. // do not do an AddRef here..
  1579. GLMPRINTF(("-X- IDirect3DDevice9::Create making depth-stencil complete -> %08x", m_defaultDepthStencilSurface));
  1580. GLMPRINTF(("-X- Direct3DDevice9::Create setting depth-stencil render target..."));
  1581. result = this->SetDepthStencilSurface(m_defaultDepthStencilSurface);
  1582. if (result != S_OK)
  1583. {
  1584. GLMDebugger();
  1585. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1586. return result;
  1587. }
  1588. GLMPRINTF(("-X- IDirect3DDevice9::Create setting depth-stencil render target complete."));
  1589. bool ready = m_drawableFBO->IsReady();
  1590. if (!ready)
  1591. {
  1592. GLMPRINTF(("<-X- IDirect3DDevice9::Create (error out)"));
  1593. return (HRESULT)-1;
  1594. }
  1595. // this next part really needs to be inside GLMContext.. or replaced with D3D style viewport setup calls.
  1596. m_ctx->GenDebugFontTex();
  1597. // blast the gl state mirror...
  1598. memset( &this->gl, 0, sizeof( this->gl ) );
  1599. GLScissorEnable_t defScissorEnable = { true };
  1600. GLScissorBox_t defScissorBox = { 0,0, m_params.m_presentationParameters.BackBufferWidth,m_params.m_presentationParameters.BackBufferHeight };
  1601. GLViewportBox_t defViewportBox = { 0,0, m_params.m_presentationParameters.BackBufferWidth,m_params.m_presentationParameters.BackBufferHeight };
  1602. GLViewportDepthRange_t defViewportDepthRange = { 0.1, 1000.0 };
  1603. GLCullFaceEnable_t defCullFaceEnable = { true };
  1604. GLCullFrontFace_t defCullFrontFace = { GL_CCW };
  1605. gl.m_ScissorEnable = defScissorEnable;
  1606. gl.m_ScissorBox = defScissorBox;
  1607. gl.m_ViewportBox = defViewportBox;
  1608. gl.m_ViewportDepthRange = defViewportDepthRange;
  1609. gl.m_CullFaceEnable = defCullFaceEnable;
  1610. gl.m_CullFrontFace = defCullFrontFace;
  1611. gl.m_stateDirtyMask = (1<<kGLScissorEnable) | (1<<kGLScissorBox) | (1<<kGLViewportBox) | (1<<kGLViewportDepthRange) | (1<<kGLCullFaceEnable) | (1<<kGLCullFrontFace);
  1612. GLMPRINTF(("<-X- IDirect3DDevice9::Create complete"));
  1613. // so GetClientRect can return sane answers
  1614. uint width, height;
  1615. g_extCocoaMgr->RenderedSize( m_params.m_presentationParameters.BackBufferWidth, m_params.m_presentationParameters.BackBufferHeight, true ); // true = set
  1616. return result;
  1617. }
  1618. IDirect3DDevice9::~IDirect3DDevice9()
  1619. {
  1620. GLMPRINTF(( "-D- IDirect3DDevice9::~IDirect3DDevice9 signpost" )); // want to know when this is called, if ever
  1621. }
  1622. #pragma mark ----- Basics - (IDirect3DDevice9)
  1623. HRESULT IDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPresentationParameters)
  1624. {
  1625. HRESULT result = S_OK;
  1626. // define the task of reset as:
  1627. // provide new drawable RT's for the backbuffer (color and depthstencil).
  1628. // fix up viewport / scissor..
  1629. // then pass the new presentation parameters through to GLM.
  1630. // (it will in turn notify appframework on the next present... which may be very soon, as mode changes are usually spotted inside Present() ).
  1631. // so some of this looks a lot like Create - we're just a subset of what it does.
  1632. // with a little work you could refactor this to be common code.
  1633. //------------------------------------------------------------------------------- absorb new presentation params..
  1634. m_params.m_presentationParameters = *pPresentationParameters;
  1635. //------------------------------------------------------------------------------- color buffer..
  1636. // release old color surface if it's there..
  1637. if (m_defaultColorSurface)
  1638. {
  1639. ULONG refc = m_defaultColorSurface->Release( 0, "IDirect3DDevice9::Reset public release color surface" );
  1640. Assert( !refc );
  1641. m_defaultColorSurface = NULL;
  1642. }
  1643. GLMPRINTF(("-X- IDirect3DDevice9::Reset making new color render target..."));
  1644. // color surface
  1645. result = this->CreateRenderTarget(
  1646. m_params.m_presentationParameters.BackBufferWidth, // width
  1647. m_params.m_presentationParameters.BackBufferHeight, // height
  1648. m_params.m_presentationParameters.BackBufferFormat, // format
  1649. m_params.m_presentationParameters.MultiSampleType, // MSAA depth
  1650. m_params.m_presentationParameters.MultiSampleQuality, // MSAA quality
  1651. true, // lockable
  1652. &m_defaultColorSurface, // ppSurface
  1653. NULL // shared handle
  1654. );
  1655. if (result != S_OK)
  1656. {
  1657. GLMPRINTF(("<-X- IDirect3DDevice9::Reset (error out)"));
  1658. return result;
  1659. }
  1660. // do not do an AddRef here..
  1661. GLMPRINTF(("-X- IDirect3DDevice9::Reset making color render target complete -> %08x", m_defaultColorSurface ));
  1662. GLMPRINTF(("-X- IDirect3DDevice9::Reset setting color render target..."));
  1663. result = this->SetRenderTarget(0, m_defaultColorSurface);
  1664. if (result != S_OK)
  1665. {
  1666. GLMPRINTF(("< IDirect3DDevice9::Reset (error out)"));
  1667. return result;
  1668. }
  1669. GLMPRINTF(("-X- IDirect3DDevice9::Reset setting color render target complete."));
  1670. //-------------------------------------------------------------------------------depth stencil buffer
  1671. // release old depthstencil surface if it's there..
  1672. if (m_defaultDepthStencilSurface)
  1673. {
  1674. ULONG refc = m_defaultDepthStencilSurface->Release( 0, "IDirect3DDevice9::Reset public release depthstencil surface" );
  1675. Assert(!refc);
  1676. m_defaultDepthStencilSurface = NULL;
  1677. }
  1678. Assert (m_params.m_presentationParameters.EnableAutoDepthStencil);
  1679. GLMPRINTF(("-X- IDirect3DDevice9::Reset making depth-stencil..."));
  1680. result = CreateDepthStencilSurface(
  1681. m_params.m_presentationParameters.BackBufferWidth, // width
  1682. m_params.m_presentationParameters.BackBufferHeight, // height
  1683. m_params.m_presentationParameters.AutoDepthStencilFormat, // format
  1684. m_params.m_presentationParameters.MultiSampleType, // MSAA depth
  1685. m_params.m_presentationParameters.MultiSampleQuality, // MSAA quality
  1686. TRUE, // enable z-buffer discard ????
  1687. &m_defaultDepthStencilSurface, // ppSurface
  1688. NULL // shared handle
  1689. );
  1690. if (result != S_OK)
  1691. {
  1692. GLMPRINTF(("<-X- IDirect3DDevice9::Reset (error out)"));
  1693. return result;
  1694. }
  1695. // do not do an AddRef here..
  1696. GLMPRINTF(("-X- IDirect3DDevice9::Reset making depth-stencil complete -> %08x", m_defaultDepthStencilSurface));
  1697. GLMPRINTF(("-X- IDirect3DDevice9::Reset setting depth-stencil render target..."));
  1698. result = this->SetDepthStencilSurface(m_defaultDepthStencilSurface);
  1699. if (result != S_OK)
  1700. {
  1701. GLMPRINTF(("<-X- IDirect3DDevice9::Reset (error out)"));
  1702. return result;
  1703. }
  1704. GLMPRINTF(("-X- IDirect3DDevice9::Reset setting depth-stencil render target complete."));
  1705. bool ready = m_drawableFBO->IsReady();
  1706. if (!ready)
  1707. {
  1708. GLMPRINTF(("<-X- IDirect3DDevice9::Reset (error out)"));
  1709. return D3DERR_DEVICELOST;
  1710. }
  1711. //-------------------------------------------------------------------------------zap viewport and scissor to new backbuffer size
  1712. GLScissorEnable_t defScissorEnable = { true };
  1713. GLScissorBox_t defScissorBox = { 0,0, m_params.m_presentationParameters.BackBufferWidth,m_params.m_presentationParameters.BackBufferHeight };
  1714. GLViewportBox_t defViewportBox = { 0,0, m_params.m_presentationParameters.BackBufferWidth,m_params.m_presentationParameters.BackBufferHeight };
  1715. GLViewportDepthRange_t defViewportDepthRange = { 0.1, 1000.0 };
  1716. GLCullFaceEnable_t defCullFaceEnable = { true };
  1717. GLCullFrontFace_t defCullFrontFace = { GL_CCW };
  1718. gl.m_ScissorEnable = defScissorEnable;
  1719. gl.m_ScissorBox = defScissorBox;
  1720. gl.m_ViewportBox = defViewportBox;
  1721. gl.m_ViewportDepthRange = defViewportDepthRange;
  1722. gl.m_CullFaceEnable = defCullFaceEnable;
  1723. gl.m_CullFrontFace = defCullFrontFace;
  1724. gl.m_stateDirtyMask |= (1<<kGLScissorEnable) | (1<<kGLScissorBox) | (1<<kGLViewportBox) | (1<<kGLViewportDepthRange) | (1<<kGLCullFaceEnable) | (1<<kGLCullFrontFace);
  1725. //-------------------------------------------------------------------------------finally, propagate new display params to GLM context
  1726. GLMDisplayParams glmParams;
  1727. ConvertPresentationParamsToGLMDisplayParams( pPresentationParameters, &glmParams );
  1728. // steal back previously sent focus window...
  1729. glmParams.m_focusWindow = m_ctx->m_displayParams.m_focusWindow;
  1730. Assert( glmParams.m_focusWindow != NULL );
  1731. // so GetClientRect can return sane answers
  1732. uint width, height;
  1733. g_extCocoaMgr->RenderedSize( pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight, true ); // true = set
  1734. m_ctx->SetDisplayParams( &glmParams );
  1735. return S_OK;
  1736. }
  1737. HRESULT IDirect3DDevice9::SetViewport(CONST D3DVIEWPORT9* pViewport)
  1738. {
  1739. GLMPRINTF(("-X- IDirect3DDevice9::SetViewport : minZ %f, maxZ %f",pViewport->MinZ, pViewport->MaxZ ));
  1740. gl.m_ViewportBox.x = pViewport->X;
  1741. gl.m_ViewportBox.width = pViewport->Width;
  1742. gl.m_ViewportBox.y = pViewport->Y;
  1743. gl.m_ViewportBox.height = pViewport->Height;
  1744. gl.m_stateDirtyMask |= (1<<kGLViewportBox);
  1745. gl.m_ViewportDepthRange.near = pViewport->MinZ;
  1746. gl.m_ViewportDepthRange.far = pViewport->MaxZ;
  1747. gl.m_stateDirtyMask |= (1<<kGLViewportDepthRange);
  1748. return S_OK;
  1749. }
  1750. HRESULT IDirect3DDevice9::BeginScene()
  1751. {
  1752. m_ctx->BeginFrame();
  1753. return S_OK;
  1754. }
  1755. HRESULT IDirect3DDevice9::EndScene()
  1756. {
  1757. m_ctx->EndFrame();
  1758. return S_OK;
  1759. }
  1760. // stolen from glmgrbasics.cpp
  1761. enum ECarbonModKeyIndex
  1762. {
  1763. EcmdKeyBit = 8, /* command key down?*/
  1764. EshiftKeyBit = 9, /* shift key down?*/
  1765. EalphaLockBit = 10, /* alpha lock down?*/
  1766. EoptionKeyBit = 11, /* option key down?*/
  1767. EcontrolKeyBit = 12 /* control key down?*/
  1768. };
  1769. enum ECarbonModKeyMask
  1770. {
  1771. EcmdKey = 1 << EcmdKeyBit,
  1772. EshiftKey = 1 << EshiftKeyBit,
  1773. EalphaLock = 1 << EalphaLockBit,
  1774. EoptionKey = 1 << EoptionKeyBit,
  1775. EcontrolKey = 1 << EcontrolKeyBit
  1776. };
  1777. ConVar gl_blitmode( "gl_blitmode", "1" );
  1778. ConVar dxa_nullrefresh_capslock( "dxa_nullrefresh_capslock", "0" );
  1779. HRESULT IDirect3DDevice9::Present(CONST RECT* pSourceRect,CONST RECT* pDestRect,VD3DHWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion)
  1780. {
  1781. // before attempting to present a tex, make sure it's been resolved if it was MSAA.
  1782. // if we push that responsibility down to m_ctx->Present, it could probably do it without an extra copy.
  1783. // i.e. anticipate the blit from the resolvedtex to GL_BACK, and just do that instead.
  1784. if (dxa_nullrefresh_capslock.GetInt())
  1785. {
  1786. if (GetCurrentKeyModifiers() & EalphaLock )
  1787. {
  1788. return S_OK;
  1789. }
  1790. }
  1791. // no explicit ResolveTex call first - that got pushed down into GLMContext::Present
  1792. m_ctx->Present( m_defaultColorSurface->m_tex );
  1793. return S_OK;
  1794. }
  1795. // Sanity-chedk the results
  1796. /*
  1797. // TODO, something like the following:
  1798. // safe because of early exit on NULL above
  1799. m_rtSurfaces[ RenderTargetIndex ]->AddRef();
  1800. *ppRenderTarget = m_rtSurfaces[ RenderTargetIndex ];
  1801. */
  1802. #pragma mark ----- Textures - (IDirect3DDevice9)
  1803. #pragma mark ( create functions for each texture are now adjacent to the rest of the methods for each texture class)
  1804. HRESULT IDirect3DDevice9::SetTexture(DWORD Stage,IDirect3DBaseTexture9* pTexture)
  1805. {
  1806. // texture sets are sent through immediately to GLM
  1807. // but we also latch the value so we know which TMU's are active.
  1808. // whuch can help FlushSamplers do less work.
  1809. // place new tex
  1810. m_textures[Stage] = pTexture;
  1811. if (!pTexture)
  1812. {
  1813. m_ctx->SetSamplerTex( Stage, NULL );
  1814. }
  1815. else
  1816. {
  1817. m_ctx->SetSamplerTex( Stage, pTexture->m_tex );
  1818. }
  1819. return S_OK;
  1820. }
  1821. HRESULT IDirect3DDevice9::GetTexture(DWORD Stage,IDirect3DBaseTexture9** ppTexture)
  1822. {
  1823. // if implemented, should it increase the ref count ??
  1824. GLMDebugger();
  1825. return S_OK;
  1826. }
  1827. #pragma mark ----- RT's and Surfaces - (IDirect3DDevice9)
  1828. HRESULT IDirect3DDevice9::CreateRenderTarget(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle, char *pDebugLabel)
  1829. {
  1830. HRESULT result = S_OK;
  1831. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  1832. surf->m_restype = D3DRTYPE_SURFACE;
  1833. surf->m_device = this; // always set device on creations!
  1834. GLMTexLayoutKey rtkey;
  1835. memset( &rtkey, 0, sizeof(rtkey) );
  1836. rtkey.m_texGLTarget = GL_TEXTURE_2D;
  1837. rtkey.m_xSize = Width;
  1838. rtkey.m_ySize = Height;
  1839. rtkey.m_zSize = 1;
  1840. rtkey.m_texFormat = Format;
  1841. rtkey.m_texFlags = kGLMTexRenderable;
  1842. rtkey.m_texFlags |= kGLMTexSRGB; // all render target tex are SRGB mode
  1843. if (m_ctx->Caps().m_cantAttachSRGB)
  1844. {
  1845. // this config can't support SRGB render targets. quietly turn off the sRGB bit.
  1846. rtkey.m_texFlags &= ~kGLMTexSRGB;
  1847. }
  1848. if ( (MultiSample !=0) && (!m_ctx->Caps().m_nvG7x) )
  1849. {
  1850. rtkey.m_texFlags |= kGLMTexMultisampled;
  1851. rtkey.m_texSamples = MultiSample;
  1852. // FIXME no support for "MS quality" yet
  1853. }
  1854. surf->m_tex = m_ctx->NewTex( &rtkey, pDebugLabel );
  1855. surf->m_face = 0;
  1856. surf->m_mip = 0;
  1857. //desc
  1858. surf->m_desc.Format = Format;
  1859. surf->m_desc.Type = D3DRTYPE_SURFACE;
  1860. surf->m_desc.Usage = 0; //FIXME ???????????
  1861. surf->m_desc.Pool = D3DPOOL_DEFAULT; //FIXME ???????????
  1862. surf->m_desc.MultiSampleType = MultiSample;
  1863. surf->m_desc.MultiSampleQuality = MultisampleQuality;
  1864. surf->m_desc.Width = Width;
  1865. surf->m_desc.Height = Height;
  1866. *ppSurface = (result==S_OK) ? surf : NULL;
  1867. #if IUNKNOWN_ALLOC_SPEW
  1868. char scratch[1024];
  1869. sprintf(scratch,"RT %s", surf->m_tex->m_layout->m_layoutSummary );
  1870. surf->SetMark( true, scratch );
  1871. #endif
  1872. return result;
  1873. }
  1874. HRESULT IDirect3DDevice9::SetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget)
  1875. {
  1876. HRESULT result = S_OK;
  1877. GLMPRINTF(("-F- SetRenderTarget index=%d, surface=%8x (tex=%8x %s)",
  1878. RenderTargetIndex,
  1879. pRenderTarget,
  1880. pRenderTarget ? pRenderTarget->m_tex : NULL,
  1881. pRenderTarget ? pRenderTarget->m_tex->m_layout->m_layoutSummary : ""
  1882. ));
  1883. // 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
  1884. // behaviors...
  1885. // if new surf is same as old surf, no change in refcount, in fact, it's early exit
  1886. IDirect3DSurface9 *oldTarget = m_rtSurfaces[RenderTargetIndex];
  1887. if (pRenderTarget == oldTarget)
  1888. {
  1889. GLMPRINTF(("-F- --> no change",RenderTargetIndex));
  1890. return S_OK;
  1891. }
  1892. // we now know that the new surf is not the same as the old surf.
  1893. // you can't assume either one is non NULL here though.
  1894. if (m_rtSurfaces[RenderTargetIndex])
  1895. {
  1896. m_rtSurfaces[RenderTargetIndex]->Release( 1, "-A SetRenderTarget private release" ); // note this is the private refcount being lowered
  1897. }
  1898. if (pRenderTarget)
  1899. {
  1900. pRenderTarget->AddRef( 1, "+A SetRenderTarget private addref" ); // again, private refcount being raised
  1901. }
  1902. m_rtSurfaces[RenderTargetIndex] = pRenderTarget; // emplace it whether NULL or not
  1903. if (!pRenderTarget)
  1904. {
  1905. GLMPRINTF(("-F- --> Setting NULL render target on index=%d ",RenderTargetIndex));
  1906. }
  1907. else
  1908. {
  1909. GLMPRINTF(("-F- --> attaching index=%d on drawing FBO (%8x)",RenderTargetIndex, m_drawableFBO));
  1910. // attach color to FBO
  1911. GLMFBOTexAttachParams rtParams;
  1912. memset( &rtParams, 0, sizeof(rtParams) );
  1913. rtParams.m_tex = pRenderTarget->m_tex;
  1914. rtParams.m_face = pRenderTarget->m_face;
  1915. rtParams.m_mip = pRenderTarget->m_mip;
  1916. rtParams.m_zslice = 0; // FIXME if you ever want to be able to render to slices of a 3D tex..
  1917. m_drawableFBO->TexAttach( &rtParams, (EGLMFBOAttachment)(kAttColor0 + RenderTargetIndex) );
  1918. }
  1919. return result;
  1920. }
  1921. HRESULT IDirect3DDevice9::GetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget)
  1922. {
  1923. if ( !m_rtSurfaces[ RenderTargetIndex ] )
  1924. return D3DERR_NOTFOUND;
  1925. if ( ( RenderTargetIndex < 0 ) || ( RenderTargetIndex > 4 ) || !ppRenderTarget )
  1926. return D3DERR_INVALIDCALL;
  1927. // safe because of early exit on NULL above
  1928. m_rtSurfaces[ RenderTargetIndex ]->AddRef(0, "+B GetRenderTarget public addref"); // per http://msdn.microsoft.com/en-us/library/bb174404(VS.85).aspx
  1929. *ppRenderTarget = m_rtSurfaces[ RenderTargetIndex ];
  1930. return S_OK;
  1931. }
  1932. HRESULT IDirect3DDevice9::CreateOffscreenPlainSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle)
  1933. {
  1934. // set surf->m_restype to D3DRTYPE_SURFACE...
  1935. // this is almost identical to CreateRenderTarget..
  1936. HRESULT result = S_OK;
  1937. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  1938. surf->m_restype = D3DRTYPE_SURFACE;
  1939. surf->m_device = this; // always set device on creations!
  1940. GLMTexLayoutKey rtkey;
  1941. memset( &rtkey, 0, sizeof(rtkey) );
  1942. rtkey.m_texGLTarget = GL_TEXTURE_2D;
  1943. rtkey.m_xSize = Width;
  1944. rtkey.m_ySize = Height;
  1945. rtkey.m_zSize = 1;
  1946. rtkey.m_texFormat = Format;
  1947. rtkey.m_texFlags = kGLMTexRenderable;
  1948. surf->m_tex = m_ctx->NewTex( &rtkey, "offscreen plain surface" );
  1949. surf->m_face = 0;
  1950. surf->m_mip = 0;
  1951. //desc
  1952. surf->m_desc.Format = Format;
  1953. surf->m_desc.Type = D3DRTYPE_SURFACE;
  1954. surf->m_desc.Usage = 0;
  1955. surf->m_desc.Pool = D3DPOOL_DEFAULT;
  1956. surf->m_desc.MultiSampleType = D3DMULTISAMPLE_NONE;
  1957. surf->m_desc.MultiSampleQuality = 0;
  1958. surf->m_desc.Width = Width;
  1959. surf->m_desc.Height = Height;
  1960. *ppSurface = (result==S_OK) ? surf : NULL;
  1961. return result;
  1962. }
  1963. HRESULT IDirect3DDevice9::CreateDepthStencilSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle)
  1964. {
  1965. HRESULT result = S_OK;
  1966. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  1967. surf->m_restype = D3DRTYPE_SURFACE;
  1968. surf->m_device = this; // always set device on creations!
  1969. GLMTexLayoutKey depthkey;
  1970. memset( &depthkey, 0, sizeof(depthkey) );
  1971. depthkey.m_texGLTarget = GL_TEXTURE_2D;
  1972. depthkey.m_xSize = Width;
  1973. depthkey.m_ySize = Height;
  1974. depthkey.m_zSize = 1;
  1975. depthkey.m_texFormat = Format;
  1976. depthkey.m_texFlags = kGLMTexRenderable | kGLMTexIsDepth | kGLMTexIsStencil;
  1977. if ( (MultiSample !=0) && (!m_ctx->Caps().m_nvG7x) )
  1978. {
  1979. depthkey.m_texFlags |= kGLMTexMultisampled;
  1980. depthkey.m_texSamples = MultiSample;
  1981. // FIXME no support for "MS quality" yet
  1982. }
  1983. surf->m_tex = m_ctx->NewTex( &depthkey, "depth-stencil surface" );
  1984. surf->m_face = 0;
  1985. surf->m_mip = 0;
  1986. //desc
  1987. surf->m_desc.Format = Format;
  1988. surf->m_desc.Type = D3DRTYPE_SURFACE;
  1989. surf->m_desc.Usage = 0; //FIXME ???????????
  1990. surf->m_desc.Pool = D3DPOOL_DEFAULT; //FIXME ???????????
  1991. surf->m_desc.MultiSampleType = MultiSample;
  1992. surf->m_desc.MultiSampleQuality = MultisampleQuality;
  1993. surf->m_desc.Width = Width;
  1994. surf->m_desc.Height = Height;
  1995. *ppSurface = (result==S_OK) ? surf : NULL;
  1996. return result;
  1997. }
  1998. HRESULT IDirect3DDevice9::SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil)
  1999. {
  2000. HRESULT result = S_OK;
  2001. GLMPRINTF(("-F- SetDepthStencilSurface, surface=%8x (tex=%8x %s)",
  2002. pNewZStencil,
  2003. pNewZStencil ? pNewZStencil->m_tex : NULL,
  2004. pNewZStencil ? pNewZStencil->m_tex->m_layout->m_layoutSummary : ""
  2005. ));
  2006. if (pNewZStencil)
  2007. {
  2008. pNewZStencil->AddRef(1, "+A SetDepthStencilSurface private addref");
  2009. }
  2010. if (m_dsSurface)
  2011. {
  2012. m_dsSurface->Release(1, "-A SetDepthStencilSurface private release");
  2013. // do not do a Release here..
  2014. }
  2015. if (m_dsSurface != pNewZStencil)
  2016. {
  2017. GLMPRINTF(("-F- --> attaching depthstencil %8x on drawing FBO (%8x)", pNewZStencil, m_drawableFBO));
  2018. m_dsSurface = pNewZStencil;
  2019. // aka FBO attach
  2020. GLMFBOTexAttachParams depthParams;
  2021. memset( &depthParams, 0, sizeof(depthParams) );
  2022. // NULL is OK - it means unbind the depth buffer
  2023. depthParams.m_tex = (pNewZStencil) ? pNewZStencil->m_tex : NULL;
  2024. depthParams.m_face = 0;
  2025. depthParams.m_mip = 0;
  2026. depthParams.m_zslice= 0;
  2027. // brute force baby
  2028. // clear old attachments in all D/S categories
  2029. m_drawableFBO->TexDetach( kAttStencil );
  2030. m_drawableFBO->TexDetach( kAttDepth );
  2031. m_drawableFBO->TexDetach( kAttDepthStencil );
  2032. // select dest for new attachment
  2033. if (depthParams.m_tex!=NULL)
  2034. {
  2035. EGLMFBOAttachment destAttach = (depthParams.m_tex->m_layout->m_format->m_glDataFormat != 34041) ? kAttDepth : kAttDepthStencil;
  2036. m_drawableFBO->TexAttach( &depthParams, destAttach ); // attach(NULL) is allowed to mean "detach".
  2037. }
  2038. }
  2039. else
  2040. {
  2041. GLMPRINTF(("-F- --> no change"));
  2042. }
  2043. return result;
  2044. }
  2045. HRESULT IDirect3DDevice9::GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface)
  2046. {
  2047. if ( !ppZStencilSurface )
  2048. {
  2049. return D3DERR_INVALIDCALL;
  2050. }
  2051. if ( !m_dsSurface )
  2052. {
  2053. *ppZStencilSurface = NULL;
  2054. return D3DERR_NOTFOUND;
  2055. }
  2056. m_dsSurface->AddRef(0, "+B GetDepthStencilSurface public addref"); // per http://msdn.microsoft.com/en-us/library/bb174384(VS.85).aspx
  2057. *ppZStencilSurface = m_dsSurface;
  2058. return S_OK;
  2059. }
  2060. HRESULT IDirect3DDevice9::GetRenderTargetData(IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface)
  2061. {
  2062. // is it just a blit ?
  2063. this->StretchRect( pRenderTarget, NULL, pDestSurface, NULL, D3DTEXF_NONE ); // is this good enough ???
  2064. return S_OK;
  2065. }
  2066. HRESULT IDirect3DDevice9::GetFrontBufferData(UINT iSwapChain,IDirect3DSurface9* pDestSurface)
  2067. {
  2068. Debugger();
  2069. return S_OK;
  2070. }
  2071. HRESULT IDirect3DDevice9::StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter)
  2072. {
  2073. // find relevant slices in GLM tex
  2074. CGLMTex *srcTex = pSourceSurface->m_tex;
  2075. int srcSliceIndex = srcTex->CalcSliceIndex( pSourceSurface->m_face, pSourceSurface->m_mip );
  2076. GLMTexLayoutSlice *srcSlice = &srcTex->m_layout->m_slices[ srcSliceIndex ];
  2077. CGLMTex *dstTex = pDestSurface->m_tex;
  2078. int dstSliceIndex = dstTex->CalcSliceIndex( pDestSurface->m_face, pDestSurface->m_mip );
  2079. GLMTexLayoutSlice *dstSlice = &dstTex->m_layout->m_slices[ dstSliceIndex ];
  2080. if ( dstTex->m_rboName != 0 )
  2081. {
  2082. Assert(!"No path yet for blitting into an MSAA tex");
  2083. return S_OK;
  2084. }
  2085. bool useFastBlit = (gl_blitmode.GetInt() != 0);
  2086. if ( !useFastBlit && (srcTex->m_rboName !=0)) // old way, we do a resolve to scratch tex first (necessitating two step blit)
  2087. {
  2088. m_ctx->ResolveTex( srcTex, true );
  2089. }
  2090. // set up source/dest rect in GLM form
  2091. GLMRect srcRect, dstRect;
  2092. // d3d nomenclature:
  2093. // Y=0 is the visual top and also aligned with V=0.
  2094. srcRect.xmin = pSourceRect ? pSourceRect->left : 0;
  2095. srcRect.xmax = pSourceRect ? pSourceRect->right : srcSlice->m_xSize;
  2096. srcRect.ymin = pSourceRect ? pSourceRect->top : 0;
  2097. srcRect.ymax = pSourceRect ? pSourceRect->bottom : srcSlice->m_ySize;
  2098. dstRect.xmin = pDestRect ? pDestRect->left : 0;
  2099. dstRect.xmax = pDestRect ? pDestRect->right : dstSlice->m_xSize;
  2100. dstRect.ymin = pDestRect ? pDestRect->top : 0;
  2101. dstRect.ymax = pDestRect ? pDestRect->bottom : dstSlice->m_ySize;
  2102. GLenum filterGL = 0;
  2103. switch(Filter)
  2104. {
  2105. case D3DTEXF_NONE:
  2106. case D3DTEXF_POINT:
  2107. filterGL = GL_NEAREST;
  2108. break;
  2109. case D3DTEXF_LINEAR:
  2110. filterGL = GL_LINEAR;
  2111. break;
  2112. default: // D3DTEXF_ANISOTROPIC
  2113. Assert(!"Impl aniso stretch");
  2114. break;
  2115. }
  2116. if (useFastBlit)
  2117. {
  2118. m_ctx->Blit2( srcTex, &srcRect, pSourceSurface->m_face, pSourceSurface->m_mip,
  2119. dstTex, &dstRect, pDestSurface->m_face, pDestSurface->m_mip,
  2120. filterGL
  2121. );
  2122. }
  2123. else
  2124. {
  2125. m_ctx->BlitTex( srcTex, &srcRect, pSourceSurface->m_face, pSourceSurface->m_mip,
  2126. dstTex, &dstRect, pDestSurface->m_face, pDestSurface->m_mip,
  2127. filterGL
  2128. );
  2129. }
  2130. return S_OK;
  2131. }
  2132. // This totally sucks, but this information can't be gleaned any
  2133. // other way when translating from D3D to GL at this level
  2134. //
  2135. // This returns a mask, since multiple GLSL "varyings" can be tagged with centroid
  2136. static uint32 CentroidMaskFromName( bool bPixelShader, const char *pName )
  2137. {
  2138. if ( !pName )
  2139. return 0;
  2140. if ( bPixelShader )
  2141. {
  2142. if ( V_stristr( pName, "lightmappedpaint_ps" ) || V_stristr( pName, "lightmappedgeneric_ps" ) || V_stristr( pName, "flashlight_ps" ) )
  2143. {
  2144. return (0x01 << 1); // iterator 1
  2145. }
  2146. else if ( V_stristr( pName, "shadow_ps" ) )
  2147. {
  2148. return (0x01 << 1) | (0x01 << 2) | (0x01 << 3); // iterators 1, 2 and 3
  2149. }
  2150. else if ( V_stristr( pName, "water_ps" ) )
  2151. {
  2152. return (0x01 << 5) | (0x01 << 6) | (0x01 << 7); // iterators 5, 6 and 7
  2153. }
  2154. }
  2155. else // vertex shader
  2156. {
  2157. // Vertex shaders also
  2158. if ( V_stristr( pName, "lightmappedgeneric_vs" ) || V_stristr( pName, "flashlight_vs" ) )
  2159. {
  2160. return (0x01 << 1); // iterator 1
  2161. }
  2162. else if ( V_stristr( pName, "shadow_vs" ) )
  2163. {
  2164. return (0x01 << 1) | (0x01 << 2) | (0x01 << 3); // iterators 1, 2 and 3
  2165. }
  2166. else if ( V_stristr( pName, "water_vs" ) )
  2167. {
  2168. return (0x01 << 5) | (0x01 << 6) | (0x01 << 7); // iterators 5, 6 and 7
  2169. }
  2170. }
  2171. // This shader doesn't have any centroid iterators
  2172. return 0;
  2173. }
  2174. // This totally sucks, but this information can't be gleaned any
  2175. // other way when translating from D3D to GL at this level
  2176. static int ShadowDepthSamplerFromName( const char *pName )
  2177. {
  2178. if ( !pName )
  2179. return -1;
  2180. if ( V_stristr( pName, "water_ps" ) )
  2181. {
  2182. return 7;
  2183. }
  2184. else if ( V_stristr( pName, "phong_ps" ) )
  2185. {
  2186. return 4;
  2187. }
  2188. else if ( V_stristr( pName, "vertexlit_and_unlit_generic_bump_ps" ) )
  2189. {
  2190. return 8;
  2191. }
  2192. else if ( V_stristr( pName, "vertexlit_and_unlit_generic_ps" ) )
  2193. {
  2194. return 8;
  2195. }
  2196. else if ( V_stristr( pName, "eye_refract_ps" ) )
  2197. {
  2198. return 6;
  2199. }
  2200. else if ( V_stristr( pName, "eyes_flashlight_ps" ) )
  2201. {
  2202. return 4;
  2203. }
  2204. else if ( V_stristr( pName, "worldtwotextureblend_ps" ) )
  2205. {
  2206. return 7;
  2207. }
  2208. else if ( V_stristr( pName, "teeth_flashlight_ps" ) )
  2209. {
  2210. return 2;
  2211. }
  2212. else if ( V_stristr( pName, "flashlight_ps" ) ) // substring of above, make sure this comes last!!
  2213. {
  2214. return 7;
  2215. }
  2216. // This shader doesn't have a shadow depth map sampler
  2217. return -1;
  2218. }
  2219. #pragma mark ----- Pixel Shaders - (IDirect3DDevice9)
  2220. HRESULT IDirect3DDevice9::CreatePixelShader(CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader, const char *pShaderName, char *pDebugLabel)
  2221. {
  2222. HRESULT result = D3DERR_INVALIDCALL;
  2223. *ppShader = NULL;
  2224. int nShadowDepthSampler = ShadowDepthSamplerFromName( pShaderName );
  2225. uint32 nCentroidMask = CentroidMaskFromName( true, pShaderName );
  2226. if ( g_bUseControlFlow || !m_ctx->Caps().m_hasDualShaders )
  2227. {
  2228. // either having control-flow 'on' or -glmdualshaders 'off' disqualifies ARB assembler mode
  2229. g_useASMTranslations = false;
  2230. }
  2231. if ( ! (g_useASMTranslations || g_useGLSLTranslations) )
  2232. {
  2233. Assert(!"Must set at least one translation option..");
  2234. *ppShader = NULL;
  2235. return -1;
  2236. }
  2237. else
  2238. {
  2239. int numTranslations = (g_useASMTranslations!=0) + (g_useGLSLTranslations!=0);
  2240. bool bVertexShader = false;
  2241. // 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.
  2242. // 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.
  2243. int maxTranslationSize = 50000; // size of any one translation
  2244. CUtlBuffer transbuf( 3000, numTranslations * maxTranslationSize, CUtlBuffer::TEXT_BUFFER );
  2245. CUtlBuffer tempbuf( 3000, maxTranslationSize, CUtlBuffer::TEXT_BUFFER );
  2246. if ( g_useASMTranslations )
  2247. {
  2248. // no extra tag needed for ARBfp, just use the !!ARBfp marker
  2249. tempbuf.EnsureCapacity( maxTranslationSize );
  2250. g_D3DToOpenGLTranslatorASM.TranslateShader( (uint32 *) pFunction, &tempbuf, &bVertexShader, D3DToGL_OptionUseEnvParams, nShadowDepthSampler, 0, pDebugLabel );
  2251. // grow to encompass...
  2252. transbuf.PutString ( (char*)tempbuf.Base() );
  2253. transbuf.PutString( "\n\n" ); // whitespace
  2254. }
  2255. if ( g_useGLSLTranslations )
  2256. {
  2257. transbuf.PutString( "//GLSLfp\n" ); // this is required so GLM can crack the text apart
  2258. // note the GLSL translator wants its own buffer
  2259. tempbuf.EnsureCapacity( maxTranslationSize );
  2260. uint glslPixelShaderOptions = D3DToGL_OptionGLSL | D3DToGL_OptionUseEnvParams;
  2261. // Fake SRGB mode - needed on R500, probably indefinitely.
  2262. // Do this stuff if caps show m_needsFakeSRGB=true and the sRGBWrite state is true
  2263. // (but not if it's engine_post which is special)
  2264. if (!m_ctx->Caps().m_hasGammaWrites)
  2265. {
  2266. if ( pShaderName )
  2267. {
  2268. if ( !V_stristr( pShaderName, "engine_post" ) )
  2269. {
  2270. glslPixelShaderOptions |= D3DToGL_OptionSRGBWriteSuffix;
  2271. }
  2272. }
  2273. }
  2274. if (m_ctx->Caps().m_hasBindableUniforms)
  2275. {
  2276. glslPixelShaderOptions |= D3DToGL_OptionUseBindableUniforms;
  2277. }
  2278. g_D3DToOpenGLTranslatorGLSL.TranslateShader( (uint32 *) pFunction, &tempbuf, &bVertexShader, glslPixelShaderOptions, nShadowDepthSampler, nCentroidMask, pDebugLabel );
  2279. transbuf.PutString( (char*)tempbuf.Base() );
  2280. transbuf.PutString( "\n\n" ); // whitespace
  2281. }
  2282. if ( bVertexShader )
  2283. {
  2284. // don't cross the streams
  2285. Assert(!"Can't accept vertex shader in CreatePixelShader");
  2286. result = D3DERR_INVALIDCALL;
  2287. }
  2288. else
  2289. {
  2290. IDirect3DPixelShader9 *newprog = new IDirect3DPixelShader9;
  2291. newprog->m_pixProgram = m_ctx->NewProgram( kGLMFragmentProgram, (char *)transbuf.Base() ) ;
  2292. newprog->m_device = this;
  2293. //------ find the frag program metadata and extract it..
  2294. // find the highwater mark
  2295. char *highWaterPrefix = "//HIGHWATER-"; // try to arrange this so it can work with pure GLSL if needed
  2296. char *highWaterStr = strstr( (char *)transbuf.Base(), highWaterPrefix );
  2297. if (highWaterStr)
  2298. {
  2299. char *highWaterActualData = highWaterStr + strlen( highWaterPrefix );
  2300. int value = -1;
  2301. sscanf( highWaterActualData, "%d", &value );
  2302. newprog->m_pixHighWater = value;
  2303. newprog->m_pixProgram->m_descs[kGLMGLSL].m_highWater = value;
  2304. }
  2305. else
  2306. {
  2307. Assert(!"couldn't find sampler map in pixel shader");
  2308. }
  2309. // find the sampler map
  2310. char *samplerMaskPrefix = "//SAMPLERMASK-"; // try to arrange this so it can work with pure GLSL if needed
  2311. char *samplerMaskStr = strstr( (char *)transbuf.Base(), samplerMaskPrefix );
  2312. if (samplerMaskStr)
  2313. {
  2314. char *samplerMaskActualData = samplerMaskStr + strlen( samplerMaskPrefix );
  2315. int value = -1;
  2316. sscanf( samplerMaskActualData, "%04x", &value );
  2317. newprog->m_pixSamplerMask = value;
  2318. newprog->m_pixProgram->m_samplerMask = value; // helps GLM maintain a better linked pair cache even when SRGB sampler state changes
  2319. }
  2320. else
  2321. {
  2322. Assert(!"couldn't find sampler map in pixel shader");
  2323. }
  2324. *ppShader = newprog;
  2325. result = S_OK;
  2326. }
  2327. }
  2328. return result;
  2329. }
  2330. IDirect3DPixelShader9::~IDirect3DPixelShader9()
  2331. {
  2332. GLMPRINTF(( ">-A- ~IDirect3DPixelShader9" ));
  2333. if (m_device)
  2334. {
  2335. m_device->ReleasedPixelShader( this );
  2336. if (m_pixProgram)
  2337. {
  2338. m_pixProgram->m_ctx->DelProgram( m_pixProgram );
  2339. m_pixProgram = NULL;
  2340. }
  2341. m_device = NULL;
  2342. }
  2343. GLMPRINTF(( "<-A- ~IDirect3DPixelShader9" ));
  2344. }
  2345. HRESULT IDirect3DDevice9::SetPixelShader(IDirect3DPixelShader9* pShader)
  2346. {
  2347. if (pShader)
  2348. {
  2349. m_ctx->SetDrawingProgram( kGLMFragmentProgram, pShader->m_pixProgram );
  2350. }
  2351. else
  2352. {
  2353. m_ctx->SetDrawingProgram( kGLMFragmentProgram, NULL );
  2354. }
  2355. m_pixelShader = pShader;
  2356. return S_OK;
  2357. }
  2358. HRESULT IDirect3DDevice9::SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount)
  2359. {
  2360. m_ctx->SetProgramParametersF( kGLMFragmentProgram, StartRegister, (float *)pConstantData, Vector4fCount );
  2361. return S_OK;
  2362. }
  2363. HRESULT IDirect3DDevice9::SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount)
  2364. {
  2365. GLMPRINTF(("-X- Ignoring IDirect3DDevice9::SetPixelShaderConstantB call, count was %d", BoolCount ));
  2366. // actually no way to do this yet.
  2367. // m_ctx->SetProgramParametersB( kGLMFragmentProgram, StartRegister, pConstantData, BoolCount );
  2368. return S_OK;
  2369. }
  2370. HRESULT IDirect3DDevice9::SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount)
  2371. {
  2372. GLMPRINTF(("-X- Ignoring IDirect3DDevice9::SetPixelShaderConstantI call, count was %d", Vector4iCount ));
  2373. // m_ctx->SetProgramParametersI( kGLMFragmentProgram, StartRegister, pConstantData, Vector4iCount );
  2374. return S_OK;
  2375. }
  2376. #pragma mark ----- Vertex Shaders - (IDirect3DDevice9)
  2377. HRESULT IDirect3DDevice9::CreateVertexShader(CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader, const char *pShaderName, char *pDebugLabel)
  2378. {
  2379. HRESULT result = D3DERR_INVALIDCALL;
  2380. *ppShader = NULL;
  2381. uint32 nCentroidMask = CentroidMaskFromName( false, pShaderName );
  2382. if ( g_bUseControlFlow || !m_ctx->Caps().m_hasDualShaders )
  2383. {
  2384. // either having control-flow 'on' or -glmdualshaders 'off' disqualifies ARB assembler mode
  2385. g_useASMTranslations = false;
  2386. }
  2387. if ( ! (g_useASMTranslations || g_useGLSLTranslations) )
  2388. {
  2389. Assert(!"Must set at least one translation option..");
  2390. *ppShader = NULL;
  2391. return -1;
  2392. }
  2393. else
  2394. {
  2395. int numTranslations = (g_useASMTranslations!=0) + (g_useGLSLTranslations!=0);
  2396. bool bVertexShader = false;
  2397. // 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.
  2398. // 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.
  2399. int maxTranslationSize = 500000; // size of any one translation
  2400. CUtlBuffer transbuf( 1000, numTranslations * maxTranslationSize, CUtlBuffer::TEXT_BUFFER );
  2401. CUtlBuffer tempbuf( 1000, maxTranslationSize, CUtlBuffer::TEXT_BUFFER );
  2402. if ( g_useASMTranslations )
  2403. {
  2404. // no extra tag needed for ARBvp, just use the !!ARBvp marker
  2405. tempbuf.EnsureCapacity( maxTranslationSize );
  2406. uint asmTransOptions = D3DToGL_OptionUseEnvParams | D3DToGL_OptionDoFixupZ | D3DToGL_OptionDoFixupY;
  2407. // D3DToGL_OptionDoUserClipPlanes not being set for asm yet, it generates NV VP 2..
  2408. g_D3DToOpenGLTranslatorASM.TranslateShader( (uint32 *) pFunction, &tempbuf, &bVertexShader, asmTransOptions, -1, 0, pDebugLabel );
  2409. // grow to encompass...
  2410. transbuf.PutString ( (char*)tempbuf.Base() );
  2411. transbuf.PutString( "\n\n" ); // whitespace
  2412. }
  2413. if ( g_useGLSLTranslations )
  2414. {
  2415. transbuf.PutString( "//GLSLvp\n" ); // this is required so GLM can crack the text apart
  2416. // note the GLSL translator wants its own buffer
  2417. tempbuf.EnsureCapacity( maxTranslationSize );
  2418. uint glslVertexShaderOptions = D3DToGL_OptionGLSL | D3DToGL_OptionUseEnvParams | D3DToGL_OptionDoFixupZ | D3DToGL_OptionDoFixupY;
  2419. if ( g_bUseControlFlow )
  2420. {
  2421. glslVertexShaderOptions |= D3DToGL_OptionAllowStaticControlFlow;
  2422. }
  2423. if ( m_ctx->Caps().m_hasNativeClipVertexMode )
  2424. {
  2425. // note the matched trickery over in IDirect3DDevice9::FlushStates -
  2426. // if on a chipset that does no have native gl_ClipVertex support, then
  2427. // omit writes to gl_ClipVertex, and instead submit plane equations that have been altered,
  2428. // and clipping will take place in GL space using gl_Position instead of gl_ClipVertex.
  2429. // note that this is very much a hack to mate up with ATI R5xx hardware constraints, and with older
  2430. // drivers even for later ATI parts like r6xx/r7xx. And it doesn't work on NV parts, so you really
  2431. // do have to choose the right way to go.
  2432. glslVertexShaderOptions |= D3DToGL_OptionDoUserClipPlanes;
  2433. }
  2434. if (m_ctx->Caps().m_hasBindableUniforms)
  2435. {
  2436. glslVertexShaderOptions |= D3DToGL_OptionUseBindableUniforms;
  2437. }
  2438. g_D3DToOpenGLTranslatorGLSL.TranslateShader( (uint32 *) pFunction, &tempbuf, &bVertexShader, glslVertexShaderOptions, -1, nCentroidMask, pDebugLabel );
  2439. transbuf.PutString( (char*)tempbuf.Base() );
  2440. transbuf.PutString( "\n\n" ); // whitespace
  2441. }
  2442. if ( !bVertexShader )
  2443. {
  2444. // don't cross the streams
  2445. Assert(!"Can't accept pixel shader in CreateVertexShader");
  2446. result = D3DERR_INVALIDCALL;
  2447. }
  2448. else
  2449. {
  2450. IDirect3DVertexShader9 *newprog = new IDirect3DVertexShader9;
  2451. newprog->m_device = this;
  2452. newprog->m_vtxProgram = m_ctx->NewProgram( kGLMVertexProgram, (char *)transbuf.Base() ) ;
  2453. // find the highwater mark..
  2454. char *highWaterPrefix = "//HIGHWATER-"; // try to arrange this so it can work with pure GLSL if needed
  2455. char *highWaterStr = strstr( (char *)transbuf.Base(), highWaterPrefix );
  2456. if (highWaterStr)
  2457. {
  2458. char *highWaterActualData = highWaterStr + strlen( highWaterPrefix );
  2459. int value = -1;
  2460. sscanf( highWaterActualData, "%d", &value );
  2461. newprog->m_vtxHighWater = value;
  2462. newprog->m_vtxProgram->m_descs[kGLMGLSL].m_highWater = value;
  2463. }
  2464. else
  2465. {
  2466. Assert(!"couldn't find highwater mark in vertex shader");
  2467. }
  2468. // find the attrib map..
  2469. char *attribMapPrefix = "//ATTRIBMAP-"; // try to arrange this so it can work with pure GLSL if needed
  2470. char *attribMapStr = strstr( (char *)transbuf.Base(), attribMapPrefix );
  2471. if (attribMapStr)
  2472. {
  2473. char *attribMapActualData = attribMapStr + strlen( attribMapPrefix );
  2474. for( int i=0; i<16; i++)
  2475. {
  2476. int value = -1;
  2477. char *dataItem = attribMapActualData + (i*3);
  2478. sscanf( dataItem, "%02x", &value );
  2479. if (value >=0)
  2480. {
  2481. // make sure it's not a terminator
  2482. if (value == 0xBB)
  2483. {
  2484. Debugger();
  2485. }
  2486. }
  2487. else
  2488. {
  2489. // probably an 'xx'... check
  2490. if ( (dataItem[0] != 'x') || (dataItem[1] != 'x') )
  2491. {
  2492. Debugger(); // bad news
  2493. }
  2494. else
  2495. {
  2496. value = 0xBB; // not likely to see one of these... "fog with usage index 11"
  2497. }
  2498. }
  2499. newprog->m_vtxAttribMap[i] = value;
  2500. }
  2501. }
  2502. else
  2503. {
  2504. Debugger(); // that's bad...
  2505. }
  2506. *ppShader = newprog;
  2507. result = S_OK;
  2508. }
  2509. }
  2510. return result;
  2511. }
  2512. IDirect3DVertexShader9::~IDirect3DVertexShader9()
  2513. {
  2514. GLMPRINTF(( ">-A- ~IDirect3DVertexShader9" ));
  2515. if (m_device)
  2516. {
  2517. m_device->ReleasedVertexShader( this );
  2518. if (m_vtxProgram)
  2519. {
  2520. m_vtxProgram->m_ctx->DelProgram( m_vtxProgram );
  2521. m_vtxProgram = NULL;
  2522. }
  2523. m_device = NULL;
  2524. }
  2525. else
  2526. {
  2527. }
  2528. GLMPRINTF(( "<-A- ~IDirect3DVertexShader9" ));
  2529. }
  2530. HRESULT IDirect3DDevice9::SetVertexShader(IDirect3DVertexShader9* pShader)
  2531. {
  2532. if (pShader)
  2533. {
  2534. m_ctx->SetDrawingProgram( kGLMVertexProgram, pShader->m_vtxProgram );
  2535. }
  2536. else
  2537. {
  2538. m_ctx->SetDrawingProgram( kGLMVertexProgram, NULL );
  2539. }
  2540. m_vertexShader = pShader;
  2541. return S_OK;
  2542. }
  2543. HRESULT IDirect3DDevice9::SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) // groups of 4 floats!
  2544. {
  2545. m_ctx->SetProgramParametersF( kGLMVertexProgram, StartRegister, (float *)pConstantData, Vector4fCount );
  2546. return S_OK;
  2547. }
  2548. HRESULT IDirect3DDevice9::SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) // individual bool count!
  2549. {
  2550. m_ctx->SetProgramParametersB( kGLMVertexProgram, StartRegister, (int *)pConstantData, BoolCount );
  2551. return S_OK;
  2552. }
  2553. HRESULT IDirect3DDevice9::SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) // groups of 4 ints!
  2554. {
  2555. m_ctx->SetProgramParametersI( kGLMVertexProgram, StartRegister, (int *)pConstantData, Vector4iCount );
  2556. return S_OK;
  2557. }
  2558. #pragma mark ----- Shader Pairs - (IDirect3DDevice9)
  2559. // callers need to ifdef POSIX this, because this method does not exist on real DX9
  2560. HRESULT IDirect3DDevice9::LinkShaderPair( IDirect3DVertexShader9* vs, IDirect3DPixelShader9* ps )
  2561. {
  2562. // these are really GLSL "shaders" not "programs" but the old reference to "program" persists due to the assembler heritage
  2563. if (vs->m_vtxProgram && ps->m_pixProgram)
  2564. {
  2565. m_ctx->LinkShaderPair( vs->m_vtxProgram, ps->m_pixProgram );
  2566. }
  2567. return S_OK;
  2568. }
  2569. // callers need to ifdef POSIX this, because this method does not exist on real DX9
  2570. //
  2571. HRESULT IDirect3DDevice9::QueryShaderPair( int index, GLMShaderPairInfo *infoOut )
  2572. {
  2573. // these are really GLSL "shaders" not "programs" ...
  2574. m_ctx->QueryShaderPair( index, infoOut );
  2575. return S_OK;
  2576. }
  2577. #pragma mark ----- Vertex Buffers and Vertex Declarations - (IDirect3DDevice9)
  2578. HRESULT IDirect3DDevice9::CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl)
  2579. {
  2580. *ppDecl = NULL;
  2581. // the goal here is to arrive at something which lets us quickly generate GLMVertexSetups.
  2582. // the information we don't have, that must be inferred from the decls, is:
  2583. // -> how many unique streams (buffers) are used - pure curiosity
  2584. // -> 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.
  2585. // so init an array of per-stream offsets to 0.
  2586. // each one is a cursor that gets bumped by decls.
  2587. uint streamOffsets[ D3D_MAX_STREAMS ];
  2588. uint streamCount = 0;
  2589. uint attribMap[16];
  2590. uint attribMapIndex = 0;
  2591. memset( attribMap, 0xFF, sizeof( attribMap ) );
  2592. memset( streamOffsets, 0, sizeof( streamOffsets ) );
  2593. IDirect3DVertexDeclaration9 *decl9 = new IDirect3DVertexDeclaration9;
  2594. decl9->m_elemCount = 0;
  2595. for (const D3DVERTEXELEMENT9 *src = pVertexElements; (src->Stream != 0xFF); src++)
  2596. {
  2597. // element
  2598. D3DVERTEXELEMENT9_GL *elem = &decl9->m_elements[ decl9->m_elemCount++ ];
  2599. // copy the D3D decl wholesale.
  2600. elem->m_dxdecl = *src;
  2601. // latch current offset in this stream.
  2602. elem->m_gldecl.m_offset = streamOffsets[ elem->m_dxdecl.Stream ];
  2603. // figure out size of this attr and move the cursor
  2604. // if cursor was on zero, bump the active stream count
  2605. if (!streamOffsets[ elem->m_dxdecl.Stream ])
  2606. streamCount++;
  2607. int bytes = 0;
  2608. switch( elem->m_dxdecl.Type )
  2609. {
  2610. case D3DDECLTYPE_FLOAT1: elem->m_gldecl.m_datasize = 1; elem->m_gldecl.m_datatype = GL_FLOAT; elem->m_gldecl.m_normalized=0; bytes = 4; break;
  2611. case D3DDECLTYPE_FLOAT2: elem->m_gldecl.m_datasize = 2; elem->m_gldecl.m_datatype = GL_FLOAT; elem->m_gldecl.m_normalized=0; bytes = 8; break;
  2612. //case D3DVSDT_FLOAT3:
  2613. case D3DDECLTYPE_FLOAT3: elem->m_gldecl.m_datasize = 3; elem->m_gldecl.m_datatype = GL_FLOAT; elem->m_gldecl.m_normalized=0; bytes = 12; break;
  2614. //case D3DVSDT_FLOAT4:
  2615. case D3DDECLTYPE_FLOAT4: elem->m_gldecl.m_datasize = 4; elem->m_gldecl.m_datatype = GL_FLOAT; elem->m_gldecl.m_normalized=0; bytes = 16; break;
  2616. // case D3DVSDT_UBYTE4:
  2617. case D3DDECLTYPE_D3DCOLOR:
  2618. case D3DDECLTYPE_UBYTE4:
  2619. // Force this path since we're on 10.6.2 and can't rely on EXT_vertex_array_bgra
  2620. if ( 1 )
  2621. {
  2622. // pass 4 UB's but we know this is out of order compared to D3DCOLOR data
  2623. elem->m_gldecl.m_datasize = 4; elem->m_gldecl.m_datatype = GL_UNSIGNED_BYTE;
  2624. }
  2625. else
  2626. {
  2627. // pass a GL BGRA color courtesy of http://www.opengl.org/registry/specs/ARB/vertex_array_bgra.txt
  2628. elem->m_gldecl.m_datasize = GL_BGRA; elem->m_gldecl.m_datatype = GL_UNSIGNED_BYTE;
  2629. }
  2630. elem->m_gldecl.m_normalized = (elem->m_dxdecl.Type == D3DDECLTYPE_D3DCOLOR);
  2631. bytes = 4;
  2632. break;
  2633. case D3DDECLTYPE_SHORT2:
  2634. // pass 2 US's but we know this is out of order compared to D3DCOLOR data
  2635. elem->m_gldecl.m_datasize = 2; elem->m_gldecl.m_datatype = GL_UNSIGNED_SHORT;
  2636. elem->m_gldecl.m_normalized = 0;
  2637. bytes = 4;
  2638. break;
  2639. default: Debugger(); return D3DERR_INVALIDCALL; break;
  2640. /*
  2641. typedef enum _D3DDECLTYPE
  2642. {
  2643. D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.)
  2644. D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.)
  2645. D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.)
  2646. D3DDECLTYPE_FLOAT4 = 3, // 4D float
  2647. D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range
  2648. // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
  2649. D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte
  2650. D3DDECLTYPE_SHORT2 = 6, // 2D signed short expanded to (value, value, 0., 1.)
  2651. D3DDECLTYPE_SHORT4 = 7, // 4D signed short
  2652. // The following types are valid only with vertex shaders >= 2.0
  2653. D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0
  2654. D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
  2655. D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
  2656. D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
  2657. D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
  2658. D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
  2659. 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)
  2660. D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1)
  2661. D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values
  2662. D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused.
  2663. } D3DDECLTYPE;
  2664. */
  2665. }
  2666. // write the offset and move the cursor
  2667. elem->m_gldecl.m_offset = streamOffsets[elem->m_dxdecl.Stream];
  2668. streamOffsets[ elem->m_dxdecl.Stream ] += bytes;
  2669. // cannot write m_stride yet, so zero it
  2670. elem->m_gldecl.m_stride = 0;
  2671. elem->m_gldecl.m_buffer = NULL; // must be filled in at draw time..
  2672. // elem count was already bumped.
  2673. // update attrib map
  2674. attribMap[ attribMapIndex++ ] = (elem->m_dxdecl.Usage << 4) | (elem->m_dxdecl.UsageIndex);
  2675. }
  2676. // the loop is done, we now know how many active streams there are, how many atribs are active in the declaration,
  2677. // and how big each one is in terms of stride.
  2678. // all that is left is to go back and write the strides - the stride comes from the stream offset cursors accumulated earlier.
  2679. for( int j=0; j< decl9->m_elemCount; j++)
  2680. {
  2681. D3DVERTEXELEMENT9_GL *elem = &decl9->m_elements[ j ];
  2682. elem->m_gldecl.m_stride = streamOffsets[ elem->m_dxdecl.Stream ];
  2683. }
  2684. *ppDecl = decl9;
  2685. return S_OK;
  2686. }
  2687. IDirect3DVertexDeclaration9::~IDirect3DVertexDeclaration9()
  2688. {
  2689. GLMPRINTF(("-A- ~IDirect3DVertexDeclaration9 signpost"));
  2690. }
  2691. HRESULT IDirect3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl)
  2692. {
  2693. // we just latch it. At draw time we combine the current vertex decl with the current stream set and generate a vertex setup for GLM.
  2694. // GLM can see what the differences are and act accordingly to adjust vert attrib bindings.
  2695. m_vertDecl = pDecl;
  2696. return S_OK;
  2697. }
  2698. HRESULT IDirect3DDevice9::SetFVF(DWORD FVF)
  2699. {
  2700. Debugger();
  2701. }
  2702. HRESULT IDirect3DDevice9::GetFVF(DWORD* pFVF)
  2703. {
  2704. Debugger();
  2705. }
  2706. #pragma mark ----- Vertex Buffers and Streams - (IDirect3DDevice9)
  2707. #pragma mark ----- Create function moved to be adjacent to other buffer methods
  2708. HRESULT IDirect3DDevice9::SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
  2709. {
  2710. // perfectly legal to see a vertex buffer of NULL get passed in here.
  2711. // so we need an array to track these.
  2712. // OK, we are being given the stride, we don't need to calc it..
  2713. 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_name: -1, OffsetInBytes, Stride));
  2714. if (pStreamData)
  2715. {
  2716. m_streams[ StreamNumber ].m_vtxBuffer = pStreamData;
  2717. m_streams[ StreamNumber ].m_offset = OffsetInBytes;
  2718. m_streams[ StreamNumber ].m_stride = Stride;
  2719. }
  2720. else
  2721. {
  2722. m_streams[ StreamNumber ].m_vtxBuffer = NULL;
  2723. m_streams[ StreamNumber ].m_offset = 0;
  2724. m_streams[ StreamNumber ].m_stride = 0;
  2725. }
  2726. }
  2727. #pragma mark ----- Index Buffers - (IDirect3DDevice9)
  2728. #pragma mark ----- Creatue function relocated to be adjacent to the rest of the index buffer methods
  2729. HRESULT IDirect3DDevice9::SetIndices(IDirect3DIndexBuffer9* pIndexData)
  2730. {
  2731. // just latch it.
  2732. m_indices.m_idxBuffer = pIndexData;
  2733. }
  2734. #pragma mark ----- Release Handlers - (IDirect3DDevice9)
  2735. void IDirect3DDevice9::ReleasedTexture( IDirect3DBaseTexture9 *baseTex )
  2736. {
  2737. // see if this texture is referenced in any of the texture units and scrub it if so.
  2738. for( int i=0; i<16; i++)
  2739. {
  2740. if (m_textures[i] == baseTex)
  2741. {
  2742. m_textures[i] = NULL;
  2743. m_ctx->SetSamplerTex( i, NULL ); // texture sets go straight through to GLM, no dirty bit
  2744. }
  2745. }
  2746. }
  2747. void IDirect3DDevice9::ReleasedSurface( IDirect3DSurface9 *surface )
  2748. {
  2749. for( int i=0; i<16; i++)
  2750. {
  2751. if (m_rtSurfaces[i]==surface)
  2752. {
  2753. // this was a surprise release... scrub it
  2754. m_rtSurfaces[i] = NULL;
  2755. GLMPRINTF(( "-A- Scrubbed surface %08x from m_rtSurfaces[%d]", surface, i ));
  2756. }
  2757. }
  2758. if( m_dsSurface == surface )
  2759. {
  2760. m_dsSurface = NULL;
  2761. GLMPRINTF(( "-A- Scrubbed surface %08x from m_dsSurface", surface ));
  2762. }
  2763. if ( m_defaultColorSurface == surface )
  2764. {
  2765. m_defaultColorSurface = NULL;
  2766. GLMPRINTF(( "-A- Scrubbed surface %08x from m_defaultColorSurface", surface ));
  2767. }
  2768. if ( m_defaultDepthStencilSurface == surface )
  2769. {
  2770. m_defaultDepthStencilSurface = NULL;
  2771. GLMPRINTF(( "-A- Scrubbed surface %08x from m_defaultDepthStencilSurface", surface ));
  2772. }
  2773. }
  2774. void IDirect3DDevice9::ReleasedPixelShader( IDirect3DPixelShader9 *pixelShader )
  2775. {
  2776. if ( m_pixelShader == pixelShader )
  2777. {
  2778. m_pixelShader = NULL;
  2779. GLMPRINTF(( "-A- Scrubbed pixel shader %08x from m_pixelShader", pixelShader ));
  2780. }
  2781. }
  2782. void IDirect3DDevice9::ReleasedVertexShader( IDirect3DVertexShader9 *vertexShader )
  2783. {
  2784. if ( m_vertexShader == vertexShader )
  2785. {
  2786. m_vertexShader = NULL;
  2787. GLMPRINTF(( "-A- Scrubbed vertex shader %08x from m_vertexShader", vertexShader ));
  2788. }
  2789. }
  2790. void IDirect3DDevice9::ReleasedVertexBuffer( IDirect3DVertexBuffer9 *vertexBuffer )
  2791. {
  2792. for (int i=0; i< D3D_MAX_STREAMS; i++)
  2793. {
  2794. if ( m_streams[i].m_vtxBuffer == vertexBuffer )
  2795. {
  2796. m_streams[i].m_vtxBuffer = NULL;
  2797. GLMPRINTF(( "-A- Scrubbed vertex buffer %08x from m_streams[%d]", vertexBuffer, i ));
  2798. }
  2799. }
  2800. }
  2801. void IDirect3DDevice9::ReleasedIndexBuffer( IDirect3DIndexBuffer9 *indexBuffer )
  2802. {
  2803. if ( m_indices.m_idxBuffer == indexBuffer )
  2804. {
  2805. m_indices.m_idxBuffer = NULL;
  2806. GLMPRINTF(( "-A- Scrubbed index buffer %08x from m_indices", indexBuffer ));
  2807. }
  2808. }
  2809. void IDirect3DDevice9::ReleasedQuery( IDirect3DQuery9 *query )
  2810. {
  2811. // nothing to do yet..
  2812. }
  2813. #pragma mark ----- Queries - (IDirect3DDevice9)
  2814. // note that detection of whether queries are supported is done by trying to create one.
  2815. // so for GL, be observant here of whether we have that capability or not.
  2816. // pretty much have this everywhere but i950.
  2817. HRESULT IDirect3DDevice9::CreateQuery(D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery)
  2818. {
  2819. if (m_ctx->Caps().m_hasOcclusionQuery)
  2820. {
  2821. IDirect3DQuery9 *newquery = new IDirect3DQuery9;
  2822. newquery->m_device = this;
  2823. newquery->m_type = Type;
  2824. newquery->m_ctx = m_ctx;
  2825. GLMQueryParams params;
  2826. memset( &params, 0, sizeof(params) );
  2827. bool known = false;
  2828. switch(newquery->m_type)
  2829. {
  2830. case D3DQUERYTYPE_OCCLUSION: /* D3DISSUE_BEGIN, D3DISSUE_END */
  2831. // create an occlusion query
  2832. params.m_type = EOcclusion;
  2833. break;
  2834. case D3DQUERYTYPE_EVENT: /* D3DISSUE_END */
  2835. params.m_type = EFence;
  2836. break;
  2837. case D3DQUERYTYPE_RESOURCEMANAGER: /* D3DISSUE_END */
  2838. case D3DQUERYTYPE_TIMESTAMP: /* D3DISSUE_END */
  2839. case D3DQUERYTYPE_TIMESTAMPFREQ: /* D3DISSUE_END */
  2840. case D3DQUERYTYPE_INTERFACETIMINGS: /* D3DISSUE_BEGIN, D3DISSUE_END */
  2841. case D3DQUERYTYPE_PIXELTIMINGS: /* D3DISSUE_BEGIN, D3DISSUE_END */
  2842. case D3DQUERYTYPE_CACHEUTILIZATION: /* D3DISSUE_BEGIN, D3DISSUE_END */
  2843. Assert( !"Un-implemented query type" );
  2844. break;
  2845. default:
  2846. Assert( !"Unknown query type" );
  2847. break;
  2848. }
  2849. newquery->m_query = m_ctx->NewQuery( &params );
  2850. *ppQuery = newquery;
  2851. return S_OK;
  2852. }
  2853. else
  2854. {
  2855. *ppQuery = NULL;
  2856. return -1; // failed
  2857. }
  2858. }
  2859. IDirect3DQuery9::~IDirect3DQuery9()
  2860. {
  2861. GLMPRINTF((">-A- ~IDirect3DQuery9"));
  2862. if (m_device)
  2863. {
  2864. m_device->ReleasedQuery( this );
  2865. if (m_query)
  2866. {
  2867. GLMPRINTF((">-A- ~IDirect3DQuery9 freeing m_query"));
  2868. m_query->m_ctx->DelQuery( m_query );
  2869. m_query = NULL;
  2870. GLMPRINTF(("<-A- ~IDirect3DQuery9 freeing m_query done"));
  2871. }
  2872. m_device = NULL;
  2873. }
  2874. GLMPRINTF(("<-A- ~IDirect3DQuery9"));
  2875. }
  2876. #pragma mark ----- Render States - (IDirect3DDevice9)
  2877. struct D3D_RSINFO
  2878. {
  2879. int m_class;
  2880. D3DRENDERSTATETYPE m_state;
  2881. DWORD m_defval;
  2882. // m_class runs 0-3.
  2883. // 3 = must implement - fully general - "obey"
  2884. // 2 = implement setup to the default value (it has a GL effect but does not change later) "obey once"
  2885. // 1 = "fake implement" setup to the default value no GL effect, debug break if anything but default value comes through - "ignore"
  2886. // 0 = game never ever sets this one, break if someone even tries. "complain"
  2887. };
  2888. #define D3DRS_VALUE_LIMIT 210
  2889. bool g_D3DRS_INFO_unpacked_ready = false; // set to true after unpack
  2890. D3D_RSINFO g_D3DRS_INFO_unpacked[ D3DRS_VALUE_LIMIT+1 ];
  2891. #ifdef D3D_RSI
  2892. #error macro collision... rename this
  2893. #else
  2894. #define D3D_RSI(nclass,nstate,ndefval) { nclass, nstate, ndefval }
  2895. #endif
  2896. // FP conversions to hex courtesy of http://babbage.cs.qc.cuny.edu/IEEE-754/Decimal.html
  2897. #define CONST_DZERO 0x00000000
  2898. #define CONST_DONE 0x3F800000
  2899. #define CONST_D64 0x42800000
  2900. #define DONT_KNOW_YET 0x31415926
  2901. // see http://www.toymaker.info/Games/html/render_states.html
  2902. D3D_RSINFO g_D3DRS_INFO_packed[] =
  2903. {
  2904. // these do not have to be in any particular order. they get unpacked into the empty array above for direct indexing.
  2905. D3D_RSI( 3, D3DRS_ZENABLE, DONT_KNOW_YET ), // enable Z test (or W buffering)
  2906. D3D_RSI( 3, D3DRS_ZWRITEENABLE, DONT_KNOW_YET ), // enable Z write
  2907. D3D_RSI( 3, D3DRS_ZFUNC, DONT_KNOW_YET ), // select Z func
  2908. D3D_RSI( 3, D3DRS_COLORWRITEENABLE, TRUE ), // see transitiontable.cpp "APPLY_RENDER_STATE_FUNC( D3DRS_COLORWRITEENABLE, ColorWriteEnable )"
  2909. D3D_RSI( 3, D3DRS_CULLMODE, D3DCULL_CCW ), // backface cull control
  2910. D3D_RSI( 3, D3DRS_ALPHABLENDENABLE, DONT_KNOW_YET ), // ->CTransitionTable::ApplySeparateAlphaBlend and ApplyAlphaBlend
  2911. D3D_RSI( 3, D3DRS_BLENDOP, D3DBLENDOP_ADD ),
  2912. D3D_RSI( 3, D3DRS_SRCBLEND, DONT_KNOW_YET ),
  2913. D3D_RSI( 3, D3DRS_DESTBLEND, DONT_KNOW_YET ),
  2914. D3D_RSI( 1, D3DRS_SEPARATEALPHABLENDENABLE, FALSE ), // hit in CTransitionTable::ApplySeparateAlphaBlend
  2915. D3D_RSI( 1, D3DRS_SRCBLENDALPHA, D3DBLEND_ONE ), // going to demote these to class 1 until I figure out if they are implementable
  2916. D3D_RSI( 1, D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO ),
  2917. D3D_RSI( 1, D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD ),
  2918. // what is the deal with alpha test... looks like it is inited to off.
  2919. D3D_RSI( 3, D3DRS_ALPHATESTENABLE, 0 ),
  2920. D3D_RSI( 3, D3DRS_ALPHAREF, 0 ),
  2921. D3D_RSI( 3, D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL ),
  2922. D3D_RSI( 3, D3DRS_STENCILENABLE, FALSE ),
  2923. D3D_RSI( 3, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP ),
  2924. D3D_RSI( 3, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP ),
  2925. D3D_RSI( 3, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP ),
  2926. D3D_RSI( 3, D3DRS_STENCILFUNC, D3DCMP_ALWAYS ),
  2927. D3D_RSI( 3, D3DRS_STENCILREF, 0 ),
  2928. D3D_RSI( 3, D3DRS_STENCILMASK, 0xFFFFFFFF ),
  2929. D3D_RSI( 3, D3DRS_STENCILWRITEMASK, 0xFFFFFFFF ),
  2930. D3D_RSI( 3, D3DRS_TWOSIDEDSTENCILMODE, FALSE ),
  2931. D3D_RSI( 3, D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP ),
  2932. D3D_RSI( 3, D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP ),
  2933. D3D_RSI( 3, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP ),
  2934. D3D_RSI( 3, D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS ),
  2935. D3D_RSI( 3, D3DRS_FOGENABLE, FALSE ), // see CShaderAPIDx8::FogMode and friends - be ready to do the ARB fog linear option madness
  2936. D3D_RSI( 3, D3DRS_FOGCOLOR, 0 ),
  2937. D3D_RSI( 3, D3DRS_FOGTABLEMODE, D3DFOG_NONE ),
  2938. D3D_RSI( 3, D3DRS_FOGSTART, CONST_DZERO ),
  2939. D3D_RSI( 3, D3DRS_FOGEND, CONST_DONE ),
  2940. D3D_RSI( 3, D3DRS_FOGDENSITY, CONST_DZERO ),
  2941. D3D_RSI( 3, D3DRS_RANGEFOGENABLE, FALSE ),
  2942. D3D_RSI( 3, D3DRS_FOGVERTEXMODE, D3DFOG_NONE ), // watch out for CShaderAPIDx8::CommitPerPassFogMode....
  2943. D3D_RSI( 3, D3DRS_MULTISAMPLEANTIALIAS, TRUE ),
  2944. D3D_RSI( 3, D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF ),
  2945. D3D_RSI( 3, D3DRS_SCISSORTESTENABLE, FALSE ), // heed IDirect3DDevice9::SetScissorRect
  2946. D3D_RSI( 3, D3DRS_DEPTHBIAS, CONST_DZERO ),
  2947. D3D_RSI( 3, D3DRS_SLOPESCALEDEPTHBIAS, CONST_DZERO ),
  2948. D3D_RSI( 3, D3DRS_COLORWRITEENABLE1, 0x0000000f ),
  2949. D3D_RSI( 3, D3DRS_COLORWRITEENABLE2, 0x0000000f ),
  2950. D3D_RSI( 3, D3DRS_COLORWRITEENABLE3, 0x0000000f ),
  2951. D3D_RSI( 3, D3DRS_SRGBWRITEENABLE, 0 ), // heeded but ignored..
  2952. D3D_RSI( 2, D3DRS_CLIPPING, TRUE ), // um, yeah, clipping is enabled (?)
  2953. D3D_RSI( 3, D3DRS_CLIPPLANEENABLE, 0 ), // mask 1<<n of active user clip planes.
  2954. D3D_RSI( 0, D3DRS_LIGHTING, 0 ), // strange, someone turns it on then off again. move to class 0 and just ignore it (lie)?
  2955. D3D_RSI( 3, D3DRS_FILLMODE, D3DFILL_SOLID ),
  2956. D3D_RSI( 1, D3DRS_SHADEMODE, D3DSHADE_GOURAUD ),
  2957. D3D_RSI( 1, D3DRS_LASTPIXEL, TRUE ),
  2958. D3D_RSI( 1, D3DRS_DITHERENABLE, 0 ), //set to false by game, no one sets it to true
  2959. D3D_RSI( 1, D3DRS_SPECULARENABLE, FALSE ),
  2960. D3D_RSI( 1, D3DRS_TEXTUREFACTOR, 0xFFFFFFFF ), // watch out for CShaderAPIDx8::Color3f et al.
  2961. D3D_RSI( 1, D3DRS_WRAP0, 0 ),
  2962. D3D_RSI( 1, D3DRS_WRAP1, 0 ),
  2963. D3D_RSI( 1, D3DRS_WRAP2, 0 ),
  2964. D3D_RSI( 1, D3DRS_WRAP3, 0 ),
  2965. D3D_RSI( 1, D3DRS_WRAP4, 0 ),
  2966. D3D_RSI( 1, D3DRS_WRAP5, 0 ),
  2967. D3D_RSI( 1, D3DRS_WRAP6, 0 ),
  2968. D3D_RSI( 1, D3DRS_WRAP7, 0 ),
  2969. D3D_RSI( 1, D3DRS_AMBIENT, 0 ), // FF lighting, no
  2970. D3D_RSI( 1, D3DRS_COLORVERTEX, TRUE ), // FF lighing again
  2971. D3D_RSI( 1, D3DRS_LOCALVIEWER, TRUE ), // FF lighting
  2972. D3D_RSI( 1, D3DRS_NORMALIZENORMALS, FALSE ), // FF mode I think. CShaderAPIDx8::SetVertexBlendState says it might switch this on when skinning is in play
  2973. D3D_RSI( 1, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL ), // hit only in CShaderAPIDx8::ResetRenderState
  2974. D3D_RSI( 1, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2 ),
  2975. D3D_RSI( 1, D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL ),
  2976. D3D_RSI( 1, D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL ),
  2977. D3D_RSI( 1, D3DRS_VERTEXBLEND, D3DVBF_DISABLE ), // also being set by CShaderAPIDx8::SetVertexBlendState, so might be FF
  2978. D3D_RSI( 1, D3DRS_POINTSIZE, CONST_DONE ),
  2979. D3D_RSI( 1, D3DRS_POINTSIZE_MIN, CONST_DONE ),
  2980. D3D_RSI( 1, D3DRS_POINTSPRITEENABLE, FALSE ),
  2981. D3D_RSI( 1, D3DRS_POINTSCALEENABLE, FALSE ),
  2982. D3D_RSI( 1, D3DRS_POINTSCALE_A, CONST_DONE ),
  2983. D3D_RSI( 1, D3DRS_POINTSCALE_B, CONST_DZERO ),
  2984. D3D_RSI( 1, D3DRS_POINTSCALE_C, CONST_DZERO ),
  2985. D3D_RSI( 1, D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE ),
  2986. D3D_RSI( 1, D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE ),
  2987. D3D_RSI( 1, D3DRS_POINTSIZE_MAX, CONST_D64 ),
  2988. D3D_RSI( 1, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE ),
  2989. D3D_RSI( 1, D3DRS_TWEENFACTOR, CONST_DZERO ),
  2990. D3D_RSI( 1, D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC ),
  2991. D3D_RSI( 1, D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR ),
  2992. D3D_RSI( 1, D3DRS_ANTIALIASEDLINEENABLE, FALSE ), // just ignore it
  2993. D3D_RSI( 1, D3DRS_MINTESSELLATIONLEVEL, CONST_DONE ),
  2994. D3D_RSI( 1, D3DRS_MAXTESSELLATIONLEVEL, CONST_DONE ),
  2995. D3D_RSI( 1, D3DRS_ADAPTIVETESS_X, CONST_DZERO ),
  2996. D3D_RSI( 1, D3DRS_ADAPTIVETESS_Y, CONST_DZERO ), // Overridden as Alpha-to-coverage contrl
  2997. D3D_RSI( 1, D3DRS_ADAPTIVETESS_Z, CONST_DONE ),
  2998. D3D_RSI( 1, D3DRS_ADAPTIVETESS_W, CONST_DZERO ),
  2999. D3D_RSI( 1, D3DRS_ENABLEADAPTIVETESSELLATION, FALSE ),
  3000. D3D_RSI( 1, D3DRS_BLENDFACTOR, 0xffffffff ),
  3001. D3D_RSI( 1, D3DRS_WRAP8, 0 ),
  3002. D3D_RSI( 1, D3DRS_WRAP9, 0 ),
  3003. D3D_RSI( 1, D3DRS_WRAP10, 0 ),
  3004. D3D_RSI( 1, D3DRS_WRAP11, 0 ),
  3005. D3D_RSI( 1, D3DRS_WRAP12, 0 ),
  3006. D3D_RSI( 1, D3DRS_WRAP13, 0 ),
  3007. D3D_RSI( 1, D3DRS_WRAP14, 0 ),
  3008. D3D_RSI( 1, D3DRS_WRAP15, 0 ),
  3009. D3D_RSI( -1, (D3DRENDERSTATETYPE)0, 0 ) // terminator
  3010. };
  3011. void UnpackD3DRSITable( void )
  3012. {
  3013. memset (g_D3DRS_INFO_unpacked, 0, sizeof(g_D3DRS_INFO_unpacked) );
  3014. for( D3D_RSINFO *packed = g_D3DRS_INFO_packed; packed->m_class >= 0; packed++ )
  3015. {
  3016. if ( (packed->m_state <0) || (packed->m_state >= D3DRS_VALUE_LIMIT) )
  3017. {
  3018. // bad
  3019. Debugger();
  3020. }
  3021. else
  3022. {
  3023. // dispatch it to the unpacked array
  3024. g_D3DRS_INFO_unpacked[ packed->m_state ] = *packed;
  3025. }
  3026. }
  3027. }
  3028. // convenience functions
  3029. GLenum D3DCompareFuncToGL( DWORD function )
  3030. {
  3031. switch ( function )
  3032. {
  3033. case D3DCMP_NEVER : return GL_NEVER; // Always fail the test.
  3034. case D3DCMP_LESS : return GL_LESS; // Accept the new pixel if its value is less than the value of the current pixel.
  3035. case D3DCMP_EQUAL : return GL_EQUAL; // Accept the new pixel if its value equals the value of the current pixel.
  3036. case D3DCMP_LESSEQUAL : return GL_LEQUAL; // Accept the new pixel if its value is less than or equal to the value of the current pixel. **
  3037. case D3DCMP_GREATER : return GL_GREATER; // Accept the new pixel if its value is greater than the value of the current pixel.
  3038. case D3DCMP_NOTEQUAL : return GL_NOTEQUAL; // Accept the new pixel if its value does not equal the value of the current pixel.
  3039. case D3DCMP_GREATEREQUAL: return GL_GEQUAL; // Accept the new pixel if its value is greater than or equal to the value of the current pixel.
  3040. case D3DCMP_ALWAYS : return GL_ALWAYS; // Always pass the test.
  3041. default : Debugger(); return 0xFFFFFFFF;
  3042. }
  3043. }
  3044. static GLenum D3DStencilOpToGL( DWORD operation )
  3045. {
  3046. switch( operation )
  3047. {
  3048. case D3DSTENCILOP_KEEP : return GL_KEEP;
  3049. case D3DSTENCILOP_ZERO : return GL_ZERO;
  3050. case D3DSTENCILOP_REPLACE : return GL_REPLACE;
  3051. case D3DSTENCILOP_INCRSAT : return GL_INCR;
  3052. case D3DSTENCILOP_DECRSAT : return GL_DECR;
  3053. case D3DSTENCILOP_INVERT : return GL_INVERT;
  3054. case D3DSTENCILOP_INCR : return GL_INCR_WRAP_EXT;
  3055. case D3DSTENCILOP_DECR : return GL_DECR_WRAP_EXT;
  3056. default : Debugger(); return 0xFFFFFFFF;
  3057. }
  3058. }
  3059. static GLenum D3DBlendFactorToGL( DWORD equation )
  3060. {
  3061. switch (equation)
  3062. {
  3063. case D3DBLEND_ZERO : return GL_ZERO; // Blend factor is (0, 0, 0, 0).
  3064. case D3DBLEND_ONE : return GL_ONE; // Blend factor is (1, 1, 1, 1).
  3065. case D3DBLEND_SRCCOLOR : return GL_SRC_COLOR; // Blend factor is (Rs, Gs, Bs, As).
  3066. case D3DBLEND_INVSRCCOLOR : return GL_ONE_MINUS_SRC_COLOR; // Blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As).
  3067. case D3DBLEND_SRCALPHA : return GL_SRC_ALPHA; // Blend factor is (As, As, As, As).
  3068. case D3DBLEND_INVSRCALPHA : return GL_ONE_MINUS_SRC_ALPHA; // Blend factor is ( 1 - As, 1 - As, 1 - As, 1 - As).
  3069. case D3DBLEND_DESTALPHA : return GL_DST_ALPHA; // Blend factor is (Ad Ad Ad Ad).
  3070. case D3DBLEND_INVDESTALPHA : return GL_ONE_MINUS_DST_ALPHA; // Blend factor is (1 - Ad 1 - Ad 1 - Ad 1 - Ad).
  3071. case D3DBLEND_DESTCOLOR : return GL_DST_COLOR; // Blend factor is (Rd, Gd, Bd, Ad).
  3072. case D3DBLEND_INVDESTCOLOR : return GL_ONE_MINUS_DST_COLOR; // Blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad).
  3073. case D3DBLEND_SRCALPHASAT : return GL_SRC_ALPHA_SATURATE; // Blend factor is (f, f, f, 1); where f = min(As, 1 - Ad).
  3074. /*
  3075. // these are weird.... break if we hit them
  3076. case D3DBLEND_BOTHSRCALPHA : Assert(0); return GL_ZERO; // Obsolete. Starting with DirectX 6, you can achieve the same effect by setting the source and destination blend factors to D3DBLEND_SRCALPHA and D3DBLEND_INVSRCALPHA in separate calls.
  3077. case D3DBLEND_BOTHINVSRCALPHA: Assert(0); return GL_ZERO; // Source blend factor is (1 - As, 1 - As, 1 - As, 1 - As), and destination blend factor is (As, As, As, As); the destination blend selection is overridden. This blend mode is supported only for the D3DRS_SRCBLEND render state.
  3078. case D3DBLEND_BLENDFACTOR : Assert(0); return GL_ZERO; // Constant color blending factor used by the frame-buffer blender. This blend mode is supported only if D3DPBLENDCAPS_BLENDFACTOR is set in the SrcBlendCaps or DestBlendCaps members of D3DCAPS9.
  3079. dxabstract.h has not heard of these, so let them hit the debugger if they come through
  3080. case D3DBLEND_INVBLENDFACTOR: //Inverted constant color-blending factor used by the frame-buffer blender. This blend mode is supported only if the D3DPBLENDCAPS_BLENDFACTOR bit is set in the SrcBlendCaps or DestBlendCaps members of D3DCAPS9.
  3081. case D3DBLEND_SRCCOLOR2: // Blend factor is (PSOutColor[1]r, PSOutColor[1]g, PSOutColor[1]b, not used). This flag is available in Direct3D 9Ex only.
  3082. case D3DBLEND_INVSRCCOLOR2: // Blend factor is (1 - PSOutColor[1]r, 1 - PSOutColor[1]g, 1 - PSOutColor[1]b, not used)). This flag is available in Direct3D 9Ex only.
  3083. */
  3084. default:
  3085. Debugger();
  3086. return 0xFFFFFFFF;
  3087. break;
  3088. }
  3089. }
  3090. static GLenum D3DBlendOperationToGL( DWORD operation )
  3091. {
  3092. switch (operation)
  3093. {
  3094. case D3DBLENDOP_ADD : return GL_FUNC_ADD; // The result is the destination added to the source. Result = Source + Destination
  3095. /* not covered by dxabstract.h..
  3096. case D3DBLENDOP_SUBTRACT : return GL_FUNC_SUBTRACT; // The result is the destination subtracted from to the source. Result = Source - Destination
  3097. case D3DBLENDOP_REVSUBTRACT : return GL_FUNC_REVERSE_SUBTRACT; // The result is the source subtracted from the destination. Result = Destination - Source
  3098. case D3DBLENDOP_MIN : return GL_MIN; // The result is the minimum of the source and destination. Result = MIN(Source, Destination)
  3099. case D3DBLENDOP_MAX : return GL_MAX; // The result is the maximum of the source and destination. Result = MAX(Source, Destination)
  3100. */
  3101. default:
  3102. Debugger();
  3103. return 0xFFFFFFFF;
  3104. break;
  3105. }
  3106. }
  3107. HRESULT IDirect3DDevice9::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value )
  3108. {
  3109. char rsSpew = 1;
  3110. char ignored = 0;
  3111. if (!g_D3DRS_INFO_unpacked_ready)
  3112. {
  3113. UnpackD3DRSITable();
  3114. g_D3DRS_INFO_unpacked_ready = true;
  3115. }
  3116. if (State >= D3DRS_VALUE_LIMIT)
  3117. {
  3118. Debugger(); // bad
  3119. }
  3120. else
  3121. {
  3122. D3D_RSINFO *info = &g_D3DRS_INFO_unpacked[ State ];
  3123. if (info->m_state != State)
  3124. {
  3125. Debugger(); // bad - we never set up that state in our list
  3126. }
  3127. if (rsSpew)
  3128. {
  3129. 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 ));
  3130. }
  3131. switch( info->m_class )
  3132. {
  3133. case 0: // just ignore quietly. example: D3DRS_LIGHTING
  3134. ignored = 1;
  3135. break;
  3136. case 1:
  3137. {
  3138. // no GL response - and no error as long as the write value matches the default
  3139. if (Value != info->m_defval)
  3140. {
  3141. static char stop_here_1 = 0;
  3142. if (stop_here_1)
  3143. Debugger();
  3144. }
  3145. }
  3146. break;
  3147. case 2:
  3148. // provide GL response, but only support known default value
  3149. if (Value != info->m_defval)
  3150. {
  3151. static char stop_here_2 = 0;
  3152. if (stop_here_2)
  3153. Debugger();
  3154. }
  3155. // fall through to mode 3
  3156. case 3:
  3157. // full GL response, support any legal value
  3158. // note we're handling the class-2's as well.
  3159. switch(State)
  3160. {
  3161. case D3DRS_ZENABLE: // kGLDepthTestEnable
  3162. gl.m_DepthTestEnable.enable = Value;
  3163. gl.m_stateDirtyMask |= (1<<kGLDepthTestEnable);
  3164. break;
  3165. case D3DRS_ZWRITEENABLE: // kGLDepthMask
  3166. gl.m_DepthMask.mask = Value;
  3167. gl.m_stateDirtyMask |= (1<<kGLDepthMask);
  3168. break;
  3169. case D3DRS_ZFUNC:
  3170. {
  3171. // kGLDepthFunc
  3172. GLenum func = D3DCompareFuncToGL( Value );
  3173. gl.m_DepthFunc.func = func;
  3174. gl.m_stateDirtyMask |= (1<<kGLDepthFunc);
  3175. }
  3176. break;
  3177. case D3DRS_COLORWRITEENABLE: // kGLColorMaskSingle
  3178. {
  3179. gl.m_ColorMaskSingle.r = ((Value & D3DCOLORWRITEENABLE_RED) != 0) ? 0xFF : 0x00;
  3180. gl.m_ColorMaskSingle.g = ((Value & D3DCOLORWRITEENABLE_GREEN)!= 0) ? 0xFF : 0x00;
  3181. gl.m_ColorMaskSingle.b = ((Value & D3DCOLORWRITEENABLE_BLUE) != 0) ? 0xFF : 0x00;
  3182. gl.m_ColorMaskSingle.a = ((Value & D3DCOLORWRITEENABLE_ALPHA)!= 0) ? 0xFF : 0x00;
  3183. gl.m_stateDirtyMask |= (1<<kGLColorMaskSingle);
  3184. }
  3185. break;
  3186. case D3DRS_COLORWRITEENABLE1: // kGLColorMaskMultiple
  3187. case D3DRS_COLORWRITEENABLE2: // kGLColorMaskMultiple
  3188. case D3DRS_COLORWRITEENABLE3: // kGLColorMaskMultiple
  3189. ignored = 1;
  3190. break;
  3191. case D3DRS_CULLMODE: // kGLCullFaceEnable / kGLCullFrontFace
  3192. {
  3193. switch(Value)
  3194. {
  3195. case D3DCULL_NONE:
  3196. gl.m_CullFaceEnable.enable = false;
  3197. gl.m_CullFrontFace.value = GL_CCW; //doesn't matter
  3198. gl.m_stateDirtyMask |= (1<<kGLCullFaceEnable) | (1<<kGLCullFrontFace);
  3199. break;
  3200. case D3DCULL_CW:
  3201. gl.m_CullFaceEnable.enable = true;
  3202. gl.m_CullFrontFace.value = GL_CW; //origGL_CCW;
  3203. gl.m_stateDirtyMask |= (1<<kGLCullFaceEnable) | (1<<kGLCullFrontFace);
  3204. break;
  3205. case D3DCULL_CCW:
  3206. gl.m_CullFaceEnable.enable = true;
  3207. gl.m_CullFrontFace.value = GL_CCW; //origGL_CW;
  3208. gl.m_stateDirtyMask |= (1<<kGLCullFaceEnable) | (1<<kGLCullFrontFace);
  3209. break;
  3210. default: Debugger(); break;
  3211. }
  3212. }
  3213. break;
  3214. //-------------------------------------------------------------------------------------------- alphablend stuff
  3215. case D3DRS_ALPHABLENDENABLE: // kGLBlendEnable
  3216. gl.m_BlendEnable.enable = Value;
  3217. gl.m_stateDirtyMask |= (1<<kGLBlendEnable);
  3218. break;
  3219. case D3DRS_BLENDOP: // kGLBlendEquation // D3D blend-op ==> GL blend equation
  3220. {
  3221. GLenum equation = D3DBlendOperationToGL( Value );
  3222. gl.m_BlendEquation.equation = equation;
  3223. gl.m_stateDirtyMask |= (1<<kGLBlendEquation);
  3224. }
  3225. break;
  3226. case D3DRS_SRCBLEND: // kGLBlendFactor // D3D blend-factor ==> GL blend factor
  3227. case D3DRS_DESTBLEND: // kGLBlendFactor
  3228. {
  3229. GLenum factor = D3DBlendFactorToGL( Value );
  3230. if (State==D3DRS_SRCBLEND)
  3231. {
  3232. gl.m_BlendFactor.srcfactor = factor;
  3233. }
  3234. else
  3235. {
  3236. gl.m_BlendFactor.dstfactor = factor;
  3237. }
  3238. gl.m_stateDirtyMask |= (1<<kGLBlendFactor);
  3239. }
  3240. break;
  3241. case D3DRS_SEPARATEALPHABLENDENABLE:
  3242. case D3DRS_BLENDOPALPHA:
  3243. case D3DRS_SRCBLENDALPHA:
  3244. case D3DRS_DESTBLENDALPHA:
  3245. ignored = 1;
  3246. break;
  3247. case D3DRS_SRGBWRITEENABLE: // kGLBlendEnableSRGB
  3248. gl.m_BlendEnableSRGB.enable = Value;
  3249. gl.m_stateDirtyMask |= (1<<kGLBlendEnableSRGB);
  3250. break;
  3251. //-------------------------------------------------------------------------------------------- alphatest stuff
  3252. case D3DRS_ALPHATESTENABLE:
  3253. gl.m_AlphaTestEnable.enable = Value;
  3254. gl.m_stateDirtyMask |= (1<<kGLAlphaTestEnable);
  3255. break;
  3256. case D3DRS_ALPHAREF:
  3257. gl.m_AlphaTestFunc.ref = Value / 255.0f;
  3258. gl.m_stateDirtyMask |= (1<<kGLAlphaTestFunc);
  3259. break;
  3260. case D3DRS_ALPHAFUNC:
  3261. {
  3262. GLenum func = D3DCompareFuncToGL( Value );;
  3263. gl.m_AlphaTestFunc.func = func;
  3264. gl.m_stateDirtyMask |= (1<<kGLAlphaTestFunc);
  3265. }
  3266. break;
  3267. //-------------------------------------------------------------------------------------------- stencil stuff
  3268. case D3DRS_STENCILENABLE: // GLStencilTestEnable_t
  3269. {
  3270. gl.m_StencilTestEnable.enable = Value;
  3271. gl.m_stateDirtyMask |= (1<<kGLStencilTestEnable);
  3272. }
  3273. break;
  3274. case D3DRS_STENCILFAIL: // GLStencilOp_t "what do you do if stencil test fails"
  3275. {
  3276. GLenum stencilop = D3DStencilOpToGL( Value );
  3277. gl.m_StencilOp.sfail = stencilop;
  3278. gl.m_stateDirtyMask |= (1<<kGLStencilOp);
  3279. }
  3280. break;
  3281. case D3DRS_STENCILZFAIL: // GLStencilOp_t "what do you do if stencil test passes *but* depth test fails, if depth test happened"
  3282. {
  3283. GLenum stencilop = D3DStencilOpToGL( Value );
  3284. gl.m_StencilOp.dpfail = stencilop;
  3285. gl.m_stateDirtyMask |= (1<<kGLStencilOp);
  3286. }
  3287. break;
  3288. case D3DRS_STENCILPASS: // GLStencilOp_t "what do you do if stencil test and depth test both pass"
  3289. {
  3290. GLenum stencilop = D3DStencilOpToGL( Value );
  3291. gl.m_StencilOp.dppass = stencilop;
  3292. gl.m_stateDirtyMask |= (1<<kGLStencilOp);
  3293. }
  3294. break;
  3295. case D3DRS_STENCILFUNC: // GLStencilFunc_t
  3296. {
  3297. GLenum stencilfunc = D3DCompareFuncToGL( Value );
  3298. gl.m_StencilFunc.frontfunc = gl.m_StencilFunc.backfunc = stencilfunc;
  3299. gl.m_stateDirtyMask |= (1<<kGLStencilFunc);
  3300. }
  3301. break;
  3302. case D3DRS_STENCILREF: // GLStencilFunc_t
  3303. {
  3304. gl.m_StencilFunc.ref = Value;
  3305. gl.m_stateDirtyMask |= (1<<kGLStencilFunc);
  3306. }
  3307. break;
  3308. case D3DRS_STENCILMASK: // GLStencilFunc_t
  3309. {
  3310. //if (Value==255)
  3311. //{
  3312. // Value = 0xFFFFFFFF; // mask blast
  3313. //}
  3314. gl.m_StencilFunc.mask = Value;
  3315. gl.m_stateDirtyMask |= (1<<kGLStencilFunc);
  3316. }
  3317. break;
  3318. case D3DRS_STENCILWRITEMASK: // GLStencilWriteMask_t
  3319. {
  3320. //if (Value==255)
  3321. //{
  3322. // Value = 0xFFFFFFFF; // mask blast
  3323. //}
  3324. gl.m_StencilWriteMask.mask = Value;
  3325. gl.m_stateDirtyMask |= (1<<kGLStencilWriteMask);
  3326. }
  3327. break;
  3328. //-------------------------------------------------------------------------------------------- two-sided stencil stuff
  3329. case D3DRS_TWOSIDEDSTENCILMODE: // -> GL_STENCIL_TEST_TWO_SIDE_EXT... not yet implemented ?
  3330. case D3DRS_CCW_STENCILFAIL: // GLStencilOp_t
  3331. case D3DRS_CCW_STENCILZFAIL: // GLStencilOp_t
  3332. case D3DRS_CCW_STENCILPASS: // GLStencilOp_t
  3333. case D3DRS_CCW_STENCILFUNC: // GLStencilFunc_t
  3334. ignored = 1;
  3335. break;
  3336. case D3DRS_FOGENABLE: // none of these are implemented yet... erk
  3337. gl.m_FogEnable = (Value != 0);
  3338. GLMPRINTF(("-D- fogenable = %d",Value ));
  3339. //ignored = 1;
  3340. break;
  3341. case D3DRS_FOGCOLOR:
  3342. case D3DRS_FOGTABLEMODE:
  3343. case D3DRS_FOGSTART:
  3344. case D3DRS_FOGEND:
  3345. case D3DRS_FOGDENSITY:
  3346. case D3DRS_RANGEFOGENABLE:
  3347. case D3DRS_FOGVERTEXMODE:
  3348. ignored = 1;
  3349. break;
  3350. case D3DRS_MULTISAMPLEANTIALIAS:
  3351. case D3DRS_MULTISAMPLEMASK:
  3352. ignored = 1;
  3353. break;
  3354. case D3DRS_SCISSORTESTENABLE: // kGLScissorEnable
  3355. {
  3356. gl.m_ScissorEnable.enable = Value;
  3357. gl.m_stateDirtyMask |= (1<<kGLScissorEnable);
  3358. }
  3359. break;
  3360. case D3DRS_DEPTHBIAS: // kGLDepthBias
  3361. {
  3362. // the value in the dword is actually a float
  3363. float fvalue = *(float*)&Value;
  3364. gl.m_DepthBias.units = fvalue;
  3365. gl.m_stateDirtyMask |= (1<<kGLDepthBias);
  3366. }
  3367. break;
  3368. // good ref on these: http://aras-p.info/blog/2008/06/12/depth-bias-and-the-power-of-deceiving-yourself/
  3369. case D3DRS_SLOPESCALEDEPTHBIAS:
  3370. {
  3371. // the value in the dword is actually a float
  3372. float fvalue = *(float*)&Value;
  3373. gl.m_DepthBias.factor = fvalue;
  3374. gl.m_stateDirtyMask |= (1<<kGLDepthBias);
  3375. }
  3376. break;
  3377. // Alpha to coverage
  3378. case D3DRS_CLIPPING: // ???? is clipping ever turned off ??
  3379. ignored = 1;
  3380. break;
  3381. case D3DRS_CLIPPLANEENABLE: // kGLClipPlaneEnable
  3382. // d3d packs all the enables into one word.
  3383. // we break that out so we don't do N glEnable calls to sync -
  3384. // GLM is tracking one unique enable per plane.
  3385. for( int i=0; i<kGLMUserClipPlanes; i++)
  3386. {
  3387. gl.m_ClipPlaneEnable[i].enable = (Value & (1<<i)) != 0;
  3388. }
  3389. gl.m_stateDirtyMask |= (1<<kGLClipPlaneEnable);
  3390. break;
  3391. //-------------------------------------------------------------------------------------------- polygon/fill mode
  3392. case D3DRS_FILLMODE:
  3393. GLuint mode = 0;
  3394. switch(Value)
  3395. {
  3396. case D3DFILL_POINT: mode = GL_POINT; break;
  3397. case D3DFILL_WIREFRAME: mode = GL_LINE; break;
  3398. case D3DFILL_SOLID: mode = GL_FILL; break;
  3399. default:
  3400. Assert(!"unknown fill mode");
  3401. }
  3402. gl.m_PolygonMode.values[0] = gl.m_PolygonMode.values[1] = mode;
  3403. gl.m_stateDirtyMask |= (1<<kGLPolygonMode);
  3404. break;
  3405. }
  3406. break;
  3407. }
  3408. }
  3409. if (rsSpew && ignored)
  3410. {
  3411. GLMPRINTF(("-X- (ignored)"));
  3412. }
  3413. //Debugger();
  3414. return S_OK;
  3415. }
  3416. #pragma mark ----- Sampler States - (IDirect3DDevice9)
  3417. HRESULT IDirect3DDevice9::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value )
  3418. {
  3419. Assert(Sampler<16);
  3420. // the D3D-to-GL translation has been moved to FlushSamplers since we want to do it at draw time
  3421. // so this call just stuffs values in slots.
  3422. D3DSamplerDesc *samp = &m_samplers[ Sampler ];
  3423. switch( Type )
  3424. {
  3425. // addressing modes can be
  3426. // D3DTADDRESS_WRAP Tile the texture at every integer junction.
  3427. // D3DTADDRESS_MIRROR Similar to D3DTADDRESS_WRAP, except that the texture is flipped at every integer junction.
  3428. // D3DTADDRESS_CLAMP Texture coordinates outside the range [0.0, 1.0] are set to the texture color at 0.0 or 1.0, respectively.
  3429. // D3DTADDRESS_BORDER Texture coordinates outside the range [0.0, 1.0] are set to the border color.
  3430. // D3DTADDRESS_MIRRORONCE Similar to D3DTADDRESS_MIRROR and D3DTADDRESS_CLAMP.
  3431. // Takes the absolute value of the texture coordinate (thus, mirroring around 0),
  3432. // and then clamps to the maximum value. The most common usage is for volume textures,
  3433. // where support for the full D3DTADDRESS_MIRRORONCE texture-addressing mode is not
  3434. // necessary, but the data is symmetric around the one axis.
  3435. case D3DSAMP_ADDRESSU:
  3436. case D3DSAMP_ADDRESSV:
  3437. case D3DSAMP_ADDRESSW:
  3438. samp->m_addressModes[ Type - (int)D3DSAMP_ADDRESSU ] = (D3DTEXTUREADDRESS)Value;
  3439. break;
  3440. case D3DSAMP_BORDERCOLOR:
  3441. samp->m_borderColor = Value;
  3442. break;
  3443. case D3DSAMP_MAGFILTER: samp->m_magFilter = (D3DTEXTUREFILTERTYPE)Value; break;
  3444. case D3DSAMP_MINFILTER: samp->m_minFilter = (D3DTEXTUREFILTERTYPE)Value; break;
  3445. case D3DSAMP_MIPFILTER: samp->m_mipFilter = (D3DTEXTUREFILTERTYPE)Value; break;
  3446. case D3DSAMP_MIPMAPLODBIAS: samp->m_mipmapBias = Value; break; // float in sheep's clothing - check this one out
  3447. case D3DSAMP_MAXMIPLEVEL: samp->m_maxMipLevel = Value; break;
  3448. case D3DSAMP_MAXANISOTROPY: samp->m_maxAniso = Value; break;
  3449. case D3DSAMP_SRGBTEXTURE: samp->m_srgb = Value; break;
  3450. case D3DSAMP_SHADOWFILTER: samp->m_shadowFilter = Value; break;
  3451. default:
  3452. Assert(!"Unknown sampler parameter");
  3453. break;
  3454. }
  3455. gl.m_samplerDirtyMask |= (1<<Sampler); // at draw time, push the dirty samplers down to GLM
  3456. return S_OK;
  3457. }
  3458. HRESULT IDirect3DDevice9::FlushStates( uint mask )
  3459. {
  3460. uint stateHitMask = gl.m_stateDirtyMask & mask;
  3461. // note that we will turn off all the bits that are set in the hit mask, once the work is done
  3462. // so no need to individually clear.
  3463. if ( stateHitMask & (1<<kGLAlphaTestEnable) )
  3464. m_ctx->WriteAlphaTestEnable( &gl.m_AlphaTestEnable );
  3465. if ( stateHitMask & (1<<kGLAlphaTestFunc) )
  3466. m_ctx->WriteAlphaTestFunc( &gl.m_AlphaTestFunc );
  3467. if ( stateHitMask & (1<<kGLCullFaceEnable) )
  3468. m_ctx->WriteCullFaceEnable( &gl.m_CullFaceEnable );
  3469. if ( stateHitMask & (1<<kGLCullFrontFace) )
  3470. m_ctx->WriteCullFrontFace( &gl.m_CullFrontFace );
  3471. if ( stateHitMask & (1<<kGLPolygonMode) )
  3472. m_ctx->WritePolygonMode( &gl.m_PolygonMode );
  3473. if ( stateHitMask & (1<<kGLDepthBias) )
  3474. m_ctx->WriteDepthBias( &gl.m_DepthBias );
  3475. if ( stateHitMask & (1<<kGLScissorEnable) )
  3476. m_ctx->WriteScissorEnable( &gl.m_ScissorEnable );
  3477. if ( stateHitMask & (1<<kGLScissorBox) )
  3478. m_ctx->WriteScissorBox( &gl.m_ScissorBox );
  3479. if ( stateHitMask & (1<<kGLViewportBox) )
  3480. m_ctx->WriteViewportBox( &gl.m_ViewportBox );
  3481. if ( stateHitMask & (1<<kGLViewportDepthRange) )
  3482. m_ctx->WriteViewportDepthRange( &gl.m_ViewportDepthRange );
  3483. if ( stateHitMask & (1<<kGLClipPlaneEnable) )
  3484. {
  3485. for( int x=0; x<kGLMUserClipPlanes; x++)
  3486. {
  3487. m_ctx->WriteClipPlaneEnable( &gl.m_ClipPlaneEnable[x], x );
  3488. }
  3489. }
  3490. if ( stateHitMask & (1<<kGLClipPlaneEquation) )
  3491. {
  3492. for( int x=0; x<kGLMUserClipPlanes; x++)
  3493. {
  3494. GLClipPlaneEquation_t temp1; // Antonio's way
  3495. GLClipPlaneEquation_t temp2; // our way
  3496. // if we don't have native clip vertex support. then munge the plane coeffs
  3497. // this should engage on ALL ATI PARTS < 10.6.4
  3498. // and should continue to engage on R5xx forever.
  3499. if ( !m_ctx->Caps().m_hasNativeClipVertexMode )
  3500. {
  3501. // hacked coeffs = { src->x, -src->y, 0.5f * src->z, src->w + (0.5f * src->z) };
  3502. // Antonio's trick - so we can use gl_Position as the clippee, not gl_ClipVertex.
  3503. GLClipPlaneEquation_t *equ = &gl.m_ClipPlaneEquation[x];
  3504. ///////////////// temp1
  3505. temp1.x = equ->x;
  3506. temp1.y = equ->y * -1.0;
  3507. temp1.z = equ->z * 0.5;
  3508. temp1.w = equ->w + (equ->z * 0.5);
  3509. //////////////// temp2
  3510. VMatrix mat1( 1, 0, 0, 0,
  3511. 0, -1, 0, 0,
  3512. 0, 0, 2, -1,
  3513. 0, 0, 0, 1
  3514. );
  3515. //mat1 = mat1.Transpose();
  3516. VMatrix mat2;
  3517. bool success = mat1.InverseGeneral( mat2 );
  3518. if (success)
  3519. {
  3520. VMatrix mat3;
  3521. mat3 = mat2.Transpose();
  3522. VPlane origPlane( Vector( equ->x, equ->y, equ->z ), equ->w );
  3523. VPlane newPlane;
  3524. newPlane = mat3 * origPlane /* * mat3 */;
  3525. VPlane finalPlane = newPlane;
  3526. temp2.x = newPlane.m_Normal.x;
  3527. temp2.y = newPlane.m_Normal.y;
  3528. temp2.z = newPlane.m_Normal.z;
  3529. temp2.w = newPlane.m_Dist;
  3530. }
  3531. else
  3532. {
  3533. temp2.x = 0;
  3534. temp2.y = 0;
  3535. temp2.z = 0;
  3536. temp2.w = 0;
  3537. }
  3538. }
  3539. else
  3540. {
  3541. temp1 = temp2 = gl.m_ClipPlaneEquation[x];
  3542. }
  3543. if (1) //GLMKnob("caps-key",NULL)==0.0)
  3544. {
  3545. m_ctx->WriteClipPlaneEquation( &temp1, x ); // no caps lock = Antonio or classic
  3546. /*
  3547. if (x<1)
  3548. {
  3549. GLMPRINTF(( " plane %d √vers1[ %5.2f %5.2f %5.2f %5.2f ] vers2[ %5.2f %5.2f %5.2f %5.2f ]",
  3550. x,
  3551. temp1.x,temp1.y,temp1.z,temp1.w,
  3552. temp2.x,temp2.y,temp2.z,temp2.w
  3553. ));
  3554. }
  3555. */
  3556. }
  3557. else
  3558. {
  3559. m_ctx->WriteClipPlaneEquation( &temp2, x ); // caps = our way or classic
  3560. /*
  3561. if (x<1)
  3562. {
  3563. GLMPRINTF(( " plane %d vers1[ %5.2f %5.2f %5.2f %5.2f ] √vers2[ %5.2f %5.2f %5.2f %5.2f ]",
  3564. x,
  3565. temp1.x,temp1.y,temp1.z,temp1.w,
  3566. temp2.x,temp2.y,temp2.z,temp2.w
  3567. ));
  3568. }
  3569. */
  3570. }
  3571. }
  3572. }
  3573. if ( stateHitMask & (1<<kGLColorMaskSingle) )
  3574. m_ctx->WriteColorMaskSingle( &gl.m_ColorMaskSingle );
  3575. // if ( stateHitMask & (1<<kGLColorMaskMultiple) )
  3576. // m_ctx->WriteColorMaskMultiple( &gl.m_ColorMaskMultiple ); // ???????????? hmmmmmmmm
  3577. if ( stateHitMask & (1<<kGLBlendEnable) )
  3578. m_ctx->WriteBlendEnable( &gl.m_BlendEnable );
  3579. if ( stateHitMask & (1<<kGLBlendFactor) )
  3580. m_ctx->WriteBlendFactor( &gl.m_BlendFactor );
  3581. if ( stateHitMask & (1<<kGLBlendEquation) )
  3582. m_ctx->WriteBlendEquation( &gl.m_BlendEquation );
  3583. if ( stateHitMask & (1<<kGLBlendColor) )
  3584. m_ctx->WriteBlendColor( &gl.m_BlendColor );
  3585. if ( stateHitMask & (1<<kGLBlendEnableSRGB) )
  3586. m_ctx->WriteBlendEnableSRGB( &gl.m_BlendEnableSRGB );
  3587. if ( stateHitMask & (1<<kGLDepthTestEnable) )
  3588. m_ctx->WriteDepthTestEnable( &gl.m_DepthTestEnable );
  3589. if ( stateHitMask & (1<<kGLDepthFunc) )
  3590. m_ctx->WriteDepthFunc( &gl.m_DepthFunc );
  3591. if ( stateHitMask & (1<<kGLDepthMask) )
  3592. m_ctx->WriteDepthMask( &gl.m_DepthMask );
  3593. if ( stateHitMask & (1<<kGLStencilTestEnable) )
  3594. m_ctx->WriteStencilTestEnable( &gl.m_StencilTestEnable );
  3595. if ( stateHitMask & (1<<kGLStencilFunc) )
  3596. m_ctx->WriteStencilFunc( &gl.m_StencilFunc );
  3597. if ( stateHitMask & (1<<kGLStencilOp) )
  3598. {
  3599. m_ctx->WriteStencilOp( &gl.m_StencilOp,0 );
  3600. m_ctx->WriteStencilOp( &gl.m_StencilOp,1 ); // ********* need to recheck this
  3601. }
  3602. if ( stateHitMask & (1<<kGLStencilWriteMask) )
  3603. m_ctx->WriteStencilWriteMask( &gl.m_StencilWriteMask );
  3604. if ( stateHitMask & (1<<kGLClearColor) )
  3605. m_ctx->WriteClearColor( &gl.m_ClearColor );
  3606. if ( stateHitMask & (1<<kGLClearDepth) )
  3607. m_ctx->WriteClearDepth( &gl.m_ClearDepth );
  3608. if ( stateHitMask & (1<<kGLClearStencil) )
  3609. m_ctx->WriteClearStencil( &gl.m_ClearStencil );
  3610. gl.m_stateDirtyMask &= (~stateHitMask);
  3611. }
  3612. // addressing modes
  3613. // 1 D3DTADDRESS_WRAP Tile the texture at every integer junction.
  3614. // D3DTADDRESS_MIRROR Similar to D3DTADDRESS_WRAP, except that the texture is flipped at every integer junction.
  3615. // 3 D3DTADDRESS_CLAMP Texture coordinates outside the range [0.0, 1.0] are set to the texture color at 0.0 or 1.0, respectively.
  3616. // 4 D3DTADDRESS_BORDER Texture coordinates outside the range [0.0, 1.0] are set to the border color.
  3617. // D3DTADDRESS_MIRRORONCE Similar to D3DTADDRESS_MIRROR and D3DTADDRESS_CLAMP.
  3618. // Takes the absolute value of the texture coordinate (thus, mirroring around 0),
  3619. // and then clamps to the maximum value. The most common usage is for volume textures,
  3620. // where support for the full D3DTADDRESS_MIRRORONCE texture-addressing mode is not
  3621. // necessary, but the data is symmetric around the one axis.
  3622. static GLenum dxtogl_addressMode[] =
  3623. {
  3624. (GLenum)-1, // no zero entry
  3625. GL_REPEAT, // from D3DTADDRESS_WRAP
  3626. (GLenum)-1, // no D3DTADDRESS_MIRROR support
  3627. GL_CLAMP_TO_EDGE, // from D3DTADDRESS_CLAMP
  3628. GL_CLAMP, // from D3DTADDRESS_BORDER
  3629. (GLenum)-1, // no D3DTADDRESS_MIRRORONCE support
  3630. };
  3631. /*
  3632. _D3DTEXTUREFILTERTYPE:
  3633. D3DTEXF_NONE = 0, // filtering disabled (valid for mip filter only)
  3634. D3DTEXF_POINT = 1, // nearest
  3635. D3DTEXF_LINEAR = 2, // linear interpolation
  3636. D3DTEXF_ANISOTROPIC = 3, // anisotropic
  3637. */
  3638. static GLenum dxtogl_magFilter[4] = // indexed by _D3DTEXTUREFILTERTYPE
  3639. {
  3640. GL_NEAREST, // D3DTEXF_NONE not applicable to mag filter but we handle it like POINT (mat_showmiplevels hits this)
  3641. GL_NEAREST, // D3DTEXF_POINT
  3642. GL_LINEAR, // D3DTEXF_LINEAR
  3643. GL_LINEAR, // D3DTEXF_ANISOTROPIC (aniso will be driven by setting maxAniso, not by a GL filter mode)
  3644. };
  3645. static GLenum dxtogl_minFilter[4][4] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter].
  3646. {
  3647. /* mip filter ---------------> D3DTEXF_NONE D3DTEXF_POINT D3DTEXF_LINEAR (D3DTEXF_ANISOTROPIC not applicable to mip filter)
  3648. /* min = D3DTEXF_NONE */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 }, // D3DTEXF_NONE we just treat like POINT
  3649. /* min = D3DTEXF_POINT */ { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, (GLenum)-1 },
  3650. /* min = D3DTEXF_LINEAR */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 },
  3651. /* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, (GLenum)-1 }, // no diff from prior row, set maxAniso to effect the sampling
  3652. };
  3653. HRESULT IDirect3DDevice9::FlushSamplers()
  3654. {
  3655. // a minor optimization we could do here would be to only write sampler state for
  3656. // TMU's that are active (i.e. consult m_textures)
  3657. uint activeSamplerMask = m_pixelShader ? m_pixelShader->m_pixSamplerMask : 0; // if no pixel shader bound at time of draw, act like it references no samplers
  3658. // (and avoid an access violation while yer at it)
  3659. // ho, we're not clearing the dirty mask for samplers as we go... need to do that...
  3660. uint samplerHitMask = gl.m_samplerDirtyMask;
  3661. for( int index = 0; (index < 16) && (samplerHitMask !=0); index++)
  3662. {
  3663. uint nCurrentSamplerMask = 1<<index;
  3664. // only push a sampler to GLM if the sampler is dirty *and* there is a live texture on that TMU
  3665. // else the values will sit quietly in the d3d sampler side until conditions permit pushing them
  3666. if ( ( samplerHitMask & nCurrentSamplerMask ) && ( m_textures[index] != NULL ) )
  3667. {
  3668. // Clear that dirty bit before you forget...
  3669. gl.m_samplerDirtyMask &= (~nCurrentSamplerMask);
  3670. // Translate from D3D sampler desc
  3671. D3DSamplerDesc *dxsamp = &m_samplers[ index ];
  3672. GLMTexSamplingParams *glsamp = &gl.m_samplers[ index ];
  3673. // Address modes
  3674. glsamp->m_addressModes[0] = dxtogl_addressMode[ dxsamp->m_addressModes[0] ];
  3675. glsamp->m_addressModes[1] = dxtogl_addressMode[ dxsamp->m_addressModes[1] ];
  3676. glsamp->m_addressModes[2] = dxtogl_addressMode[ dxsamp->m_addressModes[2] ];
  3677. // Border color
  3678. uint dxcolor = dxsamp->m_borderColor;
  3679. glsamp->m_borderColor[0] = ((dxcolor >> 16) & 0xFF) / 255.0f; //R
  3680. glsamp->m_borderColor[1] = ((dxcolor >> 8) & 0xFF) / 255.0f; //G
  3681. glsamp->m_borderColor[2] = ((dxcolor ) & 0xFF) / 255.0f; //B
  3682. glsamp->m_borderColor[3] = ((dxcolor >> 24) & 0xFF) / 255.0f; //A
  3683. // mag filter - pretty easy
  3684. Assert( dxsamp->m_magFilter <= D3DTEXF_ANISOTROPIC );
  3685. Assert( dxsamp->m_magFilter >= D3DTEXF_POINT );
  3686. glsamp->m_magFilter = dxtogl_magFilter[ dxsamp->m_magFilter ];
  3687. // min filter - more involved
  3688. Assert( dxsamp->m_minFilter <= D3DTEXF_ANISOTROPIC );
  3689. Assert( dxsamp->m_minFilter >= D3DTEXF_POINT );
  3690. Assert( dxsamp->m_mipFilter <= D3DTEXF_LINEAR );
  3691. Assert( dxsamp->m_mipFilter >= D3DTEXF_NONE );
  3692. D3DTEXTUREFILTERTYPE mipFilterLimit = D3DTEXF_LINEAR;
  3693. /*
  3694. if (GLMKnob("caps-key",NULL) > 0.0)
  3695. {
  3696. if (dxsamp->m_mipFilter > D3DTEXF_NONE)
  3697. {
  3698. // evil hack
  3699. glsamp->m_magFilter = GL_LINEAR_MIPMAP_NEAREST;
  3700. }
  3701. }
  3702. if (GLMKnob("option-key",NULL) > 0.0)
  3703. {
  3704. // limit to point
  3705. mipFilterLimit = D3DTEXF_POINT;
  3706. }
  3707. if (GLMKnob("control-key",NULL) > 0.0)
  3708. {
  3709. // limit to none
  3710. mipFilterLimit = D3DTEXF_NONE;
  3711. }
  3712. */
  3713. D3DTEXTUREFILTERTYPE mipFilterChoice = MIN( dxsamp->m_mipFilter, mipFilterLimit );
  3714. glsamp->m_minFilter = dxtogl_minFilter[ dxsamp->m_minFilter ][ mipFilterChoice ];
  3715. // should we check for mip filtering being requested on unmipped textures ? does it matter ?
  3716. // mipmap bias
  3717. glsamp->m_mipmapBias = dxsamp->m_mipmapBias;
  3718. // d3d "MAX MIP LEVEL" means the *largest size* MIP that will be selected. (max size)
  3719. // this is the same as GL's "MIN LOD level" which means the GL_TEXTURE_MIN_LOD level. (min index)
  3720. int texMipCount = m_textures[index]->m_tex->m_layout->m_mipCount;
  3721. Assert( texMipCount >=1 );
  3722. glsamp->m_minMipLevel = dxsamp->m_maxMipLevel; // it says gl_minMipLevel because we're setting GL's "GL_TEXTURE_MIN_LOD" aka d3d's "maximum mip size index".
  3723. if (glsamp->m_minMipLevel >= texMipCount)
  3724. {
  3725. // clamp - you can't have the GL base tex level be higher than the index of the last mip
  3726. glsamp->m_minMipLevel = texMipCount - 1;
  3727. }
  3728. // d3d has no idea of a "MIN MIP LEVEL" i.e. smallest size allowed.
  3729. // this would be expressed in GL by setting the GL_TEXTURE_MIN_LOD meaning largest index to select.
  3730. // for now, just set it to the index of the last mip.
  3731. glsamp->m_maxMipLevel = texMipCount-1; // d3d has no value for constraining how small we can sample.
  3732. // however we may need to set this more intelligently if textures are not being fully submitted.
  3733. // On OpenGL, GL_TEXTURE_MAX_ANISOTROPY_EXT needs to be 1 if we don't want aniso
  3734. glsamp->m_maxAniso = (dxsamp->m_minFilter != D3DTEXF_ANISOTROPIC) ? 1 : dxsamp->m_maxAniso;
  3735. // SRGB
  3736. glsamp->m_srgb = dxsamp->m_srgb != 0;
  3737. // Shadow compare mode
  3738. glsamp->m_compareMode = dxsamp->m_shadowFilter ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE;
  3739. // write that sampler.
  3740. m_ctx->SetSamplerParams( index, glsamp );
  3741. samplerHitMask ^= nCurrentSamplerMask; //turn bit off
  3742. // finally, if the SRGB state of the sampler does not match the SRGB format of the underlying texture...
  3743. // ... and the tex is not a renderable...
  3744. // ... and it is possible to re-submit the tex in an sRGB format...
  3745. // ******** AND THE TEX IS ACTUALLY REFERENCED BY THE ACTIVE PIXEL SHADER *******
  3746. // fix it.
  3747. // else complain ?
  3748. if ( nCurrentSamplerMask & activeSamplerMask ) // don't do SRGB check on unreferenced textures.
  3749. {
  3750. bool bTexSRGB = (m_textures[index]->m_tex->m_layout->m_key.m_texFlags & kGLMTexSRGB) != 0;
  3751. bool bMismatch = (bTexSRGB != glsamp->m_srgb);
  3752. bool bSRGBCapableTex = false; // not yet known
  3753. bool bRenderableTex = false; // not yet known.
  3754. if ( bMismatch )
  3755. {
  3756. bSRGBCapableTex = m_textures[index]->m_tex->m_layout->m_format->m_glIntFormatSRGB != 0;
  3757. bRenderableTex = (m_textures[index]->m_tex->m_layout->m_key.m_texFlags & kGLMTexRenderable) != 0;
  3758. // we can fix it if it's not a renderable, and an sRGB enabled format variation is available.
  3759. if ( bSRGBCapableTex && !bRenderableTex )
  3760. {
  3761. char *pTexName = m_textures[index]->m_tex->m_debugLabel;
  3762. if (!pTexName)
  3763. pTexName = "-";
  3764. m_textures[index]->m_srgbFlipCount++;
  3765. static bool bCheckedCommandline = false;
  3766. static bool bPrintAllflips = false;
  3767. static bool bPrintFirstflips = false;
  3768. static bool bPrintFreqflips = false;
  3769. static bool bPrintCrawls = false;
  3770. static bool bPrintMaxCrawls = false;
  3771. if ( !bCheckedCommandline )
  3772. {
  3773. bPrintAllflips = CommandLine()->FindParm( "-glmspewallsrgbflips" );
  3774. bPrintFirstflips = CommandLine()->FindParm( "-glmspewfirstsrgbflips" );
  3775. bPrintFreqflips = CommandLine()->FindParm( "-glmspewfreqsrgbflips" );
  3776. bPrintCrawls = CommandLine()->FindParm( "-glmspewsrgbcrawls" );
  3777. bPrintMaxCrawls = CommandLine()->FindParm( "-glmspewsrgbmaxcrawls" );
  3778. bCheckedCommandline = true;
  3779. }
  3780. bool bPrintIt = bPrintAllflips;
  3781. if ( bPrintFirstflips ) // report on first flip
  3782. {
  3783. bPrintIt = bPrintIt || m_textures[index]->m_srgbFlipCount==1;
  3784. }
  3785. if ( bPrintFreqflips ) // report on 50th flip
  3786. {
  3787. bPrintIt = bPrintIt || m_textures[index]->m_srgbFlipCount==50;
  3788. }
  3789. if ( bPrintIt )
  3790. {
  3791. char *pFormatStr;
  3792. pFormatStr = "srgb change (samp=%d): tex '%-30s' %08x %s (srgb=%d, %d times)";
  3793. if ( strlen( pTexName ) >= 30 )
  3794. {
  3795. pFormatStr = "srgb change (samp=%d): tex '%s' %08x %s (srgb=%d, %d times)";
  3796. }
  3797. printf( "\n" );
  3798. printf( pFormatStr, index, pTexName, m_textures[index], m_textures[index]->m_tex->m_layout->m_layoutSummary, (int)glsamp->m_srgb, m_textures[index]->m_srgbFlipCount );
  3799. if ( bPrintCrawls )
  3800. {
  3801. static char *interesting_crawl_substrs[] = { "CShader::OnDrawElements", NULL }; // add more as needed
  3802. CStackCrawlParams cp;
  3803. memset( &cp, 0, sizeof(cp) );
  3804. cp.m_frameLimit = 20;
  3805. g_extCocoaMgr->GetStackCrawl(&cp);
  3806. for( int i=0; i< cp.m_frameCount; i++)
  3807. {
  3808. // for each row of crawl, decide if name is interesting
  3809. bool bHit = bPrintMaxCrawls;
  3810. for( char **match = interesting_crawl_substrs; (!bHit) && (*match != NULL); match++)
  3811. {
  3812. if (strstr(cp.m_crawlNames[i], *match))
  3813. {
  3814. bHit = true;
  3815. }
  3816. }
  3817. if ( bHit )
  3818. {
  3819. printf( "\n\t%s", cp.m_crawlNames[i] );
  3820. }
  3821. }
  3822. printf( "\n");
  3823. }
  3824. }
  3825. #if GLMDEBUG && 0
  3826. //"toi" = texture of interest
  3827. static char s_toi[256] = "colorcorrection";
  3828. if (strstr( pTexName, s_toi ))
  3829. {
  3830. // breakpoint on this if you like
  3831. GLMPRINTF(( "srgb change %d for %s", m_textures[index]->m_srgbFlipCount, pTexName ));
  3832. }
  3833. #endif
  3834. // re-submit the tex unless we're stifling it
  3835. if (!CommandLine()->FindParm( "-glmnosrgbflips" ))
  3836. {
  3837. m_textures[index]->m_tex->ResetSRGB( glsamp->m_srgb, false );
  3838. }
  3839. }
  3840. else
  3841. {
  3842. //GLMPRINTF(("-Z- srgb sampling conflict: NOT fixing tex %08x [%s] (srgb req: %d) because (tex-srgb-capable=%d tex-renderable=%d)", m_textures[index], m_textures[index]->m_tex->m_layout->m_layoutSummary, (int)glsamp->m_srgb, (int)bSRGBCapableTex, (int)bRenderableTex ));
  3843. // we just leave the sampler state where it is, and that's life
  3844. }
  3845. }
  3846. }
  3847. }
  3848. }
  3849. }
  3850. HRESULT IDirect3DDevice9::FlushIndexBindings( void )
  3851. {
  3852. // push index buffer state
  3853. m_ctx->SetIndexBuffer( m_indices.m_idxBuffer->m_idxBuffer );
  3854. }
  3855. #if 0
  3856. HRESULT IDirect3DDevice9::FlushVertexBindings( void )
  3857. {
  3858. // push vertex buffer state for the current vertex decl
  3859. GLMVertexSetup setup;
  3860. IDirect3DVertexDeclaration9 *vxdecl = m_vertDecl;
  3861. memset( &setup, 0, sizeof( setup ) );
  3862. // see if the elems in the vertex decl match the attrib map of the shader we're about to draw with.
  3863. // can we do this in a simple style that handles both matched and unmatched orderings?
  3864. // just pick up each elem from the decl.
  3865. // visit the same slot in the shader attrib map.
  3866. // if the usage/usageindex matches, you're good.
  3867. // if not, hunt through the shader attrib map and find it.
  3868. // if you can't find it, then the shader is not consuming that attribute - odd but not fatal ?
  3869. // the serious one is shader trying to consume an attrib that isn't being sourced.
  3870. // we can check for that though with a little more work (copy the shader attrib map and mark the attribs as each one gets satisfied)
  3871. unsigned char vshAttribMap[ 16 ];
  3872. uint activeAttribCount = 0;
  3873. for( int i=0; i<16; i++)
  3874. {
  3875. vshAttribMap[i] = m_vertexShader->m_vtxAttribMap[i];
  3876. if (vshAttribMap[i] != 0xBB)
  3877. {
  3878. activeAttribCount++; // this counting could be done at shader creation time, or changed to a mask
  3879. }
  3880. }
  3881. for( int elemIndex=0; elemIndex<vxdecl->m_elemCount; elemIndex++)
  3882. {
  3883. D3DVERTEXELEMENT9_GL *srcelem = &vxdecl->m_elements[elemIndex];
  3884. int matchIndex = elemIndex; // initial guess - will iterate if this does not match
  3885. int tries = 0; // >16 means done
  3886. bool matched = false;
  3887. do
  3888. {
  3889. if ( ((vshAttribMap[matchIndex] >>4) == srcelem->m_dxdecl.Usage) && ((vshAttribMap[matchIndex] & 0x0F) == srcelem->m_dxdecl.UsageIndex) )
  3890. {
  3891. // hit
  3892. int attribIndex = matchIndex;
  3893. int streamIndex = srcelem->m_dxdecl.Stream;
  3894. GLMVertexAttributeDesc *dstAttr = &setup.m_attrs[ matchIndex ];
  3895. // copy whole thing
  3896. *dstAttr = srcelem->m_gldecl;
  3897. // then fix buffer, stride, offset
  3898. dstAttr->m_buffer = m_streams[ streamIndex ].m_vtxBuffer->m_vtxBuffer;
  3899. dstAttr->m_stride = m_streams[ streamIndex ].m_stride;
  3900. dstAttr->m_offset += m_streams[ streamIndex ].m_offset;
  3901. // set mask
  3902. setup.m_attrMask |= (1<<attribIndex);
  3903. vshAttribMap[matchIndex] = 0xBB; // can't match it again...
  3904. activeAttribCount--;
  3905. matched = true; // confirm we found it
  3906. tries = 999; // end the loop
  3907. }
  3908. else
  3909. {
  3910. // miss.
  3911. // just skip ahead one slot and wrap. Increment the try count. Top of loop can try to match on it.
  3912. // if we run out of tries, it just means the vert decl is sourcing an attrib that the VS is not reading.
  3913. matchIndex = (matchIndex+1) & 15;
  3914. tries++;
  3915. }
  3916. } while (tries<=16);
  3917. if ( !matched )
  3918. {
  3919. // this one is somewhat innocuous so we just do the AssertOnce
  3920. if ( !CommandLine()->FindParm("-hushasserts") )
  3921. {
  3922. AssertOnce( !"Vertex shader not consuming attribs that are sourced by decl");
  3923. }
  3924. }
  3925. }
  3926. if (activeAttribCount >0)
  3927. {
  3928. // this one is more serious
  3929. if ( !CommandLine()->FindParm("-hushasserts") )
  3930. {
  3931. Assert( !"Vertex shader consuming attribs not sourced by decl");
  3932. }
  3933. }
  3934. // pass the whole shebang to GLM
  3935. m_ctx->SetVertexAttributes( &setup );
  3936. }
  3937. #endif
  3938. HRESULT IDirect3DDevice9::FlushVertexBindings( uint baseVertexIndex )
  3939. {
  3940. // push vertex buffer state for the current vertex decl
  3941. // in this variant we just walk the attrib map in the VS and do a pull for each one.
  3942. // if we can't find a match in the vertex decl, we may fall back to the secret 'dummy' VBO that GLM maintains
  3943. GLMVertexSetup setup;
  3944. memset( &setup, 0, sizeof( setup ) );
  3945. IDirect3DVertexDeclaration9 *vxdecl = m_vertDecl;
  3946. unsigned char *vshAttribMap = m_vertexShader->m_vtxAttribMap;
  3947. // this loop could be tightened if we knew the number of live entries in the shader attrib map.
  3948. // which of course would be easy to do in the create shader function or even in the translator.
  3949. GLMVertexAttributeDesc *dstAttr = setup.m_attrs;
  3950. for( int i=0; i<16; i++,dstAttr++ )
  3951. {
  3952. unsigned char vshattrib = vshAttribMap[ i ];
  3953. if (vshattrib != 0xBB)
  3954. {
  3955. // try to find the match in the decl.
  3956. // idea: put some inverse table in the decl which could accelerate this search.
  3957. D3DVERTEXELEMENT9_GL *elem = m_vertDecl->m_elements;
  3958. for( int j=0; j< m_vertDecl->m_elemCount; j++,elem++)
  3959. {
  3960. // if it matches, install it, change vshattrib so the code below does not trigger, then end the loop
  3961. if ( ((vshattrib>>4) == elem->m_dxdecl.Usage) && ((vshattrib & 0x0F) == elem->m_dxdecl.UsageIndex) )
  3962. {
  3963. // targeting attribute #i in the setup with element data #j from the decl
  3964. *dstAttr = elem->m_gldecl;
  3965. // then fix buffer, stride, offset - note that we honor the base vertex index here by fiddling the offset
  3966. int streamIndex = elem->m_dxdecl.Stream;
  3967. dstAttr->m_buffer = m_streams[ streamIndex ].m_vtxBuffer->m_vtxBuffer;
  3968. dstAttr->m_stride = m_streams[ streamIndex ].m_stride;
  3969. dstAttr->m_offset += m_streams[ streamIndex ].m_offset + (baseVertexIndex * dstAttr->m_stride);
  3970. // set mask
  3971. setup.m_attrMask |= (1<<i);
  3972. // end loop
  3973. vshattrib = 0xBB;
  3974. j = 999;
  3975. }
  3976. }
  3977. // if vshattrib is not 0xBB here, that means we could not find a source in the decl for it
  3978. if (vshattrib != 0xBB)
  3979. {
  3980. // fill out attr the same way as usual, we just pass NULL for the buffer and ask GLM to have mercy on us
  3981. dstAttr->m_buffer = NULL;
  3982. dstAttr->m_stride = 0;
  3983. dstAttr->m_offset = 0;
  3984. // only implement certain usages... if we haven't seen it before, stop.
  3985. switch( vshattrib >>4 ) // aka usage
  3986. {
  3987. case D3DDECLUSAGE_POSITION:
  3988. case D3DDECLUSAGE_BLENDWEIGHT:
  3989. case D3DDECLUSAGE_BLENDINDICES:
  3990. Debugger();
  3991. break;
  3992. case D3DDECLUSAGE_NORMAL:
  3993. dstAttr->m_datasize = 3;
  3994. dstAttr->m_datatype = GL_FLOAT;
  3995. dstAttr->m_normalized = false;
  3996. break;
  3997. case D3DDECLUSAGE_PSIZE:
  3998. Debugger();
  3999. break;
  4000. case D3DDECLUSAGE_TEXCOORD:
  4001. dstAttr->m_datasize = 3;
  4002. dstAttr->m_datatype = GL_FLOAT;
  4003. dstAttr->m_normalized = false;
  4004. break;
  4005. case D3DDECLUSAGE_TANGENT:
  4006. case D3DDECLUSAGE_BINORMAL:
  4007. case D3DDECLUSAGE_TESSFACTOR:
  4008. case D3DDECLUSAGE_PLUGH:
  4009. Debugger();
  4010. break;
  4011. case D3DDECLUSAGE_COLOR:
  4012. dstAttr->m_datasize = 4;
  4013. dstAttr->m_datatype = GL_UNSIGNED_BYTE;
  4014. dstAttr->m_normalized = true;
  4015. break;
  4016. case D3DDECLUSAGE_FOG:
  4017. case D3DDECLUSAGE_DEPTH:
  4018. case D3DDECLUSAGE_SAMPLE:
  4019. Debugger();
  4020. break;
  4021. }
  4022. }
  4023. }
  4024. }
  4025. // copy active program's vertex attrib map into the vert setup info
  4026. memcpy( &setup.m_vtxAttribMap, m_vertexShader->m_vtxAttribMap, sizeof( m_vertexShader->m_vtxAttribMap ) );
  4027. m_ctx->SetVertexAttributes( &setup );
  4028. }
  4029. HRESULT IDirect3DDevice9::FlushGLM( void )
  4030. {
  4031. Debugger();// old routine not used now
  4032. }
  4033. HRESULT IDirect3DDevice9::DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount)
  4034. {
  4035. this->FlushStates( 0xFFFFFFFF );
  4036. Debugger();
  4037. return S_OK;
  4038. }
  4039. // Type
  4040. // [in] Member of the D3DPRIMITIVETYPE enumerated type, describing the type of primitive to render. D3DPT_POINTLIST is not supported with this method. See Remarks.
  4041. // BaseVertexIndex
  4042. // [in] Offset from the start of the vertex buffer to the first vertex. See Scenario 4.
  4043. // MinIndex
  4044. // [in] Minimum vertex index for vertices used during this call. This is a zero based index relative to BaseVertexIndex.
  4045. // NumVertices
  4046. // [in] Number of vertices used during this call. The first vertex is located at index: BaseVertexIndex + MinIndex.
  4047. // StartIndex
  4048. // [in] Index of the first index to use when accesssing the vertex buffer. Beginning at StartIndex to index vertices from the vertex buffer.
  4049. // PrimitiveCount
  4050. // [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.
  4051. HRESULT IDirect3DDevice9::DrawIndexedPrimitive( D3DPRIMITIVETYPE Type,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount )
  4052. {
  4053. this->FlushStates( 0xFFFFFFFF );
  4054. this->FlushSamplers();
  4055. this->FlushIndexBindings( );
  4056. this->FlushVertexBindings( BaseVertexIndex );
  4057. m_ctx->FlushDrawStates( true );
  4058. if (gl.m_FogEnable)
  4059. {
  4060. GLMPRINTF(("-D- IDirect3DDevice9::DrawIndexedPrimitive is seeing enabled fog..."));
  4061. }
  4062. switch(Type)
  4063. {
  4064. case D3DPT_POINTLIST:
  4065. Debugger();
  4066. break;
  4067. case D3DPT_LINELIST:
  4068. GLMPRINTF(("-X- IDirect3DDevice9::DrawIndexedPrimitive( D3DPT_LINELIST ) - ignored."));
  4069. // Debugger();
  4070. m_ctx->DrawRangeElements( (GLenum)GL_LINES, (GLuint)MinVertexIndex, (GLuint)(MinVertexIndex + NumVertices), (GLsizei)primCount*2, (GLenum)GL_UNSIGNED_SHORT, (const GLvoid *)(startIndex * sizeof(short)) );
  4071. break;
  4072. case D3DPT_TRIANGLELIST:
  4073. m_ctx->DrawRangeElements(GL_TRIANGLES, (GLuint)MinVertexIndex, (GLuint)(MinVertexIndex + NumVertices), (GLsizei)primCount*3, (GLenum)GL_UNSIGNED_SHORT, (const GLvoid *)(startIndex * sizeof(short)) );
  4074. break;
  4075. case D3DPT_TRIANGLESTRIP:
  4076. // enabled... Debugger();
  4077. m_ctx->DrawRangeElements(GL_TRIANGLE_STRIP, (GLuint)MinVertexIndex, (GLuint)(MinVertexIndex + NumVertices), (GLsizei)(2+primCount), (GLenum)GL_UNSIGNED_SHORT, (const GLvoid *)(startIndex * sizeof(short)) );
  4078. break;
  4079. }
  4080. return S_OK;
  4081. }
  4082. HRESULT IDirect3DDevice9::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride)
  4083. {
  4084. this->FlushStates( 0xFFFFFFFF );
  4085. Debugger();
  4086. return S_OK;
  4087. }
  4088. BOOL IDirect3DDevice9::ShowCursor(BOOL bShow)
  4089. {
  4090. // FIXME NOP
  4091. //Debugger();
  4092. return TRUE;
  4093. }
  4094. void d3drect_to_glmbox( D3DRECT *src, GLScissorBox_t *dst )
  4095. {
  4096. // 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.
  4097. // you can't fix it without knowing the height.
  4098. dst->width = src->x2 - src->x1;
  4099. dst->x = src->x1; // left edge
  4100. dst->height = src->y2 - src->y1;
  4101. dst->y = src->y1; // bottom edge - take large Y from d3d and subtract from surf height.
  4102. }
  4103. HRESULT IDirect3DDevice9::Clear(DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil)
  4104. {
  4105. this->FlushStates( (1<<kGLViewportBox) | (1<<kGLViewportDepthRange) ); // i.e. viewport changes..
  4106. m_ctx->FlushDrawStates( false );
  4107. //debugging Color = (rand() | 0xFF0000FF) & 0xFF3F3FFF;
  4108. if (!Count)
  4109. {
  4110. // run clear with no added rectangle
  4111. m_ctx->Clear( (Flags&D3DCLEAR_TARGET)!=0, Color,
  4112. (Flags&D3DCLEAR_ZBUFFER)!=0, Z,
  4113. (Flags&D3DCLEAR_STENCIL)!=0, Stencil,
  4114. NULL
  4115. );
  4116. }
  4117. else
  4118. {
  4119. GLScissorBox_t tempbox;
  4120. // do the rects one by one and convert each one to GL form
  4121. for( int i=0; i<Count; i++)
  4122. {
  4123. D3DRECT d3dtempbox = pRects[i];
  4124. d3drect_to_glmbox( &d3dtempbox, &tempbox );
  4125. m_ctx->Clear( (Flags&D3DCLEAR_TARGET)!=0, Color,
  4126. (Flags&D3DCLEAR_ZBUFFER)!=0, Z,
  4127. (Flags&D3DCLEAR_STENCIL)!=0, Stencil,
  4128. &tempbox
  4129. );
  4130. }
  4131. }
  4132. return S_OK;
  4133. }
  4134. HRESULT IDirect3DDevice9::SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix)
  4135. {
  4136. Debugger();
  4137. return S_OK;
  4138. }
  4139. HRESULT IDirect3DDevice9::SetTextureStageState(DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value)
  4140. {
  4141. Debugger();
  4142. return S_OK;
  4143. }
  4144. HRESULT IDirect3DDevice9::ValidateDevice(DWORD* pNumPasses)
  4145. {
  4146. Debugger();
  4147. return S_OK;
  4148. }
  4149. HRESULT IDirect3DDevice9::SetMaterial(CONST D3DMATERIAL9* pMaterial)
  4150. {
  4151. GLMPRINTF(("-X- IDirect3DDevice9::SetMaterial - ignored."));
  4152. // Debugger();
  4153. return S_OK;
  4154. }
  4155. HRESULT IDirect3DDevice9::LightEnable(DWORD Index,BOOL Enable)
  4156. {
  4157. Debugger();
  4158. return S_OK;
  4159. }
  4160. HRESULT IDirect3DDevice9::SetScissorRect(CONST RECT* pRect)
  4161. {
  4162. int nSurfaceHeight = m_drawableFBO->m_attach[ kAttColor0 ].m_tex->m_layout->m_key.m_ySize;
  4163. GLScissorBox_t newScissorBox = { pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top };
  4164. gl.m_ScissorBox = newScissorBox;
  4165. gl.m_stateDirtyMask |= (1<<kGLScissorBox);
  4166. return S_OK;
  4167. }
  4168. HRESULT IDirect3DDevice9::GetDeviceCaps(D3DCAPS9* pCaps)
  4169. {
  4170. Debugger();
  4171. return S_OK;
  4172. }
  4173. HRESULT IDirect3DDevice9::TestCooperativeLevel()
  4174. {
  4175. // game calls this to see if device was lost.
  4176. // last I checked the device was still attached to the computer.
  4177. // so, return OK.
  4178. return S_OK;
  4179. }
  4180. HRESULT IDirect3DDevice9::SetClipPlane(DWORD Index,CONST float* pPlane)
  4181. {
  4182. Assert(Index<2);
  4183. // We actually push the clip plane coeffs to two places
  4184. // - into a shader param for ARB mode
  4185. // - and into the API defined clip plane slots for GLSL mode.
  4186. // if ARB mode... THIS NEEDS TO GO... it's messing up the dirty ranges..
  4187. {
  4188. // this->SetVertexShaderConstantF( DXABSTRACT_VS_CLIP_PLANE_BASE+Index, pPlane, 1 ); // stash the clip plane values into shader param - translator knows where to look
  4189. }
  4190. // if GLSL mode... latch it and let FlushStates push it out
  4191. {
  4192. GLClipPlaneEquation_t peq;
  4193. peq.x = pPlane[0];
  4194. peq.y = pPlane[1];
  4195. peq.z = pPlane[2];
  4196. peq.w = pPlane[3];
  4197. gl.m_ClipPlaneEquation[ Index ] = peq;
  4198. gl.m_stateDirtyMask |= (1<<kGLClipPlaneEquation);
  4199. // m_ctx->WriteClipPlaneEquation( &peq, Index );
  4200. }
  4201. return S_OK;
  4202. }
  4203. HRESULT IDirect3DDevice9::EvictManagedResources()
  4204. {
  4205. GLMPRINTF(("-X- IDirect3DDevice9::EvictManagedResources --> IGNORED"));
  4206. return S_OK;
  4207. }
  4208. HRESULT IDirect3DDevice9::SetLight(DWORD Index,CONST D3DLIGHT9*)
  4209. {
  4210. Debugger();
  4211. return S_OK;
  4212. }
  4213. void IDirect3DDevice9::SetGammaRamp(UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp)
  4214. {
  4215. // just slam it directly for the time being
  4216. // this code is OS X specific
  4217. CGTableCount sampleCount;
  4218. CGDisplayErr cgErr;
  4219. CGGammaValue redt[256];
  4220. CGGammaValue grnt[256];
  4221. CGGammaValue blut[256];
  4222. for( int i=0; i<256; i++)
  4223. {
  4224. redt[i] = ((float)pRamp->red[i]) / 65535.0f;
  4225. grnt[i] = ((float)pRamp->green[i]) / 65535.0f;
  4226. blut[i] = ((float)pRamp->blue[i]) / 65535.0f;
  4227. }
  4228. cgErr = CGSetDisplayTransferByTable( 0, 256, redt, grnt, blut );
  4229. }
  4230. // ------------------------------------------------------------------------------------------------------------------------------ //
  4231. void* ID3DXBuffer::GetBufferPointer()
  4232. {
  4233. Debugger();
  4234. return NULL;
  4235. }
  4236. DWORD ID3DXBuffer::GetBufferSize()
  4237. {
  4238. Debugger();
  4239. return 0;
  4240. }
  4241. #pragma mark ----- More D3DX stuff
  4242. // ------------------------------------------------------------------------------------------------------------------------------ //
  4243. // D3DX stuff.
  4244. // ------------------------------------------------------------------------------------------------------------------------------ //
  4245. // matrix stack...
  4246. HRESULT D3DXCreateMatrixStack( DWORD Flags, LPD3DXMATRIXSTACK* ppStack)
  4247. {
  4248. *ppStack = new ID3DXMatrixStack;
  4249. (*ppStack)->Create();
  4250. return S_OK;
  4251. }
  4252. HRESULT ID3DXMatrixStack::Create()
  4253. {
  4254. m_stack.EnsureCapacity( 16 ); // 1KB ish
  4255. m_stack.AddToTail();
  4256. m_stackTop = 0; // top of stack is at index 0 currently
  4257. LoadIdentity();
  4258. return S_OK;
  4259. }
  4260. D3DXMATRIX* ID3DXMatrixStack::GetTop()
  4261. {
  4262. return (D3DXMATRIX*)&m_stack[ m_stackTop ];
  4263. }
  4264. void ID3DXMatrixStack::Push()
  4265. {
  4266. D3DMATRIX temp = m_stack[ m_stackTop ];
  4267. m_stack.AddToTail( temp );
  4268. m_stackTop ++;
  4269. }
  4270. void ID3DXMatrixStack::Pop()
  4271. {
  4272. int elem = m_stackTop--;
  4273. m_stack.Remove( elem );
  4274. }
  4275. void ID3DXMatrixStack::LoadIdentity()
  4276. {
  4277. D3DXMATRIX *mat = GetTop();
  4278. D3DXMatrixIdentity( mat );
  4279. }
  4280. void ID3DXMatrixStack::LoadMatrix( const D3DXMATRIX *pMat )
  4281. {
  4282. *(GetTop()) = *pMat;
  4283. }
  4284. void ID3DXMatrixStack::MultMatrix( const D3DXMATRIX *pMat )
  4285. {
  4286. // http://msdn.microsoft.com/en-us/library/bb174057(VS.85).aspx
  4287. // This method right-multiplies the given matrix to the current matrix
  4288. // (transformation is about the current world origin).
  4289. // m_pstack[m_currentPos] = m_pstack[m_currentPos] * (*pMat);
  4290. // This method does not add an item to the stack, it replaces the current
  4291. // matrix with the product of the current matrix and the given matrix.
  4292. Debugger();
  4293. }
  4294. void ID3DXMatrixStack::MultMatrixLocal( const D3DXMATRIX *pMat )
  4295. {
  4296. // http://msdn.microsoft.com/en-us/library/bb174058(VS.85).aspx
  4297. // This method left-multiplies the given matrix to the current matrix
  4298. // (transformation is about the local origin of the object).
  4299. // m_pstack[m_currentPos] = (*pMat) * m_pstack[m_currentPos];
  4300. // This method does not add an item to the stack, it replaces the current
  4301. // matrix with the product of the given matrix and the current matrix.
  4302. Debugger();
  4303. }
  4304. HRESULT ID3DXMatrixStack::ScaleLocal(FLOAT x, FLOAT y, FLOAT z)
  4305. {
  4306. // http://msdn.microsoft.com/en-us/library/bb174066(VS.85).aspx
  4307. // Scale the current matrix about the object origin.
  4308. // This method left-multiplies the current matrix with the computed
  4309. // scale matrix. The transformation is about the local origin of the object.
  4310. //
  4311. // D3DXMATRIX tmp;
  4312. // D3DXMatrixScaling(&tmp, x, y, z);
  4313. // m_stack[m_currentPos] = tmp * m_stack[m_currentPos];
  4314. Debugger();
  4315. }
  4316. HRESULT ID3DXMatrixStack::RotateAxisLocal(CONST D3DXVECTOR3* pV, FLOAT Angle)
  4317. {
  4318. // http://msdn.microsoft.com/en-us/library/bb174062(VS.85).aspx
  4319. // Left multiply the current matrix with the computed rotation
  4320. // matrix, counterclockwise about the given axis with the given angle.
  4321. // (rotation is about the local origin of the object)
  4322. // D3DXMATRIX tmp;
  4323. // D3DXMatrixRotationAxis( &tmp, pV, angle );
  4324. // m_stack[m_currentPos] = tmp * m_stack[m_currentPos];
  4325. // Because the rotation is left-multiplied to the matrix stack, the rotation
  4326. // is relative to the object's local coordinate space.
  4327. Debugger();
  4328. }
  4329. HRESULT ID3DXMatrixStack::TranslateLocal(FLOAT x, FLOAT y, FLOAT z)
  4330. {
  4331. // http://msdn.microsoft.com/en-us/library/bb174068(VS.85).aspx
  4332. // Left multiply the current matrix with the computed translation
  4333. // matrix. (transformation is about the local origin of the object)
  4334. // D3DXMATRIX tmp;
  4335. // D3DXMatrixTranslation( &tmp, x, y, z );
  4336. // m_stack[m_currentPos] = tmp * m_stack[m_currentPos];
  4337. Debugger();
  4338. }
  4339. const char* D3DXGetPixelShaderProfile( IDirect3DDevice9 *pDevice )
  4340. {
  4341. Debugger();
  4342. return "";
  4343. }
  4344. D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 )
  4345. {
  4346. D3DXMATRIX temp;
  4347. for( int i=0; i<4; i++)
  4348. {
  4349. for( int j=0; j<4; j++)
  4350. {
  4351. temp.m[i][j] = (pM1->m[ i ][ 0 ] * pM2->m[ 0 ][ j ])
  4352. + (pM1->m[ i ][ 1 ] * pM2->m[ 1 ][ j ])
  4353. + (pM1->m[ i ][ 2 ] * pM2->m[ 2 ][ j ])
  4354. + (pM1->m[ i ][ 3 ] * pM2->m[ 3 ][ j ]);
  4355. }
  4356. }
  4357. *pOut = temp;
  4358. return pOut;
  4359. }
  4360. // Transform a 3D vector by a given matrix, projecting the result back into w = 1
  4361. // http://msdn.microsoft.com/en-us/library/ee417622(VS.85).aspx
  4362. D3DXVECTOR3* D3DXVec3TransformCoord(D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM)
  4363. {
  4364. D3DXVECTOR3 vOut;
  4365. vOut.x = vOut.y = vOut.z = 0.0f;
  4366. float norm = (pM->m[0][3] * pV->x) + (pM->m[1][3] * pV->y) + (pM->m[2][3] *pV->z) + pM->m[3][3];
  4367. if ( norm )
  4368. {
  4369. 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;
  4370. 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;
  4371. 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;
  4372. }
  4373. *pOut = vOut;
  4374. return pOut;
  4375. }
  4376. void D3DXMatrixIdentity( D3DXMATRIX *mat )
  4377. {
  4378. for( int i=0; i<4; i++)
  4379. {
  4380. for( int j=0; j<4; j++)
  4381. {
  4382. mat->m[i][j] = (i==j) ? 1.0f : 0.0f; // 1's on the diagonal.
  4383. }
  4384. }
  4385. }
  4386. D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z )
  4387. {
  4388. D3DXMatrixIdentity( pOut );
  4389. pOut->m[3][0] = x;
  4390. pOut->m[3][1] = y;
  4391. pOut->m[3][2] = z;
  4392. return pOut;
  4393. }
  4394. D3DXMATRIX* D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM )
  4395. {
  4396. Assert( sizeof( D3DXMATRIX ) == (16 * sizeof(float) ) );
  4397. Assert( sizeof( VMatrix ) == (16 * sizeof(float) ) );
  4398. Assert( pDeterminant == NULL ); // homey don't play that
  4399. VMatrix *origM = (VMatrix*)pM;
  4400. VMatrix *destM = (VMatrix*)pOut;
  4401. bool success = MatrixInverseGeneral( *origM, *destM );
  4402. Assert( success );
  4403. return pOut;
  4404. }
  4405. D3DXMATRIX* D3DXMatrixTranspose( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM )
  4406. {
  4407. if (pOut != pM)
  4408. {
  4409. for( int i=0; i<4; i++)
  4410. {
  4411. for( int j=0; j<4; j++)
  4412. {
  4413. pOut->m[i][j] = pM->m[j][i];
  4414. }
  4415. }
  4416. }
  4417. else
  4418. {
  4419. D3DXMATRIX temp = *pM;
  4420. D3DXMatrixTranspose( pOut, &temp );
  4421. }
  4422. return NULL;
  4423. }
  4424. D3DXPLANE* D3DXPlaneNormalize( D3DXPLANE *pOut, CONST D3DXPLANE *pP)
  4425. {
  4426. // not very different from normalizing a vector.
  4427. // figure out the square root of the sum-of-squares of the x,y,z components
  4428. // make sure that's non zero
  4429. // then divide all four components by that value
  4430. // or return some dummy plane like 0,0,1,0 if it fails
  4431. float len = sqrt( (pP->a * pP->a) + (pP->b * pP->b) + (pP->c * pP->c) );
  4432. if (len > 1e-10) //FIXME need a real epsilon here ?
  4433. {
  4434. pOut->a = pP->a / len; pOut->b = pP->b / len; pOut->c = pP->c / len; pOut->d = pP->d / len;
  4435. }
  4436. else
  4437. {
  4438. pOut->a = 0.0f; pOut->b = 0.0f; pOut->c = 1.0f; pOut->d = 0.0f;
  4439. }
  4440. return pOut;
  4441. }
  4442. D3DXVECTOR4* D3DXVec4Transform( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM )
  4443. {
  4444. VMatrix *mat = (VMatrix*)pM;
  4445. Vector4D *vIn = (Vector4D*)pV;
  4446. Vector4D *vOut = (Vector4D*)pOut;
  4447. Vector4DMultiplyTranspose( *mat, *vIn, *vOut );
  4448. return pOut;
  4449. }
  4450. D3DXVECTOR4* D3DXVec4Normalize( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV )
  4451. {
  4452. Vector4D *vIn = (Vector4D*) pV;
  4453. Vector4D *vOut = (Vector4D*) pOut;
  4454. *vOut = *vIn;
  4455. Vector4DNormalize( *vOut );
  4456. return pOut;
  4457. }
  4458. D3DXMATRIX* D3DXMatrixOrthoOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn,FLOAT zf )
  4459. {
  4460. Debugger();
  4461. return NULL;
  4462. }
  4463. D3DXMATRIX* D3DXMatrixPerspectiveRH( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf )
  4464. {
  4465. Debugger();
  4466. return NULL;
  4467. }
  4468. D3DXMATRIX* D3DXMatrixPerspectiveOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf )
  4469. {
  4470. Debugger();
  4471. return NULL;
  4472. }
  4473. D3DXPLANE* D3DXPlaneTransform( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM )
  4474. {
  4475. float *out = &pOut->a;
  4476. // dot dot dot
  4477. for( int x=0; x<4; x++ )
  4478. {
  4479. out[x] = (pM->m[0][x] * pP->a)
  4480. + (pM->m[1][x] * pP->b)
  4481. + (pM->m[2][x] * pP->c)
  4482. + (pM->m[3][x] * pP->d);
  4483. }
  4484. return pOut;
  4485. }
  4486. // ------------------------------------------------------------------------------------------------------------------------------ //
  4487. IDirect3D9 *Direct3DCreate9(UINT SDKVersion)
  4488. {
  4489. GLMPRINTF(( "-X- Direct3DCreate9: %d", SDKVersion ));
  4490. return new IDirect3D9;
  4491. }
  4492. // ------------------------------------------------------------------------------------------------------------------------------ //
  4493. void D3DPERF_SetOptions( DWORD dwOptions )
  4494. {
  4495. }
  4496. HRESULT D3DXCompileShader(
  4497. LPCSTR pSrcData,
  4498. UINT SrcDataLen,
  4499. CONST D3DXMACRO* pDefines,
  4500. LPD3DXINCLUDE pInclude,
  4501. LPCSTR pFunctionName,
  4502. LPCSTR pProfile,
  4503. DWORD Flags,
  4504. LPD3DXBUFFER* ppShader,
  4505. LPD3DXBUFFER* ppErrorMsgs,
  4506. LPD3DXCONSTANTTABLE* ppConstantTable)
  4507. {
  4508. Debugger(); // is anyone calling this ?
  4509. return S_OK;
  4510. }
  4511. #endif