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.

3568 lines
111 KiB

  1. //================ Copyright (c) Valve Corporation. All Rights Reserved. ===========================
  2. //
  3. // LibGcm implementation of DX
  4. //
  5. //==================================================================================================
  6. #ifndef SPU
  7. #define CELL_GCM_MEMCPY memcpy // PPU SNC has no such intrinsic
  8. #endif
  9. #include "tier0/platform.h"
  10. #include "tier0/dbg.h"
  11. #include "tier1/strtools.h"
  12. #include "tier1/utlbuffer.h"
  13. #include "dxabstract.h"
  14. #include "materialsystem/imaterialsystem.h"
  15. #include "ps3gcmmemory.h"
  16. #include "gcmtexture.h"
  17. #include "gcmstate.h"
  18. #include "gcmdrawstate.h"
  19. #include "vprof.h"
  20. #include "cgutils.h"
  21. #include "tier0/memdbgon.h"
  22. extern IDirect3DDevice9 *m_pD3DDevice;
  23. //--------------------------------------------------------------------------------------------------
  24. // Direct3DCreate9
  25. //
  26. // IDirect3D9:: GetAdapterCount
  27. // GetAdapterIdentifier
  28. // CheckDeviceFormat
  29. // GetAdapterModeCount
  30. // EnumAdapterModes
  31. // CheckDeviceType
  32. // GetAdapterDisplayMode
  33. // CheckDepthStencilMatch
  34. // CheckDeviceMultiSampleType
  35. // CreateDevice
  36. // BeginZcullMeasurement
  37. // EndZcullMeasurement
  38. //--------------------------------------------------------------------------------------------------
  39. IDirect3D9 *Direct3DCreate9(UINT SDKVersion)
  40. {
  41. return new IDirect3D9;
  42. }
  43. UINT IDirect3D9::GetAdapterCount()
  44. {
  45. return 1; //FIXME revisit later when we know how many screems there are
  46. }
  47. HRESULT IDirect3D9::GetDeviceCaps(UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps)
  48. {
  49. // Generally called from "CShaderDeviceMgrDx8::ComputeCapsFromD3D" in ShaderDeviceDX8.cpp
  50. //cheese: fill in the pCaps record for adapter... we zero most of it and just fill in the fields that we think the caller wants.
  51. Q_memset( pCaps, 0, sizeof(*pCaps) );
  52. /* Device Info */
  53. pCaps->DeviceType = D3DDEVTYPE_HAL;
  54. /* Caps from DX7 Draw */
  55. pCaps->Caps = 0; // does anyone look at this ?
  56. pCaps->Caps2 = D3DCAPS2_DYNAMICTEXTURES;
  57. /* Cursor Caps */
  58. pCaps->CursorCaps = 0; // nobody looks at this
  59. /* 3D Device Caps */
  60. pCaps->DevCaps = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
  61. pCaps->TextureCaps = D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_MIPCUBEMAP | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PROJECTED;
  62. // D3DPTEXTURECAPS_NOPROJECTEDBUMPENV ?
  63. // D3DPTEXTURECAPS_POW2 ?
  64. // caller looks at POT support like this:
  65. // pCaps->m_SupportsNonPow2Textures =
  66. // ( !( caps.TextureCaps & D3DPTEXTURECAPS_POW2 ) ||
  67. // ( caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL ) );
  68. // so we should set D3DPTEXTURECAPS_NONPOW2CONDITIONAL bit ?
  69. pCaps->PrimitiveMiscCaps = 0; //only the HDR setup looks at this for D3DPMISCCAPS_SEPARATEALPHABLEND.
  70. // ? D3DPMISCCAPS_SEPARATEALPHABLEND
  71. // ? D3DPMISCCAPS_BLENDOP
  72. // ? D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
  73. // ? D3DPMISCCAPS_CLIPTLVERTS D3DPMISCCAPS_COLORWRITEENABLE D3DPMISCCAPS_MASKZ D3DPMISCCAPS_TSSARGTEMP
  74. pCaps->RasterCaps = D3DPRASTERCAPS_SCISSORTEST
  75. | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS // ref'd in CShaderDeviceMgrDx8::ComputeCapsFromD3D
  76. | D3DPRASTERCAPS_DEPTHBIAS // ref'd in CShaderDeviceMgrDx8::ComputeCapsFromD3D
  77. ;
  78. pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MAGFANISOTROPIC;
  79. pCaps->MaxTextureWidth = 4096;
  80. pCaps->MaxTextureHeight = 4096;
  81. pCaps->MaxVolumeExtent = 1024; //guesses
  82. pCaps->MaxTextureAspectRatio = 0; // imply no limit on AR
  83. pCaps->MaxAnisotropy = 8; //guess
  84. pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_MODULATE2X; //guess
  85. DWORD MaxTextureBlendStages;
  86. DWORD MaxSimultaneousTextures;
  87. pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN_SPHEREMAP;
  88. pCaps->MaxActiveLights = 8; // guess
  89. pCaps->MaxUserClipPlanes = 0; // guess until we know better
  90. pCaps->MaxVertexBlendMatrices = 0; // see if anyone cares
  91. pCaps->MaxVertexBlendMatrixIndex = 0; // see if anyone cares
  92. pCaps->MaxPrimitiveCount = 32768; // guess
  93. pCaps->MaxStreams = 4; // guess
  94. pCaps->VertexShaderVersion = 0x200; // model 2.0
  95. pCaps->MaxVertexShaderConst = 256; // number of vertex shader constant registers
  96. pCaps->PixelShaderVersion = 0x200; // model 2.0
  97. // Here are the DX9 specific ones
  98. pCaps->DevCaps2 = 0; // D3DDEVCAPS2_STREAMOFFSET - leave it off
  99. pCaps->PS20Caps.NumInstructionSlots = 512; // guess
  100. // only examined once:
  101. // pCaps->m_SupportsPixelShaders_2_b = ( ( caps.PixelShaderVersion & 0xffff ) >= 0x0200) && (caps.PS20Caps.NumInstructionSlots >= 512);
  102. //pCaps->m_SupportsPixelShaders_2_b = 1;
  103. pCaps->NumSimultaneousRTs = 1; // Will be at least 1
  104. pCaps->MaxVertexShader30InstructionSlots = 0;
  105. pCaps->MaxPixelShader30InstructionSlots = 0;
  106. return S_OK;
  107. }
  108. HRESULT IDirect3D9::GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier)
  109. {
  110. // Generally called from "CShaderDeviceMgrDx8::ComputeCapsFromD3D" in ShaderDeviceDX8.cpp
  111. Assert( Adapter==0 ); // only one adapter now
  112. Assert( Flags == D3DENUM_WHQL_LEVEL ); // we're not handling any other queries than this yet
  113. Q_memset( pIdentifier, 0, sizeof(*pIdentifier) );
  114. // this came from the shaderapigl effort
  115. Q_strncpy( pIdentifier->Driver, "Fake-Video-Card", MAX_DEVICE_IDENTIFIER_STRING );
  116. Q_strncpy( pIdentifier->Description, "Fake-Video-Card", MAX_DEVICE_IDENTIFIER_STRING );
  117. pIdentifier->VendorId = 4318;
  118. pIdentifier->DeviceId = 401;
  119. pIdentifier->SubSysId = 3358668866;
  120. pIdentifier->Revision = 162;
  121. return S_OK;
  122. }
  123. HRESULT IDirect3D9::CheckDeviceFormat(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat)
  124. {
  125. HRESULT result = -1; // failure
  126. DWORD knownUsageMask = D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP
  127. | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
  128. | D3DUSAGE_QUERY_VERTEXTEXTURE;
  129. Assert ((Usage & knownUsageMask) == Usage);
  130. DWORD legalUsage = 0;
  131. switch( AdapterFormat )
  132. {
  133. case D3DFMT_X8R8G8B8:
  134. switch( RType )
  135. {
  136. case D3DRTYPE_TEXTURE:
  137. switch( CheckFormat )
  138. {
  139. case D3DFMT_DXT1:
  140. case D3DFMT_DXT3:
  141. case D3DFMT_DXT5:
  142. legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  143. legalUsage |= D3DUSAGE_QUERY_SRGBREAD;
  144. //open question: is auto gen of mipmaps is allowed or attempted on any DXT textures.
  145. break;
  146. case D3DFMT_A8R8G8B8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  147. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  148. break;
  149. case D3DFMT_R32F: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  150. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  151. break;
  152. case D3DFMT_A16B16G16R16: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP /* --- OSX specific? --- | D3DUSAGE_QUERY_FILTER --- */;
  153. legalUsage |= IsPS3() ? D3DUSAGE_QUERY_FILTER : 0;
  154. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  155. break;
  156. case D3DFMT_A16B16G16R16F: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  157. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  158. case D3DFMT_A32B32G32R32F: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  159. legalUsage |= D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
  160. break;
  161. case D3DFMT_R5G6B5: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  162. break;
  163. //-----------------------------------------------------------
  164. // these come in from TestTextureFormat in ColorFormatDX8.cpp which is being driven by InitializeColorInformation...
  165. // which is going to try all 8 combinations of (vertex texturable / render targetable / filterable ) on every image format it knows.
  166. case D3DFMT_R8G8B8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  167. legalUsage |= D3DUSAGE_QUERY_SRGBREAD;
  168. break;
  169. case D3DFMT_X8R8G8B8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  170. legalUsage |= D3DUSAGE_QUERY_SRGBREAD;
  171. break;
  172. // one and two channel textures... we'll have to fake these as four channel tex if we want to support them
  173. case D3DFMT_L8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  174. break;
  175. case D3DFMT_A8L8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  176. break;
  177. case D3DFMT_A8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  178. break;
  179. // going to need to go back and double check all of these..
  180. case D3DFMT_X1R5G5B5: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  181. break;
  182. case D3DFMT_A4R4G4B4: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  183. break;
  184. case D3DFMT_A1R5G5B5: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  185. break;
  186. case D3DFMT_V8U8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  187. break;
  188. case D3DFMT_Q8W8V8U8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  189. // what the heck is QWVU8 ... ?
  190. break;
  191. case D3DFMT_X8L8V8U8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_QUERY_FILTER;
  192. // what the heck is XLVU8 ... ?
  193. break;
  194. // formats with depth...
  195. case D3DFMT_D16: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL;
  196. // just a guess on the legal usages
  197. break;
  198. case D3DFMT_D24S8: legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL;
  199. // just a guess on the legal usages
  200. break;
  201. // vendor formats... try marking these all invalid for now
  202. case D3DFMT_NV_INTZ:
  203. case D3DFMT_NV_RAWZ:
  204. case D3DFMT_NV_NULL:
  205. case D3DFMT_ATI_D16:
  206. case D3DFMT_ATI_D24S8:
  207. case D3DFMT_ATI_2N:
  208. case D3DFMT_ATI_1N:
  209. legalUsage = 0;
  210. break;
  211. //-----------------------------------------------------------
  212. default:
  213. Assert(!"Unknown check format");
  214. result = -1;
  215. break;
  216. }
  217. if ((Usage & legalUsage) == Usage)
  218. {
  219. //NC(( " --> OK!" ));
  220. result = S_OK;
  221. }
  222. else
  223. {
  224. DWORD unsatBits = Usage & (~legalUsage); // clear the bits of the req that were legal, leaving the illegal ones
  225. //NC(( " --> NOT OK: flags %8x:%s", unsatBits,GLMDecodeMask( eD3D_USAGE, unsatBits ) ));
  226. result = -1;
  227. }
  228. break;
  229. case D3DRTYPE_SURFACE:
  230. switch( CheckFormat )
  231. {
  232. case D3DFMT_D16:
  233. case D3DFMT_D24S8:
  234. legalUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL;
  235. if ((Usage & legalUsage) == Usage)
  236. {
  237. result = S_OK;
  238. }
  239. break;
  240. case 0x434f5441:
  241. case 0x41415353:
  242. result = -1;
  243. break;
  244. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=434f5441:UNKNOWN
  245. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=41415353:UNKNOWN
  246. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=434f5441:UNKNOWN
  247. //** IDirect3D9::CheckDeviceFormat adapter=0, DeviceType= 1:D3DDEVTYPE_HAL, AdapterFormat= 5:D3DFMT_X8R8G8B8, RType= 1:D3DRTYPE_SURFACE, CheckFormat=41415353:UNKNOWN
  248. }
  249. break;
  250. default:
  251. Assert(!"Unknown resource type");
  252. result = -1;
  253. break;
  254. }
  255. break;
  256. default:
  257. Assert(!"Unknown adapter format");
  258. result = -1;
  259. break;
  260. }
  261. return result;
  262. }
  263. UINT IDirect3D9::GetAdapterModeCount(UINT Adapter,D3DFORMAT Format)
  264. {
  265. return 1;
  266. }
  267. HRESULT IDirect3D9::EnumAdapterModes(UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode)
  268. {
  269. if ( IsPC() )
  270. {
  271. pMode->Width = 1024;
  272. pMode->Height = 768;
  273. }
  274. else
  275. {
  276. pMode->Width = 640;
  277. pMode->Height = 480;
  278. }
  279. pMode->RefreshRate = 0; // "adapter default"
  280. pMode->Format = Format;
  281. return S_OK;
  282. }
  283. HRESULT IDirect3D9::CheckDeviceType(UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed)
  284. {
  285. return S_OK;
  286. }
  287. HRESULT IDirect3D9::GetAdapterDisplayMode(UINT Adapter,D3DDISPLAYMODE* pMode)
  288. {
  289. pMode->Width = 1024;
  290. pMode->Height = 768;
  291. pMode->RefreshRate = 0; // "adapter default"
  292. pMode->Format = D3DFMT_X8R8G8B8;
  293. return S_OK;
  294. }
  295. HRESULT IDirect3D9::CheckDepthStencilMatch(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat)
  296. {
  297. // one known request looks like this:
  298. // AdapterFormat=5:D3DFMT_X8R8G8B8 || RenderTargetFormat=3:D3DFMT_A8R8G8B8 || DepthStencilFormat=2:D3DFMT_D24S8
  299. // return S_OK for that one combo, Debugger() on anything else
  300. HRESULT result = -1; // failure
  301. switch( AdapterFormat )
  302. {
  303. case D3DFMT_X8R8G8B8:
  304. {
  305. if ( (RenderTargetFormat == D3DFMT_A8R8G8B8) && (DepthStencilFormat == D3DFMT_D24S8) )
  306. {
  307. result = S_OK;
  308. }
  309. }
  310. break;
  311. }
  312. Assert( result == S_OK );
  313. return result;
  314. }
  315. HRESULT IDirect3D9::CheckDeviceMultiSampleType(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels)
  316. {
  317. switch( MultiSampleType )
  318. {
  319. case D3DMULTISAMPLE_NONE:
  320. *pQualityLevels = 1;
  321. return S_OK;
  322. break;
  323. default:
  324. if(pQualityLevels)
  325. {
  326. *pQualityLevels = 0;
  327. }
  328. return D3DERR_NOTAVAILABLE;
  329. break;
  330. }
  331. return D3DERR_NOTAVAILABLE;
  332. }
  333. HRESULT IDirect3D9::CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,VD3DHWND hFocusWindow,DWORD BehaviorFlags,
  334. D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface)
  335. {
  336. // constrain these inputs for the time being
  337. // BackBufferFormat -> A8R8G8B8
  338. // BackBufferCount -> 1;
  339. // MultiSampleType -> D3DMULTISAMPLE_NONE
  340. // AutoDepthStencilFormat -> D3DFMT_D24S8
  341. // NULL out the return pointer so if we exit early it is not set
  342. *ppReturnedDeviceInterface = NULL;
  343. //extern void UnpackD3DRSITable( void );
  344. //UnpackD3DRSITable();
  345. // assume success unless something is sour
  346. HRESULT result = S_OK;
  347. // relax this check for now
  348. //if (pPresentationParameters->BackBufferFormat != D3DFMT_A8R8G8B8)
  349. //{
  350. // Debugger();
  351. // result = -1;
  352. //}
  353. if (pPresentationParameters->BackBufferCount != 1)
  354. {
  355. Debugger();
  356. result = -1;
  357. }
  358. if (pPresentationParameters->MultiSampleType != D3DMULTISAMPLE_NONE)
  359. {
  360. Debugger();
  361. result = -1;
  362. }
  363. if (pPresentationParameters->AutoDepthStencilFormat != D3DFMT_D24S8)
  364. {
  365. Debugger();
  366. result = -1;
  367. }
  368. if (result == S_OK)
  369. {
  370. // create an IDirect3DDevice9
  371. // make a GLMContext and set up some drawables
  372. IDirect3DDevice9Params devparams;
  373. memset( &devparams, 0, sizeof(devparams) );
  374. devparams.m_adapter = Adapter;
  375. devparams.m_deviceType = DeviceType;
  376. devparams.m_focusWindow = hFocusWindow;
  377. devparams.m_behaviorFlags = BehaviorFlags;
  378. devparams.m_presentationParameters = *pPresentationParameters;
  379. IDirect3DDevice9 *dev = new IDirect3DDevice9;
  380. result = dev->Create( &devparams );
  381. if (result == S_OK)
  382. {
  383. *ppReturnedDeviceInterface = dev;
  384. }
  385. }
  386. return result;
  387. }
  388. //--------------------------------------------------------------------------------------------------
  389. // IDirect3DDevice9:: Create
  390. // Release
  391. // Reset
  392. // SetViewport
  393. // BeginScene
  394. // EndScene
  395. // Present
  396. // Ps3Helper_ResetSurfaceToKnownDefaultState
  397. // ReloadZcullMemory
  398. //--------------------------------------------------------------------------------------------------
  399. HRESULT IDirect3DDevice9::Create( IDirect3DDevice9Params *params )
  400. {
  401. HRESULT result = S_OK;
  402. // create an IDirect3DDevice9
  403. // make a GLMContext and set up some drawables
  404. m_params = *params;
  405. V_memset( m_rtSurfaces, 0, sizeof(m_rtSurfaces) );
  406. m_dsSurface = NULL;
  407. m_defaultColorSurface = NULL;
  408. m_defaultDepthStencilSurface = NULL;
  409. // Init GCM
  410. int nGcmInitError = g_ps3gcmGlobalState.Init();
  411. if( nGcmInitError < CELL_OK )
  412. {
  413. Debugger(); // bad news
  414. Warning( "IDirect3DDevice9::Create error 0x%X", nGcmInitError );
  415. return (HRESULT) -1;
  416. }
  417. gpGcmDrawState->Init(params);
  418. // we create two IDirect3DSurface9's. These will be known as the internal render target 0 and the depthstencil.
  419. // color surface
  420. result = this->CreateRenderTarget(
  421. m_params.m_presentationParameters.BackBufferWidth, // width
  422. m_params.m_presentationParameters.BackBufferHeight, // height
  423. m_params.m_presentationParameters.BackBufferFormat, // format
  424. D3DMULTISAMPLE_NONE, // FIXME
  425. 0, // MSAA quality
  426. true, // lockable ????
  427. &m_defaultColorSurface, // ppSurface
  428. (VD3DHANDLE*)this // shared handle, signal that it is internal RT
  429. );
  430. if (result != S_OK)
  431. {
  432. Debugger();
  433. return result;
  434. }
  435. else
  436. {
  437. m_defaultColorSurface->AddRef();
  438. }
  439. if (!m_params.m_presentationParameters.EnableAutoDepthStencil)
  440. {
  441. Debugger(); // bad news
  442. }
  443. result = CreateDepthStencilSurface(
  444. m_params.m_presentationParameters.BackBufferWidth, // width
  445. m_params.m_presentationParameters.BackBufferHeight, // height
  446. m_params.m_presentationParameters.AutoDepthStencilFormat, // format
  447. D3DMULTISAMPLE_NONE, // FIXME
  448. 0, // MSAA quality
  449. TRUE, // enable z-buffer discard ????
  450. &m_defaultDepthStencilSurface, // ppSurface
  451. (VD3DHANDLE*)this // shared handle, signal that it is internal RT
  452. );
  453. if (result != S_OK)
  454. {
  455. Debugger();
  456. return result;
  457. }
  458. else
  459. {
  460. m_defaultDepthStencilSurface->AddRef();
  461. }
  462. // Set the default surfaces
  463. (m_rtSurfaces[0] = m_defaultColorSurface)->AddRef();
  464. (m_dsSurface = m_defaultDepthStencilSurface)->AddRef();
  465. Ps3Helper_UpdateSurface( 0 ); // submit the change to GCM
  466. // Create internal textures
  467. void Ps3gcmInitializeArtificialTexture( int iHandle, IDirect3DBaseTexture9 *pPtr );
  468. Ps3gcmInitializeArtificialTexture( PS3GCM_ARTIFICIAL_TEXTURE_HANDLE_INDEX_BACKBUFFER,
  469. ( IDirect3DBaseTexture9 * ) m_defaultColorSurface );
  470. Ps3gcmInitializeArtificialTexture( PS3GCM_ARTIFICIAL_TEXTURE_HANDLE_INDEX_DEPTHBUFFER,
  471. ( IDirect3DBaseTexture9 * ) m_defaultDepthStencilSurface );
  472. D3DVIEWPORT9 viewport = { 0, 0,
  473. m_params.m_presentationParameters.BackBufferWidth,
  474. m_params.m_presentationParameters.BackBufferHeight,
  475. 0.1f, 1000.0f
  476. };
  477. SetViewport( &viewport );
  478. Ps3Helper_ResetSurfaceToKnownDefaultState();
  479. return result;
  480. }
  481. ULONG __stdcall IDirect3DDevice9::Release()
  482. {
  483. g_ps3gcmGlobalState.Shutdown();
  484. return 0;
  485. }
  486. HRESULT IDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPresentationParameters)
  487. {
  488. // nothing interesting here
  489. return S_OK;
  490. }
  491. HRESULT IDirect3DDevice9::SetViewport(CONST D3DVIEWPORT9* pViewport)
  492. {
  493. return gpGcmDrawState->SetViewport(pViewport);
  494. }
  495. HRESULT IDirect3DDevice9::BeginScene()
  496. {
  497. // m_isZPass = false; // z pres pass off at this time
  498. g_ps3gcmGlobalState.BeginScene();
  499. //m_nAntiAliasingStatus = AA_STATUS_NORMAL; // AA FXAA
  500. return S_OK;
  501. }
  502. HRESULT IDirect3DDevice9::EndScene()
  503. {
  504. g_ps3gcmGlobalState.EndScene();
  505. return S_OK;
  506. }
  507. HRESULT IDirect3DDevice9::Present(CONST RECT* pSourceRect,CONST RECT* pDestRect,VD3DHWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion)
  508. {
  509. m_nAntiAliasingStatus = AA_STATUS_NORMAL;// we aren't drawing into previous frame, we just set the current frame and we're about to set the surface for drawing
  510. // Flip frames and Advance display counters
  511. g_ps3gcmGlobalState.Flip();
  512. // Set our new default color buffer offset
  513. m_defaultColorSurface->m_tex->m_lmBlock.Assign( g_ps3gcmGlobalState.m_display.surfaceColor[g_ps3gcmGlobalState.m_display.surfaceFlipIdx] );
  514. //
  515. // Starting next frame
  516. //
  517. // Bind our default surfaces for the first time this frame here:
  518. if ( m_rtSurfaces[0] != m_defaultColorSurface )
  519. {
  520. m_defaultColorSurface->AddRef();
  521. if ( m_rtSurfaces[0] ) m_rtSurfaces[0]->Release();
  522. m_rtSurfaces[0] = m_defaultColorSurface;
  523. }
  524. if ( m_dsSurface != m_defaultDepthStencilSurface )
  525. {
  526. m_defaultDepthStencilSurface->AddRef();
  527. if ( m_dsSurface ) m_dsSurface->Release();
  528. m_dsSurface = m_defaultDepthStencilSurface;
  529. }
  530. Ps3Helper_UpdateSurface( 0 );
  531. Ps3Helper_ResetSurfaceToKnownDefaultState();
  532. return S_OK;
  533. }
  534. void IDirect3DDevice9::Ps3Helper_ResetSurfaceToKnownDefaultState()
  535. {
  536. gpGcmDrawState->ResetSurfaceToKnownDefaultState();
  537. }
  538. //--------------------------------------------------------------------------------------------------
  539. // IDirect3DGcmBufferBase - Lock, unlock, mem mgmt via CPs3gcmBuffer
  540. //--------------------------------------------------------------------------------------------------
  541. HRESULT IDirect3DGcmBufferBase::Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags)
  542. {
  543. // FIXME would be good to have "can't lock twice" logic
  544. Assert( !(Flags & D3DLOCK_READONLY) ); // not impl'd
  545. // Assert( !(Flags & D3DLOCK_NOSYSLOCK) ); // not impl'd - it triggers though
  546. if ( Flags & D3DLOCK_DISCARD )
  547. {
  548. // When the buffer is being discarded we need to allocate a new
  549. // instance of the buffer in case the current instance has been
  550. // in use:
  551. m_pBuffer->m_lmBlock.FreeAndAllocNew();
  552. gpGcmDrawState->UpdateVtxBufferOffset(( IDirect3DVertexBuffer9 * )this, m_pBuffer->Offset());
  553. }
  554. // We assume that we are always locking in NOOVERWRITE mode otherwise!
  555. // Return the buffer data pointer at requested offset
  556. *ppbData = m_pBuffer->m_lmBlock.DataInAnyMemory() + OffsetToLock;
  557. return S_OK;
  558. }
  559. HRESULT IDirect3DGcmBufferBase::Unlock()
  560. {
  561. // if this buffer is dirty, we need to invalidate vertex cache when we bind it
  562. gpGcmDrawState->m_dirtyCachesMask |= CGcmDrawState::kDirtyVxCache;
  563. return S_OK;
  564. }
  565. //--------------------------------------------------------------------------------------------------
  566. // TEXTURE
  567. // -------
  568. // PreparePs3TextureKey
  569. // IDirect3DDevice9:: CreateTexture
  570. // CreateCubeTexture
  571. // CreateVolumeTexture
  572. // AllocateTextureStorage
  573. // SetTexture
  574. // GetTexture
  575. // FlushTextureCache
  576. //
  577. //--------------------------------------------------------------------------------------------------
  578. static void PreparePs3TextureKey( CPs3gcmTextureLayout::Key_t &key, D3DFORMAT Format, UINT Levels, DWORD Usage )
  579. {
  580. memset( &key, 0, sizeof(key) );
  581. key.m_texFormat = Format;
  582. if ( Levels > 1 )
  583. {
  584. key.m_texFlags |= CPs3gcmTextureLayout::kfMip;
  585. }
  586. key.m_nActualMipCount = Levels;
  587. // http://msdn.microsoft.com/en-us/library/bb172625(VS.85).aspx
  588. // complain if any usage bits come down that I don't know.
  589. uint knownUsageBits = (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET | D3DUSAGE_DYNAMIC | D3DUSAGE_TEXTURE_SRGB | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_TEXTURE_NOD3DMEMORY);
  590. if ( (Usage & knownUsageBits) != Usage )
  591. {
  592. Debugger();
  593. }
  594. if (Usage & D3DUSAGE_AUTOGENMIPMAP)
  595. {
  596. key.m_texFlags |= CPs3gcmTextureLayout::kfMip | CPs3gcmTextureLayout::kfMipAuto;
  597. }
  598. if ( Usage & D3DUSAGE_DEPTHSTENCIL )
  599. {
  600. key.m_texFlags |= CPs3gcmTextureLayout::kfTypeRenderable;
  601. key.m_texFlags |= CPs3gcmTextureLayout::kfTypeDepthStencil;
  602. }
  603. else if (Usage & D3DUSAGE_RENDERTARGET)
  604. {
  605. key.m_texFlags |= CPs3gcmTextureLayout::kfTypeRenderable;
  606. key.m_texFlags |= CPs3gcmTextureLayout::kfSrgbEnabled; // this catches callers of CreateTexture who set the "renderable" option - they get an SRGB tex
  607. }
  608. if (Usage & D3DUSAGE_DYNAMIC)
  609. {
  610. key.m_texFlags |= CPs3gcmTextureLayout::kfDynamicNoSwizzle;
  611. }
  612. if (Usage & D3DUSAGE_TEXTURE_SRGB)
  613. {
  614. key.m_texFlags |= CPs3gcmTextureLayout::kfSrgbEnabled;
  615. }
  616. if (Usage & D3DUSAGE_TEXTURE_NOD3DMEMORY)
  617. {
  618. key.m_texFlags |= CPs3gcmTextureLayout::kfNoD3DMemory;
  619. }
  620. }
  621. HRESULT IDirect3DDevice9::CreateTexture(UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,VD3DHANDLE* pSharedHandle)
  622. {
  623. IDirect3DTexture9 *dxtex = new IDirect3DTexture9;
  624. dxtex->m_restype = D3DRTYPE_TEXTURE;
  625. dxtex->m_device = this;
  626. dxtex->m_descZero.Format = Format;
  627. dxtex->m_descZero.Type = D3DRTYPE_TEXTURE;
  628. dxtex->m_descZero.Usage = Usage;
  629. dxtex->m_descZero.Pool = Pool;
  630. dxtex->m_descZero.MultiSampleType = D3DMULTISAMPLE_NONE;
  631. dxtex->m_descZero.MultiSampleQuality = 0;
  632. dxtex->m_descZero.Width = Width;
  633. dxtex->m_descZero.Height = Height;
  634. CPs3gcmTextureLayout::Key_t key;
  635. PreparePs3TextureKey( key, Format, Levels, Usage );
  636. key.m_size[0] = Width;
  637. key.m_size[1] = Height;
  638. key.m_size[2] = 1;
  639. dxtex->m_tex = CPs3gcmTexture::New( key );
  640. //
  641. // Create surface
  642. //
  643. dxtex->m_surfZero = new IDirect3DSurface9;
  644. dxtex->m_surfZero->m_desc = dxtex->m_descZero;
  645. dxtex->m_surfZero->m_tex = dxtex->m_tex;
  646. dxtex->m_surfZero->m_bOwnsTexture = false;
  647. dxtex->m_surfZero->m_face = 0;
  648. dxtex->m_surfZero->m_mip = 0;
  649. *ppTexture = dxtex;
  650. return S_OK;
  651. }
  652. HRESULT IDirect3DDevice9::CreateCubeTexture(UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,VD3DHANDLE* pSharedHandle)
  653. {
  654. IDirect3DCubeTexture9 *dxtex = new IDirect3DCubeTexture9;
  655. dxtex->m_restype = D3DRTYPE_CUBETEXTURE;
  656. dxtex->m_device = this;
  657. dxtex->m_descZero.Format = Format;
  658. dxtex->m_descZero.Type = D3DRTYPE_CUBETEXTURE;
  659. dxtex->m_descZero.Usage = Usage;
  660. dxtex->m_descZero.Pool = Pool;
  661. dxtex->m_descZero.MultiSampleType = D3DMULTISAMPLE_NONE;
  662. dxtex->m_descZero.MultiSampleQuality = 0;
  663. dxtex->m_descZero.Width = EdgeLength;
  664. dxtex->m_descZero.Height = EdgeLength;
  665. CPs3gcmTextureLayout::Key_t key;
  666. PreparePs3TextureKey( key, Format, Levels, Usage );
  667. key.m_texFlags |= CPs3gcmTextureLayout::kfTypeCubeMap;
  668. key.m_size[0] = EdgeLength;
  669. key.m_size[1] = EdgeLength;
  670. key.m_size[2] = 1;
  671. dxtex->m_tex = CPs3gcmTexture::New( key );
  672. //
  673. // Create surfaces
  674. //
  675. for( int face = 0; face < 6; face ++)
  676. {
  677. dxtex->m_surfZero[face] = new IDirect3DSurface9;
  678. dxtex->m_surfZero[face]->m_desc = dxtex->m_descZero;
  679. dxtex->m_surfZero[face]->m_tex = dxtex->m_tex;
  680. dxtex->m_surfZero[face]->m_bOwnsTexture = false;
  681. dxtex->m_surfZero[face]->m_face = face;
  682. dxtex->m_surfZero[face]->m_mip = 0;
  683. }
  684. *ppCubeTexture = dxtex;
  685. return S_OK;
  686. }
  687. HRESULT IDirect3DDevice9::CreateVolumeTexture(UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,VD3DHANDLE* pSharedHandle)
  688. {
  689. // set dxtex->m_restype to D3DRTYPE_VOLUMETEXTURE...
  690. IDirect3DVolumeTexture9 *dxtex = new IDirect3DVolumeTexture9;
  691. dxtex->m_restype = D3DRTYPE_VOLUMETEXTURE;
  692. dxtex->m_device = this;
  693. dxtex->m_descZero.Format = Format;
  694. dxtex->m_descZero.Type = D3DRTYPE_VOLUMETEXTURE;
  695. dxtex->m_descZero.Usage = Usage;
  696. dxtex->m_descZero.Pool = Pool;
  697. dxtex->m_descZero.MultiSampleType = D3DMULTISAMPLE_NONE;
  698. dxtex->m_descZero.MultiSampleQuality = 0;
  699. dxtex->m_descZero.Width = Width;
  700. dxtex->m_descZero.Height = Height;
  701. // also a volume specific desc
  702. dxtex->m_volDescZero.Format = Format;
  703. dxtex->m_volDescZero.Type = D3DRTYPE_VOLUMETEXTURE;
  704. dxtex->m_volDescZero.Usage = Usage;
  705. dxtex->m_volDescZero.Pool = Pool;
  706. dxtex->m_volDescZero.Width = Width;
  707. dxtex->m_volDescZero.Height = Height;
  708. dxtex->m_volDescZero.Depth = Depth;
  709. CPs3gcmTextureLayout::Key_t key;
  710. PreparePs3TextureKey( key, Format, Levels, Usage );
  711. key.m_size[0] = Width;
  712. key.m_size[1] = Height;
  713. key.m_size[2] = Depth;
  714. dxtex->m_tex = CPs3gcmTexture::New( key );
  715. //
  716. // Create surface
  717. //
  718. dxtex->m_surfZero = new IDirect3DSurface9;
  719. dxtex->m_surfZero->m_desc = dxtex->m_descZero;
  720. dxtex->m_surfZero->m_tex = dxtex->m_tex;
  721. dxtex->m_surfZero->m_bOwnsTexture = false;
  722. dxtex->m_surfZero->m_face = 0;
  723. dxtex->m_surfZero->m_mip = 0;
  724. *ppVolumeTexture = dxtex;
  725. return S_OK;
  726. }
  727. bool IDirect3DDevice9::AllocateTextureStorage( IDirect3DBaseTexture9 *pTexture )
  728. {
  729. // Allocate storage for a texture's bits (if D3DUSAGE_TEXTURE_NOD3DMEMORY was used to defer allocation on creation)
  730. return pTexture->m_tex->Allocate();
  731. }
  732. HRESULT IDirect3DDevice9::SetTexture( DWORD Stage, IDirect3DBaseTexture9* pTexture )
  733. {
  734. if( pTexture /*&& pTexture->m_tex->m_lmBlock.Size()*/ )
  735. {
  736. gpGcmDrawState->SetTexture(Stage, pTexture->m_tex);
  737. }
  738. else
  739. {
  740. gpGcmDrawState->ResetTexture(Stage);
  741. }
  742. return S_OK;
  743. }
  744. HRESULT IDirect3DDevice9::GetTexture(DWORD Stage,IDirect3DBaseTexture9** ppTexture)
  745. {
  746. // if implemented, should it increase the ref count ??
  747. Debugger();
  748. return S_OK;
  749. }
  750. void IDirect3DDevice9::FlushTextureCache()
  751. {
  752. gpGcmDrawState->SetInvalidateTextureCache();
  753. }
  754. //--------------------------------------------------------------------------------------------------
  755. // IDirect3DBaseTexture9:: GetType
  756. // GetLevelCount
  757. // GetLevelDesc
  758. // LockRect
  759. // UnlockRect
  760. // IDirect3DCubeTexture9:: GetCubeMapSurface
  761. // GetLevelDesc
  762. // IDirect3DVolumeTexture9::LockBox
  763. // UnlockBox
  764. // GetLevelDesc
  765. //--------------------------------------------------------------------------------------------------
  766. D3DRESOURCETYPE IDirect3DBaseTexture9::GetType()
  767. {
  768. return m_restype; //D3DRTYPE_TEXTURE;
  769. }
  770. DWORD IDirect3DBaseTexture9::GetLevelCount()
  771. {
  772. return m_tex->m_layout->m_mipCount;
  773. }
  774. HRESULT IDirect3DBaseTexture9::GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc)
  775. {
  776. Assert (Level < m_tex->m_layout->m_mipCount);
  777. D3DSURFACE_DESC result = m_descZero;
  778. // then mutate it for the level of interest
  779. CPs3gcmTextureLayout const &layout = *m_tex->m_layout;
  780. int iSlice = layout.SliceIndex( 0, Level );
  781. CPs3gcmTextureLayout::Slice_t const &slice = layout.m_slices[iSlice];
  782. result.Width = slice.m_size[0];
  783. result.Height = slice.m_size[1];
  784. *pDesc = result;
  785. return S_OK;
  786. }
  787. HRESULT IDirect3DTexture9::LockRect(UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags)
  788. {
  789. Debugger();
  790. return S_OK;
  791. }
  792. HRESULT IDirect3DTexture9::UnlockRect(UINT Level)
  793. {
  794. Debugger();
  795. return S_OK;
  796. }
  797. HRESULT IDirect3DTexture9::GetSurfaceLevel(UINT Level,IDirect3DSurface9** ppSurfaceLevel)
  798. {
  799. // we create and pass back a surface, and the client is on the hook to release it. tidy.
  800. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  801. CPs3gcmTextureLayout const &layout = *m_tex->m_layout;
  802. int iSlice = layout.SliceIndex( 0, Level );
  803. CPs3gcmTextureLayout::Slice_t const &slice = layout.m_slices[iSlice];
  804. surf->m_desc = m_descZero;
  805. surf->m_desc.Width = slice.m_size[0];
  806. surf->m_desc.Height = slice.m_size[1];
  807. surf->m_tex = m_tex;
  808. surf->m_bOwnsTexture = false;
  809. surf->m_face = 0;
  810. surf->m_mip = Level;
  811. *ppSurfaceLevel = surf;
  812. return S_OK;
  813. }
  814. HRESULT IDirect3DCubeTexture9::GetCubeMapSurface(D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface)
  815. {
  816. // we create and pass back a surface, and the client is on the hook to release it...
  817. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  818. CPs3gcmTextureLayout const &layout = *m_tex->m_layout;
  819. int iSlice = layout.SliceIndex( FaceType, Level );
  820. CPs3gcmTextureLayout::Slice_t const &slice = layout.m_slices[iSlice];
  821. surf->m_desc = m_descZero;
  822. surf->m_desc.Width = slice.m_size[0];
  823. surf->m_desc.Height = slice.m_size[1];
  824. surf->m_tex = m_tex;
  825. surf->m_bOwnsTexture = false;
  826. surf->m_face = FaceType;
  827. surf->m_mip = Level;
  828. *ppCubeMapSurface = surf;
  829. return S_OK;
  830. }
  831. HRESULT IDirect3DCubeTexture9::GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc)
  832. {
  833. Assert (Level < m_tex->m_layout->m_mipCount);
  834. D3DSURFACE_DESC result = m_descZero;
  835. // then mutate it for the level of interest
  836. CPs3gcmTextureLayout const &layout = *m_tex->m_layout;
  837. int iSlice = layout.SliceIndex( 0, Level );
  838. CPs3gcmTextureLayout::Slice_t const &slice = layout.m_slices[iSlice];
  839. result.Width = slice.m_size[0];
  840. result.Height = slice.m_size[1];
  841. *pDesc = result;
  842. return S_OK;
  843. }
  844. HRESULT IDirect3DVolumeTexture9::LockBox(UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags)
  845. {
  846. if ( !m_tex->m_lmBlock.Size() )
  847. {
  848. Assert( 0 );
  849. Warning( "\n\nERROR: (IDirect3DSurface9::LockBox) cannot lock this texture until AllocateTextureStorage is called!!\n\n\n" );
  850. return S_FALSE;
  851. }
  852. CPs3gcmTextureLayout const &layout = *m_tex->m_layout;
  853. int iSlice = layout.SliceIndex( 0, Level );
  854. CPs3gcmTextureLayout::Slice_t const &slice = layout.m_slices[iSlice];
  855. int iOffsetInDataSlab = slice.m_storageOffset;
  856. int iPitch = layout.SlicePitch( iSlice );
  857. int iDepthPitch = iPitch * slice.m_size[1];
  858. Assert( !layout.IsTiledMemory() );
  859. // Account for locking request on a subrect:
  860. if ( pBox )
  861. {
  862. // Assert that locking the box can yield a pointer to a legitimate byte:
  863. Assert( !pBox->Left || !layout.IsTiledMemory() );
  864. Assert( 0 == ( ( pBox->Left * layout.GetFormatPtr()->m_gcmPitchPer4X ) % 4 ) );
  865. iOffsetInDataSlab += pBox->Left * layout.GetFormatPtr()->m_gcmPitchPer4X / 4;
  866. iOffsetInDataSlab += pBox->Top * iPitch;
  867. iOffsetInDataSlab += pBox->Front * iDepthPitch;
  868. }
  869. // Set the locked rect data:
  870. pLockedVolume->pBits = m_tex->Data() + iOffsetInDataSlab;
  871. pLockedVolume->RowPitch = iPitch;
  872. pLockedVolume->SlicePitch = iDepthPitch;
  873. return S_OK;
  874. }
  875. HRESULT IDirect3DVolumeTexture9::UnlockBox(UINT Level)
  876. {
  877. // Since the texture has just been modified, and this same texture bits may have been used in one of the previous draw calls
  878. // and may still linger in the texture cache (even if this is a new texture, it may theoretically share bits with some old texture,
  879. // which was just destroyed, and if we didn't have a lot of texture traffic in the last frame, those bits in texture cache may conceivably
  880. // survive until the next draw call)
  881. gpGcmDrawState->m_dirtyCachesMask |= CGcmDrawState::kDirtyTxCache;
  882. return S_OK;
  883. }
  884. HRESULT IDirect3DVolumeTexture9::GetLevelDesc( UINT Level, D3DVOLUME_DESC *pDesc )
  885. {
  886. if (Level > m_tex->m_layout->m_mipCount)
  887. {
  888. Debugger();
  889. }
  890. D3DVOLUME_DESC result = m_volDescZero;
  891. // then mutate it for the level of interest
  892. CPs3gcmTextureLayout const &layout = *m_tex->m_layout;
  893. int iSlice = layout.SliceIndex( 0, Level );
  894. CPs3gcmTextureLayout::Slice_t const &slice = layout.m_slices[iSlice];
  895. result.Width = slice.m_size[0];
  896. result.Height = slice.m_size[1];
  897. result.Depth = slice.m_size[2];
  898. *pDesc = result;
  899. return S_OK;
  900. }
  901. //--------------------------------------------------------------------------------------------------
  902. // RENDER TARGETS and SURFACES
  903. // IDirect3DDevice9:: CreateRenderTarget
  904. // SetRenderTarget
  905. // GetRenderTarget
  906. // CreateOffscreenPlainSurface
  907. // CreateDepthStencilSurface
  908. // Ps3Helper_UpdateSurface
  909. // DxDeviceForceUpdateRenderTarget
  910. // SetDepthStencilSurface
  911. // GetDepthStencilSurface
  912. // GetRenderTargetData
  913. // GetFrontBufferData
  914. // StretchRect
  915. // SetScissorRect
  916. // SetClipPlane
  917. //--------------------------------------------------------------------------------------------------
  918. HRESULT IDirect3DDevice9::CreateRenderTarget(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle)
  919. {
  920. HRESULT result = S_OK;
  921. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  922. surf->m_restype = D3DRTYPE_SURFACE;
  923. surf->m_device = this; // always set device on creations!
  924. CPs3gcmTextureLayout::Key_t key;
  925. PreparePs3TextureKey( key, Format, 0, 0 );
  926. key.m_size[0] = Width;
  927. key.m_size[1] = Height;
  928. key.m_size[2] = 1;
  929. key.m_texFlags = CPs3gcmTextureLayout::kfTypeRenderable;
  930. key.m_texFlags |= CPs3gcmTextureLayout::kfSrgbEnabled; // all render target tex are SRGB mode
  931. if ( pSharedHandle == ( VD3DHANDLE* ) this )
  932. {
  933. // internal RT, reuse the color buffer
  934. surf->m_tex = new CPs3gcmTexture;
  935. surf->m_tex->m_layout = CPs3gcmTextureLayout::New( key );
  936. surf->m_tex->m_lmBlock.Assign( g_ps3gcmGlobalState.m_display.surfaceColor[ g_ps3gcmGlobalState.m_display.surfaceFlipIdx ] );
  937. }
  938. else
  939. {
  940. surf->m_tex = CPs3gcmTexture::New( key );
  941. }
  942. surf->m_bOwnsTexture = true;
  943. surf->m_face = 0;
  944. surf->m_mip = 0;
  945. //desc
  946. surf->m_desc.Format = Format;
  947. surf->m_desc.Type = D3DRTYPE_SURFACE;
  948. surf->m_desc.Usage = 0; //FIXME ???????????
  949. surf->m_desc.Pool = D3DPOOL_DEFAULT; //FIXME ???????????
  950. surf->m_desc.MultiSampleType = MultiSample;
  951. surf->m_desc.MultiSampleQuality = MultisampleQuality;
  952. surf->m_desc.Width = Width;
  953. surf->m_desc.Height = Height;
  954. *ppSurface = (result==S_OK) ? surf : NULL;
  955. return result;
  956. }
  957. HRESULT IDirect3DDevice9::SetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget)
  958. {
  959. if ( pRenderTarget != m_rtSurfaces[RenderTargetIndex] )
  960. {
  961. if (pRenderTarget)
  962. pRenderTarget->AddRef();
  963. if (m_rtSurfaces[RenderTargetIndex])
  964. m_rtSurfaces[RenderTargetIndex]->Release();
  965. m_rtSurfaces[RenderTargetIndex] = pRenderTarget;
  966. Ps3Helper_UpdateSurface( RenderTargetIndex );
  967. }
  968. return S_OK;
  969. }
  970. HRESULT IDirect3DDevice9::GetRenderTarget(DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget)
  971. {
  972. m_rtSurfaces[ RenderTargetIndex ]->AddRef(); // per http://msdn.microsoft.com/en-us/library/bb174404(VS.85).aspx
  973. *ppRenderTarget = m_rtSurfaces[ RenderTargetIndex ];
  974. return S_OK;
  975. }
  976. HRESULT IDirect3DDevice9::CreateOffscreenPlainSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle)
  977. {
  978. // set surf->m_restype to D3DRTYPE_SURFACE...
  979. // this is almost identical to CreateRenderTarget..
  980. HRESULT result = S_OK;
  981. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  982. surf->m_restype = D3DRTYPE_SURFACE;
  983. surf->m_device = this; // always set device on creations!
  984. CPs3gcmTextureLayout::Key_t key;
  985. PreparePs3TextureKey( key, Format, 0, 0 );
  986. key.m_size[0] = Width;
  987. key.m_size[1] = Height;
  988. key.m_size[2] = 1;
  989. key.m_texFlags = CPs3gcmTextureLayout::kfTypeRenderable;
  990. surf->m_tex = CPs3gcmTexture::New( key );
  991. surf->m_bOwnsTexture = true;
  992. surf->m_face = 0;
  993. surf->m_mip = 0;
  994. //desc
  995. surf->m_desc.Format = Format;
  996. surf->m_desc.Type = D3DRTYPE_SURFACE;
  997. surf->m_desc.Usage = 0;
  998. surf->m_desc.Pool = D3DPOOL_DEFAULT;
  999. surf->m_desc.MultiSampleType = D3DMULTISAMPLE_NONE;
  1000. surf->m_desc.MultiSampleQuality = 0;
  1001. surf->m_desc.Width = Width;
  1002. surf->m_desc.Height = Height;
  1003. *ppSurface = (result==S_OK) ? surf : NULL;
  1004. return result;
  1005. }
  1006. HRESULT IDirect3DDevice9::CreateDepthStencilSurface(UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,
  1007. BOOL Discard,IDirect3DSurface9** ppSurface,VD3DHANDLE* pSharedHandle)
  1008. {
  1009. HRESULT result = S_OK;
  1010. IDirect3DSurface9 *surf = new IDirect3DSurface9;
  1011. surf->m_restype = D3DRTYPE_SURFACE;
  1012. surf->m_device = this; // always set device on creations!
  1013. CPs3gcmTextureLayout::Key_t key;
  1014. PreparePs3TextureKey( key, Format, 0, 0 );
  1015. key.m_size[0] = Width;
  1016. key.m_size[1] = Height;
  1017. key.m_size[2] = 1;
  1018. key.m_texFlags = CPs3gcmTextureLayout::kfTypeRenderable | CPs3gcmTextureLayout::kfTypeDepthStencil;
  1019. if ( pSharedHandle == ( VD3DHANDLE* ) this )
  1020. {
  1021. // internal RT, reuse the depth buffer
  1022. surf->m_tex = new CPs3gcmTexture;
  1023. surf->m_tex->m_layout = CPs3gcmTextureLayout::New( key );
  1024. surf->m_tex->m_lmBlock.Assign( g_ps3gcmGlobalState.m_display.surfaceDepth );
  1025. }
  1026. else
  1027. {
  1028. surf->m_tex = CPs3gcmTexture::New( key );
  1029. }
  1030. surf->m_bOwnsTexture = true;
  1031. surf->m_face = 0;
  1032. surf->m_mip = 0;
  1033. //desc
  1034. surf->m_desc.Format = Format;
  1035. surf->m_desc.Type = D3DRTYPE_SURFACE;
  1036. surf->m_desc.Usage = 0; //FIXME ???????????
  1037. surf->m_desc.Pool = D3DPOOL_DEFAULT; //FIXME ???????????
  1038. surf->m_desc.MultiSampleType = MultiSample;
  1039. surf->m_desc.MultiSampleQuality = MultisampleQuality;
  1040. surf->m_desc.Width = Width;
  1041. surf->m_desc.Height = Height;
  1042. *ppSurface = (result==S_OK) ? surf : NULL;
  1043. return result;
  1044. }
  1045. uint s_nUpdateSurfaceCounter = 0, s_nUpdateSurfaceDebug = -1;
  1046. void IDirect3DDevice9::Ps3Helper_UpdateSurface( int idx )
  1047. {
  1048. CPs3gcmTexture *texC = m_rtSurfaces[idx] ? m_rtSurfaces[idx]->m_tex : NULL;
  1049. // If color buffer is 8x8 or less, we assume this is a dummy color buffer, and Z only the surface
  1050. if (texC)
  1051. {
  1052. if(texC->m_layout->m_key.m_size[0] < 9)
  1053. {
  1054. texC = NULL;
  1055. }
  1056. }
  1057. CPs3gcmTexture *texZ = ( m_dsSurface && !idx ) ? m_dsSurface->m_tex : NULL;
  1058. CPs3gcmTexture *texCZ = texC ? texC : texZ;
  1059. UpdateSurface_t surface, *pSurfaceUpdate=&surface;
  1060. pSurfaceUpdate->m_texC.Assign( texC );
  1061. pSurfaceUpdate->m_texZ.Assign( texZ );
  1062. gpGcmDrawState->Ps3Helper_UpdateSurface(pSurfaceUpdate);
  1063. }
  1064. void DxDeviceForceUpdateRenderTarget( )
  1065. {
  1066. extern IDirect3DDevice9 *m_pD3DDevice;
  1067. m_pD3DDevice->Ps3Helper_UpdateSurface( 0 );
  1068. }
  1069. HRESULT IDirect3DDevice9::SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil)
  1070. {
  1071. if ( pNewZStencil != m_dsSurface )
  1072. {
  1073. if (pNewZStencil)
  1074. pNewZStencil->AddRef();
  1075. if (m_dsSurface)
  1076. m_dsSurface->Release();
  1077. m_dsSurface = pNewZStencil;
  1078. Ps3Helper_UpdateSurface( 0 );
  1079. }
  1080. return S_OK;
  1081. }
  1082. HRESULT IDirect3DDevice9::GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface)
  1083. {
  1084. m_dsSurface->AddRef(); // per http://msdn.microsoft.com/en-us/library/bb174384(VS.85).aspx
  1085. *ppZStencilSurface = m_dsSurface;
  1086. return S_OK;
  1087. }
  1088. HRESULT IDirect3DDevice9::GetRenderTargetData(IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface)
  1089. {
  1090. // is it just a blit ?
  1091. this->StretchRect( pRenderTarget, NULL, pDestSurface, NULL, D3DTEXF_NONE ); // is this good enough ???
  1092. return S_OK;
  1093. }
  1094. HRESULT IDirect3DDevice9::GetFrontBufferData(UINT iSwapChain,IDirect3DSurface9* pDestSurface)
  1095. {
  1096. Debugger();
  1097. return S_OK;
  1098. }
  1099. HRESULT IDirect3DDevice9::StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter)
  1100. {
  1101. // find relevant slices in GLM tex
  1102. int nRenderTargetIndex = ( int ) pSourceSurface;
  1103. Assert( nRenderTargetIndex >= -1 && nRenderTargetIndex < 4 );
  1104. //
  1105. // Source texture
  1106. //
  1107. CPs3gcmTexture *srcTex = NULL;
  1108. if ( nRenderTargetIndex == -1 )
  1109. srcTex = m_dsSurface ? m_dsSurface->m_tex : NULL;
  1110. else
  1111. srcTex = m_rtSurfaces[nRenderTargetIndex] ? m_rtSurfaces[nRenderTargetIndex]->m_tex : NULL;
  1112. if ( !srcTex )
  1113. return S_FALSE;
  1114. CPs3gcmTextureLayout::Slice_t const srcSlice = srcTex->m_layout->m_slices[ 0 ];
  1115. //
  1116. // Destination texture
  1117. //
  1118. CPs3gcmTexture *dstTex = pDestSurface->m_tex;
  1119. // we're assuming that we always transfer into the main mip, because it was the case so far. not gonna change it now.
  1120. int dstSliceIndex = 0;//dstTex->m_layout->SliceIndex( pDestSurface->m_face, pDestSurface->m_mip );
  1121. CPs3gcmTextureLayout::Slice_t const dstSlice = dstTex->m_layout->m_slices[ dstSliceIndex ];
  1122. //
  1123. // Perform RSX data transfer
  1124. //
  1125. RECT srcSizeRect = {0,0,srcSlice.m_size[0],srcSlice.m_size[1]};
  1126. RECT dstSizeRect = {0,0,dstSlice.m_size[0],dstSlice.m_size[1]};
  1127. if( !pDestRect )
  1128. pDestRect = &dstSizeRect;
  1129. if( !pSourceRect )
  1130. pSourceRect = &srcSizeRect;
  1131. // explicit signed int, so that width/height intermediate values may be negative
  1132. signed int nWidth = pSourceRect->right - pSourceRect->left, nHeight = pSourceRect->bottom-pSourceRect->top;
  1133. if( pDestRect->left + nWidth > dstSizeRect.right )
  1134. {
  1135. nWidth = dstSizeRect.right - pDestRect->left;
  1136. }
  1137. if( pDestRect->top + nHeight > dstSizeRect.bottom )
  1138. {
  1139. nHeight = dstSizeRect.bottom - pDestRect->top;
  1140. }
  1141. if( pSourceRect->left + nWidth > srcSizeRect.right )
  1142. {
  1143. nWidth = srcSizeRect.right - pSourceRect->left;
  1144. }
  1145. if( pSourceRect->top + nHeight > srcSizeRect.bottom )
  1146. {
  1147. nHeight = srcSizeRect.bottom - pSourceRect->top;
  1148. }
  1149. if( nWidth > 0 && nHeight > 0 )
  1150. {
  1151. gpGcmDrawState->SetTransferImage(
  1152. CELL_GCM_TRANSFER_LOCAL_TO_LOCAL,
  1153. dstTex->Offset(),
  1154. dstTex->m_layout->DefaultPitch(),
  1155. pDestRect->left, pDestRect->top,
  1156. srcTex->Offset(),
  1157. srcTex->m_layout->DefaultPitch(),
  1158. pSourceRect->left, pSourceRect->top,
  1159. nWidth, nHeight,
  1160. // The only supported formats are R5G6B5 for a 2-byte transfer and A8R8G8B8 for a 4-byte transfer.
  1161. !srcTex->m_layout->IsTiledMemory() ? srcTex->m_layout->GetFormatPtr()->m_gcmPitchPer4X/4 : 4
  1162. );
  1163. }
  1164. return S_OK;
  1165. }
  1166. HRESULT IDirect3DDevice9::SetScissorRect(CONST RECT* pRect)
  1167. {
  1168. // SpuDrawScissor_t * pScissor = g_spuGcm.GetDrawQueue()->AllocWithHeader<SpuDrawScissor_t>( SPUDRAWQUEUE_SETSCISSORRECT_METHOD );
  1169. // V_memcpy( &m_gcmStatePpu.m_scissor[0], &pScissor->x, 4 * sizeof( uint16 ) );
  1170. DrawScissor_t scissor, *pScissor = &scissor;
  1171. // clamping the values to the allowed by RSX. Values outside of this range (e.g. negative width/height) will crash RSX
  1172. // this came up w.r.t. scissor stack optimization, when used with r_portalscissor 1
  1173. // it would be better to do this on SPU, but it would make scissor state on PPU different from SPU
  1174. // we could "& 4095", but it's late in the project, so it seems safer to logically clamp the values
  1175. pScissor->x = clamp( pRect->left, 0, 4095 );
  1176. pScissor->y = clamp( pRect->top, 0, 4095 );
  1177. pScissor->w = clamp( pRect->right - pRect->left, 0, 4096 );
  1178. pScissor->h = clamp( pRect->bottom - pRect->top, 0, 4096 );
  1179. gpGcmDrawState->SetScissorRect(pScissor);
  1180. return S_OK;
  1181. }
  1182. HRESULT IDirect3DDevice9::SetClipPlane(DWORD Index,CONST float* pPlane)
  1183. {
  1184. Assert(Index<2);
  1185. this->SetVertexShaderConstantF( 253 + Index, pPlane, 1 ); // stash the clip plane values into shader param - translator knows where to look
  1186. return S_OK;
  1187. }
  1188. //--------------------------------------------------------------------------------------------------
  1189. // IDirect3DSurface9::LockRect
  1190. // UnlockRect
  1191. // GetDesc
  1192. //--------------------------------------------------------------------------------------------------
  1193. HRESULT IDirect3DSurface9::LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags)
  1194. {
  1195. if ( !m_tex->m_lmBlock.Size() )
  1196. {
  1197. Assert( 0 );
  1198. Warning( "\n\nERROR: (IDirect3DSurface9::LockRect) cannot lock this texture until AllocateTextureStorage is called!!\n\n\n" );
  1199. return S_FALSE;
  1200. }
  1201. CPs3gcmTextureLayout const &layout = *m_tex->m_layout;
  1202. int iSlice = layout.SliceIndex( this->m_face, this->m_mip );
  1203. CPs3gcmTextureLayout::Slice_t const &slice = layout.m_slices[iSlice];
  1204. int iOffsetInDataSlab = slice.m_storageOffset;
  1205. int iPitch = layout.SlicePitch( iSlice );
  1206. // Account for locking request on a subrect:
  1207. if ( pRect )
  1208. {
  1209. // Assert that locking the rect can yield a pointer to a legitimate byte:
  1210. Assert( !pRect->left || !layout.IsTiledMemory() );
  1211. Assert( 0 == ( ( pRect->left * layout.GetFormatPtr()->m_gcmPitchPer4X ) % 4 ) );
  1212. iOffsetInDataSlab += pRect->left * layout.GetFormatPtr()->m_gcmPitchPer4X / 4;
  1213. iOffsetInDataSlab += pRect->top * iPitch;
  1214. }
  1215. // Set the locked rect data:
  1216. pLockedRect->pBits = m_tex->Data() + iOffsetInDataSlab;
  1217. pLockedRect->Pitch = iPitch;
  1218. return S_OK;
  1219. }
  1220. HRESULT IDirect3DSurface9::UnlockRect()
  1221. {
  1222. // Since the texture has just been modified, and this same texture bits may have been used in one of the previous draw calls
  1223. // and may still linger in the texture cache (even if this is a new texture, it may theoretically share bits with some old texture,
  1224. // which was just destroyed, and if we didn't have a lot of texture traffic in the last frame, those bits in texture cache may conceivably
  1225. // survive until the next draw call)
  1226. gpGcmDrawState->m_dirtyCachesMask |= CGcmDrawState::kDirtyTxCache;
  1227. return S_OK;
  1228. }
  1229. HRESULT IDirect3DSurface9::GetDesc(D3DSURFACE_DESC *pDesc)
  1230. {
  1231. *pDesc = m_desc;
  1232. return S_OK;
  1233. }
  1234. //--------------------------------------------------------------------------------------------------
  1235. // PIXEL SHADERS
  1236. //
  1237. // IDirect3DDevice9::CreatePixelShader
  1238. // IDirect3DPixelShader9::IDirect3DPixelShader9
  1239. // ~IDirect3DPixelShader9
  1240. // IDirect3DDevice9::SetPixelShader
  1241. // SetPixelShaderConstantF
  1242. //--------------------------------------------------------------------------------------------------
  1243. //--------------------------------------------------------------------------------------------------
  1244. // Util funcs for Cg etc..
  1245. //--------------------------------------------------------------------------------------------------
  1246. struct DatatypeRec_t
  1247. {
  1248. CGtype type;
  1249. CGparameterclass parameterClass;
  1250. };
  1251. static DatatypeRec_t s_datatypeClassname[] = {
  1252. #define CG_DATATYPE_MACRO(name, compiler_name, enum_name, base_enum, nrows, ncols,classname) \
  1253. { enum_name, classname },
  1254. #include <Cg/cg_datatypes.h>
  1255. #undef CG_DATATYPE_MACRO
  1256. };
  1257. CGparameterclass vcgGetTypeClass( CGtype type )
  1258. {
  1259. if( type <= CG_TYPE_START_ENUM || type > CG_TYPE_START_ENUM + sizeof( s_datatypeClassname ) / sizeof( s_datatypeClassname[0] ) )
  1260. {
  1261. return CG_PARAMETERCLASS_UNKNOWN;
  1262. }
  1263. else
  1264. {
  1265. DatatypeRec_t & rec = s_datatypeClassname[type - CG_TYPE_START_ENUM - 1];
  1266. Assert( rec.type == type );
  1267. return rec.parameterClass;
  1268. }
  1269. }
  1270. static uint fspatchGetLength( CGtype nType )
  1271. {
  1272. uint32_t length = 0;
  1273. switch ( nType )
  1274. {
  1275. case CG_FLOAT:
  1276. case CG_BOOL:
  1277. case CG_FLOAT1:
  1278. case CG_BOOL1:
  1279. length = 1;
  1280. break;
  1281. case CG_FLOAT2:
  1282. case CG_BOOL2:
  1283. length = 2;
  1284. break;
  1285. case CG_FLOAT3:
  1286. case CG_BOOL3:
  1287. length = 3;
  1288. break;
  1289. case CG_FLOAT4:
  1290. case CG_BOOL4:
  1291. length = 4;
  1292. break;
  1293. case CG_FLOAT3x3:
  1294. case CG_BOOL3x3:
  1295. case CG_FLOAT3x4:
  1296. case CG_BOOL3x4:
  1297. length = 3;
  1298. break;
  1299. case CG_FLOAT4x4:
  1300. case CG_BOOL4x4:
  1301. case CG_FLOAT4x3:
  1302. case CG_BOOL4x3:
  1303. length = 4;
  1304. break;
  1305. default:
  1306. //DebuggerBreak();
  1307. length = 0;
  1308. }
  1309. return length;
  1310. }
  1311. // recursive set bit count
  1312. uint CountBits32( uint32 a )
  1313. {
  1314. uint a1 = ( a & 0x55555555 ) + ( ( a >> 1 ) & 0x55555555 );
  1315. uint a2 = ( a1 & 0x33333333 ) + ( ( a1 >> 2 ) & 0x33333333 );
  1316. uint a3 = ( a2 & 0x0F0F0F0F ) + ( ( a2 >> 4 ) & 0x0F0F0F0F );
  1317. uint a4 = ( a3 & 0x00FF00FF ) + ( ( a3 >> 8 ) & 0x00FF00FF );
  1318. uint a5 = ( a4 & 0xFFFF ) + ( a4 >> 16 );
  1319. #ifdef DBGFLAG_ASSERT
  1320. uint nCheckCount = 0;
  1321. for( uint i = 0; i < 32; ++i )
  1322. nCheckCount += ( a >> i ) & 1;
  1323. Assert( nCheckCount == a5 );
  1324. #endif
  1325. return a5;
  1326. }
  1327. //--------------------------------------------------------------------------------------------------
  1328. // IDirect3D pixel shader code
  1329. //--------------------------------------------------------------------------------------------------
  1330. HRESULT IDirect3DDevice9::CreatePixelShader(CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader, const char *pShaderName, char *debugLabel)
  1331. {
  1332. CgBinaryProgram *pProg = (CgBinaryProgram *)pFunction;
  1333. // Msg(">>>Pixel Shader : %s at 0x%08x sz 0x%04d no.param 0x%04d \n", pShaderName, pFunction, pProg->ucodeSize, pProg->parameterCount);
  1334. IDirect3DPixelShader9 *newprog = new IDirect3DPixelShader9( ( CgBinaryProgram * ) ( char* ) pFunction );
  1335. Assert( !( 0xF & uint( &newprog->m_data ) ) );
  1336. *ppShader = newprog;
  1337. return S_OK;
  1338. }
  1339. uint32 g_nPixelShaderTotalSize = 0;
  1340. uint32 g_nPixelShaderTotalUcode = 0;
  1341. IDirect3DPixelShader9::IDirect3DPixelShader9( CgBinaryProgram* prog )
  1342. {
  1343. g_nPixelShaderTotalSize += prog->totalSize;
  1344. g_nPixelShaderTotalUcode += prog->ucodeSize;
  1345. uint nPatchCount = 0;
  1346. //--------------------------------------------------------------------------------------------------
  1347. // Get Attribute input mask, register count and check revision
  1348. //--------------------------------------------------------------------------------------------------
  1349. CgBinaryFragmentProgram *pCgFragmentProgram = ( CgBinaryFragmentProgram * )( uintp( prog ) + prog->program );
  1350. m_data.m_attributeInputMask = pCgFragmentProgram->attributeInputMask;
  1351. // check binary format revision -- offline recompile necessary
  1352. // -- enforce the correct ucode for nv40/nv47/rsx
  1353. Assert( prog->binaryFormatRevision == CG_BINARY_FORMAT_REVISION );
  1354. uint registerCount = pCgFragmentProgram->registerCount;
  1355. // NOTE: actual register count can be modified by specifying an artificial e.g. PS3REGCOUNT48 static combo to force it to 48
  1356. Assert( registerCount <= 48 );
  1357. if (registerCount < 2)
  1358. {
  1359. // register count must be [2, 48]
  1360. registerCount = 2;
  1361. }
  1362. //--------------------------------------------------------------------------------------------------
  1363. // Build shader control0 and get tex control info, including number of tex controls
  1364. //--------------------------------------------------------------------------------------------------
  1365. uint8_t controlTxp = CELL_GCM_FALSE;
  1366. uint32 shCtrl0 = ( CELL_GCM_COMMAND_CAST( controlTxp ) << CELL_GCM_SHIFT_SET_SHADER_CONTROL_CONTROL_TXP )
  1367. & CELL_GCM_MASK_SET_SHADER_CONTROL_CONTROL_TXP;
  1368. shCtrl0 |= ( 1<<10 ) | ( registerCount << 24 );
  1369. shCtrl0 |= pCgFragmentProgram->depthReplace ? 0xE : 0x0;
  1370. shCtrl0 |= pCgFragmentProgram->outputFromH0 ? 0x00 : 0x40;
  1371. shCtrl0 |= pCgFragmentProgram->pixelKill ? 0x80 : 0x00;
  1372. uint texMask = pCgFragmentProgram->texCoordsInputMask;
  1373. uint texMask2D = pCgFragmentProgram->texCoords2D;
  1374. uint texMaskCentroid = pCgFragmentProgram->texCoordsCentroid;
  1375. uint nTexControls = CountBits32( texMask );
  1376. if( !IsCert() && nTexControls > 16 )
  1377. Error( "Corrupted pixel shader with %d tex controls is requested.\n", nTexControls );
  1378. //--------------------------------------------------------------------------------------------------
  1379. // Walk params, count number of embedded constant patches and build sampler input mask
  1380. //--------------------------------------------------------------------------------------------------
  1381. m_data.m_samplerInputMask = 0;
  1382. CgBinaryParameter * pParameters = ( CgBinaryParameter * )( uintp( prog ) + prog->parameterArray ) ;
  1383. for ( uint nPar = 0; nPar < prog->parameterCount; ++nPar )
  1384. {
  1385. CgBinaryParameter * pPar = pParameters + nPar;
  1386. if( pPar->isReferenced )
  1387. {
  1388. if( vcgGetTypeClass( pPar->type ) == CG_PARAMETERCLASS_SAMPLER )
  1389. {
  1390. Assert( pPar->var == CG_UNIFORM ); // if there are varying textures, I'm not sure what they mean, exactly
  1391. Assert( pPar->direction == CG_IN ); // fragment shaders don't generally output samplers. They take them as parameters.
  1392. Assert( pPar->res >= CG_TEXUNIT0 && pPar->res <= CG_TEXUNIT15 );
  1393. m_data.m_samplerInputMask |= 1 << ( pPar->res - CG_TEXUNIT0 );
  1394. }
  1395. else if ( pPar->embeddedConst )
  1396. {
  1397. const CgBinaryEmbeddedConstant * pEmbedded = ( const CgBinaryEmbeddedConstant* )( uintp( prog ) + pPar->embeddedConst );
  1398. nPatchCount += pEmbedded->ucodeCount;
  1399. }
  1400. }
  1401. else
  1402. {
  1403. Assert( !pPar->embeddedConst );
  1404. }
  1405. }
  1406. //--------------------------------------------------------------------------------------------------
  1407. // Allocate memory layout as :
  1408. // FpHeader_t
  1409. // uCode
  1410. // Patches
  1411. // Texcontrols
  1412. //--------------------------------------------------------------------------------------------------
  1413. uint nUcodeSize = AlignValue( prog->ucodeSize, 16 );
  1414. uint nTotalSize = AlignValue( sizeof( FpHeader_t ) + nUcodeSize + (sizeof( uint32 ) * nPatchCount)
  1415. + (2 * sizeof( uint32 ) * nTexControls) , 16);
  1416. m_data.m_nTotalSize = nTotalSize;
  1417. m_data.m_eaFp = ( FpHeader_t* )MemAlloc_AllocAligned( nTotalSize, 16 );
  1418. //--------------------------------------------------------------------------------------------------
  1419. // header and mictocode
  1420. //--------------------------------------------------------------------------------------------------
  1421. m_data.m_eaFp->m_nUcodeSize = nUcodeSize;
  1422. m_data.m_eaFp->m_nPatchCount = nPatchCount;
  1423. m_data.m_eaFp->m_nShaderControl0 = shCtrl0;
  1424. m_data.m_eaFp->m_nTexControls = nTexControls;
  1425. V_memcpy( m_data.m_eaFp + 1, (void*)( uintp( prog ) + prog->ucode) , prog->ucodeSize );
  1426. //--------------------------------------------------------------------------------------------------
  1427. // Patches : Each patch is : Bits 31&30 hold the patch len - 1. Bits 16-24 constant number , bits 0-16 qw index to patch
  1428. //--------------------------------------------------------------------------------------------------
  1429. uint32 *pPatches = ( uint32* ) ( uintp( m_data.m_eaFp + 1 ) + nUcodeSize ), *pPatchesEnd = pPatches + nPatchCount;
  1430. for ( uint nPar = 0; nPar < prog->parameterCount; ++nPar )
  1431. {
  1432. CgBinaryParameter * pPar = pParameters + nPar;
  1433. if ( pPar->embeddedConst )
  1434. {
  1435. uint nLength = fspatchGetLength( pPar->type );
  1436. uint32 nPatch = ( ( pPar->resIndex ) << 16 ) | ( ( nLength - 1 ) << 30 );
  1437. if( pPar->resIndex > 0xFF )
  1438. {
  1439. Error( "Fragment Program Patch table refers to non-existing virtual register %d\n", pPar->resIndex );
  1440. }
  1441. if( nLength == 0 )
  1442. Error(" Unsupported fragment program parameter type %d\n", pPar->type ); // only 4-element types are supported by the patcher so far
  1443. const CgBinaryEmbeddedConstant * pEmbedded = ( const CgBinaryEmbeddedConstant* )( uintp( prog ) + pPar->embeddedConst );
  1444. for ( uint nEm = 0; nEm < pEmbedded->ucodeCount; ++ nEm )
  1445. {
  1446. uint ucodeOffset = pEmbedded->ucodeOffset[nEm]; // is this the offset from prog structure start?
  1447. if( !IsCert() && ( ucodeOffset & 0xF ) )
  1448. {
  1449. const char * pParname = (const char * )( uintp( prog ) + pPar->name );
  1450. Error( "Patch table too big: offset 0x%X, resIndex %d, parameter %d '%s'\n", ucodeOffset, pPar->resIndex, nPar, pParname );
  1451. }
  1452. Assert( pPatches < pPatchesEnd );
  1453. *( pPatches ++ ) = nPatch | ( ucodeOffset >> 4 );
  1454. }
  1455. }
  1456. }
  1457. Assert( pPatches == pPatchesEnd );
  1458. //--------------------------------------------------------------------------------------------------
  1459. // Tex Controls
  1460. //--------------------------------------------------------------------------------------------------
  1461. uint32 * pTexControls = (uint32*)( uintp( m_data.m_eaFp ) + sizeof( FpHeader_t ) + nUcodeSize + (sizeof( uint32 ) * nPatchCount) );
  1462. uint32 * pTexControlsEnd = pTexControls + nTexControls * 2;
  1463. for( uint i = 0; texMask; i++)
  1464. {
  1465. // keep the cached variable in sync
  1466. if (texMask&1) {
  1467. uint32_t hwTexCtrl = ( texMask2D & 1) | ( ( texMaskCentroid & 1 ) << 4 );
  1468. CELL_GCM_METHOD_SET_TEX_COORD_CONTROL( pTexControls, i, hwTexCtrl );
  1469. }
  1470. texMask >>= 1;
  1471. texMask2D >>= 1;
  1472. texMaskCentroid >>= 1;
  1473. }
  1474. Assert( pTexControls == pTexControlsEnd ); // The CELL_GCM macro bumps pTexControls along..
  1475. }
  1476. IDirect3DPixelShader9::~IDirect3DPixelShader9()
  1477. {
  1478. MemAlloc_FreeAligned( m_data.m_eaFp );
  1479. }
  1480. HRESULT IDirect3DDevice9::SetPixelShader( IDirect3DPixelShader9* pShader )
  1481. {
  1482. m_pixelShader = pShader;
  1483. gpGcmDrawState->m_dirtyCachesMask |= CGcmDrawState::kDirtyPxShader;
  1484. gpGcmDrawState->m_pPixelShaderData = m_pixelShader ? &pShader->m_data : 0;
  1485. return S_OK;
  1486. }
  1487. HRESULT IDirect3DDevice9::SetPixelShaderConstantF(UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount)
  1488. {
  1489. gpGcmDrawState->SetPixelShaderConstantF(StartRegister, (float*)pConstantData, Vector4fCount);
  1490. return S_OK;
  1491. }
  1492. HRESULT IDirect3DDevice9::SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount)
  1493. {
  1494. // Not implemented on PS3!
  1495. return S_OK;
  1496. }
  1497. HRESULT IDirect3DDevice9::SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount)
  1498. {
  1499. // Not implemented on PS3!
  1500. return S_OK;
  1501. }
  1502. //--------------------------------------------------------------------------------------------------
  1503. // VERTEX SHADERS
  1504. //
  1505. // IDirect3DDevice9:: CreateVertexShader
  1506. // IDirect3DVertexShader9::~IDirect3DVertexShader9
  1507. // IDirect3DDevice9:: SetVertexShader
  1508. // SetVertexShaderConstantF
  1509. // SetVertexShaderConstantB
  1510. //--------------------------------------------------------------------------------------------------
  1511. HRESULT IDirect3DDevice9::CreateVertexShader(CONST DWORD* pFunction,IDirect3DVertexShader9** ppShader, char *debugLabel)
  1512. {
  1513. IDirect3DVertexShader9 *newprog = new IDirect3DVertexShader9;
  1514. newprog->m_pProgram = NULL; // don't copy (base member unused)
  1515. //--------------------------------------------------------------------------------------------------
  1516. // get program and in/out attr
  1517. //--------------------------------------------------------------------------------------------------
  1518. const CgBinaryProgram *prog = ( const CgBinaryProgram * )pFunction;
  1519. CgBinaryVertexProgram * binaryVertexProgram = ( CgBinaryVertexProgram* ) ( ( char* )prog + prog->program );
  1520. newprog->m_data.m_attributeInputMask = binaryVertexProgram->attributeInputMask;
  1521. newprog->m_data.m_attributeOutputMask = binaryVertexProgram->attributeOutputMask;
  1522. //--------------------------------------------------------------------------------------------------
  1523. // Determine size of VP, allocate command buffer to set VP
  1524. //--------------------------------------------------------------------------------------------------
  1525. uint nReserveWords = AlignValue( cellGcmSetVertexProgramMeasureSizeInline( 0, ( const CGprogram )prog, ( ( uint8* )prog ) + prog->ucode ), 4 );
  1526. if( nReserveWords > 4 * 1024 )
  1527. {
  1528. Error( "Vertex shader too big (%d words): won't fit into a single DMA, tell Sergiy to perform Large DMA transfer everywhere vertex shader command subbuffer is used\n", nReserveWords );
  1529. }
  1530. newprog->m_data.m_nVertexShaderCmdBufferWords = nReserveWords;
  1531. newprog->m_data.m_pVertexShaderCmdBuffer = ( uint32* ) MemAlloc_AllocAligned( nReserveWords * sizeof( uint32 ), 16 );
  1532. //--------------------------------------------------------------------------------------------------
  1533. // Use GCM to output SetVertexProgram commands
  1534. //--------------------------------------------------------------------------------------------------
  1535. CellGcmContextData tempCtx;
  1536. tempCtx.current = tempCtx.begin = newprog->m_data.m_pVertexShaderCmdBuffer;
  1537. tempCtx.end = tempCtx.begin + nReserveWords;
  1538. tempCtx.callback = NULL;
  1539. cellGcmSetVertexProgramUnsafeInline( &tempCtx, ( const CGprogram )prog, ( ( uint8* )prog ) + prog->ucode );
  1540. Assert( tempCtx.current <= tempCtx.end && tempCtx.end - tempCtx.current < 4 );
  1541. while( tempCtx.current < tempCtx.end )
  1542. {
  1543. *( tempCtx.current++ ) = CELL_GCM_METHOD_NOP; // make it 16-byte aligned
  1544. }
  1545. *ppShader = newprog;
  1546. return S_OK;
  1547. }
  1548. IDirect3DVertexShader9::~IDirect3DVertexShader9()
  1549. {
  1550. MemAlloc_FreeAligned( m_data.m_pVertexShaderCmdBuffer );
  1551. }
  1552. HRESULT IDirect3DDevice9::SetVertexShader( IDirect3DVertexShader9* pVertexShader )
  1553. {
  1554. m_vertexShader = pVertexShader;
  1555. gpGcmDrawState->m_dirtyCachesMask |= CGcmDrawState::kDirtyVxShader;
  1556. gpGcmDrawState->m_pVertexShaderData = &pVertexShader->m_data;
  1557. return S_OK;
  1558. }
  1559. HRESULT IDirect3DDevice9::SetVertexShaderConstantF( UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount )
  1560. {
  1561. gpGcmDrawState->SetVertexShaderConstantF(StartRegister, (void*)pConstantData, Vector4fCount);
  1562. return S_OK;
  1563. }
  1564. HRESULT IDirect3DDevice9::SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount)
  1565. {
  1566. gpGcmDrawState->SetVertexShaderConstantB(StartRegister, pConstantData, BoolCount);
  1567. return S_OK;
  1568. }
  1569. HRESULT IDirect3DDevice9::SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount)
  1570. {
  1571. // Not implemented on PS3!
  1572. return S_OK;
  1573. }
  1574. //--------------------------------------------------------------------------------------------------
  1575. // RENDERSTATES
  1576. //IDirect3DDevice9::SetRenderState
  1577. // SetSamplerState
  1578. // SetSamplerStatePart1
  1579. //--------------------------------------------------------------------------------------------------
  1580. struct D3D_RSINFO
  1581. {
  1582. int m_class;
  1583. D3DRENDERSTATETYPE m_state;
  1584. DWORD m_defval;
  1585. // m_class runs 0-3.
  1586. // 3 = must implement - fully general - "obey"
  1587. // 2 = implement setup to the default value (it has a GL effect but does not change later) "obey once"
  1588. // 1 = "fake implement" setup to the default value no GL effect, debug break if anything but default value comes through - "ignore"
  1589. // 0 = game never ever sets this one, break if someone even tries. "complain"
  1590. };
  1591. bool g_D3DRS_INFO_unpacked_ready = false; // set to true after unpack
  1592. D3D_RSINFO g_D3DRS_INFO_unpacked[ D3DRS_VALUE_LIMIT+1 ];
  1593. #ifdef D3D_RSI
  1594. #error macro collision... rename this
  1595. #else
  1596. #define D3D_RSI(nclass,nstate,ndefval) { nclass, nstate, ndefval }
  1597. #endif
  1598. // FP conversions to hex courtesy of http://babbage.cs.qc.cuny.edu/IEEE-754/Decimal.html
  1599. #define CONST_DZERO 0x00000000
  1600. #define CONST_DONE 0x3F800000
  1601. #define CONST_D64 0x42800000
  1602. #define DONT_KNOW_YET 0x31415926
  1603. // see http://www.toymaker.info/Games/html/render_states.html
  1604. D3D_RSINFO g_D3DRS_INFO_packed[] =
  1605. {
  1606. // these do not have to be in any particular order. they get unpacked into the empty array above for direct indexing.
  1607. D3D_RSI( 3, D3DRS_ZENABLE, DONT_KNOW_YET ), // enable Z test (or W buffering)
  1608. D3D_RSI( 3, D3DRS_ZWRITEENABLE, DONT_KNOW_YET ), // enable Z write
  1609. D3D_RSI( 3, D3DRS_ZFUNC, DONT_KNOW_YET ), // select Z func
  1610. D3D_RSI( 3, D3DRS_COLORWRITEENABLE, TRUE ), // see transitiontable.cpp "APPLY_RENDER_STATE_FUNC( D3DRS_COLORWRITEENABLE, ColorWriteEnable )"
  1611. D3D_RSI( 3, D3DRS_CULLMODE, D3DCULL_CCW ), // backface cull control
  1612. D3D_RSI( 3, D3DRS_ALPHABLENDENABLE, DONT_KNOW_YET ), // ->CTransitionTable::ApplySeparateAlphaBlend and ApplyAlphaBlend
  1613. D3D_RSI( 3, D3DRS_BLENDOP, D3DBLENDOP_ADD ),
  1614. D3D_RSI( 3, D3DRS_SRCBLEND, DONT_KNOW_YET ),
  1615. D3D_RSI( 3, D3DRS_DESTBLEND, DONT_KNOW_YET ),
  1616. D3D_RSI( 1, D3DRS_SEPARATEALPHABLENDENABLE, FALSE ), // hit in CTransitionTable::ApplySeparateAlphaBlend
  1617. D3D_RSI( 1, D3DRS_SRCBLENDALPHA, D3DBLEND_ONE ), // going to demote these to class 1 until I figure out if they are implementable
  1618. D3D_RSI( 1, D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO ),
  1619. D3D_RSI( 1, D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD ),
  1620. // what is the deal with alpha test... looks like it is inited to off.
  1621. D3D_RSI( 3, D3DRS_ALPHATESTENABLE, 0 ),
  1622. D3D_RSI( 3, D3DRS_ALPHAREF, 0 ),
  1623. D3D_RSI( 3, D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL ),
  1624. D3D_RSI( 3, D3DRS_STENCILENABLE, FALSE ),
  1625. D3D_RSI( 3, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP ),
  1626. D3D_RSI( 3, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP ),
  1627. D3D_RSI( 3, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP ),
  1628. D3D_RSI( 3, D3DRS_STENCILFUNC, D3DCMP_ALWAYS ),
  1629. D3D_RSI( 3, D3DRS_STENCILREF, 0 ),
  1630. D3D_RSI( 3, D3DRS_STENCILMASK, 0xFFFFFFFF ),
  1631. D3D_RSI( 3, D3DRS_STENCILWRITEMASK, 0xFFFFFFFF ),
  1632. D3D_RSI( 3, D3DRS_TWOSIDEDSTENCILMODE, FALSE ),
  1633. D3D_RSI( 3, D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP ),
  1634. D3D_RSI( 3, D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP ),
  1635. D3D_RSI( 3, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP ),
  1636. D3D_RSI( 3, D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS ),
  1637. D3D_RSI( 3, D3DRS_FOGENABLE, FALSE ), // see CShaderAPIDx8::FogMode and friends - be ready to do the ARB fog linear option madness
  1638. D3D_RSI( 3, D3DRS_FOGCOLOR, 0 ),
  1639. D3D_RSI( 3, D3DRS_FOGTABLEMODE, D3DFOG_NONE ),
  1640. D3D_RSI( 3, D3DRS_FOGSTART, CONST_DZERO ),
  1641. D3D_RSI( 3, D3DRS_FOGEND, CONST_DONE ),
  1642. D3D_RSI( 3, D3DRS_FOGDENSITY, CONST_DZERO ),
  1643. D3D_RSI( 3, D3DRS_RANGEFOGENABLE, FALSE ),
  1644. D3D_RSI( 3, D3DRS_FOGVERTEXMODE, D3DFOG_NONE ), // watch out for CShaderAPIDx8::CommitPerPassFogMode....
  1645. D3D_RSI( 3, D3DRS_MULTISAMPLEANTIALIAS, TRUE ),
  1646. D3D_RSI( 3, D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF ),
  1647. D3D_RSI( 3, D3DRS_SCISSORTESTENABLE, FALSE ), // heed IDirect3DDevice9::SetScissorRect
  1648. D3D_RSI( 3, D3DRS_DEPTHBIAS, CONST_DZERO ),
  1649. D3D_RSI( 3, D3DRS_SLOPESCALEDEPTHBIAS, CONST_DZERO ),
  1650. D3D_RSI( 3, D3DRS_COLORWRITEENABLE1, 0x0000000f ),
  1651. D3D_RSI( 3, D3DRS_COLORWRITEENABLE2, 0x0000000f ),
  1652. D3D_RSI( 3, D3DRS_COLORWRITEENABLE3, 0x0000000f ),
  1653. D3D_RSI( 3, D3DRS_SRGBWRITEENABLE, 0 ), // heeded but ignored..
  1654. D3D_RSI( 2, D3DRS_CLIPPING, TRUE ), // um, yeah, clipping is enabled (?)
  1655. D3D_RSI( 3, D3DRS_CLIPPLANEENABLE, 0 ), // mask 1<<n of active user clip planes.
  1656. D3D_RSI( 0, D3DRS_LIGHTING, 0 ), // strange, someone turns it on then off again. move to class 0 and just ignore it (lie)?
  1657. D3D_RSI( 3, D3DRS_FILLMODE, D3DFILL_SOLID ),
  1658. D3D_RSI( 1, D3DRS_SHADEMODE, D3DSHADE_GOURAUD ),
  1659. D3D_RSI( 1, D3DRS_LASTPIXEL, TRUE ),
  1660. D3D_RSI( 1, D3DRS_DITHERENABLE, 0 ), //set to false by game, no one sets it to true
  1661. D3D_RSI( 1, D3DRS_SPECULARENABLE, FALSE ),
  1662. D3D_RSI( 1, D3DRS_TEXTUREFACTOR, 0xFFFFFFFF ), // watch out for CShaderAPIDx8::Color3f et al.
  1663. D3D_RSI( 1, D3DRS_WRAP0, 0 ),
  1664. D3D_RSI( 1, D3DRS_WRAP1, 0 ),
  1665. D3D_RSI( 1, D3DRS_WRAP2, 0 ),
  1666. D3D_RSI( 1, D3DRS_WRAP3, 0 ),
  1667. D3D_RSI( 1, D3DRS_WRAP4, 0 ),
  1668. D3D_RSI( 1, D3DRS_WRAP5, 0 ),
  1669. D3D_RSI( 1, D3DRS_WRAP6, 0 ),
  1670. D3D_RSI( 1, D3DRS_WRAP7, 0 ),
  1671. D3D_RSI( 1, D3DRS_AMBIENT, 0 ), // FF lighting, no
  1672. D3D_RSI( 1, D3DRS_COLORVERTEX, TRUE ), // FF lighing again
  1673. D3D_RSI( 1, D3DRS_LOCALVIEWER, TRUE ), // FF lighting
  1674. D3D_RSI( 1, D3DRS_NORMALIZENORMALS, FALSE ), // FF mode I think. CShaderAPIDx8::SetVertexBlendState says it might switch this on when skinning is in play
  1675. D3D_RSI( 1, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL ), // hit only in CShaderAPIDx8::ResetRenderState
  1676. D3D_RSI( 1, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2 ),
  1677. D3D_RSI( 1, D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL ),
  1678. D3D_RSI( 1, D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL ),
  1679. D3D_RSI( 1, D3DRS_VERTEXBLEND, D3DVBF_DISABLE ), // also being set by CShaderAPIDx8::SetVertexBlendState, so might be FF
  1680. D3D_RSI( 1, D3DRS_POINTSIZE, CONST_DONE ),
  1681. D3D_RSI( 1, D3DRS_POINTSIZE_MIN, CONST_DONE ),
  1682. D3D_RSI( 1, D3DRS_POINTSPRITEENABLE, FALSE ),
  1683. D3D_RSI( 1, D3DRS_POINTSCALEENABLE, FALSE ),
  1684. D3D_RSI( 1, D3DRS_POINTSCALE_A, CONST_DONE ),
  1685. D3D_RSI( 1, D3DRS_POINTSCALE_B, CONST_DZERO ),
  1686. D3D_RSI( 1, D3DRS_POINTSCALE_C, CONST_DZERO ),
  1687. D3D_RSI( 1, D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE ),
  1688. D3D_RSI( 1, D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE ),
  1689. D3D_RSI( 1, D3DRS_POINTSIZE_MAX, CONST_D64 ),
  1690. D3D_RSI( 1, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE ),
  1691. D3D_RSI( 1, D3DRS_TWEENFACTOR, CONST_DZERO ),
  1692. D3D_RSI( 1, D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC ),
  1693. D3D_RSI( 1, D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR ),
  1694. D3D_RSI( 1, D3DRS_ANTIALIASEDLINEENABLE, FALSE ), // just ignore it
  1695. D3D_RSI( 1, D3DRS_MINTESSELLATIONLEVEL, CONST_DONE ),
  1696. D3D_RSI( 1, D3DRS_MAXTESSELLATIONLEVEL, CONST_DONE ),
  1697. D3D_RSI( 1, D3DRS_ADAPTIVETESS_X, CONST_DZERO ),
  1698. D3D_RSI( 1, D3DRS_ADAPTIVETESS_Y, CONST_DZERO ),
  1699. D3D_RSI( 1, D3DRS_ADAPTIVETESS_Z, CONST_DONE ),
  1700. D3D_RSI( 1, D3DRS_ADAPTIVETESS_W, CONST_DZERO ),
  1701. D3D_RSI( 1, D3DRS_ENABLEADAPTIVETESSELLATION, FALSE ),
  1702. D3D_RSI( 1, D3DRS_BLENDFACTOR, 0xffffffff ),
  1703. D3D_RSI( 1, D3DRS_WRAP8, 0 ),
  1704. D3D_RSI( 1, D3DRS_WRAP9, 0 ),
  1705. D3D_RSI( 1, D3DRS_WRAP10, 0 ),
  1706. D3D_RSI( 1, D3DRS_WRAP11, 0 ),
  1707. D3D_RSI( 1, D3DRS_WRAP12, 0 ),
  1708. D3D_RSI( 1, D3DRS_WRAP13, 0 ),
  1709. D3D_RSI( 1, D3DRS_WRAP14, 0 ),
  1710. D3D_RSI( 1, D3DRS_WRAP15, 0 ),
  1711. D3D_RSI( -1, (D3DRENDERSTATETYPE)0, 0 ) // terminator
  1712. };
  1713. uint FindOrInsert( CUtlVector<uint32> &arrDefValues, uint32 nDefValue )
  1714. {
  1715. // the def value array is supposed to be VERY short, so linear search is faster than binary
  1716. Assert( arrDefValues.Count() < 16 );
  1717. for( uint i = 0; i < arrDefValues.Count(); ++i )
  1718. {
  1719. if( arrDefValues[i] == nDefValue )
  1720. return i;
  1721. }
  1722. arrDefValues.AddToTail( nDefValue );
  1723. return arrDefValues.Count() - 1 ;
  1724. }
  1725. void UnpackD3DRSITable( void )
  1726. {
  1727. V_memset (g_D3DRS_INFO_unpacked, 0, sizeof(g_D3DRS_INFO_unpacked) );
  1728. for( D3D_RSINFO *packed = g_D3DRS_INFO_packed; packed->m_class >= 0; packed++ )
  1729. {
  1730. if ( (packed->m_state <0) || (packed->m_state >= D3DRS_VALUE_LIMIT) )
  1731. {
  1732. // bad
  1733. Debugger();
  1734. }
  1735. else
  1736. {
  1737. // dispatch it to the unpacked array
  1738. g_D3DRS_INFO_unpacked[ packed->m_state ] = *packed;
  1739. }
  1740. }
  1741. }
  1742. HRESULT IDirect3DDevice9::SetRenderState(D3DRENDERSTATETYPE State,DWORD Value)
  1743. {
  1744. gpGcmDrawState->SetRenderState(State, Value);
  1745. return S_OK;
  1746. }
  1747. HRESULT IDirect3DDevice9::SetSamplerState(DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value)
  1748. {
  1749. gpGcmDrawState->SetSamplerState(Sampler, Type, Value);
  1750. return S_OK;
  1751. }
  1752. //--------------------------------------------------------------------------------------------------
  1753. // VERTEX DECLS, STREAMS, BUFFERS, INDICES
  1754. // IDirect3DDevice9:: CreateVertexDeclaration
  1755. // SetVertexDeclaration
  1756. // CreateVertexBuffer
  1757. // SetVertexStreamSource
  1758. // SetStreamSource
  1759. // FlushVertexCache
  1760. // SetRawHardwareDataStreams
  1761. // IDirect3DIndexBuffer9::GetDesc
  1762. // IDirect3DDevice9:: CreateIndexBuffer
  1763. // SetIndices
  1764. // ValidateDrawPrimitiveStreams
  1765. //--------------------------------------------------------------------------------------------------
  1766. // Lookup table used by CreateVertexDeclaration
  1767. unsigned char g_D3DDeclFromPSGL_UsageMappingTable[] =
  1768. {
  1769. /*0x00*/ 0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1770. /*0x10*/ 1, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1771. /*0x20*/ 7, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1772. /*0x30*/ 2, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1773. /*0x40*/ 6, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1774. /*0x50*/ 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1775. /*0x60*/ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1776. /*0x70*/ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1777. /*0x80*/ 5, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1778. /*0x90*/ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1779. /*0xA0*/ 3, 4, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1780. /*0xB0*/ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1781. /*0xC0*/ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1782. /*0xD0*/ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1783. /*0xE0*/ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1784. /*0xF0*/ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
  1785. };
  1786. HRESULT IDirect3DDevice9::CreateVertexDeclaration( CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl)
  1787. {
  1788. *ppDecl = NULL;
  1789. // the goal here is to arrive at something which lets us quickly generate GLMVertexSetups.
  1790. // the information we don't have, that must be inferred from the decls, is:
  1791. // -> how many unique streams (buffers) are used - pure curiosity
  1792. // -> 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.
  1793. // so init an array of per-stream offsets to 0.
  1794. // each one is a cursor that gets bumped by decls.
  1795. uint streamOffsets[ D3D_MAX_STREAMS ];
  1796. memset( streamOffsets, 0, sizeof( streamOffsets ) );
  1797. IDirect3DVertexDeclaration9 *decl9 = new IDirect3DVertexDeclaration9;
  1798. Assert( !( uintp( decl9 ) & 0xF ) );
  1799. decl9->m_elemCount = 0;
  1800. for (const D3DVERTEXELEMENT9 *src = pVertexElements; (src->Stream != 0xFF); src++)
  1801. {
  1802. // element
  1803. D3DVERTEXELEMENT9_GCM *elem = &decl9->m_elements[ decl9->m_elemCount++ ];
  1804. // copy the D3D decl wholesale.
  1805. elem->m_dxdecl = *src;
  1806. // On PS3:
  1807. // TEXCOORD4 == POSITION1 (this semantic doesn't exist in Cg, see #define in common_vs_fxc.h)
  1808. // TEXCOORD5 == NORMAL1 (this semantic doesn't exist in Cg, see #define in common_vs_fxc.h)
  1809. // TEXCOORD6 == TANGENT (Cg remaps this automatically)
  1810. // TEXCOORD7 == BINORMAL (Cg remaps this automatically)
  1811. if ( elem->m_dxdecl.Usage == D3DDECLUSAGE_TANGENT )
  1812. {
  1813. Assert( elem->m_dxdecl.UsageIndex == 0 );
  1814. elem->m_dxdecl.Usage = D3DDECLUSAGE_TEXCOORD;
  1815. elem->m_dxdecl.UsageIndex = 6;
  1816. }
  1817. else if ( elem->m_dxdecl.Usage == D3DDECLUSAGE_BINORMAL )
  1818. {
  1819. Assert( elem->m_dxdecl.UsageIndex == 0 );
  1820. elem->m_dxdecl.Usage = D3DDECLUSAGE_TEXCOORD;
  1821. elem->m_dxdecl.UsageIndex = 7;
  1822. }
  1823. else if ( elem->m_dxdecl.Usage == D3DDECLUSAGE_POSITION && elem->m_dxdecl.UsageIndex >= 1 )
  1824. {
  1825. Assert( elem->m_dxdecl.UsageIndex == 1 );
  1826. elem->m_dxdecl.Usage = D3DDECLUSAGE_TEXCOORD;
  1827. elem->m_dxdecl.UsageIndex = 4;
  1828. }
  1829. else if ( elem->m_dxdecl.Usage == D3DDECLUSAGE_NORMAL && elem->m_dxdecl.UsageIndex >= 1 )
  1830. {
  1831. Assert( elem->m_dxdecl.UsageIndex == 1 );
  1832. elem->m_dxdecl.Usage = D3DDECLUSAGE_TEXCOORD;
  1833. elem->m_dxdecl.UsageIndex = 5;
  1834. }
  1835. // latch current offset in this stream.
  1836. elem->m_gcmdecl.m_offset = streamOffsets[ elem->m_dxdecl.Stream ];
  1837. // figure out size of this attr and move the cursor
  1838. // if cursor was on zero, bump the active stream count
  1839. int bytes = 0;
  1840. switch( elem->m_dxdecl.Type )
  1841. {
  1842. case D3DDECLTYPE_FLOAT1: elem->m_gcmdecl.m_datasize = 1; elem->m_gcmdecl.m_datatype = CELL_GCM_VERTEX_F; bytes = 4; break;
  1843. case D3DDECLTYPE_FLOAT2: elem->m_gcmdecl.m_datasize = 2; elem->m_gcmdecl.m_datatype = CELL_GCM_VERTEX_F; bytes = 8; break;
  1844. //case D3DVSDT_FLOAT3:
  1845. case D3DDECLTYPE_FLOAT3: elem->m_gcmdecl.m_datasize = 3; elem->m_gcmdecl.m_datatype = CELL_GCM_VERTEX_F; bytes = 12; break;
  1846. //case D3DVSDT_FLOAT4:
  1847. case D3DDECLTYPE_FLOAT4: elem->m_gcmdecl.m_datasize = 4; elem->m_gcmdecl.m_datatype = CELL_GCM_VERTEX_F; bytes = 16; break;
  1848. case D3DDECLTYPE_SHORT2: elem->m_gcmdecl.m_datasize = 2; elem->m_gcmdecl.m_datatype = CELL_GCM_VERTEX_S32K; bytes = 4; break;
  1849. case D3DDECLTYPE_UBYTE4: elem->m_gcmdecl.m_datasize = 4; elem->m_gcmdecl.m_datatype = CELL_GCM_VERTEX_UB256; bytes = 4; break;
  1850. case D3DDECLTYPE_UBYTE4N: elem->m_gcmdecl.m_datasize = 4; elem->m_gcmdecl.m_datatype = CELL_GCM_VERTEX_UB; bytes = 4; break;
  1851. // case D3DVSDT_UBYTE4:
  1852. case D3DDECLTYPE_D3DCOLOR:
  1853. // pass 4 UB's but we know this is out of order compared to D3DCOLOR data
  1854. elem->m_gcmdecl.m_datasize = 4; elem->m_gcmdecl.m_datatype = CELL_GCM_VERTEX_UB;
  1855. bytes = 4;
  1856. break;
  1857. default: Debugger(); return (HRESULT)-1; break;
  1858. }
  1859. // write the offset and move the cursor
  1860. streamOffsets[ elem->m_dxdecl.Stream ] += bytes;
  1861. // elem count was already bumped.
  1862. }
  1863. // the loop is done, we now know how many active streams there are, how many atribs are active in the declaration,
  1864. // and how big each one is in terms of stride.
  1865. // PS3 has fixed semantics of 16 attributes, to avoid searches later when
  1866. // binding to slots perform the search now once:
  1867. memset( decl9->m_cgAttrSlots, 0, sizeof( decl9->m_cgAttrSlots ) );
  1868. for ( int j = 0; j < decl9->m_elemCount; ++ j )
  1869. {
  1870. D3DVERTEXELEMENT9_GCM *elem = &decl9->m_elements[ j ];
  1871. unsigned char uchType = ( ( elem->m_dxdecl.Usage & 0xF ) << 4 ) | ( elem->m_dxdecl.UsageIndex & 0xF );
  1872. unsigned char chType = g_D3DDeclFromPSGL_UsageMappingTable[ uchType ];
  1873. if ( chType < ARRAYSIZE( decl9->m_cgAttrSlots ) )
  1874. {
  1875. if ( !decl9->m_cgAttrSlots[chType] )
  1876. {
  1877. decl9->m_cgAttrSlots[chType] = j + 1;
  1878. }
  1879. else
  1880. {
  1881. // An input element has already been mapped to this slot.
  1882. // This can happen when the vertex decl uses POSITION1/NORMAL1 (flex deltas), which we map to TEXCOORD4/5, and the decl already uses TEXCOORD4/5.
  1883. // For now we ignore these elements, which it turns out are always unused when the vertex shader actually uses TEXCOORD4/5.
  1884. }
  1885. }
  1886. else
  1887. {
  1888. Assert( false );
  1889. }
  1890. }
  1891. *ppDecl = decl9;
  1892. return S_OK;
  1893. }
  1894. HRESULT IDirect3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl)
  1895. {
  1896. // 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.
  1897. // GLM can see what the differences are and act accordingly to adjust vert attrib bindings.
  1898. m_vertDecl = pDecl;
  1899. return S_OK;
  1900. }
  1901. HRESULT IDirect3DDevice9::SetFVF(DWORD FVF)
  1902. {
  1903. Debugger();
  1904. return S_OK;
  1905. }
  1906. HRESULT IDirect3DDevice9::GetFVF(DWORD* pFVF)
  1907. {
  1908. Debugger();
  1909. return S_OK;
  1910. }
  1911. HRESULT IDirect3DDevice9::CreateVertexBuffer(UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,VD3DHANDLE* pSharedHandle)
  1912. {
  1913. IDirect3DVertexBuffer9 *pNewVertexBuffer = new IDirect3DVertexBuffer9;
  1914. //pNewVertexBuffer->m_restype = D3DRTYPE_VERTEXBUFFER; hmmmmmmm why are we not derived from d3dresource..
  1915. CPs3gcmAllocationType_t eAllocType = kAllocPs3GcmVertexBuffer;
  1916. if ( Usage & D3DUSAGE_EDGE_DMA_INPUT )
  1917. eAllocType = kAllocPs3GcmVertexBufferDma;
  1918. else if ( Usage & D3DUSAGE_DYNAMIC )
  1919. eAllocType = kAllocPs3GcmVertexBufferDynamic;
  1920. pNewVertexBuffer->m_pBuffer = CPs3gcmBuffer::New( Length, eAllocType );
  1921. pNewVertexBuffer->m_vtxDesc.Type = D3DRTYPE_VERTEXBUFFER;
  1922. pNewVertexBuffer->m_vtxDesc.Usage = Usage;
  1923. pNewVertexBuffer->m_vtxDesc.Pool = Pool;
  1924. pNewVertexBuffer->m_vtxDesc.Size = Length;
  1925. *ppVertexBuffer = pNewVertexBuffer;
  1926. return S_OK;
  1927. }
  1928. inline void IDirect3DDevice9::SetVertexStreamSource( uint nStreamIndex, IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride )
  1929. {
  1930. gpGcmDrawState->SetVertexStreamSource(nStreamIndex, pStreamData, OffsetInBytes, Stride);
  1931. }
  1932. HRESULT IDirect3DDevice9::SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
  1933. {
  1934. // perfectly legal to see a vertex buffer of NULL get passed in here.
  1935. // so we need an array to track these.
  1936. // OK, we are being given the stride, we don't need to calc it..
  1937. SetVertexStreamSource( StreamNumber, pStreamData, OffsetInBytes, Stride );
  1938. return S_OK;
  1939. }
  1940. HRESULT IDirect3DDevice9::SetRawHardwareDataStreams( IDirect3DVertexBuffer9** ppRawHardwareDataStreams )
  1941. {
  1942. // Unused on PS3
  1943. // if ( ppRawHardwareDataStreams )
  1944. // {
  1945. // V_memcpy( gpGcmDrawState->m_arrRawHardwareDataStreams, ppRawHardwareDataStreams, sizeof( gpGcmDrawState->m_arrRawHardwareDataStreams ) );
  1946. // }
  1947. // else
  1948. // {
  1949. // V_memset( gpGcmDrawState->m_arrRawHardwareDataStreams, 0, sizeof( gpGcmDrawState->m_arrRawHardwareDataStreams ) );
  1950. // }
  1951. return S_OK;
  1952. }
  1953. void IDirect3DDevice9::FlushVertexCache()
  1954. {
  1955. gpGcmDrawState->SetInvalidateVertexCache();
  1956. }
  1957. HRESULT IDirect3DIndexBuffer9::GetDesc(D3DINDEXBUFFER_DESC *pDesc)
  1958. {
  1959. *pDesc = m_idxDesc;
  1960. return S_OK;
  1961. }
  1962. // index buffers
  1963. HRESULT IDirect3DDevice9::CreateIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,VD3DHANDLE* pSharedHandle)
  1964. {
  1965. // it is important to save all the create info, since GetDesc could get called later to query it
  1966. IDirect3DIndexBuffer9 *pNewIndexBuffer = new IDirect3DIndexBuffer9;
  1967. CPs3gcmAllocationType_t eAllocType = kAllocPs3GcmIndexBuffer;
  1968. if ( Usage & D3DUSAGE_EDGE_DMA_INPUT )
  1969. eAllocType = kAllocPs3GcmIndexBufferDma;
  1970. else if ( Usage & D3DUSAGE_DYNAMIC )
  1971. eAllocType = kAllocPs3GcmIndexBufferDynamic;
  1972. pNewIndexBuffer->m_pBuffer = CPs3gcmBuffer::New( Length, eAllocType );
  1973. pNewIndexBuffer->m_idxDesc.Format = Format;
  1974. pNewIndexBuffer->m_idxDesc.Type = D3DRTYPE_INDEXBUFFER;
  1975. pNewIndexBuffer->m_idxDesc.Usage = Usage;
  1976. pNewIndexBuffer->m_idxDesc.Pool = Pool;
  1977. pNewIndexBuffer->m_idxDesc.Size = Length;
  1978. *ppIndexBuffer = pNewIndexBuffer;
  1979. return S_OK;
  1980. }
  1981. HRESULT IDirect3DDevice9::SetIndices( IDirect3DIndexBuffer9* pIndexData )
  1982. {
  1983. // just latch it.
  1984. m_indices.m_idxBuffer = pIndexData;
  1985. return S_OK;
  1986. }
  1987. ConVar r_ps3_validatestreams( "r_ps3_validatestreams", "0", FCVAR_DEVELOPMENTONLY );
  1988. HRESULT IDirect3DDevice9::ValidateDrawPrimitiveStreams( D3DPRIMITIVETYPE Type, UINT baseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount )
  1989. {
  1990. return S_OK;
  1991. }
  1992. //--------------------------------------------------------------------------------------------------
  1993. // DRAW
  1994. //
  1995. // IDirect3DDevice9:: DrawPrimitive
  1996. // DrawPrimitiveUP
  1997. // DrawIndexedPrimitive
  1998. // Clear
  1999. //--------------------------------------------------------------------------------------------------
  2000. HRESULT IDirect3DDevice9::DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount)
  2001. {
  2002. Debugger();
  2003. return S_OK;
  2004. }
  2005. void IDirect3DDevice9::DrawPrimitiveUP( D3DPRIMITIVETYPE nPrimitiveType,UINT nPrimitiveCount,
  2006. CONST void *pVertexStreamZeroData, UINT nVertexStreamZeroStride )
  2007. {
  2008. gpGcmDrawState->DrawPrimitiveUP(m_vertDecl, nPrimitiveType, nPrimitiveCount, pVertexStreamZeroData, nVertexStreamZeroStride);
  2009. }
  2010. HRESULT IDirect3DDevice9::DrawIndexedPrimitive( D3DPRIMITIVETYPE Type,INT BaseVertexIndex,UINT MinVertexIndex,
  2011. UINT NumVertices,UINT startIndex,UINT nDrawPrimCount )
  2012. {
  2013. uint32 offset = m_indices.m_idxBuffer->m_pBuffer->Offset();
  2014. gpGcmDrawState->DrawIndexedPrimitive(offset, m_vertDecl, Type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, nDrawPrimCount );
  2015. return S_OK;
  2016. }
  2017. HRESULT IDirect3DDevice9::Clear( DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil )
  2018. {
  2019. uint32 depth = ( ( m_dsSurface ) && ( m_dsSurface->m_desc.Format == D3DFMT_D16 ) ) ? 16 : 32;
  2020. gpGcmDrawState->ClearSurface(Flags, Color, Z, Stencil, depth );
  2021. return S_OK;
  2022. }
  2023. HRESULT IDirect3DDevice9::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride)
  2024. {
  2025. Debugger();
  2026. return S_OK;
  2027. }
  2028. //--------------------------------------------------------------------------------------------------
  2029. // Zpass
  2030. //--------------------------------------------------------------------------------------------------
  2031. void IDirect3DDevice9::BeginZPass( DWORD Flags )
  2032. {
  2033. // Assert( Flags == 0 );
  2034. // if( !m_isZPass )
  2035. // {
  2036. // m_isZPass = g_spuGcm.BeginZPass();
  2037. // }
  2038. }
  2039. void IDirect3DDevice9::SetPredication( DWORD PredicationMask )
  2040. {
  2041. // Assert( PredicationMask == 0 || PredicationMask == D3DPRED_ALL_RENDER || PredicationMask == D3DPRED_ALL_Z || PredicationMask == ( D3DPRED_ALL_RENDER | D3DPRED_ALL_Z ) );
  2042. // g_spuGcm.SetPredication( PredicationMask );
  2043. }
  2044. HRESULT IDirect3DDevice9::EndZPass()
  2045. {
  2046. // if( m_isZPass )
  2047. // {
  2048. // g_spuGcm.EndZPass( true ); // ZPass may have ended prematurely, we still pop the marker
  2049. // m_isZPass = false;
  2050. // }
  2051. return S_OK;
  2052. }
  2053. //--------------------------------------------------------------------------------------------------
  2054. // Anti-Aliasing
  2055. //--------------------------------------------------------------------------------------------------
  2056. ConVar r_mlaa_hints("r_mlaa_hints", "1");
  2057. void IDirect3DDevice9::StartRenderingIntoPreviousFramebuffer()
  2058. {
  2059. // g_flipHandler.QmsAdviceBeforeDrawPrevFramebuffer();
  2060. // m_defaultColorSurface->m_tex->m_lmBlock.Assign( g_ps3gcmGlobalState.m_display.surfaceColor[ g_ps3gcmGlobalState.m_display.PrevSurfaceIndex( 1 ) ] );
  2061. // if( m_defaultColorSurface == m_rtSurfaces[ 0 ] )
  2062. // {
  2063. // Ps3Helper_UpdateSurface( 0 );
  2064. // }
  2065. }
  2066. void IDirect3DDevice9::AntiAliasingHint( int nHint )
  2067. {
  2068. // if( 0 && !IsCert() && IsDebug() )
  2069. // {
  2070. // const char * pAaHintReadableNames[] = {
  2071. // "AA_HINT_MESHES",
  2072. // "AA_HINT_TEXT",
  2073. // "AA_HINT_DEBUG_TEXT",
  2074. // "AA_HINT_HEAVY_UI_OVERLAY",
  2075. // "AA_HINT_ALIASING_PUSH",
  2076. // "AA_HINT_ALIASING_POP",
  2077. // "AA_HINT_POSTPROCESS",
  2078. // "AA_HINT_MOVIE",
  2079. // "AA_HINT_MENU"
  2080. // };
  2081. //
  2082. // Msg( "AntiAliasingHint( %s )\n", nHint >= ARRAYSIZE( pAaHintReadableNames ) ? "Out Of Range" : pAaHintReadableNames[ nHint ] );
  2083. // }
  2084. //
  2085. // switch( nHint )
  2086. // {
  2087. // case AA_HINT_HEAVY_UI_OVERLAY:
  2088. // if( r_mlaa_hints.GetInt() & 2 )
  2089. // {
  2090. // g_spuGcm.DrawQueueNormal();
  2091. //
  2092. // StartRenderingIntoPreviousFramebuffer();
  2093. //
  2094. // // from now and until the end of frame, render into previous surface (or in this surface, but deferred to next frame)
  2095. // // this means we'll have a potential without VGUI rendering and proper post-processing
  2096. // m_nAntiAliasingStatus = AA_STATUS_PREV_FRAME;
  2097. // }
  2098. // g_spuGcm.DisableMlaa();
  2099. // //g_spuGcm.DisableMlaaForTwoFrames();
  2100. // break;
  2101. //
  2102. // case AA_HINT_ALIASING_PUSH:
  2103. // g_spuGcm.DisableMlaaPermanently();
  2104. // break;
  2105. //
  2106. // case AA_HINT_ALIASING_POP:
  2107. // g_flipHandler.EnableMlaaPermannetly();
  2108. // break;
  2109. //
  2110. // case AA_HINT_MOVIE:
  2111. // case AA_HINT_MENU:
  2112. // //g_spuGcm.DrawQueueNormal();
  2113. // g_spuGcm.DisableMlaa();
  2114. // // if drawing into previous frame, do we need to continue that? both ways will probably work
  2115. // break;
  2116. //
  2117. // case AA_HINT_MESHES:
  2118. // if( g_flipHandler.IsMlaaEnabled() && m_nAntiAliasingStatus != AA_STATUS_NORMAL )
  2119. // {
  2120. // // switch back to default surface now...
  2121. // if( g_spuGcm.m_bUseDeferredDrawQueue )
  2122. // {
  2123. // g_spuGcm.DrawQueueNormal();
  2124. // if( m_nAntiAliasingStatus == AA_STATUS_PREV_FRAME )
  2125. // {
  2126. // // the first time this frame we need to set deferred queue surface
  2127. // Ps3Helper_UpdateSurface( 0 );
  2128. // }
  2129. // }
  2130. // else
  2131. // {
  2132. // m_defaultColorSurface->m_tex->m_lmBlock.Assign( g_ps3gcmGlobalState.m_display.surfaceColor[ g_ps3gcmGlobalState.m_display.surfaceFlipIdx ] );
  2133. // if( m_defaultColorSurface == m_rtSurfaces[ 0 ] )
  2134. // {
  2135. // Ps3Helper_UpdateSurface( 0 );
  2136. // }
  2137. // // from now and until the end of frame, render into previous surface
  2138. // // this means we'll have a potential without VGUI rendering and proper post-processing when we
  2139. // }
  2140. // m_nAntiAliasingStatus = AA_STATUS_NORMAL;
  2141. // GCM_PERF_MARKER( "AntiAliasing_ON" );
  2142. // }
  2143. // break;
  2144. //
  2145. // case AA_HINT_DEBUG_TEXT:
  2146. // if( g_flipHandler.IsMlaaEnabled() && m_nAntiAliasingStatus != AA_STATUS_PREV_FRAME && r_mlaa_hints.GetBool() )
  2147. // {
  2148. // // switch not normal ( non-deferred ) drawing in case we peruse deferred drawing
  2149. // if( g_spuGcm.m_bUseDeferredDrawQueue )
  2150. // {
  2151. // g_spuGcm.DrawQueueNormal();
  2152. // }
  2153. //
  2154. // StartRenderingIntoPreviousFramebuffer();
  2155. //
  2156. // m_nAntiAliasingStatus = AA_STATUS_PREV_FRAME;
  2157. // }
  2158. // break;
  2159. //
  2160. // case AA_HINT_TEXT:
  2161. // case AA_HINT_POSTPROCESS:
  2162. // if( g_flipHandler.IsMlaaEnabled() && m_nAntiAliasingStatus != AA_STATUS_DEFERRED && r_mlaa_hints.GetBool() )
  2163. // {
  2164. // GCM_PERF_MARKER("AntiAliasing_OFF");
  2165. // // switch back to default surface now...
  2166. // if( g_spuGcm.m_bUseDeferredDrawQueue )
  2167. // {
  2168. // if( g_spuGcm.DrawQueueDeferred().isFirstInFrame ) // this doesn't do actual rendering, so we don't need to switch render surface to previous frame
  2169. // {
  2170. // // this is the first time this frame, so record switching the surface
  2171. // // even if the surface is not framebuffer, we still need to record it
  2172. // g_spuGcm.OpenDeferredChunk( SPUDRAWQUEUE_DEFERRED_GCMFLUSH_DRAW_METHOD );
  2173. // Ps3Helper_UpdateSurface( 0 );
  2174. // g_spuGcm.OpenDeferredChunk( );
  2175. // }
  2176. // if( g_spuGcm.IsDeferredDrawQueue() )
  2177. // {
  2178. // // we should've succeeded; if we didn't it means we ran out of memory or something. TODO: test the failure code path
  2179. // m_nAntiAliasingStatus = AA_STATUS_DEFERRED;
  2180. // }
  2181. // }
  2182. // else
  2183. // {
  2184. // StartRenderingIntoPreviousFramebuffer();
  2185. //
  2186. // // from now and until the end of frame, render into previous surface (or in this surface, but deferred to next frame)
  2187. // // this means we'll have a potential without VGUI rendering and proper post-processing
  2188. // m_nAntiAliasingStatus = AA_STATUS_PREV_FRAME;
  2189. // }
  2190. // }
  2191. // break;
  2192. //
  2193. // }
  2194. }
  2195. //--------------------------------------------------------------------------------------------------
  2196. // IDirect3DDevice9:: CreateQuery
  2197. // QueryGlobalStateFence_t::PrepareForQuery
  2198. // QueryGlobalStateOcclusion_t::PrepareForQuery
  2199. // IDirect3DQuery9::Issue
  2200. // GetData
  2201. //--------------------------------------------------------------------------------------------------
  2202. IDirect3DQuery9::QueryGlobalStateOcclusion_t IDirect3DQuery9::s_GlobalStateOcclusion;
  2203. uint32 IDirect3DQuery9::QueryGlobalStateOcclusion_t::PrepareForQuery()
  2204. {
  2205. uint32 uiQuery = (m_queryIdx ++) % kMaxQueries;
  2206. if ( !m_Values[uiQuery] )
  2207. m_Values[uiQuery] = cellGcmGetReportDataAddress( uiQuery + QueryGlobalStateOcclusion_t::kGcmQueryBase );
  2208. m_Values[ uiQuery ]->zero = ~0;
  2209. return uiQuery;
  2210. }
  2211. IDirect3DQuery9::QueryGlobalStateFence_t IDirect3DQuery9::s_GlobalStateFence;
  2212. uint32 IDirect3DQuery9::QueryGlobalStateFence_t::PrepareForQuery()
  2213. {
  2214. uint32 uiQuery = (m_queryIdx ++) % kMaxQueries;
  2215. if ( !m_Values[uiQuery] )
  2216. m_Values[uiQuery] = cellGcmGetLabelAddress( uiQuery + QueryGlobalStateFence_t::kGcmLabelBase );
  2217. (*m_Values[uiQuery]) = ~0;
  2218. return uiQuery;
  2219. }
  2220. HRESULT IDirect3DDevice9::CreateQuery(D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery)
  2221. {
  2222. IDirect3DQuery9 *newquery = new IDirect3DQuery9;
  2223. newquery->m_type = Type;
  2224. newquery->m_queryIdx = ~0;
  2225. switch ( Type )
  2226. {
  2227. case D3DQUERYTYPE_OCCLUSION: /* D3DISSUE_BEGIN, D3DISSUE_END */
  2228. // newquery->m_query = newquery->s_GlobalStateOcclusion.PrepareForQuery();
  2229. break;
  2230. case D3DQUERYTYPE_EVENT: /* D3DISSUE_END */
  2231. // newquery->m_query = newquery->s_GlobalStateFence.PrepareForQuery();
  2232. break;
  2233. case D3DQUERYTYPE_RESOURCEMANAGER: /* D3DISSUE_END */
  2234. case D3DQUERYTYPE_TIMESTAMP: /* D3DISSUE_END */
  2235. case D3DQUERYTYPE_TIMESTAMPFREQ: /* D3DISSUE_END */
  2236. case D3DQUERYTYPE_INTERFACETIMINGS: /* D3DISSUE_BEGIN, D3DISSUE_END */
  2237. case D3DQUERYTYPE_PIXELTIMINGS: /* D3DISSUE_BEGIN, D3DISSUE_END */
  2238. case D3DQUERYTYPE_CACHEUTILIZATION: /* D3DISSUE_BEGIN, D3DISSUE_END */
  2239. Assert( !"Un-implemented query type" );
  2240. break;
  2241. default:
  2242. Assert( !"Unknown query type" );
  2243. break;
  2244. }
  2245. *ppQuery = newquery;
  2246. return S_OK;
  2247. }
  2248. HRESULT IDirect3DQuery9::Issue(DWORD dwIssueFlags)
  2249. {
  2250. // Flags field for Issue
  2251. // #define D3DISSUE_END (1 << 0) // Tells the runtime to issue the end of a query, changing it's state to "non-signaled".
  2252. // #define D3DISSUE_BEGIN (1 << 1) // Tells the runtime to issue the beginng of a query.
  2253. if (dwIssueFlags & D3DISSUE_BEGIN)
  2254. {
  2255. switch( m_type )
  2256. {
  2257. case D3DQUERYTYPE_OCCLUSION:
  2258. if ( !( m_queryIdx & kQueryFinished ) )
  2259. {
  2260. // Query is still pending!
  2261. Assert( 0 );
  2262. return S_OK;
  2263. }
  2264. m_queryIdx = s_GlobalStateOcclusion.PrepareForQuery();
  2265. gpGcmDrawState->SetZpassPixelCountEnable( CELL_GCM_TRUE );
  2266. gpGcmDrawState->SetClearReport( CELL_GCM_ZPASS_PIXEL_CNT );
  2267. break;
  2268. default:
  2269. Assert(!"Can't use D3DISSUE_BEGIN on this query");
  2270. break;
  2271. }
  2272. }
  2273. if (dwIssueFlags & D3DISSUE_END)
  2274. {
  2275. switch( m_type )
  2276. {
  2277. case D3DQUERYTYPE_OCCLUSION:
  2278. if ( !!( m_queryIdx & kQueryFinished ) )
  2279. {
  2280. // Query has finished earlier!
  2281. Assert( 0 );
  2282. return S_OK;
  2283. }
  2284. gpGcmDrawState->SetReport ( CELL_GCM_ZPASS_PIXEL_CNT, m_queryIdx + QueryGlobalStateOcclusion_t::kGcmQueryBase );
  2285. gpGcmDrawState->SetZpassPixelCountEnable ( CELL_GCM_FALSE );
  2286. m_queryIdx |= kQueryFinished; // mark the query as finished
  2287. break;
  2288. case D3DQUERYTYPE_EVENT:
  2289. // End is very weird with respect to Events (fences).
  2290. // DX9 docs say to use End to put the fence in the stream. So we map End to GLM's Start.
  2291. // http://msdn.microsoft.com/en-us/library/ee422167(VS.85).aspx
  2292. m_queryIdx = s_GlobalStateFence.PrepareForQuery();
  2293. gpGcmDrawState->SetWriteBackEndLabel ( m_queryIdx + QueryGlobalStateFence_t::kGcmLabelBase, 0 ); // drop "set fence" into stream
  2294. m_queryIdx |= kQueryFinished;
  2295. break;
  2296. }
  2297. }
  2298. return S_OK;
  2299. }
  2300. HRESULT IDirect3DQuery9::GetData(void* pData,DWORD dwSize,DWORD dwGetDataFlags)
  2301. {
  2302. HRESULT result = -1;
  2303. // GetData is not always called with the flush bit.
  2304. // if an answer is not yet available - return S_FALSE.
  2305. // if an answer is available - return S_OK and write the answer into *pData.
  2306. bool flush = (dwGetDataFlags & D3DGETDATA_FLUSH) != 0; // aka spin until done
  2307. // hmmm both of these paths are the same, maybe we could fold them up
  2308. if ( ( m_queryIdx == kQueryUninitialized ) || !( m_queryIdx & kQueryFinished ) )
  2309. {
  2310. Assert(!"Can't GetData before start-stop");
  2311. if ( pData ) { *(int32*)(pData) = 0; }
  2312. result = -1;
  2313. }
  2314. else
  2315. {
  2316. switch( m_type )
  2317. {
  2318. case D3DQUERYTYPE_OCCLUSION: {
  2319. // expectation - caller already did an issue begin (start) and an issue end (stop).
  2320. // we can probe using IsDone.
  2321. union RptData {
  2322. CellGcmReportData data;
  2323. vector int vFetch;
  2324. };
  2325. RptData volatile const *rpt = reinterpret_cast< RptData volatile const * >( s_GlobalStateOcclusion.m_Values[ m_queryIdx & kQueryValueMask ] );
  2326. RptData rptValue;
  2327. rptValue.vFetch = rpt->vFetch;
  2328. if ( rptValue.data.zero && flush )
  2329. {
  2330. //
  2331. // Disabled out the wait for (flush) of occlusion query
  2332. // c_pixel_vis, seems to flush queries every couple of seconds, and it seems pointless on PS3
  2333. // Flushing the GPU and waiting for the report to write it's value seems a bad situation on PS3
  2334. // We can literally stall the CPU for 10ms
  2335. // Need to test this on levels with many coronas etc.. But in that case we need a bigger query list
  2336. // and to look closer at the higher level code
  2337. //
  2338. // Flush GPU right up to current point - Endframe call does this...
  2339. // gpGcmDrawState->EndFrame();
  2340. // gpGcmDrawState->CmdBufferFlush();
  2341. //
  2342. // while ( ( ( rptValue.vFetch = rpt->vFetch ), rptValue.data.zero )
  2343. // && ( ThreadSleep(1), 1 ) ) // yield CPU when spin-waiting
  2344. // continue;
  2345. rptValue.data.zero = 0;
  2346. }
  2347. if ( !rptValue.data.zero )
  2348. {
  2349. if (pData)
  2350. {
  2351. *(int32*)pData = rptValue.data.value;
  2352. }
  2353. result = S_OK;
  2354. }
  2355. else
  2356. {
  2357. result = S_FALSE;
  2358. }
  2359. } break;
  2360. case D3DQUERYTYPE_EVENT: {
  2361. // expectation - caller already did an issue end (for fence => start) but has not done anything that would call Stop.
  2362. // that's ok because Stop is a no-op for fences.
  2363. uint32 volatile const& lbl = *s_GlobalStateFence.m_Values[ m_queryIdx & kQueryValueMask ];
  2364. uint32 lblValue = lbl;
  2365. if ( lblValue && flush )
  2366. {
  2367. // Flush GPU right up to current point - Endframe call does this...
  2368. gpGcmDrawState->EndFrame();
  2369. gpGcmDrawState->CmdBufferFlush();
  2370. while ( ( (lblValue = lbl) != 0 )
  2371. && ( ThreadSleep(1), 1 ) ) // yield CPU when spin-waiting
  2372. continue;
  2373. }
  2374. if ( !lblValue )
  2375. {
  2376. *(uint*)pData = 0;
  2377. result = S_OK;
  2378. }
  2379. else
  2380. {
  2381. result = S_FALSE;
  2382. }
  2383. } break;
  2384. }
  2385. }
  2386. return result;
  2387. }
  2388. //--------------------------------------------------------------------------------------------------
  2389. // MISC
  2390. //--------------------------------------------------------------------------------------------------
  2391. BOOL IDirect3DDevice9::ShowCursor(BOOL bShow)
  2392. {
  2393. // FIXME NOP
  2394. //Debugger();
  2395. return TRUE;
  2396. }
  2397. HRESULT IDirect3DDevice9::SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix)
  2398. {
  2399. Debugger();
  2400. return S_OK;
  2401. }
  2402. HRESULT IDirect3DDevice9::SetTextureStageState(DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value)
  2403. {
  2404. Debugger();
  2405. return S_OK;
  2406. }
  2407. HRESULT IDirect3DDevice9::ValidateDevice(DWORD* pNumPasses)
  2408. {
  2409. Debugger();
  2410. return S_OK;
  2411. }
  2412. HRESULT IDirect3DDevice9::SetMaterial(CONST D3DMATERIAL9* pMaterial)
  2413. {
  2414. return S_OK;
  2415. }
  2416. HRESULT IDirect3DDevice9::LightEnable(DWORD Index,BOOL Enable)
  2417. {
  2418. Debugger();
  2419. return S_OK;
  2420. }
  2421. HRESULT IDirect3DDevice9::GetDeviceCaps(D3DCAPS9* pCaps)
  2422. {
  2423. Debugger();
  2424. return S_OK;
  2425. }
  2426. HRESULT IDirect3DDevice9::TestCooperativeLevel()
  2427. {
  2428. // game calls this to see if device was lost.
  2429. // last I checked the device was still attached to the computer.
  2430. // so, return OK.
  2431. return S_OK;
  2432. }
  2433. HRESULT IDirect3DDevice9::EvictManagedResources()
  2434. {
  2435. return S_OK;
  2436. }
  2437. HRESULT IDirect3DDevice9::SetLight(DWORD Index,CONST D3DLIGHT9*)
  2438. {
  2439. Debugger();
  2440. return S_OK;
  2441. }
  2442. void IDirect3DDevice9::SetGammaRamp(UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp)
  2443. {
  2444. }
  2445. void D3DPERF_SetOptions( DWORD dwOptions )
  2446. {
  2447. }
  2448. HRESULT D3DXCompileShader(
  2449. LPCSTR pSrcData,
  2450. UINT SrcDataLen,
  2451. CONST D3DXMACRO* pDefines,
  2452. LPD3DXINCLUDE pInclude,
  2453. LPCSTR pFunctionName,
  2454. LPCSTR pProfile,
  2455. DWORD Flags,
  2456. LPD3DXBUFFER* ppShader,
  2457. LPD3DXBUFFER* ppErrorMsgs,
  2458. LPD3DXCONSTANTTABLE* ppConstantTable)
  2459. {
  2460. return S_OK;
  2461. }
  2462. //--------------------------------------------------------------------------------------------------
  2463. // D3DX funcs
  2464. //--------------------------------------------------------------------------------------------------
  2465. void* ID3DXBuffer::GetBufferPointer()
  2466. {
  2467. Debugger();
  2468. return NULL;
  2469. }
  2470. DWORD ID3DXBuffer::GetBufferSize()
  2471. {
  2472. Debugger();
  2473. return 0;
  2474. }
  2475. // matrix stack...
  2476. HRESULT D3DXCreateMatrixStack( DWORD Flags, LPD3DXMATRIXSTACK* ppStack)
  2477. {
  2478. *ppStack = new ID3DXMatrixStack;
  2479. (*ppStack)->Create();
  2480. return S_OK;
  2481. }
  2482. HRESULT ID3DXMatrixStack::Create()
  2483. {
  2484. m_stack.EnsureCapacity( 16 ); // 1KB ish
  2485. m_stack.AddToTail();
  2486. m_stackTop = 0; // top of stack is at index 0 currently
  2487. LoadIdentity();
  2488. return S_OK;
  2489. }
  2490. D3DXMATRIX* ID3DXMatrixStack::GetTop()
  2491. {
  2492. return (D3DXMATRIX*)&m_stack[ m_stackTop ];
  2493. }
  2494. void ID3DXMatrixStack::Push()
  2495. {
  2496. D3DMATRIX temp = m_stack[ m_stackTop ];
  2497. m_stack.AddToTail( temp );
  2498. m_stackTop ++;
  2499. }
  2500. void ID3DXMatrixStack::Pop()
  2501. {
  2502. int elem = m_stackTop--;
  2503. m_stack.Remove( elem );
  2504. }
  2505. void ID3DXMatrixStack::LoadIdentity()
  2506. {
  2507. D3DXMATRIX *mat = GetTop();
  2508. D3DXMatrixIdentity( mat );
  2509. }
  2510. void ID3DXMatrixStack::LoadMatrix( const D3DXMATRIX *pMat )
  2511. {
  2512. *(GetTop()) = *pMat;
  2513. }
  2514. void ID3DXMatrixStack::MultMatrix( const D3DXMATRIX *pMat )
  2515. {
  2516. // http://msdn.microsoft.com/en-us/library/bb174057(VS.85).aspx
  2517. // This method right-multiplies the given matrix to the current matrix
  2518. // (transformation is about the current world origin).
  2519. // m_pstack[m_currentPos] = m_pstack[m_currentPos] * (*pMat);
  2520. // This method does not add an item to the stack, it replaces the current
  2521. // matrix with the product of the current matrix and the given matrix.
  2522. Debugger();
  2523. }
  2524. void ID3DXMatrixStack::MultMatrixLocal( const D3DXMATRIX *pMat )
  2525. {
  2526. // http://msdn.microsoft.com/en-us/library/bb174058(VS.85).aspx
  2527. // This method left-multiplies the given matrix to the current matrix
  2528. // (transformation is about the local origin of the object).
  2529. // m_pstack[m_currentPos] = (*pMat) * m_pstack[m_currentPos];
  2530. // This method does not add an item to the stack, it replaces the current
  2531. // matrix with the product of the given matrix and the current matrix.
  2532. Debugger();
  2533. }
  2534. HRESULT ID3DXMatrixStack::ScaleLocal(FLOAT x, FLOAT y, FLOAT z)
  2535. {
  2536. // http://msdn.microsoft.com/en-us/library/bb174066(VS.85).aspx
  2537. // Scale the current matrix about the object origin.
  2538. // This method left-multiplies the current matrix with the computed
  2539. // scale matrix. The transformation is about the local origin of the object.
  2540. //
  2541. // D3DXMATRIX tmp;
  2542. // D3DXMatrixScaling(&tmp, x, y, z);
  2543. // m_stack[m_currentPos] = tmp * m_stack[m_currentPos];
  2544. Debugger();
  2545. return S_OK;
  2546. }
  2547. HRESULT ID3DXMatrixStack::RotateAxisLocal(CONST D3DXVECTOR3* pV, FLOAT Angle)
  2548. {
  2549. // http://msdn.microsoft.com/en-us/library/bb174062(VS.85).aspx
  2550. // Left multiply the current matrix with the computed rotation
  2551. // matrix, counterclockwise about the given axis with the given angle.
  2552. // (rotation is about the local origin of the object)
  2553. // D3DXMATRIX tmp;
  2554. // D3DXMatrixRotationAxis( &tmp, pV, angle );
  2555. // m_stack[m_currentPos] = tmp * m_stack[m_currentPos];
  2556. // Because the rotation is left-multiplied to the matrix stack, the rotation
  2557. // is relative to the object's local coordinate space.
  2558. Debugger();
  2559. return S_OK;
  2560. }
  2561. HRESULT ID3DXMatrixStack::TranslateLocal(FLOAT x, FLOAT y, FLOAT z)
  2562. {
  2563. // http://msdn.microsoft.com/en-us/library/bb174068(VS.85).aspx
  2564. // Left multiply the current matrix with the computed translation
  2565. // matrix. (transformation is about the local origin of the object)
  2566. // D3DXMATRIX tmp;
  2567. // D3DXMatrixTranslation( &tmp, x, y, z );
  2568. // m_stack[m_currentPos] = tmp * m_stack[m_currentPos];
  2569. Debugger();
  2570. return S_OK;
  2571. }
  2572. const char* D3DXGetPixelShaderProfile( IDirect3DDevice9 *pDevice )
  2573. {
  2574. Debugger();
  2575. return "";
  2576. }
  2577. D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 )
  2578. {
  2579. D3DXMATRIX temp;
  2580. for( int i=0; i<4; i++)
  2581. {
  2582. for( int j=0; j<4; j++)
  2583. {
  2584. temp.m[i][j] = (pM1->m[ i ][ 0 ] * pM2->m[ 0 ][ j ])
  2585. + (pM1->m[ i ][ 1 ] * pM2->m[ 1 ][ j ])
  2586. + (pM1->m[ i ][ 2 ] * pM2->m[ 2 ][ j ])
  2587. + (pM1->m[ i ][ 3 ] * pM2->m[ 3 ][ j ]);
  2588. }
  2589. }
  2590. *pOut = temp;
  2591. return pOut;
  2592. }
  2593. D3DXVECTOR3* D3DXVec3TransformCoord( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ) // http://msdn.microsoft.com/en-us/library/ee417622(VS.85).aspx
  2594. {
  2595. // this one is tricky because
  2596. // "Transforms a 3D vector by a given matrix, projecting the result back into w = 1".
  2597. // but the vector has no W attached to it coming in, so we have to go through the motions of figuring out what w' would be
  2598. // assuming the input vector had a W of 1.
  2599. // dot product of [a b c 1] against w column
  2600. float wp = (pM->m[3][0] * pV->x) + (pM->m[3][1] * pV->y) + (pM->m[3][2] * pV->z) + (pM->m[3][3]);
  2601. if (wp == 0.0f )
  2602. {
  2603. // do something to avoid dividing by zero..
  2604. Debugger();
  2605. }
  2606. else
  2607. {
  2608. // unclear on whether I should include the fake W in the sum (last term) before dividing by wp... hmmmm
  2609. // leave it out for now and see how well it works
  2610. pOut->x = ((pM->m[0][0] * pV->x) + (pM->m[0][1] * pV->y) + (pM->m[0][2] * pV->z) /* + (pM->m[0][3]) */ ) / wp;
  2611. pOut->y = ((pM->m[1][0] * pV->x) + (pM->m[1][1] * pV->y) + (pM->m[1][2] * pV->z) /* + (pM->m[1][3]) */ ) / wp;
  2612. pOut->z = ((pM->m[2][0] * pV->x) + (pM->m[2][1] * pV->y) + (pM->m[2][2] * pV->z) /* + (pM->m[2][3]) */ ) / wp;
  2613. }
  2614. return pOut;
  2615. }
  2616. void D3DXMatrixIdentity( D3DXMATRIX *mat )
  2617. {
  2618. for( int i=0; i<4; i++)
  2619. {
  2620. for( int j=0; j<4; j++)
  2621. {
  2622. mat->m[i][j] = (i==j) ? 1.0f : 0.0f; // 1's on the diagonal.
  2623. }
  2624. }
  2625. }
  2626. D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z )
  2627. {
  2628. D3DXMatrixIdentity( pOut );
  2629. pOut->m[3][0] = x;
  2630. pOut->m[3][1] = y;
  2631. pOut->m[3][2] = z;
  2632. return pOut;
  2633. }
  2634. D3DXMATRIX* D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM )
  2635. {
  2636. Assert( sizeof( D3DXMATRIX ) == (16 * sizeof(float) ) );
  2637. Assert( sizeof( VMatrix ) == (16 * sizeof(float) ) );
  2638. Assert( pDeterminant == NULL ); // homey don't play that
  2639. VMatrix *origM = (VMatrix*)pM;
  2640. VMatrix *destM = (VMatrix*)pOut;
  2641. bool success = MatrixInverseGeneral( *origM, *destM );
  2642. Assert( success );
  2643. return pOut;
  2644. }
  2645. D3DXMATRIX* D3DXMatrixTranspose( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM )
  2646. {
  2647. if (pOut != pM)
  2648. {
  2649. for( int i=0; i<4; i++)
  2650. {
  2651. for( int j=0; j<4; j++)
  2652. {
  2653. pOut->m[i][j] = pM->m[j][i];
  2654. }
  2655. }
  2656. }
  2657. else
  2658. {
  2659. D3DXMATRIX temp = *pM;
  2660. D3DXMatrixTranspose( pOut, &temp );
  2661. }
  2662. return NULL;
  2663. }
  2664. D3DXPLANE* D3DXPlaneNormalize( D3DXPLANE *pOut, CONST D3DXPLANE *pP)
  2665. {
  2666. // not very different from normalizing a vector.
  2667. // figure out the square root of the sum-of-squares of the x,y,z components
  2668. // make sure that's non zero
  2669. // then divide all four components by that value
  2670. // or return some dummy plane like 0,0,1,0 if it fails
  2671. float len = sqrt( (pP->a * pP->a) + (pP->b * pP->b) + (pP->c * pP->c) );
  2672. if (len > 1e-10) //FIXME need a real epsilon here ?
  2673. {
  2674. pOut->a = pP->a / len; pOut->b = pP->b / len; pOut->c = pP->c / len; pOut->d = pP->d / len;
  2675. }
  2676. else
  2677. {
  2678. pOut->a = 0.0f; pOut->b = 0.0f; pOut->c = 1.0f; pOut->d = 0.0f;
  2679. }
  2680. return pOut;
  2681. }
  2682. D3DXVECTOR4* D3DXVec4Transform( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM )
  2683. {
  2684. VMatrix *mat = (VMatrix*)pM;
  2685. Vector4D *vIn = (Vector4D*)pV;
  2686. Vector4D *vOut = (Vector4D*)pOut;
  2687. Vector4DMultiply( *mat, *vIn, *vOut );
  2688. return pOut;
  2689. }
  2690. D3DXVECTOR4* D3DXVec4Normalize( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV )
  2691. {
  2692. Vector4D *vIn = (Vector4D*) pV;
  2693. Vector4D *vOut = (Vector4D*) pOut;
  2694. *vOut = *vIn;
  2695. Vector4DNormalize( *vOut );
  2696. return pOut;
  2697. }
  2698. D3DXMATRIX* D3DXMatrixOrthoOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn,FLOAT zf )
  2699. {
  2700. Debugger();
  2701. return NULL;
  2702. }
  2703. D3DXMATRIX* D3DXMatrixPerspectiveRH( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf )
  2704. {
  2705. Debugger();
  2706. return NULL;
  2707. }
  2708. D3DXMATRIX* D3DXMatrixPerspectiveOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf )
  2709. {
  2710. Debugger();
  2711. return NULL;
  2712. }
  2713. D3DXPLANE* D3DXPlaneTransform( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM )
  2714. {
  2715. Debugger();
  2716. return NULL;
  2717. }
  2718. //--------------------------------------------------------------------------------------------------
  2719. //
  2720. //--------------------------------------------------------------------------------------------------
  2721. D3DXMATRIX D3DXMATRIX::operator*( const D3DXMATRIX &o ) const
  2722. {
  2723. D3DXMATRIX result;
  2724. D3DXMatrixMultiply( &result, this, &o ); // this = lhs o = rhs result = this * o
  2725. return result;
  2726. }
  2727. D3DXMATRIX::operator FLOAT* ()
  2728. {
  2729. return (float*)this;
  2730. }
  2731. float& D3DXMATRIX::operator()( int row, int column )
  2732. {
  2733. return m[row][column];
  2734. }
  2735. const float& D3DXMATRIX::operator()( int row, int column ) const
  2736. {
  2737. return m[row][column];
  2738. }
  2739. // ------------------------------------------------------------------------------------------------------------------------------ //
  2740. float& D3DXPLANE::operator[]( int i )
  2741. {
  2742. return ((float*)this)[i];
  2743. }
  2744. bool D3DXPLANE::operator==( const D3DXPLANE &o )
  2745. {
  2746. return a == o.a && b == o.b && c == o.c && d == o.d;
  2747. }
  2748. bool D3DXPLANE::operator!=( const D3DXPLANE &o )
  2749. {
  2750. return !( *this == o );
  2751. }
  2752. D3DXPLANE::operator float*()
  2753. {
  2754. return (float*)this;
  2755. }
  2756. D3DXPLANE::operator const float*() const
  2757. {
  2758. return (const float*)this;
  2759. }
  2760. // ------------------------------------------------------------------------------------------------------------------------------ //
  2761. D3DXVECTOR2::operator FLOAT* ()
  2762. {
  2763. return (float*)this;
  2764. }
  2765. D3DXVECTOR2::operator CONST FLOAT* () const
  2766. {
  2767. return (const float*)this;
  2768. }
  2769. // ------------------------------------------------------------------------------------------------------------------------------ //
  2770. D3DXVECTOR3::D3DXVECTOR3( float a, float b, float c )
  2771. {
  2772. x = a;
  2773. y = b;
  2774. z = c;
  2775. }
  2776. D3DXVECTOR3::operator FLOAT* ()
  2777. {
  2778. return (float*)this;
  2779. }
  2780. D3DXVECTOR3::operator CONST FLOAT* () const
  2781. {
  2782. return (const float*)this;
  2783. }
  2784. // ------------------------------------------------------------------------------------------------------------------------------ //
  2785. D3DXVECTOR4::D3DXVECTOR4( float a, float b, float c, float d )
  2786. {
  2787. x = a;
  2788. y = b;
  2789. z = c;
  2790. w = d;
  2791. }
  2792. // ------------------------------------------------------------------------------------------------------------------------------ //
  2793. DWORD IDirect3DResource9::SetPriority(DWORD PriorityNew)
  2794. {
  2795. // Debugger();
  2796. return 0;
  2797. }
  2798. //--------------------------------------------------------------------------------------------------
  2799. // Screen shot for VX console
  2800. //--------------------------------------------------------------------------------------------------
  2801. // returns a pointer to the screen shot frame buffer and some associated header info.
  2802. // returns NULL on failure (which it can't right now)
  2803. char *GetScreenShotInfoForVX( IDirect3DDevice9 *pDevice, uint32 *uWidth, uint32 *uHeight, uint32 *uPitch, uint32 *colour )
  2804. {
  2805. const CPs3gcmTextureLayout & layout = *pDevice->m_defaultColorSurface->m_tex->m_layout;
  2806. *uWidth = layout.m_key.m_size[0];
  2807. *uHeight = layout.m_key.m_size[1];
  2808. *uPitch = g_ps3gcmGlobalState.m_nSurfaceRenderPitch; // layout.DefaultPitch();
  2809. switch ( layout.GetFormatPtr()->m_gcmFormat )
  2810. {
  2811. case CELL_GCM_TEXTURE_A8R8G8B8 :
  2812. case CELL_GCM_TEXTURE_D8R8G8B8:
  2813. case CELL_GCM_SURFACE_A8R8G8B8:
  2814. *colour = IMaterialSystem::kX8R8G8B8;
  2815. break;
  2816. case CELL_GCM_SURFACE_A8B8G8R8:
  2817. *colour = IMaterialSystem::kX8B8G8R8;
  2818. break;
  2819. case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
  2820. *colour = IMaterialSystem::kR16G16B16X16;
  2821. break;
  2822. default:
  2823. *colour = (IMaterialSystem::VRAMScreenShotInfoColorFormat_t) 0;
  2824. }
  2825. // send oldest buffer
  2826. return g_ps3gcmGlobalState.m_display.surfaceColor[ (g_ps3gcmGlobalState.m_display.surfaceFlipIdx + 1) & 1 ].DataInAnyMemory();
  2827. }
  2828. //--------------------------------------------------------------------------------------------------
  2829. // Windows Stubs
  2830. //--------------------------------------------------------------------------------------------------
  2831. void GlobalMemoryStatus( MEMORYSTATUS *pOut )
  2832. {
  2833. pOut->dwTotalPhys = (1<<31);
  2834. }
  2835. void Sleep( unsigned int ms )
  2836. {
  2837. Debugger();
  2838. ThreadSleep( ms );
  2839. }
  2840. bool IsIconic( VD3DHWND hWnd )
  2841. {
  2842. return false;
  2843. }
  2844. void GetClientRect( VD3DHWND hWnd, RECT *destRect )
  2845. {
  2846. destRect->left = 0;
  2847. destRect->top = 0;
  2848. destRect->right = g_ps3gcmGlobalState.m_nRenderSize[0];
  2849. destRect->bottom = g_ps3gcmGlobalState.m_nRenderSize[1];
  2850. }
  2851. BOOL ClientToScreen( VD3DHWND hWnd, LPPOINT pPoint )
  2852. {
  2853. Debugger();
  2854. return true;
  2855. }
  2856. void* GetCurrentThread()
  2857. {
  2858. Debugger();
  2859. return 0;
  2860. }
  2861. void SetThreadAffinityMask( void *hThread, int nMask )
  2862. {
  2863. Debugger();
  2864. }
  2865. bool operator==( const struct _GUID &lhs, const struct _GUID &rhs )
  2866. {
  2867. Debugger();
  2868. return memcmp( &lhs, &rhs, sizeof( GUID ) ) == 0;
  2869. }