Source code of Windows XP (NT5)
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.

4432 lines
153 KiB

  1. #include "pch.cpp"
  2. #pragma hdrstop
  3. /*==========================================================================;
  4. *
  5. * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * File: ddi.cpp
  8. * Content: Direct3D DDI encapsulation implementations
  9. *
  10. ***************************************************************************/
  11. #include "d3d8p.h"
  12. #include "ddi.h"
  13. #include "ddrawint.h"
  14. #include "fe.h"
  15. #include "pvvid.h"
  16. #include "ddi.inl"
  17. #ifndef WIN95
  18. extern BOOL bVBSwapEnabled, bVBSwapWorkaround;
  19. #endif // WIN95
  20. extern HRESULT ProcessClippedPointSprites(D3DFE_PROCESSVERTICES *pv);
  21. extern DWORD D3DFE_GenClipFlags(D3DFE_PROCESSVERTICES *pv);
  22. extern DWORD g_DebugFlags;
  23. HRESULT ValidateCommandBuffer(LPBYTE pBuffer, DWORD dwCommandLength, DWORD dwStride);
  24. /////////////////////////////////////////////////////////////////////////////
  25. // //
  26. // CD3DDDI //
  27. // //
  28. /////////////////////////////////////////////////////////////////////////////
  29. CD3DDDI::CD3DDDI()
  30. {
  31. m_StartIndex = 0;
  32. m_MinVertexIndex = 0;
  33. m_NumVertices = 0;
  34. m_BaseVertexIndex = 0;
  35. }
  36. //---------------------------------------------------------------------------
  37. CD3DDDI::~CD3DDDI()
  38. {
  39. return;
  40. }
  41. /////////////////////////////////////////////////////////////////////////////
  42. // //
  43. // CD3DDDIDX6 //
  44. // //
  45. /////////////////////////////////////////////////////////////////////////////
  46. // Command buffer size tuned to 16K to minimize flushes in Unreal
  47. // * 1 = 16K bytes
  48. const DWORD CD3DDDIDX6::dwD3DDefaultCommandBatchSize = 16384;
  49. CD3DDDIDX6::CD3DDDIDX6() : CD3DDDI()
  50. {
  51. m_ddiType = D3DDDITYPE_DX6;
  52. m_pDevice = NULL;
  53. m_bWithinPrimitive = FALSE;
  54. m_dwhContext = 0;
  55. m_pfnProcessPrimitive = NULL;
  56. m_pfnProcessIndexedPrimitive = NULL;
  57. m_dwInterfaceNumber = 3;
  58. lpDP2CurrBatchVBI = NULL;
  59. TLVbuf_size = 0;
  60. TLVbuf_base = 0;
  61. dwDP2CommandBufSize = 0;
  62. dwDP2CommandLength = 0;
  63. lpvDP2Commands = NULL;
  64. lpDP2CurrCommand = NULL;
  65. wDP2CurrCmdCnt = 0;
  66. bDP2CurrCmdOP = 0;
  67. bDummy = 0;
  68. memset(&dp2data, 0x00, sizeof(dp2data) ) ;
  69. dwDP2VertexCount = 0;
  70. dwVertexBase = 0;
  71. lpDDSCB1 = NULL;
  72. allocatedBuf = NULL;
  73. alignedBuf = NULL;
  74. dwTLVbufChanges = 0;
  75. dwDP2Flags = 0;
  76. m_pPointStream = NULL;
  77. // For the legacy DDI, we say we are DX7
  78. m_dwInterfaceNumber = 3;
  79. lpwDPBuffer = NULL;
  80. dwDPBufferSize = 0;
  81. m_pNullVB = 0;
  82. #if DBG
  83. m_bValidateCommands = FALSE;
  84. #endif
  85. }
  86. //---------------------------------------------------------------------
  87. CD3DDDIDX6::~CD3DDDIDX6()
  88. {
  89. delete m_pPointStream;
  90. m_pPointStream = NULL;
  91. if (m_pNullVB)
  92. m_pNullVB->DecrementUseCount();
  93. if (allocatedBuf)
  94. allocatedBuf->DecrementUseCount();
  95. allocatedBuf = NULL;
  96. if (lpDP2CurrBatchVBI)
  97. lpDP2CurrBatchVBI->DecrementUseCount();
  98. lpDP2CurrBatchVBI = NULL;
  99. if (lpDDSCB1)
  100. lpDDSCB1->DecrementUseCount();
  101. lpDDSCB1 = NULL;
  102. DestroyContext();
  103. }
  104. //---------------------------------------------------------------------------
  105. #undef DPF_MODNAME
  106. #define DPF_MODNAME "CD3DDDIDX6::NotSupported"
  107. void
  108. CD3DDDIDX6::NotSupported(char* msg)
  109. {
  110. D3D_ERR("%s is not supported by the current DDI", msg);
  111. throw D3DERR_INVALIDCALL;
  112. }
  113. //---------------------------------------------------------------------
  114. #undef DPF_MODNAME
  115. #define DPF_MODNAME "CD3DDDIDX6::SceneCapture"
  116. void
  117. CD3DDDIDX6::SceneCapture(BOOL bState)
  118. {
  119. D3D8_SCENECAPTUREDATA data;
  120. if (m_pDevice->GetHalCallbacks()->SceneCapture == 0)
  121. return;
  122. D3D_INFO(6, "SceneCapture, setting %d dwhContext = %d",
  123. bState, m_dwhContext);
  124. memset(&data, 0, sizeof(D3DHAL_SCENECAPTUREDATA));
  125. data.dwhContext = m_dwhContext;
  126. data.dwFlag = bState ? D3DHAL_SCENE_CAPTURE_START : D3DHAL_SCENE_CAPTURE_END;
  127. HRESULT ret = m_pDevice->GetHalCallbacks()->SceneCapture(&data);
  128. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK)
  129. {
  130. D3D_ERR("Driver failed to handle SceneCapture");
  131. throw (data.ddrval);
  132. }
  133. }
  134. //---------------------------------------------------------------------
  135. #undef DPF_MODNAME
  136. #define DPF_MODNAME "CD3DDDIDX6::ClearBatch"
  137. void
  138. CD3DDDIDX6::ClearBatch(BOOL bWithinPrimitive)
  139. {
  140. // Reset command buffer
  141. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)lpvDP2Commands;
  142. dwDP2CommandLength = 0;
  143. dp2data.dwCommandOffset = 0;
  144. dp2data.dwCommandLength = 0;
  145. bDP2CurrCmdOP = 0;
  146. // Reset vertex buffer
  147. if (!bWithinPrimitive)
  148. {
  149. dp2data.dwVertexOffset = 0;
  150. this->dwDP2VertexCount = 0;
  151. this->dwVertexBase = 0;
  152. TLVbuf_Base() = 0;
  153. if (dp2data.dwFlags & D3DHALDP2_USERMEMVERTICES)
  154. {
  155. // We are flushing a user mem primitive.
  156. // We need to clear dp2data.lpUMVertices
  157. // since we are done with it. We replace
  158. // it with TLVbuf.
  159. DDASSERT(lpDP2CurrBatchVBI == NULL);
  160. dp2data.hDDVertex = TLVbuf_GetVBI()->DriverAccessibleKernelHandle();
  161. lpDP2CurrBatchVBI = TLVbuf_GetVBI();
  162. lpDP2CurrBatchVBI->IncrementUseCount();
  163. dp2data.dwFlags &= ~D3DHALDP2_USERMEMVERTICES;
  164. }
  165. }
  166. }
  167. //-----------------------------------------------------------------------------
  168. #undef DPF_MODNAME
  169. #define DPF_MODNAME "CD3DDDIDX6::Init"
  170. void
  171. CD3DDDIDX6::Init( LPD3DBASE pDevice )
  172. {
  173. m_pDevice = pDevice;
  174. CreateContext();
  175. GrowCommandBuffer(dwD3DDefaultCommandBatchSize);
  176. // Fill the dp2data structure with initial values
  177. dp2data.dwFlags = D3DHALDP2_SWAPCOMMANDBUFFER;
  178. dp2data.dwVertexType = D3DFVF_TLVERTEX; // Initial assumption
  179. dp2data.dwVertexSize = sizeof(D3DTLVERTEX); // Initial assumption
  180. ClearBatch(FALSE);
  181. // Since we plan to call TLV_Grow for the first time with "TRUE"
  182. dwDP2Flags |= D3DDDI_TLVBUFWRITEONLY;
  183. GrowTLVbuf((__INIT_VERTEX_NUMBER*2)*sizeof(D3DTLVERTEX), TRUE);
  184. // Create a dummy sysmem VB to be used as a backup for lowmem situations
  185. LPDIRECT3DVERTEXBUFFER8 t;
  186. HRESULT ret = CVertexBuffer::Create(pDevice,
  187. sizeof(D3DTLVERTEX),
  188. D3DUSAGE_INTERNALBUFFER | D3DUSAGE_DYNAMIC,
  189. D3DFVF_TLVERTEX,
  190. D3DPOOL_SYSTEMMEM,
  191. REF_INTERNAL,
  192. &t);
  193. if (ret != D3D_OK)
  194. {
  195. D3D_THROW(ret, "Cannot allocate internal backup TLVBuf");
  196. }
  197. m_pNullVB = static_cast<CVertexBuffer*>(t);
  198. m_pPointStream = new CTLStream(FALSE);
  199. if (m_pPointStream == NULL)
  200. D3D_THROW(E_OUTOFMEMORY, "Cannot allocate internal data structure CTLStream");
  201. m_pStream0 = NULL;
  202. m_CurrentVertexShader = 0;
  203. #if DBG
  204. m_VertexSizeFromShader = 0;
  205. #endif
  206. m_pIStream = NULL;
  207. }
  208. //-----------------------------------------------------------------------------
  209. #undef DPF_MODNAME
  210. #define DPF_MODNAME "CD3DDDIDX6::CreateContext"
  211. void
  212. CD3DDDIDX6::CreateContext()
  213. {
  214. D3D8_CONTEXTCREATEDATA data;
  215. HRESULT ret;
  216. D3D_INFO(6, "in CreateContext. Creating Context for driver = %08lx",
  217. this);
  218. memset(&data, 0, sizeof(data));
  219. data.hDD = m_pDevice->GetHandle();
  220. data.hSurface = m_pDevice->RenderTarget()->KernelHandle();
  221. if(m_pDevice->ZBuffer() != 0)
  222. data.hDDSZ = m_pDevice->ZBuffer()->KernelHandle();
  223. // Hack Alert!! dwhContext is used to inform the driver which version
  224. // of the D3D interface is calling it.
  225. data.dwhContext = m_dwInterfaceNumber;
  226. data.dwPID = GetCurrentProcessId();
  227. // Hack Alert!! ddrval is used to inform the driver which driver type
  228. // the runtime thinks it is (DriverStyle registry setting)
  229. data.ddrval = m_ddiType;
  230. data.cjBuffer = dwDPBufferSize;
  231. data.pvBuffer = NULL;
  232. ret = m_pDevice->GetHalCallbacks()->CreateContext(&data);
  233. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK)
  234. {
  235. D3D_ERR( "Driver did not handle ContextCreate" );
  236. throw D3DERR_INVALIDCALL;
  237. }
  238. m_dwhContext = data.dwhContext;
  239. #if 0 //def WIN95
  240. LPWORD lpwDPBufferAlloced = NULL;
  241. if (D3DMalloc((void**)&lpwDPBufferAlloced, dwDPBufferSize) != DD_OK)
  242. {
  243. D3D_ERR( "Out of memory in DeviceCreate" );
  244. throw E_OUTOFMEMORY;
  245. }
  246. lpwDPBuffer = (LPWORD)(((DWORD) lpwDPBufferAlloced+31) & (~31));
  247. #else
  248. if( dwDPBufferSize && (data.cjBuffer < dwDPBufferSize) )
  249. {
  250. D3D_ERR( "Driver did not correctly allocate DrawPrim buffer");
  251. throw D3DERR_INVALIDCALL;
  252. }
  253. // Need to save the buffer space provided and its size
  254. dwDPBufferSize = data.cjBuffer;
  255. lpwDPBuffer = (LPWORD)data.pvBuffer;
  256. #endif
  257. D3D_INFO(6, "in CreateContext. Succeeded. dwhContext = %d",
  258. data.dwhContext);
  259. }
  260. //-----------------------------------------------------------------------------
  261. #undef DPF_MODNAME
  262. #define DPF_MODNAME "CD3DDDIDX6::DestroyContext"
  263. void
  264. CD3DDDIDX6::DestroyContext()
  265. {
  266. D3D8_CONTEXTDESTROYDATA data;
  267. HRESULT ret;
  268. D3D_INFO(6, "Destroying Context for driver = %08lx", this);
  269. D3D_INFO(6, "dwhContext = %d", m_dwhContext);
  270. if( m_dwhContext )
  271. {
  272. memset(&data, 0, sizeof(D3DHAL_CONTEXTDESTROYDATA));
  273. data.dwhContext = m_dwhContext;
  274. ret = m_pDevice->GetHalCallbacks()->ContextDestroy(&data);
  275. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK)
  276. {
  277. D3D_WARN(0,"Failed ContextDestroy HAL call");
  278. return;
  279. }
  280. }
  281. }
  282. //-----------------------------------------------------------------------------
  283. // This code may be needed when we debug some problems
  284. #if 0
  285. void PrintBuffer(LPBYTE alignedBuf, D3D8_DRAWPRIMITIVES2DATA* dp2data, LPBYTE lpvDP2Commands)
  286. {
  287. FILE* f = fopen("\\ddi.log", "a+");
  288. if (f == NULL)
  289. return;
  290. fprintf(f, "-----------\n");
  291. fprintf(f, "dwFlags: %d, dwVertexType: 0x%xh, CommandOffset: %d, CommandLength: %d, VertexOffset: %d, VertexLength: %d\n",
  292. dp2data->dwFlags,
  293. dp2data->dwVertexType,
  294. dp2data->dwCommandOffset,
  295. dp2data->dwCommandLength,
  296. dp2data->dwVertexOffset,
  297. dp2data->dwVertexLength,
  298. dp2data->dwVertexSize);
  299. float* p = (float*)alignedBuf;
  300. UINT nTex = FVF_TEXCOORD_NUMBER(dp2data->dwVertexType);
  301. for (UINT i=0; i < dp2data->dwVertexLength; i++)
  302. {
  303. fprintf(f, "%4d %10.5f %10.5f %10.5f %10.5f ", i, p[0], p[1], p[2], p[3]);
  304. UINT index = 4;
  305. if (dp2data->dwVertexType & D3DFVF_DIFFUSE)
  306. {
  307. // fprintf(f, "0x%6x ", *(DWORD*)&p[index]);
  308. index++;
  309. }
  310. if (dp2data->dwVertexType & D3DFVF_SPECULAR)
  311. {
  312. // fprintf(f, "0x%6x ", *(DWORD*)&p[index]);
  313. index++;
  314. }
  315. for (UINT j=0; j < nTex; j++)
  316. {
  317. fprintf(f, "%10.5f %10.5f ", p[index], p[index+1]);
  318. index += 2;
  319. }
  320. fprintf(f, "\n");
  321. p = (float*)((BYTE*)p + dp2data->dwVertexSize);
  322. }
  323. fclose(f);
  324. }
  325. #endif // 0
  326. //-----------------------------------------------------------------------------
  327. #undef DPF_MODNAME
  328. #define DPF_MODNAME "CD3DDDIDX6::FlushStates"
  329. void
  330. CD3DDDIDX6::FlushStates(BOOL bReturnDriverError, BOOL bWithinPrimitive)
  331. {
  332. HRESULT dwRet=D3D_OK;
  333. if (m_bWithinPrimitive)
  334. bWithinPrimitive = TRUE;
  335. if (dwDP2CommandLength) // Do we have some instructions to flush ?
  336. {
  337. m_pDevice->IncrementBatchCount();
  338. if (lpDP2CurrBatchVBI)
  339. lpDP2CurrBatchVBI->Batch();
  340. // Check if render target and / or z buffer is lost
  341. // Save since it will get overwritten by ddrval after DDI call
  342. DWORD dwVertexSize = dp2data.dwVertexSize;
  343. dp2data.dwVertexLength = dwDP2VertexCount;
  344. dp2data.dwCommandLength = dwDP2CommandLength;
  345. //we clear this to break re-entering as SW rasterizer needs to lock DDRAWSURFACE
  346. dwDP2CommandLength = 0;
  347. // Try and set these 2 values only once during initialization
  348. dp2data.dwhContext = m_dwhContext;
  349. dp2data.lpdwRStates = (LPDWORD)lpwDPBuffer;
  350. DDASSERT(dp2data.dwVertexSize != 0);
  351. D3D_INFO(6, "FVF passed to the driver via DrawPrimitives2 = 0x%08x", dp2data.dwVertexType);
  352. // If we need the same TLVbuf next time do not swap buffers.
  353. // Save and restore this bit
  354. BOOL bSwapVB = (dp2data.dwFlags & D3DHALDP2_SWAPVERTEXBUFFER) != 0;
  355. #ifndef WIN95
  356. BOOL bDidWorkAround = FALSE;
  357. #endif // WIN95
  358. if (bWithinPrimitive)
  359. {
  360. dp2data.dwFlags &= ~D3DHALDP2_SWAPVERTEXBUFFER;
  361. }
  362. // At the end of the DP2 call we expect the VB to be unlocked if
  363. // 1. We cannot allow the driver to swap the VB
  364. // 2. We are using a VB (not USERMEMVERTICES)
  365. // 3. It is not TLVbuf
  366. // In this case we might as well tell the driver that it is unlocked.
  367. // More importantly, we need to let DDraw know that the VB is unlocked.
  368. if (!(dp2data.dwFlags & D3DHALDP2_SWAPVERTEXBUFFER))
  369. {
  370. if ((lpDP2CurrBatchVBI) && (lpDP2CurrBatchVBI != TLVbuf_GetVBI()))
  371. {
  372. // This seems contradictory, but IsLocked() checks whether
  373. // the app is holding a Lock.
  374. if(!lpDP2CurrBatchVBI->IsLocked())
  375. {
  376. lpDP2CurrBatchVBI->UnlockI();
  377. }
  378. }
  379. }
  380. #ifndef WIN95
  381. else if (bVBSwapWorkaround && lpDP2CurrBatchVBI != 0 && lpDP2CurrBatchVBI == TLVbuf_GetVBI() &&
  382. lpDP2CurrBatchVBI->GetBufferDesc()->Pool == D3DPOOL_DEFAULT)
  383. {
  384. static_cast<CDriverVertexBuffer*>(lpDP2CurrBatchVBI)->UnlockI();
  385. bDidWorkAround = TRUE;
  386. }
  387. if (!bVBSwapEnabled) // Note: bVBSwapEnabled not the same as bSwapVB above.
  388. // bVBSwapEnabled is a global to indicate whether VB
  389. // VB swapping should be turned off due to broken
  390. // Win2K kernel implementation
  391. {
  392. dp2data.dwFlags &= ~D3DHALDP2_SWAPVERTEXBUFFER;
  393. }
  394. #endif // WIN95
  395. // Spin waiting on the driver if wait requested
  396. do {
  397. // Need to set this since the driver may have overwrote it by
  398. // setting ddrval = DDERR_WASSTILLDRAWING
  399. dp2data.dwVertexSize = dwVertexSize;
  400. dwRet = m_pDevice->GetHalCallbacks()->DrawPrimitives2(&dp2data);
  401. if (dwRet != DDHAL_DRIVER_HANDLED)
  402. {
  403. D3D_ERR ( "Driver not handled in DrawPrimitives2" );
  404. // Need sensible return value in this case,
  405. // currently we return whatever the driver stuck in here.
  406. }
  407. } while (dp2data.ddrval == DDERR_WASSTILLDRAWING);
  408. dwRet = dp2data.ddrval;
  409. // update command buffer pointer
  410. if ((dwRet == D3D_OK) &&
  411. (dp2data.dwFlags & D3DHALDP2_SWAPCOMMANDBUFFER))
  412. {
  413. // Implement VidMem command buffer and
  414. // command buffer swapping.
  415. }
  416. // update vertex buffer pointer
  417. if ((dwRet == D3D_OK) &&
  418. (dp2data.dwFlags & D3DHALDP2_SWAPVERTEXBUFFER) &&
  419. dp2data.lpVertices)
  420. {
  421. #if DBG
  422. if (this->lpDP2CurrBatchVBI->GetBufferDesc()->Pool == D3DPOOL_DEFAULT)
  423. {
  424. if ((VOID*)static_cast<CDriverVertexBuffer*>(this->lpDP2CurrBatchVBI)->GetCachedDataPointer() != (VOID*)dp2data.fpVidMem_VB)
  425. {
  426. DPF(2, "Driver swapped VB pointer in FlushStates");
  427. }
  428. }
  429. #endif // DBG
  430. if (lpDP2CurrBatchVBI == TLVbuf_GetVBI())
  431. {
  432. this->alignedBuf = (LPVOID)dp2data.fpVidMem_VB;
  433. this->TLVbuf_size = dp2data.dwLinearSize_VB;
  434. }
  435. this->lpDP2CurrBatchVBI->SetCachedDataPointer(
  436. (BYTE*)dp2data.fpVidMem_VB);
  437. }
  438. #ifndef WIN95
  439. if (bDidWorkAround)
  440. {
  441. CDriverVertexBuffer *pVB = static_cast<CDriverVertexBuffer*>(lpDP2CurrBatchVBI);
  442. // Prepare a LockData structure for the HAL call
  443. D3D8_LOCKDATA lockData;
  444. ZeroMemory(&lockData, sizeof lockData);
  445. lockData.hDD = m_pDevice->GetHandle();
  446. lockData.hSurface = pVB->BaseKernelHandle();
  447. lockData.bHasRange = FALSE;
  448. lockData.dwFlags = D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK;
  449. HRESULT hr = m_pDevice->GetHalCallbacks()->Lock(&lockData);
  450. if (FAILED(hr))
  451. {
  452. D3D_ERR("Driver failed Lock in FlushStates");
  453. if (SUCCEEDED(dwRet))
  454. {
  455. dwRet = hr;
  456. }
  457. this->alignedBuf = 0;
  458. }
  459. else
  460. {
  461. #if DBG
  462. if (this->alignedBuf != lockData.lpSurfData)
  463. {
  464. DPF(2, "Driver swapped VB pointer at Lock in FlushStates");
  465. }
  466. #endif // DBG
  467. pVB->SetCachedDataPointer((BYTE*)lockData.lpSurfData);
  468. this->alignedBuf = lockData.lpSurfData;
  469. }
  470. }
  471. #endif // WIN95
  472. // Restore flag if necessary
  473. if (bSwapVB)
  474. dp2data.dwFlags |= D3DHALDP2_SWAPVERTEXBUFFER;
  475. // Restore to value before the DDI call
  476. dp2data.dwVertexSize = dwVertexSize;
  477. ClearBatch(bWithinPrimitive);
  478. }
  479. // There are situations when the command stream has no data,
  480. // but there is data in the vertex pool. This could happen, for instance
  481. // if every triangle got rejected while clipping. In this case we still
  482. // need to "Flush out" the vertex data.
  483. else if (dp2data.dwCommandLength == 0)
  484. {
  485. ClearBatch(bWithinPrimitive);
  486. }
  487. if( FAILED( dwRet ) )
  488. {
  489. ClearBatch(FALSE);
  490. if( !bReturnDriverError )
  491. {
  492. switch( dwRet )
  493. {
  494. case D3DERR_OUTOFVIDEOMEMORY:
  495. D3D_ERR("Driver out of video memory!");
  496. break;
  497. case D3DERR_COMMAND_UNPARSED:
  498. D3D_ERR("Driver could not parse this batch!");
  499. break;
  500. default:
  501. D3D_ERR("Driver returned error: %s", HrToStr(dwRet));
  502. break;
  503. }
  504. DPF_ERR("Driver failed command batch. Attempting to reset device"
  505. " state. The device may now be in an unstable state and"
  506. " the application may experience an access violation.");
  507. }
  508. else
  509. {
  510. throw dwRet;
  511. }
  512. }
  513. }
  514. //-----------------------------------------------------------------------------
  515. #undef DPF_MODNAME
  516. #define DPF_MODNAME "CD3DDDIDX6::FlushstatesReq"
  517. void
  518. CD3DDDIDX6::FlushStatesReq(DWORD dwReqSize)
  519. {
  520. DWORD sav = (dp2data.dwFlags & D3DHALDP2_SWAPVERTEXBUFFER);
  521. dp2data.dwReqVertexBufSize = dwReqSize;
  522. dp2data.dwFlags |= D3DHALDP2_SWAPVERTEXBUFFER | D3DHALDP2_REQVERTEXBUFSIZE;
  523. try
  524. {
  525. FlushStates();
  526. }
  527. catch( HRESULT hr )
  528. {
  529. dp2data.dwFlags &= ~(D3DHALDP2_SWAPVERTEXBUFFER | D3DHALDP2_REQVERTEXBUFSIZE);
  530. dp2data.dwFlags |= sav;
  531. throw hr;
  532. }
  533. dp2data.dwFlags &= ~(D3DHALDP2_SWAPVERTEXBUFFER | D3DHALDP2_REQVERTEXBUFSIZE);
  534. dp2data.dwFlags |= sav;
  535. }
  536. //-----------------------------------------------------------------------------
  537. #undef DPF_MODNAME
  538. #define DPF_MODNAME "CD3DDDIDX6::FlushStatesCmdBufReq"
  539. void
  540. CD3DDDIDX6::FlushStatesCmdBufReq(DWORD dwReqSize)
  541. {
  542. dp2data.dwReqCommandBufSize = dwReqSize;
  543. dp2data.dwFlags |= D3DHALDP2_REQCOMMANDBUFSIZE;
  544. try
  545. {
  546. FlushStates();
  547. }
  548. catch( HRESULT hr )
  549. {
  550. dp2data.dwFlags &= ~D3DHALDP2_REQCOMMANDBUFSIZE;
  551. throw hr;
  552. }
  553. dp2data.dwFlags &= ~D3DHALDP2_REQCOMMANDBUFSIZE;
  554. }
  555. //-----------------------------------------------------------------------------
  556. #undef DPF_MODNAME
  557. #define DPF_MODNAME "CD3DDDIDX6::ValidateDevice"
  558. void
  559. CD3DDDIDX6::ValidateDevice(LPDWORD lpdwNumPasses)
  560. {
  561. HRESULT ret;
  562. D3D8_VALIDATETEXTURESTAGESTATEDATA vd;
  563. memset( &vd, 0, sizeof( vd ) );
  564. vd.dwhContext = m_dwhContext;
  565. // First, Update textures since drivers pass /fail this call based
  566. // on the current texture handles
  567. m_pDevice->UpdateTextures();
  568. // Flush states, so we can validate the current state
  569. FlushStates();
  570. // Now ask the driver!
  571. ret = m_pDevice->GetHalCallbacks()->ValidateTextureStageState(&vd);
  572. *lpdwNumPasses = vd.dwNumPasses;
  573. if (ret != DDHAL_DRIVER_HANDLED)
  574. throw E_NOTIMPL;
  575. else if (FAILED(vd.ddrval))
  576. throw vd.ddrval;
  577. }
  578. //-----------------------------------------------------------------------------
  579. #undef DPF_MODNAME
  580. #define DPF_MODNAME "CD3DDDIDX6::ReserveSpaceInCommandBuffer"
  581. LPVOID CD3DDDIDX6::ReserveSpaceInCommandBuffer(UINT ByteCount)
  582. {
  583. if (dwDP2CommandLength + ByteCount > dwDP2CommandBufSize)
  584. {
  585. // Request the driver to grow the command buffer upon flush
  586. FlushStatesCmdBufReq(ByteCount);
  587. // Check if the driver did give us what we need or do it ourselves
  588. GrowCommandBuffer(ByteCount);
  589. }
  590. return (BYTE*)lpvDP2Commands + dwDP2CommandLength + dp2data.dwCommandOffset;
  591. }
  592. //-----------------------------------------------------------------------------
  593. #undef DPF_MODNAME
  594. #define DPF_MODNAME "CD3DDDIDX6::SetRenderTarget"
  595. void
  596. CD3DDDIDX6::SetRenderTarget(CBaseSurface *pTarget, CBaseSurface *pZ)
  597. {
  598. HRESULT ret;
  599. // We are going to destroy all texture handles, so we need to unset
  600. // all currently bound textures, because we have seen DX6 drivers
  601. // crash when called to destroy a texture handle of a currently set
  602. // texture - snene (4/24/00)
  603. m_pDevice->m_dwStageDirty = (1ul << m_pDevice->m_dwMaxTextureBlendStages) - 1ul; // set dirty so that UpdateTextures() is called next time around
  604. m_pDevice->m_dwRuntimeFlags |= D3DRT_NEED_TEXTURE_UPDATE;
  605. for (DWORD dwStage = 0; dwStage < m_pDevice->m_dwMaxTextureBlendStages; dwStage++)
  606. {
  607. SetTSS(dwStage, (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP, 0);
  608. m_pDevice->m_dwDDITexHandle[dwStage] = 0;
  609. }
  610. // Flush before switching RenderTarget..
  611. FlushStates();
  612. D3D8_SETRENDERTARGETDATA rtData;
  613. memset( &rtData, 0, sizeof( rtData ) );
  614. rtData.dwhContext = m_dwhContext;
  615. rtData.hDDS = pTarget->KernelHandle();
  616. if( pZ )
  617. rtData.hDDSZ = pZ->KernelHandle();
  618. ret = m_pDevice->GetHalCallbacks()->SetRenderTarget( &rtData );
  619. if ((ret != DDHAL_DRIVER_HANDLED) || (rtData.ddrval != DD_OK))
  620. {
  621. D3D_ERR( "Driver failed SetRenderTarget call" );
  622. // Need sensible return value in this case,
  623. // currently we return whatever the driver stuck in here.
  624. ret = rtData.ddrval;
  625. throw ret;
  626. }
  627. if( rtData.bNeedUpdate )
  628. {
  629. m_pDevice->UpdateDriverStates();
  630. }
  631. }
  632. //-----------------------------------------------------------------------------
  633. #undef DPF_MODNAME
  634. #define DPF_MODNAME "CD3DDDIDX6::SetRenderState"
  635. void
  636. CD3DDDIDX6::SetRenderState(D3DRENDERSTATETYPE dwStateType, DWORD value)
  637. {
  638. if (bDP2CurrCmdOP == D3DDP2OP_RENDERSTATE)
  639. { // Last instruction is a renderstate, append this one to it
  640. if (dwDP2CommandLength + sizeof(D3DHAL_DP2RENDERSTATE) <=
  641. dwDP2CommandBufSize)
  642. {
  643. LPD3DHAL_DP2RENDERSTATE lpRState = (LPD3DHAL_DP2RENDERSTATE)
  644. ((LPBYTE)lpvDP2Commands + dwDP2CommandLength +
  645. dp2data.dwCommandOffset);
  646. lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
  647. lpRState->RenderState = dwStateType;
  648. lpRState->dwState = value;
  649. dwDP2CommandLength += sizeof(D3DHAL_DP2RENDERSTATE);
  650. #ifndef _IA64_
  651. D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  652. #endif
  653. return;
  654. }
  655. }
  656. // Check for space
  657. if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
  658. sizeof(D3DHAL_DP2RENDERSTATE) > dwDP2CommandBufSize)
  659. {
  660. FlushStates();
  661. // Since we ran out of space, we were not able to put
  662. // (dwStateType, value) into the batch so rstates will reflect only
  663. // the last batched renderstate (since the driver updates rstates
  664. // from the batch). To fix this, we simply put the current
  665. // (dwStateType, value) into rstates.
  666. m_pDevice->UpdateRenderState(dwStateType, value);
  667. }
  668. // Add new renderstate instruction
  669. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  670. dwDP2CommandLength + dp2data.dwCommandOffset);
  671. lpDP2CurrCommand->bCommand = D3DDP2OP_RENDERSTATE;
  672. bDP2CurrCmdOP = D3DDP2OP_RENDERSTATE;
  673. lpDP2CurrCommand->bReserved = 0;
  674. lpDP2CurrCommand->wStateCount = 1;
  675. wDP2CurrCmdCnt = 1;
  676. #ifndef _IA64_
  677. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  678. #endif
  679. // Add renderstate data
  680. LPD3DHAL_DP2RENDERSTATE lpRState;
  681. lpRState = (LPD3DHAL_DP2RENDERSTATE)(lpDP2CurrCommand + 1);
  682. lpRState->RenderState = dwStateType;
  683. lpRState->dwState = value;
  684. dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) +
  685. sizeof(D3DHAL_DP2RENDERSTATE);
  686. }
  687. //-----------------------------------------------------------------------------
  688. #undef DPF_MODNAME
  689. #define DPF_MODNAME "CD3DDDIDX6::UpdateWInfo"
  690. void
  691. CD3DDDIDX6::UpdateWInfo(CONST D3DMATRIX* lpMat)
  692. {
  693. LPD3DHAL_DP2WINFO pData;
  694. pData = (LPD3DHAL_DP2WINFO)
  695. GetHalBufferPointer(D3DDP2OP_WINFO, sizeof(*pData));
  696. D3DMATRIX m = *lpMat;
  697. if( (m._33 == m._34) || (m._33 == 0.0f) )
  698. {
  699. D3D_WARN(1, "Cannot compute WNear and WFar from the supplied projection matrix");
  700. D3D_WARN(1, "Setting wNear to 0.0 and wFar to 1.0");
  701. pData->dvWNear = 0.0f;
  702. pData->dvWFar = 1.0f;
  703. return;
  704. }
  705. pData->dvWNear = m._44 - m._43/m._33*m._34;
  706. pData->dvWFar = (m._44 - m._43)/(m._33 - m._34)*m._34 + m._44;
  707. }
  708. //-----------------------------------------------------------------------------
  709. #undef DPF_MODNAME
  710. #define DPF_MODNAME "CD3DDDIDX6::SetViewport"
  711. void
  712. CD3DDDIDX6::SetViewport(CONST D3DVIEWPORT8* lpVwpData)
  713. {
  714. LPD3DHAL_DP2VIEWPORTINFO pData;
  715. pData = (LPD3DHAL_DP2VIEWPORTINFO)GetHalBufferPointer(D3DDP2OP_VIEWPORTINFO, sizeof(*pData));
  716. pData->dwX = lpVwpData->X;
  717. pData->dwY = lpVwpData->Y;
  718. pData->dwWidth = lpVwpData->Width;
  719. pData->dwHeight = lpVwpData->Height;
  720. }
  721. //-----------------------------------------------------------------------------
  722. #undef DPF_MODNAME
  723. #define DPF_MODNAME "CD3DDDIDX6::SetTSS"
  724. void
  725. CD3DDDIDX6::SetTSS(DWORD dwStage,
  726. D3DTEXTURESTAGESTATETYPE dwState,
  727. DWORD dwValue)
  728. {
  729. // Filter unsupported states
  730. if (dwState >= m_pDevice->m_tssMax)
  731. return;
  732. // Map DX8 filter enums to DX6/7 enums
  733. switch (dwState)
  734. {
  735. case D3DTSS_MAGFILTER: dwValue = texf2texfg[min(D3DTEXF_GAUSSIANCUBIC,dwValue)]; break;
  736. case D3DTSS_MINFILTER: dwValue = texf2texfn[min(D3DTEXF_GAUSSIANCUBIC,dwValue)]; break;
  737. case D3DTSS_MIPFILTER: dwValue = texf2texfp[min(D3DTEXF_GAUSSIANCUBIC,dwValue)]; break;
  738. }
  739. if (bDP2CurrCmdOP == D3DDP2OP_TEXTURESTAGESTATE)
  740. { // Last instruction is a texture stage state, append this one to it
  741. if (dwDP2CommandLength + sizeof(D3DHAL_DP2TEXTURESTAGESTATE) <=
  742. dwDP2CommandBufSize)
  743. {
  744. LPD3DHAL_DP2TEXTURESTAGESTATE lpRState =
  745. (LPD3DHAL_DP2TEXTURESTAGESTATE)((LPBYTE)lpvDP2Commands +
  746. dwDP2CommandLength + dp2data.dwCommandOffset);
  747. lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
  748. lpRState->wStage = (WORD)dwStage;
  749. lpRState->TSState = (WORD)dwState;
  750. lpRState->dwValue = dwValue;
  751. dwDP2CommandLength += sizeof(D3DHAL_DP2TEXTURESTAGESTATE);
  752. #ifndef _IA64_
  753. D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  754. #endif
  755. return;
  756. }
  757. }
  758. // Check for space
  759. if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
  760. sizeof(D3DHAL_DP2TEXTURESTAGESTATE) > dwDP2CommandBufSize)
  761. {
  762. FlushStates();
  763. }
  764. // Add new renderstate instruction
  765. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  766. dwDP2CommandLength + dp2data.dwCommandOffset);
  767. lpDP2CurrCommand->bCommand = D3DDP2OP_TEXTURESTAGESTATE;
  768. bDP2CurrCmdOP = D3DDP2OP_TEXTURESTAGESTATE;
  769. lpDP2CurrCommand->bReserved = 0;
  770. lpDP2CurrCommand->wStateCount = 1;
  771. wDP2CurrCmdCnt = 1;
  772. #ifndef _IA64_
  773. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  774. #endif
  775. // Add renderstate data
  776. LPD3DHAL_DP2TEXTURESTAGESTATE lpRState =
  777. (LPD3DHAL_DP2TEXTURESTAGESTATE)(lpDP2CurrCommand + 1);
  778. lpRState->wStage = (WORD)dwStage;
  779. lpRState->TSState = (WORD)dwState;
  780. lpRState->dwValue = dwValue;
  781. dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) +
  782. sizeof(D3DHAL_DP2TEXTURESTAGESTATE);
  783. }
  784. //---------------------------------------------------------------------
  785. // Map D3DPRIMITIVETYPE to D3DHAL_DP2OPERATION for indexed primitives
  786. const WORD iprim2cmdop[] = {
  787. 0, // Invalid
  788. 0, // Points are invalid too
  789. D3DDP2OP_INDEXEDLINELIST2,
  790. D3DDP2OP_INDEXEDLINESTRIP,
  791. D3DDP2OP_INDEXEDTRIANGLELIST2,
  792. D3DDP2OP_INDEXEDTRIANGLESTRIP,
  793. D3DDP2OP_INDEXEDTRIANGLEFAN
  794. };
  795. // Map D3DPRIMITIVETYPE to D3DHAL_DP2OPERATION
  796. const WORD prim2cmdop[] = {
  797. 0, // Invalid
  798. D3DDP2OP_POINTS,
  799. D3DDP2OP_LINELIST,
  800. D3DDP2OP_LINESTRIP,
  801. D3DDP2OP_TRIANGLELIST,
  802. D3DDP2OP_TRIANGLESTRIP,
  803. D3DDP2OP_TRIANGLEFAN
  804. };
  805. // Map D3DPRIMITIVETYPE to bytes needed in command stream
  806. const WORD prim2cmdsz[] = {
  807. 0, // Invalid
  808. sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2POINTS),
  809. sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2LINELIST),
  810. sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2LINESTRIP),
  811. sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2TRIANGLELIST),
  812. sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2TRIANGLESTRIP),
  813. sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2TRIANGLEFAN)
  814. };
  815. //-----------------------------------------------------------------------------
  816. #undef DPF_MODNAME
  817. #define DPF_MODNAME "CD3DDDIDX6::SetVertexShader"
  818. void CD3DDDIDX6::SetVertexShader(DWORD dwHandle)
  819. {
  820. DXGASSERT(D3DVSD_ISLEGACY(dwHandle));
  821. DXGASSERT( (dwHandle == 0) || FVF_TRANSFORMED(dwHandle) );
  822. m_CurrentVertexShader = dwHandle;
  823. #if DBG
  824. m_VertexSizeFromShader = ComputeVertexSizeFVF(dwHandle);
  825. #endif
  826. }
  827. //-----------------------------------------------------------------------------
  828. #undef DPF_MODNAME
  829. #define DPF_MODNAME "CD3DDDIDX6::SetVertexShaderHW"
  830. void CD3DDDIDX6::SetVertexShaderHW(DWORD dwHandle)
  831. {
  832. DXGASSERT(D3DVSD_ISLEGACY(dwHandle));
  833. DXGASSERT( (dwHandle == 0) || FVF_TRANSFORMED(dwHandle) );
  834. m_CurrentVertexShader = dwHandle;
  835. #if DBG
  836. m_VertexSizeFromShader = ComputeVertexSizeFVF(dwHandle);
  837. #endif
  838. }
  839. //-----------------------------------------------------------------------------
  840. #undef DPF_MODNAME
  841. #define DPF_MODNAME "CD3DDDIDX6::SetStreamSource"
  842. void CD3DDDIDX6::SetStreamSource(UINT StreamIndex, CVStream* pStream)
  843. {
  844. DXGASSERT(StreamIndex == 0);
  845. m_pStream0 = pStream;
  846. }
  847. //-----------------------------------------------------------------------------
  848. #undef DPF_MODNAME
  849. #define DPF_MODNAME "CD3DDDIDX6::SetIndices"
  850. void CD3DDDIDX6::SetIndices(CVIndexStream* pStream)
  851. {
  852. m_pIStream = pStream;
  853. }
  854. //-----------------------------------------------------------------------------
  855. // Assumes that VB has not been changed between DrawPrimitive calss
  856. //
  857. #undef DPF_MODNAME
  858. #define DPF_MODNAME "CD3DDDIDX6_DrawPrimitiveFast"
  859. void CD3DDDIDX6_DrawPrimitiveFast(CD3DBase* pDevice,
  860. D3DPRIMITIVETYPE primType,
  861. UINT StartVertex,
  862. UINT PrimitiveCount)
  863. {
  864. CD3DDDIDX6* pDDI = static_cast<CD3DDDIDX6*>(pDevice->m_pDDI);
  865. UINT NumVertices = GETVERTEXCOUNT(primType, PrimitiveCount);
  866. pDDI->SetWithinPrimitive(TRUE);
  867. if(pDevice->m_dwRuntimeFlags & D3DRT_NEED_TEXTURE_UPDATE)
  868. {
  869. pDevice->UpdateTextures();
  870. pDevice->m_dwRuntimeFlags &= ~D3DRT_NEED_TEXTURE_UPDATE;
  871. }
  872. pDDI->dwDP2VertexCount = max(pDDI->dwDP2VertexCount,
  873. StartVertex + NumVertices);
  874. // Check for space in the command buffer for new command.
  875. // The vertices are already in the vertex buffer.
  876. if (pDDI->dwDP2CommandLength + prim2cmdsz[primType] > pDDI->dwDP2CommandBufSize)
  877. {
  878. pDDI->FlushStates(FALSE, TRUE);
  879. }
  880. // Insert non indexed primitive instruction
  881. LPD3DHAL_DP2COMMAND lpDP2CurrCommand;
  882. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)pDDI->lpvDP2Commands +
  883. pDDI->dwDP2CommandLength + pDDI->dp2data.dwCommandOffset);
  884. pDDI->bDP2CurrCmdOP = (BYTE)prim2cmdop[primType];
  885. // This will initialize bCommand and bReserved
  886. *(WORD*)&lpDP2CurrCommand->bCommand = prim2cmdop[primType];
  887. if (pDDI->bDP2CurrCmdOP != D3DDP2OP_POINTS)
  888. {
  889. // Linestrip, trianglestrip, trianglefan, linelist and trianglelist are identical
  890. pDDI->wDP2CurrCmdCnt = (WORD)PrimitiveCount;
  891. lpDP2CurrCommand->wPrimitiveCount = (WORD)PrimitiveCount;
  892. LPD3DHAL_DP2LINESTRIP lpStrip = (LPD3DHAL_DP2LINESTRIP)(lpDP2CurrCommand + 1);
  893. lpStrip->wVStart = (WORD)StartVertex;
  894. }
  895. else
  896. {
  897. pDDI->wDP2CurrCmdCnt = 1;
  898. lpDP2CurrCommand->wPrimitiveCount = 1;
  899. LPD3DHAL_DP2POINTS lpPoints = (LPD3DHAL_DP2POINTS)(lpDP2CurrCommand + 1);
  900. lpPoints->wCount = (WORD)NumVertices;
  901. lpPoints->wVStart = (WORD)StartVertex;
  902. }
  903. pDDI->dwDP2CommandLength += prim2cmdsz[primType];
  904. #if DBG
  905. if (pDDI->m_bValidateCommands)
  906. pDDI->ValidateCommand(lpDP2CurrCommand);
  907. #endif
  908. pDDI->SetWithinPrimitive(FALSE);
  909. }
  910. //-----------------------------------------------------------------------------
  911. #undef DPF_MODNAME
  912. #define DPF_MODNAME "CD3DDDIDX6_DrawPrimitive"
  913. void CD3DDDIDX6_DrawPrimitive(CD3DBase* pDevice,
  914. D3DPRIMITIVETYPE primType,
  915. UINT StartVertex,
  916. UINT PrimitiveCount)
  917. {
  918. #if DBG
  919. if (!(pDevice->BehaviorFlags() & D3DCREATE_PUREDEVICE))
  920. {
  921. CD3DHal* pDev = static_cast<CD3DHal*>(pDevice);
  922. UINT nVer = GETVERTEXCOUNT(primType, PrimitiveCount);
  923. pDev->ValidateDraw2(primType, StartVertex, PrimitiveCount,
  924. nVer, FALSE);
  925. }
  926. #endif // DBG
  927. CD3DDDIDX6* pDDI = static_cast<CD3DDDIDX6*>(pDevice->m_pDDI);
  928. CVStream* pStream0 = &pDevice->m_pStream[0];
  929. D3DFE_PROCESSVERTICES* pv = static_cast<CD3DHal*>(pDevice)->m_pv;
  930. pv->dwNumVertices = GETVERTEXCOUNT(primType, PrimitiveCount);
  931. pv->dwVIDOut = pDDI->m_CurrentVertexShader;
  932. pv->dwOutputSize = pStream0->m_dwStride;
  933. DXGASSERT(pStream0->m_pVB != NULL);
  934. #if DBG
  935. if (pStream0->m_dwStride != pDDI->m_VertexSizeFromShader)
  936. {
  937. D3D_THROW_FAIL("Device requires stream stride and vertex size,"
  938. "computed from vertex shader, to be the same");
  939. }
  940. #endif
  941. if(pStream0->m_pVB->IsD3DManaged())
  942. {
  943. BOOL bDirty = FALSE;
  944. HRESULT result = pDevice->ResourceManager()->UpdateVideo(pStream0->m_pVB->RMHandle(), &bDirty);
  945. if(result != D3D_OK)
  946. {
  947. D3D_THROW(result, "Resource manager failed to create or update video memory VB");
  948. }
  949. }
  950. pDDI->StartPrimVB(pv, pStream0, StartVertex);
  951. CD3DDDIDX6_DrawPrimitiveFast(pDevice, primType, StartVertex, PrimitiveCount);
  952. pDevice->m_pfnDrawPrim = CD3DDDIDX6_DrawPrimitiveFast;
  953. }
  954. //-----------------------------------------------------------------------------
  955. // Assumes that VB has not been changed between DrawIndexedPrimitive calls
  956. //
  957. #undef DPF_MODNAME
  958. #define DPF_MODNAME "CD3DDDIDX6_IndexedDrawPrimitiveFast"
  959. void CD3DDDIDX6_DrawIndexedPrimitiveFast(CD3DBase* pDevice,
  960. D3DPRIMITIVETYPE primType,
  961. UINT BaseVertexIndex,
  962. UINT MinIndex, UINT NumVertices,
  963. UINT StartIndex, UINT PrimitiveCount)
  964. {
  965. CD3DDDIDX6* pDDI = static_cast<CD3DDDIDX6*>(pDevice->m_pDDI);
  966. CVIndexStream* pIStream = pDevice->m_pIndexStream;
  967. UINT NumIndices = GETVERTEXCOUNT(primType, PrimitiveCount);
  968. WORD* lpwIndices = (WORD*)(pIStream->Data() + StartIndex * pIStream->m_dwStride);
  969. pDDI->SetWithinPrimitive(TRUE);
  970. #if DBG
  971. // DP2 HAL supports 16 bit indices only
  972. if (pIStream->m_dwStride != 2)
  973. {
  974. D3D_THROW_FAIL("Device does not support 32-bit indices");
  975. }
  976. DXGASSERT(BaseVertexIndex <= 0xFFFF &&
  977. NumVertices <= 0xFFFF &&
  978. PrimitiveCount <= 0xFFFF);
  979. #endif
  980. DWORD dwByteCount; // Command length plus indices
  981. DWORD dwIndicesByteCount; // Indices only
  982. if(pDevice->m_dwRuntimeFlags & D3DRT_NEED_TEXTURE_UPDATE)
  983. {
  984. pDevice->UpdateTextures();
  985. pDevice->m_dwRuntimeFlags &= ~D3DRT_NEED_TEXTURE_UPDATE;
  986. }
  987. dwIndicesByteCount = NumIndices << 1;
  988. dwByteCount = dwIndicesByteCount + sizeof(D3DHAL_DP2COMMAND) +
  989. sizeof(D3DHAL_DP2STARTVERTEX);
  990. LPD3DHAL_DP2COMMAND lpDP2CurrCommand;
  991. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)
  992. pDDI->ReserveSpaceInCommandBuffer(dwByteCount);
  993. pDDI->bDP2CurrCmdOP = (BYTE)iprim2cmdop[primType];
  994. // This will initialize bCommand and bReserved
  995. *(WORD*)&lpDP2CurrCommand->bCommand = iprim2cmdop[primType];
  996. lpDP2CurrCommand->wPrimitiveCount = (WORD)PrimitiveCount;
  997. LPBYTE pIndices = (BYTE*)(lpDP2CurrCommand + 1); // Place for indices
  998. WORD* pStartVertex = &((LPD3DHAL_DP2STARTVERTEX)(lpDP2CurrCommand+1))->wVStart;
  999. pIndices += sizeof(D3DHAL_DP2STARTVERTEX);
  1000. #if DBG
  1001. if (lpDP2CurrCommand->bCommand == 0)
  1002. {
  1003. D3D_THROW_FAIL("Illegal primitive type");
  1004. }
  1005. #endif
  1006. *pStartVertex = (WORD)BaseVertexIndex;
  1007. memcpy(pIndices, lpwIndices, dwIndicesByteCount);
  1008. pDDI->wDP2CurrCmdCnt = (WORD)PrimitiveCount;
  1009. pDDI->dwDP2CommandLength += dwByteCount;
  1010. #if DBG
  1011. if (pDDI->m_bValidateCommands)
  1012. pDDI->ValidateCommand(lpDP2CurrCommand);
  1013. #endif
  1014. pDDI->dwDP2VertexCount = max(pDDI->dwDP2VertexCount, MinIndex + NumVertices);
  1015. // End of the primitive
  1016. pDDI->SetWithinPrimitive(FALSE);
  1017. }
  1018. //-----------------------------------------------------------------------------
  1019. #undef DPF_MODNAME
  1020. #define DPF_MODNAME "CD3DDDIDX6_IndexedDrawPrimitive"
  1021. void CD3DDDIDX6_DrawIndexedPrimitive(CD3DBase* pDevice,
  1022. D3DPRIMITIVETYPE primType,
  1023. UINT BaseVertexIndex,
  1024. UINT MinIndex, UINT NumVertices,
  1025. UINT StartIndex, UINT PrimitiveCount)
  1026. {
  1027. #if DBG
  1028. if (!(pDevice->BehaviorFlags() & D3DCREATE_PUREDEVICE))
  1029. {
  1030. CD3DHal* pDev = static_cast<CD3DHal*>(pDevice);
  1031. pDev->ValidateDraw2(primType, MinIndex + BaseVertexIndex,
  1032. PrimitiveCount, NumVertices, TRUE, StartIndex);
  1033. }
  1034. #endif // DBG
  1035. D3DFE_PROCESSVERTICES* pv = static_cast<CD3DHal*>(pDevice)->m_pv;
  1036. CD3DDDIDX6* pDDI = static_cast<CD3DDDIDX6*>(pDevice->m_pDDI);
  1037. CVIndexStream* pIStream = pDevice->m_pIndexStream;
  1038. CVStream* pStream0 = &pDevice->m_pStream[0];
  1039. DXGASSERT(pStream0->m_pVB != NULL);
  1040. if(pStream0->m_pVB->IsD3DManaged())
  1041. {
  1042. BOOL bDirty = FALSE;
  1043. HRESULT result = pDevice->ResourceManager()->UpdateVideo(pStream0->m_pVB->RMHandle(), &bDirty);
  1044. if(result != D3D_OK)
  1045. {
  1046. D3D_THROW(result, "Resource manager failed to create or update video memory VB");
  1047. }
  1048. }
  1049. // Parameters needed for StartPrimVB
  1050. pv->dwNumVertices = NumVertices + MinIndex;
  1051. pv->dwVIDOut = pDDI->m_CurrentVertexShader;
  1052. pv->dwOutputSize = pStream0->m_dwStride;
  1053. #if DBG
  1054. if (pStream0->m_dwStride != pDDI->m_VertexSizeFromShader)
  1055. {
  1056. D3D_THROW_FAIL("Device requires stream stride and vertex size,"
  1057. "computed from vertex shader, to be the same");
  1058. }
  1059. #endif
  1060. pDDI->StartPrimVB(pv, pStream0, BaseVertexIndex);
  1061. CD3DDDIDX6_DrawIndexedPrimitiveFast(pDevice, primType, BaseVertexIndex,
  1062. MinIndex, NumVertices,
  1063. StartIndex, PrimitiveCount);
  1064. pDevice->m_pfnDrawIndexedPrim = CD3DDDIDX6_DrawIndexedPrimitiveFast;
  1065. }
  1066. //-----------------------------------------------------------------------------
  1067. #undef DPF_MODNAME
  1068. #define DPF_MODNAME "CD3DDDIDX6::DrawPrimitiveUP"
  1069. void
  1070. CD3DDDIDX6::DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,
  1071. UINT PrimitiveCount)
  1072. {
  1073. #if DBG
  1074. if (m_pDevice->m_pStream[0].m_dwStride != m_VertexSizeFromShader)
  1075. {
  1076. D3D_THROW_FAIL("Device requires stream stride and vertex size,"
  1077. "computed from vertex shader, to be the same");
  1078. }
  1079. #endif
  1080. UINT NumVertices = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  1081. if (NumVertices > LOWVERTICESNUMBER)
  1082. {
  1083. this->FlushStates();
  1084. if (lpDP2CurrBatchVBI)
  1085. {
  1086. lpDP2CurrBatchVBI->DecrementUseCount();
  1087. lpDP2CurrBatchVBI = NULL;
  1088. }
  1089. this->dwDP2VertexCount = NumVertices;
  1090. #if DBG
  1091. DXGASSERT(PrimitiveCount <= 0xFFFF && this->dwDP2VertexCount <= 0xFFFF);
  1092. #endif
  1093. dp2data.dwVertexType = m_CurrentVertexShader;
  1094. dp2data.dwVertexSize = m_pDevice->m_pStream[0].m_dwStride;
  1095. dp2data.lpVertices = m_pDevice->m_pStream[0].m_pData;
  1096. dp2data.dwFlags |= D3DHALDP2_USERMEMVERTICES;
  1097. dp2data.dwFlags &= ~D3DHALDP2_SWAPVERTEXBUFFER;
  1098. if(m_pDevice->m_dwRuntimeFlags & D3DRT_NEED_TEXTURE_UPDATE)
  1099. {
  1100. m_pDevice->UpdateTextures();
  1101. m_pDevice->m_dwRuntimeFlags &= ~D3DRT_NEED_TEXTURE_UPDATE;
  1102. }
  1103. // Insert non indexed primitive instruction
  1104. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  1105. dwDP2CommandLength + dp2data.dwCommandOffset);
  1106. bDP2CurrCmdOP = (BYTE)prim2cmdop[PrimitiveType];
  1107. lpDP2CurrCommand->bCommand = bDP2CurrCmdOP;
  1108. lpDP2CurrCommand->bReserved = 0;
  1109. if (bDP2CurrCmdOP == D3DDP2OP_POINTS)
  1110. {
  1111. wDP2CurrCmdCnt = 1;
  1112. LPD3DHAL_DP2POINTS lpPoints = (LPD3DHAL_DP2POINTS)(lpDP2CurrCommand + 1);
  1113. lpPoints->wCount = (WORD)this->dwDP2VertexCount;
  1114. lpPoints->wVStart = 0;
  1115. }
  1116. else
  1117. {
  1118. // Linestrip, trianglestrip, trianglefan, linelist and trianglelist are identical
  1119. wDP2CurrCmdCnt = (WORD)PrimitiveCount;
  1120. LPD3DHAL_DP2LINESTRIP lpStrip = (LPD3DHAL_DP2LINESTRIP)(lpDP2CurrCommand + 1);
  1121. lpStrip->wVStart = 0;
  1122. }
  1123. lpDP2CurrCommand->wPrimitiveCount = wDP2CurrCmdCnt;
  1124. dwDP2CommandLength += prim2cmdsz[PrimitiveType];
  1125. this->FlushStates();
  1126. dp2data.dwFlags &= ~D3DHALDP2_USERMEMVERTICES;
  1127. }
  1128. else
  1129. {
  1130. // There is no PURE HAL device for pre-DX8 HALs, so this cast is safe
  1131. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1132. D3DFE_PROCESSVERTICES& pv = *pDevice->m_pv;
  1133. // Copy vertices to the internal TL buffer and insert a new
  1134. // DrawPrimitive command
  1135. UINT VertexPoolSize = m_pDevice->m_pStream[0].m_dwStride * NumVertices;
  1136. pv.dwNumVertices = NumVertices;
  1137. pv.dwOutputSize = m_pDevice->m_pStream[0].m_dwStride;
  1138. pv.primType = PrimitiveType;
  1139. pv.dwNumPrimitives = PrimitiveCount;
  1140. pv.dwVIDOut = m_CurrentVertexShader;
  1141. pv.lpvOut = StartPrimTL(&pv, VertexPoolSize, TRUE);
  1142. memcpy(pv.lpvOut, m_pDevice->m_pStream[0].m_pData, VertexPoolSize);
  1143. DrawPrim(&pv);
  1144. EndPrim(pv.dwOutputSize);
  1145. }
  1146. }
  1147. //-----------------------------------------------------------------------------
  1148. #undef DPF_MODNAME
  1149. #define DPF_MODNAME "CD3DDDIDX6::DrawIndexedPrimitiveUP"
  1150. void
  1151. CD3DDDIDX6::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,
  1152. UINT MinVertexIndex,
  1153. UINT NumVertexIndices,
  1154. UINT PrimitiveCount)
  1155. {
  1156. #if DBG
  1157. if (m_pDevice->m_pStream[0].m_dwStride != m_VertexSizeFromShader)
  1158. {
  1159. D3D_THROW_FAIL("Device requires stream stride and vertex size,"
  1160. "computed from vertex shader, to be the same");
  1161. }
  1162. #endif
  1163. if (NumVertexIndices > LOWVERTICESNUMBER)
  1164. {
  1165. this->FlushStates();
  1166. if (lpDP2CurrBatchVBI)
  1167. {
  1168. lpDP2CurrBatchVBI->DecrementUseCount();
  1169. lpDP2CurrBatchVBI = NULL;
  1170. }
  1171. this->dwDP2VertexCount = NumVertexIndices + MinVertexIndex;
  1172. #if DBG
  1173. DXGASSERT(PrimitiveCount <= 0xFFFF && this->dwDP2VertexCount <= 0xFFFF);
  1174. #endif
  1175. dp2data.dwVertexType = m_CurrentVertexShader;
  1176. dp2data.dwVertexSize = m_pDevice->m_pStream[0].m_dwStride;
  1177. dp2data.lpVertices = m_pDevice->m_pStream[0].m_pData;
  1178. dp2data.dwFlags |= D3DHALDP2_USERMEMVERTICES;
  1179. dp2data.dwFlags &= ~D3DHALDP2_SWAPVERTEXBUFFER;
  1180. DWORD dwByteCount; // Command length plus indices
  1181. DWORD dwIndicesByteCount; // Indices only
  1182. if(m_pDevice->m_dwRuntimeFlags & D3DRT_NEED_TEXTURE_UPDATE)
  1183. {
  1184. m_pDevice->UpdateTextures();
  1185. m_pDevice->m_dwRuntimeFlags &= ~D3DRT_NEED_TEXTURE_UPDATE;
  1186. }
  1187. dwIndicesByteCount = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount) << 1;
  1188. dwByteCount = dwIndicesByteCount + sizeof(D3DHAL_DP2COMMAND) +
  1189. sizeof(D3DHAL_DP2STARTVERTEX);
  1190. if (dwDP2CommandLength + dwByteCount > dwDP2CommandBufSize)
  1191. {
  1192. // Request the driver to grow the command buffer upon flush
  1193. dp2data.dwReqCommandBufSize = dwByteCount;
  1194. dp2data.dwFlags |= D3DHALDP2_REQCOMMANDBUFSIZE;
  1195. try
  1196. {
  1197. FlushStates(FALSE,TRUE);
  1198. dp2data.dwFlags &= ~D3DHALDP2_REQCOMMANDBUFSIZE;
  1199. }
  1200. catch (HRESULT ret)
  1201. {
  1202. dp2data.dwFlags &= ~D3DHALDP2_REQCOMMANDBUFSIZE;
  1203. throw ret;
  1204. }
  1205. // Check if the driver did give us what we need or do it ourselves
  1206. GrowCommandBuffer(dwByteCount);
  1207. }
  1208. // Insert indexed primitive instruction
  1209. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  1210. dwDP2CommandLength + dp2data.dwCommandOffset);
  1211. lpDP2CurrCommand->bReserved = 0;
  1212. lpDP2CurrCommand->wPrimitiveCount = (WORD)PrimitiveCount;
  1213. LPBYTE pIndices = (BYTE*)(lpDP2CurrCommand + 1); // Place for indices
  1214. lpDP2CurrCommand->bCommand = (BYTE)iprim2cmdop[PrimitiveType];
  1215. WORD* pStartVertex = &((LPD3DHAL_DP2STARTVERTEX)(lpDP2CurrCommand+1))->wVStart;
  1216. pIndices += sizeof(D3DHAL_DP2STARTVERTEX);
  1217. *pStartVertex = 0;
  1218. bDP2CurrCmdOP = lpDP2CurrCommand->bCommand;
  1219. memcpy(pIndices, m_pDevice->m_pIndexStream->m_pData, dwIndicesByteCount);
  1220. wDP2CurrCmdCnt = lpDP2CurrCommand->wPrimitiveCount;
  1221. dwDP2CommandLength += dwByteCount;
  1222. this->FlushStates();
  1223. dp2data.dwFlags &= ~D3DHALDP2_USERMEMVERTICES;
  1224. }
  1225. else
  1226. {
  1227. // There is no PURE HAL device for pre-DX8 HALs, so this cast is safe
  1228. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1229. D3DFE_PROCESSVERTICES& pv = *pDevice->m_pv;
  1230. m_MinVertexIndex = MinVertexIndex;
  1231. // Copy vertices to the internal TL buffer and insert a new
  1232. // DrawIndexedPrimitive command
  1233. UINT VertexPoolSize = m_pDevice->m_pStream[0].m_dwStride * NumVertexIndices;
  1234. pv.dwNumVertices = NumVertexIndices;
  1235. pv.dwOutputSize = m_pDevice->m_pStream[0].m_dwStride;
  1236. pv.primType = PrimitiveType;
  1237. pv.dwNumPrimitives = PrimitiveCount;
  1238. pv.dwVIDOut = m_CurrentVertexShader;
  1239. // Copy vertices
  1240. UINT FirstVertexOffset = MinVertexIndex * pv.dwOutputSize;
  1241. pv.lpvOut = StartPrimTL(&pv, VertexPoolSize, TRUE);
  1242. memcpy(pv.lpvOut, m_pDevice->m_pStream[0].m_pData + FirstVertexOffset,
  1243. VertexPoolSize);
  1244. pv.dwNumIndices = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  1245. pv.dwIndexSize = m_pDevice->m_pIndexStream->m_dwStride;
  1246. pv.lpwIndices = (WORD*)(m_pDevice->m_pIndexStream->Data());
  1247. m_dwIndexOffset = MinVertexIndex;
  1248. AddVertices(pv.dwNumVertices);
  1249. DrawIndexPrim(&pv);
  1250. MovePrimitiveBase(NumVertexIndices);
  1251. EndPrim(pv.dwOutputSize);
  1252. }
  1253. }
  1254. //---------------------------------------------------------------------
  1255. #undef DPF_MODNAME
  1256. #define DPF_MODNAME "CD3DDDIDX6::DrawPrimPS"
  1257. void
  1258. CD3DDDIDX6::DrawPrimPS(D3DFE_PROCESSVERTICES* pv)
  1259. {
  1260. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1261. BYTE* p = (BYTE*)pv->lpvOut;
  1262. float PointSize = *(float*)&pv->lpdwRStates[D3DRS_POINTSIZE];
  1263. float PointSizeMin = *(float*)&pv->lpdwRStates[D3DRS_POINTSIZE_MIN];
  1264. if (PointSize < PointSizeMin)
  1265. PointSize = PointSizeMin;
  1266. if (PointSize > pv->PointSizeMax)
  1267. PointSize = pv->PointSizeMax;
  1268. for (UINT i=0; i < pv->dwNumVertices; i++)
  1269. {
  1270. if (pv->dwVIDOut & D3DFVF_PSIZE)
  1271. {
  1272. PointSize = *(float*)(p + pv->pointSizeOffsetOut);
  1273. if (PointSize < PointSizeMin)
  1274. PointSize = PointSizeMin;
  1275. if (PointSize > pv->PointSizeMax)
  1276. PointSize = pv->PointSizeMax;
  1277. }
  1278. DWORD diffuse = 0;
  1279. DWORD specular = 0;
  1280. if (pv->dwVIDOut & D3DFVF_DIFFUSE)
  1281. diffuse = *(DWORD*)(p + pv->diffuseOffsetOut);
  1282. if (pv->dwVIDOut & D3DFVF_SPECULAR)
  1283. specular = *(DWORD*)(p + pv->specularOffsetOut);
  1284. NextSprite(((float*)p)[0], ((float*)p)[1], // x, y
  1285. ((float*)p)[2], ((float*)p)[3], // z, w
  1286. diffuse, specular,
  1287. (float*)(p + pv->texOffsetOut),
  1288. pv->dwTextureCoordSizeTotal,
  1289. PointSize);
  1290. p += pv->dwOutputSize;
  1291. }
  1292. }
  1293. //---------------------------------------------------------------------
  1294. // Uses the following members of D3DFE_PROCESSVERTICES:
  1295. // primType
  1296. // dwNumVertices
  1297. // dwNumPrimitives
  1298. //
  1299. #undef DPF_MODNAME
  1300. #define DPF_MODNAME "CD3DDDIDX6::DrawPrim"
  1301. void
  1302. CD3DDDIDX6::DrawPrim(D3DFE_PROCESSVERTICES* pv)
  1303. {
  1304. #ifdef DEBUG_PIPELINE
  1305. if (g_DebugFlags & __DEBUG_NORENDERING)
  1306. return;
  1307. #endif
  1308. D3DPRIMITIVETYPE primType = pv->primType;
  1309. if(m_pDevice->m_dwRuntimeFlags & D3DRT_NEED_TEXTURE_UPDATE)
  1310. {
  1311. m_pDevice->UpdateTextures();
  1312. m_pDevice->m_dwRuntimeFlags &= ~D3DRT_NEED_TEXTURE_UPDATE;
  1313. }
  1314. if (pv->primType == D3DPT_POINTLIST &&
  1315. pv->dwDeviceFlags & D3DDEV_DOPOINTSPRITEEMULATION)
  1316. {
  1317. DrawPrimPS(pv);
  1318. return;
  1319. }
  1320. // Check for space in the command buffer for new command.
  1321. // The vertices are already in the vertex buffer.
  1322. if (dwDP2CommandLength + prim2cmdsz[primType] > dwDP2CommandBufSize)
  1323. {
  1324. FlushStates(FALSE,TRUE);
  1325. }
  1326. this->AddVertices(pv->dwNumVertices);
  1327. // Insert non indexed primitive instruction
  1328. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  1329. dwDP2CommandLength + dp2data.dwCommandOffset);
  1330. bDP2CurrCmdOP = (BYTE)prim2cmdop[primType];
  1331. lpDP2CurrCommand->bCommand = bDP2CurrCmdOP;
  1332. lpDP2CurrCommand->bReserved = 0;
  1333. if (bDP2CurrCmdOP == D3DDP2OP_POINTS)
  1334. {
  1335. wDP2CurrCmdCnt = 1;
  1336. LPD3DHAL_DP2POINTS lpPoints = (LPD3DHAL_DP2POINTS)(lpDP2CurrCommand + 1);
  1337. lpPoints->wCount = (WORD)pv->dwNumVertices;
  1338. lpPoints->wVStart = (WORD)this->dwVertexBase;
  1339. }
  1340. else
  1341. {
  1342. // Linestrip, trianglestrip, trianglefan, linelist and trianglelist are identical
  1343. wDP2CurrCmdCnt = (WORD)pv->dwNumPrimitives;
  1344. LPD3DHAL_DP2LINESTRIP lpStrip = (LPD3DHAL_DP2LINESTRIP)(lpDP2CurrCommand + 1);
  1345. lpStrip->wVStart = (WORD)this->dwVertexBase;
  1346. }
  1347. lpDP2CurrCommand->wPrimitiveCount = wDP2CurrCmdCnt;
  1348. dwDP2CommandLength += prim2cmdsz[primType];
  1349. this->MovePrimitiveBase(pv->dwNumVertices);
  1350. #if DBG
  1351. if (m_bValidateCommands)
  1352. ValidateCommand(lpDP2CurrCommand);
  1353. #endif
  1354. }
  1355. //---------------------------------------------------------------------
  1356. //
  1357. // The vertices are already in the vertex buffer.
  1358. //
  1359. // Uses the following members of D3DFE_PROCESSVERTICES:
  1360. // primType
  1361. // dwNumVertices
  1362. // dwNumPrimitives
  1363. // dwNumIndices
  1364. // dwIndexOffset
  1365. // dwIndexSize
  1366. // lpwIndices
  1367. //
  1368. #undef DPF_MODNAME
  1369. #define DPF_MODNAME "CD3DDDDIDX6::DrawIndexPrim"
  1370. void
  1371. CD3DDDIDX6::DrawIndexPrim(D3DFE_PROCESSVERTICES* pv)
  1372. {
  1373. #ifdef DEBUG_PIPELINE
  1374. if (g_DebugFlags & __DEBUG_NORENDERING)
  1375. return;
  1376. #endif
  1377. #if DBG
  1378. // DP2 HAL supports 16 bit indices only
  1379. if (pv->dwIndexSize != 2)
  1380. {
  1381. D3D_THROW_FAIL("Device does not support 32-bit indices");
  1382. }
  1383. #endif
  1384. this->dwDP2Flags |= D3DDDI_INDEXEDPRIMDRAWN;
  1385. DWORD dwByteCount; // Command length plus indices
  1386. DWORD dwIndicesByteCount; // Indices only
  1387. if(m_pDevice->m_dwRuntimeFlags & D3DRT_NEED_TEXTURE_UPDATE)
  1388. {
  1389. m_pDevice->UpdateTextures();
  1390. m_pDevice->m_dwRuntimeFlags &= ~D3DRT_NEED_TEXTURE_UPDATE;
  1391. }
  1392. dwIndicesByteCount = pv->dwNumIndices << 1;
  1393. dwByteCount = dwIndicesByteCount + sizeof(D3DHAL_DP2COMMAND) +
  1394. sizeof(D3DHAL_DP2STARTVERTEX);
  1395. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)
  1396. ReserveSpaceInCommandBuffer(dwByteCount);
  1397. lpDP2CurrCommand->bReserved = 0;
  1398. lpDP2CurrCommand->wPrimitiveCount = (WORD)pv->dwNumPrimitives;
  1399. LPBYTE pIndices = (BYTE*)(lpDP2CurrCommand + 1); // Place for indices
  1400. lpDP2CurrCommand->bCommand = (BYTE)iprim2cmdop[pv->primType];
  1401. WORD* pStartVertex = &((LPD3DHAL_DP2STARTVERTEX)(lpDP2CurrCommand+1))->wVStart;
  1402. pIndices += sizeof(D3DHAL_DP2STARTVERTEX);
  1403. #if DBG
  1404. if (lpDP2CurrCommand->bCommand == 0)
  1405. {
  1406. D3D_THROW_FAIL("Illegal primitive type");
  1407. }
  1408. #endif
  1409. bDP2CurrCmdOP = lpDP2CurrCommand->bCommand;
  1410. // We have to handle the case when we copied vertices into our
  1411. // TL buffer, so MinVertexIndex corresponds to 0.
  1412. *pStartVertex = (WORD)this->dwVertexBase;
  1413. if (m_dwIndexOffset == 0)
  1414. {
  1415. memcpy(pIndices, pv->lpwIndices, dwIndicesByteCount);
  1416. }
  1417. else
  1418. if ((WORD)dwVertexBase > (WORD)m_dwIndexOffset)
  1419. {
  1420. // We can modify StartVertex by setting it outside vertex range
  1421. *pStartVertex = (WORD)dwVertexBase - (WORD)m_dwIndexOffset;
  1422. memcpy(pIndices, pv->lpwIndices, dwIndicesByteCount);
  1423. }
  1424. else
  1425. {
  1426. WORD* pout = (WORD*)pIndices;
  1427. WORD* pin = (WORD*)pv->lpwIndices;
  1428. for (UINT i=0; i < pv->dwNumIndices; i++)
  1429. {
  1430. pout[i] = (WORD)pin[i] - (WORD)m_dwIndexOffset;
  1431. }
  1432. }
  1433. wDP2CurrCmdCnt = lpDP2CurrCommand->wPrimitiveCount;
  1434. dwDP2CommandLength += dwByteCount;
  1435. #if DBG
  1436. if (m_bValidateCommands)
  1437. ValidateCommand(lpDP2CurrCommand);
  1438. #endif
  1439. }
  1440. //-----------------------------------------------------------------------------
  1441. // This primitive is generated by the clipper.
  1442. // The vertices of this primitive are pointed to by the
  1443. // lpvOut member, which need to be copied into the
  1444. // command stream immediately after the command itself.
  1445. //
  1446. // Uses the following members of D3DFE_PROCESSVERTICES:
  1447. // primType
  1448. // dwNumVertices
  1449. // dwNumPrimitives
  1450. // dwOutputSize
  1451. // dwFlags (D3DPV_NONCLIPPED)
  1452. // lpdwRStates (FILLMODE)
  1453. // lpvOut
  1454. // ClipperState.current_vbuf
  1455. //
  1456. #undef DPF_MODNAME
  1457. #define DPF_MODNAME "CD3DDDIDX6::DrawClippedPrim"
  1458. void
  1459. CD3DDDIDX6::DrawClippedPrim(D3DFE_PROCESSVERTICES* pv)
  1460. {
  1461. #ifdef DEBUG_PIPELINE
  1462. if (g_DebugFlags & __DEBUG_NORENDERING)
  1463. return;
  1464. #endif
  1465. if(m_pDevice->m_dwRuntimeFlags & D3DRT_NEED_TEXTURE_UPDATE)
  1466. {
  1467. m_pDevice->UpdateTextures();
  1468. m_pDevice->m_dwRuntimeFlags &= ~D3DRT_NEED_TEXTURE_UPDATE;
  1469. }
  1470. DWORD dwExtra = 0;
  1471. LPVOID lpvVerticesImm; // Place for vertices
  1472. DWORD dwVertexPoolSize = pv->dwNumVertices * pv->dwOutputSize;
  1473. if (pv->primType == D3DPT_TRIANGLEFAN)
  1474. {
  1475. if (pv->lpdwRStates[D3DRENDERSTATE_FILLMODE] == D3DFILL_WIREFRAME &&
  1476. pv->dwFlags & D3DPV_NONCLIPPED)
  1477. {
  1478. // For unclipped (but pretended to be clipped) tri fans in
  1479. // wireframe mode we generate 3-vertex tri fans to enable drawing
  1480. // of interior edges
  1481. BYTE vertices[__MAX_VERTEX_SIZE*3];
  1482. BYTE *pV1 = vertices + pv->dwOutputSize;
  1483. BYTE *pV2 = pV1 + pv->dwOutputSize;
  1484. BYTE *pInput = (BYTE*)pv->lpvOut;
  1485. memcpy(vertices, pInput, pv->dwOutputSize);
  1486. pInput += pv->dwOutputSize;
  1487. const DWORD nTriangles = pv->dwNumVertices - 2;
  1488. pv->dwNumVertices = 3;
  1489. pv->dwNumPrimitives = 1;
  1490. pv->lpvOut = vertices;
  1491. // Remove this flag for recursive call
  1492. pv->dwFlags &= ~D3DPV_NONCLIPPED;
  1493. for (DWORD i = nTriangles; i; i--)
  1494. {
  1495. memcpy(pV1, pInput, pv->dwOutputSize);
  1496. memcpy(pV2, pInput + pv->dwOutputSize, pv->dwOutputSize);
  1497. pInput += pv->dwOutputSize;
  1498. // To enable all edge flag we set the fill mode to SOLID.
  1499. // This will prevent checking the clip flags in the clipper
  1500. // state
  1501. pv->lpdwRStates[D3DRENDERSTATE_FILLMODE] = D3DFILL_SOLID;
  1502. DrawClippedPrim(pv);
  1503. pv->lpdwRStates[D3DRENDERSTATE_FILLMODE] = D3DFILL_WIREFRAME;
  1504. }
  1505. return;
  1506. }
  1507. dwExtra = sizeof(D3DHAL_DP2TRIANGLEFAN_IMM);
  1508. }
  1509. DWORD dwPad;
  1510. dwPad = (sizeof(D3DHAL_DP2COMMAND) + dwDP2CommandLength + dwExtra) & 3;
  1511. DWORD dwByteCount = sizeof(D3DHAL_DP2COMMAND) + dwPad + dwExtra +
  1512. dwVertexPoolSize;
  1513. // Check for space in the command buffer for commands & vertices
  1514. if (dwDP2CommandLength + dwByteCount > dwDP2CommandBufSize)
  1515. {
  1516. // Flush the current batch but hold on to the vertices
  1517. FlushStates(FALSE,TRUE);
  1518. if (dwByteCount > dwDP2CommandBufSize)
  1519. {
  1520. GrowCommandBuffer(dwByteCount);
  1521. }
  1522. dwPad = (sizeof(D3DHAL_DP2COMMAND) + dwExtra) & 3;
  1523. dwByteCount = sizeof(D3DHAL_DP2COMMAND) + dwExtra + dwPad +
  1524. dwVertexPoolSize;
  1525. }
  1526. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  1527. dwDP2CommandLength + dp2data.dwCommandOffset);
  1528. lpDP2CurrCommand->wPrimitiveCount = (WORD)pv->dwNumPrimitives;
  1529. lpDP2CurrCommand->bReserved = 0;
  1530. if (pv->primType == D3DPT_TRIANGLEFAN)
  1531. {
  1532. // Insert inline instruction and vertices
  1533. bDP2CurrCmdOP = D3DDP2OP_TRIANGLEFAN_IMM;
  1534. lpDP2CurrCommand->bCommand = bDP2CurrCmdOP;
  1535. LPD3DHAL_DP2TRIANGLEFAN_IMM lpTriFanImm;
  1536. lpTriFanImm = (LPD3DHAL_DP2TRIANGLEFAN_IMM)(lpDP2CurrCommand + 1);
  1537. if (pv->lpdwRStates[D3DRENDERSTATE_FILLMODE] == D3DFILL_WIREFRAME)
  1538. {
  1539. lpTriFanImm->dwEdgeFlags = 0;
  1540. ClipVertex **clip = pv->ClipperState.current_vbuf;
  1541. // Look at the exterior edges and mark the visible ones
  1542. for(DWORD i = 0; i < pv->dwNumVertices; ++i)
  1543. {
  1544. if (clip[i]->clip & CLIPPED_ENABLE)
  1545. lpTriFanImm->dwEdgeFlags |= (1 << i);
  1546. }
  1547. }
  1548. else
  1549. {
  1550. // Mark all exterior edges visible
  1551. lpTriFanImm->dwEdgeFlags = 0xFFFFFFFF;
  1552. }
  1553. lpvVerticesImm = (LPBYTE)(lpTriFanImm + 1) + dwPad;
  1554. }
  1555. else
  1556. {
  1557. // Insert inline instruction and vertices
  1558. bDP2CurrCmdOP = D3DDP2OP_LINELIST_IMM;
  1559. lpDP2CurrCommand->bCommand = bDP2CurrCmdOP;
  1560. lpvVerticesImm = (LPBYTE)(lpDP2CurrCommand + 1) + dwPad;
  1561. }
  1562. memcpy(lpvVerticesImm, pv->lpvOut, dwVertexPoolSize);
  1563. dwDP2CommandLength += dwByteCount;
  1564. #if DBG
  1565. if (m_bValidateCommands)
  1566. ValidateCommand(lpDP2CurrCommand);
  1567. #endif
  1568. }
  1569. //-----------------------------------------------------------------------------
  1570. #undef DPF_MODNAME
  1571. #define DPF_MODNAME "CD3DDDIDX6::PickProcessPrimitive"
  1572. void CD3DDDIDX6::PickProcessPrimitive()
  1573. {
  1574. D3DFE_PROCESSVERTICES* pv = static_cast<CD3DHal*>(m_pDevice)->m_pv;
  1575. if (pv->dwDeviceFlags & D3DDEV_DOPOINTSPRITEEMULATION)
  1576. {
  1577. m_pfnProcessPrimitive = ProcessPointSprites;
  1578. }
  1579. else
  1580. if (pv->dwDeviceFlags & D3DDEV_DONOTCLIP)
  1581. {
  1582. // Transformed vertices should not be processed using
  1583. // m_pfnProcessPrimitive. They should go directly to the DDI using
  1584. // pDevice->m_pfnDrawPrim
  1585. m_pfnProcessPrimitive = ProcessPrimitive;
  1586. m_pfnProcessIndexedPrimitive = ProcessIndexedPrimitive;
  1587. }
  1588. else
  1589. {
  1590. if (pv->dwDeviceFlags & D3DDEV_TRANSFORMEDFVF)
  1591. {
  1592. m_pfnProcessPrimitive = ProcessPrimitiveTC;
  1593. m_pfnProcessIndexedPrimitive = ProcessIndexedPrimitiveTC;
  1594. }
  1595. else
  1596. {
  1597. m_pfnProcessPrimitive = ProcessPrimitiveC;
  1598. m_pfnProcessIndexedPrimitive = ProcessIndexedPrimitiveC;
  1599. }
  1600. }
  1601. }
  1602. //-----------------------------------------------------------------------------
  1603. // The function does the point sprite expansion
  1604. //
  1605. #undef DPF_MODNAME
  1606. #define DPF_MODNAME "CD3DDDIDX6::ProcessPointSprites"
  1607. void
  1608. CD3DDDIDX6::ProcessPointSprites(D3DFE_PROCESSVERTICES* pv, UINT StartVertex)
  1609. {
  1610. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1611. DWORD dwOldCullMode = D3DCULL_NONE;
  1612. DWORD dwOldFillMode = D3DFILL_SOLID;
  1613. // Point spritest should not be culled. They are generated assuming that
  1614. // D3DCULL_CCW is set
  1615. if (pDevice->rstates[D3DRS_CULLMODE] == D3DCULL_CW)
  1616. {
  1617. dwOldCullMode = D3DCULL_CW;
  1618. SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  1619. }
  1620. // In case of multitexture we need to re-program texture stages to use
  1621. // texture coordonate set 0, because we generate only one set during
  1622. // emulation
  1623. DWORD TexCoordIndex[D3DDP_MAXTEXCOORD];
  1624. for (DWORD i=0; i < D3DDP_MAXTEXCOORD; i++)
  1625. {
  1626. if (pDevice->tsstates[i][D3DTSS_COLOROP] == D3DTOP_DISABLE)
  1627. break;
  1628. if (pDevice->m_lpD3DMappedTexI[i])
  1629. {
  1630. DWORD dwIndex = pDevice->tsstates[i][D3DTSS_TEXCOORDINDEX];
  1631. if (dwIndex != 0)
  1632. {
  1633. TexCoordIndex[i] = dwIndex;
  1634. SetTSS(i, D3DTSS_TEXCOORDINDEX, 0);
  1635. }
  1636. else
  1637. {
  1638. // Mark stage to not restore
  1639. TexCoordIndex[i] = 0xFFFFFFFF;
  1640. }
  1641. }
  1642. }
  1643. // Fill mode should be SOLID for point sprites
  1644. if (pDevice->rstates[D3DRS_FILLMODE] != D3DFILL_SOLID)
  1645. {
  1646. dwOldFillMode = pDevice->rstates[D3DRS_FILLMODE];
  1647. SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  1648. }
  1649. // Compute new output FVF
  1650. m_dwVIDOutPS = pv->dwVIDOut;
  1651. m_dwVIDOutPS &= ~D3DFVF_PSIZE;
  1652. if (pv->lpdwRStates[D3DRS_POINTSPRITEENABLE])
  1653. {
  1654. // Generate two floats for texture coord set
  1655. m_dwVIDOutPS &= 0xFF;
  1656. m_dwVIDOutPS |= D3DFVF_TEX1;
  1657. }
  1658. m_dwOutputSizePS = ComputeVertexSizeFVF(m_dwVIDOutPS);
  1659. StartPointSprites();
  1660. UINT VertexPoolSize = pv->dwNumVertices * pv->dwOutputSize;
  1661. if (pv->dwDeviceFlags & D3DDEV_TRANSFORMEDFVF)
  1662. {
  1663. // In case of transformed vertices, input is user memory (or vertex
  1664. // buffer) and the output is internal TL buffer
  1665. pv->dwOutputSize = pv->position.dwStride;
  1666. if (pv->dwDeviceFlags & D3DDEV_DONOTCLIP)
  1667. {
  1668. pv->lpvOut = (BYTE*)pv->position.lpvData;
  1669. DrawPrim(pv);
  1670. }
  1671. else
  1672. {
  1673. if (!(pv->dwDeviceFlags & D3DDEV_DONOTCOMPUTECLIPCODES))
  1674. PrepareForClipping(pv, StartVertex);
  1675. pv->lpvOut = (BYTE*)pv->position.lpvData;
  1676. HRESULT ret = D3D_OK;
  1677. if (!(pv->dwDeviceFlags & D3DDEV_VBPROCVER))
  1678. {
  1679. // Compute clip codes, because there was no ProcessVertices
  1680. DWORD clip_intersect = D3DFE_GenClipFlags(pv);
  1681. UpdateClipStatus(pDevice);
  1682. if (clip_intersect)
  1683. {
  1684. goto l_exit;
  1685. }
  1686. // There are some vertices inside the screen
  1687. if ( CheckIfNeedClipping(pv))
  1688. ret = ProcessClippedPointSprites(pv);
  1689. else
  1690. DrawPrim(pv);
  1691. }
  1692. else
  1693. {
  1694. // With the result of ProcessVertices as input we do not know
  1695. // clip union, so we need always do clipping
  1696. ret = ProcessClippedPointSprites(pv);
  1697. }
  1698. if (ret != D3D_OK)
  1699. {
  1700. EndPointSprites();
  1701. throw ret;
  1702. }
  1703. }
  1704. }
  1705. else
  1706. {
  1707. if (!(pv->dwDeviceFlags & D3DDEV_DONOTCLIP))
  1708. PrepareForClipping(pv, 0);
  1709. // Update lighting and related flags
  1710. if (pDevice->dwFEFlags & D3DFE_FRONTEND_DIRTY)
  1711. DoUpdateState(pDevice);
  1712. UINT VertexPoolSize = pv->dwNumVertices * pv->dwOutputSize;
  1713. pv->lpvOut = m_pPointStream->Lock(VertexPoolSize, this);
  1714. // We call ProcessVertices instead of DrawPrimitive, because we want to
  1715. // process sprites which are clippied by X or Y planes
  1716. DWORD clipIntersection = pv->pGeometryFuncs->ProcessVertices(pv);
  1717. HRESULT ret = D3D_OK;
  1718. if (pv->dwDeviceFlags & D3DDEV_DONOTCLIP)
  1719. {
  1720. DrawPrim(pv);
  1721. }
  1722. else
  1723. {
  1724. // We throw away points which are clipped by Z or by user planes.
  1725. // Otherwise a point sprite could be partially visible
  1726. clipIntersection &= ~(D3DCS_LEFT | D3DCS_RIGHT |
  1727. D3DCS_TOP | D3DCS_BOTTOM |
  1728. __D3DCLIPGB_ALL);
  1729. if (!clipIntersection)
  1730. {
  1731. // There are some vertices inside the screen
  1732. if (!CheckIfNeedClipping(pv))
  1733. DrawPrim(pv);
  1734. else
  1735. ret = ProcessClippedPointSprites(pv);
  1736. }
  1737. }
  1738. m_pPointStream->Unlock();
  1739. m_pPointStream->Reset();
  1740. if (ret != D3D_OK)
  1741. D3D_THROW(ret, "Error in PSGP");
  1742. if (!(pv->dwDeviceFlags & D3DDEV_DONOTCLIP))
  1743. UpdateClipStatus(pDevice);
  1744. }
  1745. l_exit:
  1746. EndPointSprites();
  1747. // Restore fill mode and cull mode if needed
  1748. if (dwOldCullMode != D3DCULL_NONE)
  1749. {
  1750. SetRenderState(D3DRS_CULLMODE, dwOldCullMode);
  1751. }
  1752. if (dwOldFillMode != D3DFILL_SOLID)
  1753. {
  1754. SetRenderState(D3DRS_FILLMODE, dwOldFillMode);
  1755. }
  1756. // We need to re-send API vertex shader to the driver next time
  1757. // SetVertexShader is called. If we do not call the function then next
  1758. // the same SetVertexShader call will be ignored and driver vertex shader
  1759. // will not be updated
  1760. static_cast<CD3DHal*>(m_pDevice)->ForceFVFRecompute();
  1761. // Now we need to restore re-programmed stages
  1762. for (DWORD i=0; i < D3DDP_MAXTEXCOORD; i++)
  1763. {
  1764. if (pDevice->tsstates[i][D3DTSS_COLOROP] == D3DTOP_DISABLE)
  1765. break;
  1766. if (pDevice->m_lpD3DMappedTexI[i] && TexCoordIndex[i] != 0xFFFFFFFF)
  1767. {
  1768. this->SetTSS(i, D3DTSS_TEXCOORDINDEX, TexCoordIndex[i]);
  1769. }
  1770. }
  1771. }
  1772. //-----------------------------------------------------------------------------
  1773. // Processes non-indexed primitives with transformed vertices and with
  1774. // clipping
  1775. //
  1776. // Only transformed vertices generated by ProcessVertices call are allowed here
  1777. //
  1778. #undef DPF_MODNAME
  1779. #define DPF_MODNAME "CD3DDDIDX6::ProcessPrimitiveTC"
  1780. void
  1781. CD3DDDIDX6::ProcessPrimitiveTC(D3DFE_PROCESSVERTICES* pv, UINT StartVertex)
  1782. {
  1783. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1784. CVStream* pStream = &m_pDevice->m_pStream[0];
  1785. PrepareForClipping(pv, StartVertex);
  1786. pv->dwOutputSize = pStream->m_dwStride;
  1787. pv->lpvOut = pv->position.lpvData;
  1788. if (m_pDevice->m_dwRuntimeFlags & D3DRT_USERMEMPRIMITIVE)
  1789. {
  1790. DXGASSERT(StartVertex == 0);
  1791. // Copy vertices to the TL buffer
  1792. UINT VertexPoolSize = pv->dwOutputSize * pv->dwNumVertices;
  1793. pv->lpvOut = (BYTE*)StartPrimTL(pv, VertexPoolSize, FALSE);
  1794. pv->position.lpvData = pv->lpvOut;
  1795. memcpy(pv->lpvOut, m_pDevice->m_pStream[0].m_pData, VertexPoolSize);
  1796. }
  1797. else
  1798. StartPrimVB(pv, pStream, StartVertex);
  1799. if (!(pv->dwDeviceFlags & D3DDEV_VBPROCVER))
  1800. {
  1801. pv->dwFlags |= D3DPV_TLVCLIP;
  1802. // Compute clip codes, because there was no ProcessVertices
  1803. DWORD clip_intersect = D3DFE_GenClipFlags(pDevice->m_pv);
  1804. UpdateClipStatus(pDevice);
  1805. if (clip_intersect)
  1806. goto l_exit;
  1807. }
  1808. HRESULT ret = pDevice->GeometryFuncsGuaranteed->DoDrawPrimitive(pv);
  1809. if (ret != D3D_OK)
  1810. {
  1811. EndPrim(pv->dwOutputSize);
  1812. throw ret;
  1813. }
  1814. l_exit:
  1815. EndPrim(pv->dwOutputSize);
  1816. pv->dwFlags &= ~D3DPV_TLVCLIP;
  1817. }
  1818. //-----------------------------------------------------------------------------
  1819. // Processes non-indexed primitives with untransformed vertices and with
  1820. // clipping
  1821. //
  1822. #undef DPF_MODNAME
  1823. #define DPF_MODNAME "CD3DDDIDX6::ProcessPrimitiveC"
  1824. void
  1825. CD3DDDIDX6::ProcessPrimitiveC(D3DFE_PROCESSVERTICES* pv, UINT StartVertex)
  1826. {
  1827. DXGASSERT((pv->dwVIDIn & D3DFVF_POSITION_MASK) != D3DFVF_XYZRHW);
  1828. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1829. PrepareForClipping(pv, 0);
  1830. // Update lighting and related flags
  1831. if (pDevice->dwFEFlags & D3DFE_FRONTEND_DIRTY)
  1832. DoUpdateState(pDevice);
  1833. // When a triangle strip is clipped, we draw indexed primitives
  1834. // sometimes. So we set m_dwIndexOffset to zero.
  1835. m_dwIndexOffset = 0;
  1836. UINT VertexPoolSize = pv->dwNumVertices * pv->dwOutputSize;
  1837. pv->lpvOut = StartPrimTL(pv, VertexPoolSize, TRUE);
  1838. HRESULT ret = pv->pGeometryFuncs->ProcessPrimitive(pv);
  1839. if (ret != D3D_OK)
  1840. {
  1841. EndPrim(pv->dwOutputSize);
  1842. D3D_THROW(ret, "Error in PSGP");
  1843. }
  1844. EndPrim(pv->dwOutputSize);
  1845. UpdateClipStatus(pDevice);
  1846. }
  1847. //-----------------------------------------------------------------------------
  1848. // Processes non-indexed primitives with untransformed vertices and without
  1849. // clipping
  1850. //
  1851. #undef DPF_MODNAME
  1852. #define DPF_MODNAME "CD3DDDIDX6::ProcessPrimitive"
  1853. void
  1854. CD3DDDIDX6::ProcessPrimitive(D3DFE_PROCESSVERTICES* pv, UINT StartVertex)
  1855. {
  1856. DXGASSERT((pv->dwVIDIn & D3DFVF_POSITION_MASK) != D3DFVF_XYZRHW);
  1857. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1858. // Update lighting and related flags
  1859. if (pDevice->dwFEFlags & D3DFE_FRONTEND_DIRTY)
  1860. DoUpdateState(pDevice);
  1861. UINT VertexPoolSize = pv->dwNumVertices * pv->dwOutputSize;
  1862. pv->lpvOut = StartPrimTL(pv, VertexPoolSize, NeverReadFromTLBuffer(pv));
  1863. HRESULT ret = pv->pGeometryFuncs->ProcessPrimitive(pv);
  1864. if (ret != D3D_OK)
  1865. {
  1866. EndPrim(pv->dwOutputSize);
  1867. D3D_THROW(ret, "Error in PSGP");
  1868. }
  1869. EndPrim(pv->dwOutputSize);
  1870. }
  1871. //-----------------------------------------------------------------------------
  1872. // Processes indexed primitive with untransformed vertices and without clipping
  1873. //
  1874. #undef DPF_MODNAME
  1875. #define DPF_MODNAME "CD3DDDIDX6::ProcessIndexedPrimitive"
  1876. void
  1877. CD3DDDIDX6::ProcessIndexedPrimitive(D3DFE_PROCESSVERTICES* pv, UINT StartVertex)
  1878. {
  1879. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1880. // Update lighting and related flags
  1881. if (pDevice->dwFEFlags & D3DFE_FRONTEND_DIRTY)
  1882. DoUpdateState(pDevice);
  1883. pv->lpwIndices = (WORD*)(pDevice->m_pIndexStream->Data() +
  1884. m_StartIndex * pDevice->m_pIndexStream->m_dwStride);
  1885. m_dwIndexOffset = m_MinVertexIndex;
  1886. pv->lpvOut = StartPrimTL(pv, pv->dwNumVertices * pv->dwOutputSize, TRUE);
  1887. AddVertices(pv->dwNumVertices);
  1888. HRESULT ret = pv->pGeometryFuncs->ProcessIndexedPrimitive(pv);
  1889. MovePrimitiveBase(pv->dwNumVertices);
  1890. EndPrim(pv->dwOutputSize);
  1891. if (ret != D3D_OK)
  1892. D3D_THROW(ret, "Error in PSGP");
  1893. }
  1894. //-----------------------------------------------------------------------------
  1895. // Processes indexed primitive with untransformed vertices and witht clipping
  1896. //
  1897. #undef DPF_MODNAME
  1898. #define DPF_MODNAME "CD3DDDIDX6::ProcessIndexedPrimitiveC"
  1899. void
  1900. CD3DDDIDX6::ProcessIndexedPrimitiveC(D3DFE_PROCESSVERTICES* pv, UINT StartVertex)
  1901. {
  1902. DXGASSERT((pv->dwVIDIn & D3DFVF_POSITION_MASK) != D3DFVF_XYZRHW);
  1903. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1904. pv->lpwIndices = (WORD*)(pDevice->m_pIndexStream->Data() +
  1905. m_StartIndex * pDevice->m_pIndexStream->m_dwStride);
  1906. PrepareForClipping(pv, 0);
  1907. // Update lighting and related flags
  1908. if (pDevice->dwFEFlags & D3DFE_FRONTEND_DIRTY)
  1909. DoUpdateState(pDevice);
  1910. pv->dwIndexOffset = m_MinVertexIndex; // For clipping
  1911. m_dwIndexOffset = m_MinVertexIndex; // For DrawIndexPrim
  1912. pv->lpvOut = StartPrimTL(pv, pv->dwNumVertices * pv->dwOutputSize, FALSE);
  1913. DWORD dwNumVertices = pv->dwNumVertices;
  1914. AddVertices(pv->dwNumVertices);
  1915. this->dwDP2Flags &= ~D3DDDI_INDEXEDPRIMDRAWN;
  1916. HRESULT ret = pv->pGeometryFuncs->ProcessIndexedPrimitive(pv);
  1917. if (this->dwDP2Flags & D3DDDI_INDEXEDPRIMDRAWN)
  1918. {
  1919. // There was a indexed primitive drawn
  1920. MovePrimitiveBase(dwNumVertices);
  1921. }
  1922. else
  1923. {
  1924. // All triangle were clipped. Remove vertices from TL buffer
  1925. SubVertices(dwNumVertices);
  1926. }
  1927. EndPrim(pv->dwOutputSize);
  1928. UpdateClipStatus(pDevice);
  1929. if (ret != D3D_OK)
  1930. D3D_THROW(ret, "Error in PSGP");
  1931. }
  1932. //-----------------------------------------------------------------------------
  1933. // Processes indexed primitive with transformed vertices and with clipping
  1934. //
  1935. // Only transformed vertices generated by ProcessVertices call are allowed here
  1936. //
  1937. #undef DPF_MODNAME
  1938. #define DPF_MODNAME "CD3DDDIDX6::ProcessIndexedPrimitiveTC"
  1939. void
  1940. CD3DDDIDX6::ProcessIndexedPrimitiveTC(D3DFE_PROCESSVERTICES* pv, UINT StartVertex)
  1941. {
  1942. HRESULT ret = S_OK;
  1943. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  1944. CVStream* pStream = &m_pDevice->m_pStream[0];
  1945. pv->lpwIndices = (WORD*)(pDevice->m_pIndexStream->Data() +
  1946. m_StartIndex * pDevice->m_pIndexStream->m_dwStride);
  1947. PrepareForClipping(pv, StartVertex);
  1948. pv->dwOutputSize = pStream->m_dwStride;
  1949. pv->lpvOut = pv->position.lpvData;
  1950. pv->dwNumVertices = m_MinVertexIndex + m_NumVertices;
  1951. if (m_pDevice->m_dwRuntimeFlags & D3DRT_USERMEMPRIMITIVE)
  1952. {
  1953. // We copy user vertices, starting from MinVertexIndex, to the internal
  1954. // TL buffer and do the clipping. Vertex base changes in the process.
  1955. // m_NumVertices has been computed as MinVertexIndex + NumVertices, so
  1956. // it needs to be adjusted, because vertex base has benn changed
  1957. m_NumVertices -= m_MinVertexIndex;
  1958. pv->dwNumVertices = m_NumVertices;
  1959. // Copy vertices to the TL buffer
  1960. UINT VertexPoolSize = pv->dwOutputSize * pv->dwNumVertices;
  1961. pv->lpvOut = (BYTE*)StartPrimTL(pv, VertexPoolSize, FALSE);
  1962. pv->position.lpvData = pv->lpvOut;
  1963. memcpy(pv->lpvOut,
  1964. m_pDevice->m_pStream[0].m_pData + m_MinVertexIndex * pv->dwOutputSize,
  1965. VertexPoolSize);
  1966. // Pre-DX8 DDI does not have BaseVertexIndex parameter, so we need to
  1967. // re-compute indices before passing them to the driver to reflect
  1968. // the changed vertex base
  1969. m_dwIndexOffset = m_MinVertexIndex ;
  1970. }
  1971. else
  1972. {
  1973. StartPrimVB(pv, pStream, m_BaseVertexIndex);
  1974. m_dwIndexOffset = 0; // For DrawIndexPrim
  1975. }
  1976. pv->dwNumVertices = m_NumVertices;
  1977. if (!(pv->dwDeviceFlags & D3DDEV_VBPROCVER))
  1978. {
  1979. pv->dwFlags |= D3DPV_TLVCLIP;
  1980. // Compute clip codes, because there was no ProcessVertices
  1981. DWORD clip_intersect = D3DFE_GenClipFlags(pv);
  1982. UpdateClipStatus(pDevice);
  1983. if (clip_intersect)
  1984. goto l_exit;
  1985. }
  1986. pv->dwIndexOffset = m_MinVertexIndex ; // For clipping
  1987. this->dwDP2Flags &= ~D3DDDI_INDEXEDPRIMDRAWN;
  1988. DWORD dwNumVertices = pv->dwNumVertices;
  1989. AddVertices(pv->dwNumVertices);
  1990. ret = pDevice->GeometryFuncsGuaranteed->DoDrawIndexedPrimitive(pv);
  1991. if (this->dwDP2Flags & D3DDDI_INDEXEDPRIMDRAWN)
  1992. {
  1993. // There was an indexed primitive drawn
  1994. MovePrimitiveBase(dwNumVertices);
  1995. }
  1996. else
  1997. {
  1998. // All triangles were clipped. Remove vertices from TL buffer
  1999. SubVertices(dwNumVertices);
  2000. }
  2001. l_exit:
  2002. pv->dwFlags &= ~D3DPV_TLVCLIP;
  2003. EndPrim(pv->dwOutputSize);
  2004. UpdateClipStatus(pDevice);
  2005. if (ret != D3D_OK)
  2006. throw ret;
  2007. }
  2008. //-----------------------------------------------------------------------------
  2009. #undef DPF_MODNAME
  2010. #define DPF_MODNAME "CD3DDDIDX6::GrowCommandBuffer"
  2011. // Check and grow command buffer
  2012. void CD3DDDIDX6::GrowCommandBuffer(DWORD dwSize)
  2013. {
  2014. HRESULT ret;
  2015. if (dwSize > dwDP2CommandBufSize)
  2016. {
  2017. if (lpDDSCB1)
  2018. {
  2019. lpDDSCB1->DecrementUseCount();
  2020. lpDDSCB1 = NULL;
  2021. }
  2022. // Create command buffer through Framework.
  2023. // NOTE: Command buffers are always REF_INTERNAL
  2024. // objects and must be released through
  2025. // DecrementUseCount
  2026. //
  2027. ret = CCommandBuffer::Create(m_pDevice,
  2028. dwSize,
  2029. D3DPOOL_SYSTEMMEM,
  2030. &lpDDSCB1);
  2031. if (ret != DD_OK)
  2032. {
  2033. dwDP2CommandBufSize = 0;
  2034. D3D_THROW(ret, "Failed to allocate Command Buffer");
  2035. }
  2036. // Lock command buffer
  2037. ret = lpDDSCB1->Lock(0, dwSize, (BYTE**)&lpvDP2Commands, NULL);
  2038. if (ret != DD_OK)
  2039. {
  2040. lpDDSCB1->DecrementUseCount();
  2041. lpDDSCB1 = NULL;
  2042. dwDP2CommandBufSize = 0;
  2043. D3D_THROW(ret, "Could not lock command buffer");
  2044. }
  2045. // lpDDCommands will be filled in by the thunk layer
  2046. dp2data.hDDCommands = lpDDSCB1->DriverAccessibleKernelHandle();
  2047. dwDP2CommandBufSize = dwSize;
  2048. }
  2049. }
  2050. //-----------------------------------------------------------------------------
  2051. // This function prepares the batch for new primitive.
  2052. // Called if vertices from user memory are used for rendering
  2053. //
  2054. // If bWriteOnly is set to TRUE, then there will be no read from the vertex
  2055. // processing output (no clipping or TL HAL).
  2056. //
  2057. // Expects the following members of D3DFE_PROCESSVERTICES to be initialized
  2058. // dwNumVertices
  2059. // lpvOut
  2060. // dwOutputSize
  2061. // dwVIDOut
  2062. //
  2063. // We fail vid mem VB for clipping
  2064. //
  2065. #undef DPF_MODNAME
  2066. #define DPF_MODNAME "CD3DDDIDX6::StartPrimUserMem"
  2067. void
  2068. CD3DDDIDX6::StartPrimUserMem(D3DFE_PROCESSVERTICES* pv, UINT VertexPoolSize)
  2069. {
  2070. // If the primitive is small, we copy vertices into the TL buffer
  2071. if (pv->dwNumVertices < LOWVERTICESNUMBER)
  2072. {
  2073. LPVOID tmp = StartPrimTL(pv, VertexPoolSize, TRUE);
  2074. memcpy(tmp, pv->lpvOut, VertexPoolSize);
  2075. this->dwDP2VertexCount += pv->dwNumVertices;
  2076. }
  2077. else
  2078. {
  2079. // We can not mix user memory primitive with other primitives, so
  2080. // flush the batch.
  2081. // Do not forget to flush the batch after rendering this primitive
  2082. this->FlushStates();
  2083. SetWithinPrimitive( TRUE );
  2084. // Release previously used vertex buffer (if any), because we do not
  2085. // it any more
  2086. if (lpDP2CurrBatchVBI)
  2087. {
  2088. lpDP2CurrBatchVBI->DecrementUseCount();
  2089. lpDP2CurrBatchVBI = NULL;
  2090. }
  2091. dp2data.dwVertexType = pv->dwVIDOut;
  2092. dp2data.dwVertexSize = pv->dwOutputSize;
  2093. dp2data.lpVertices = pv->lpvOut;
  2094. dp2data.dwFlags |= D3DHALDP2_USERMEMVERTICES;
  2095. dp2data.dwFlags &= ~D3DHALDP2_SWAPVERTEXBUFFER;
  2096. this->dwDP2Flags |= D3DDDI_USERMEMVERTICES;
  2097. this->dwDP2VertexCount = pv->dwNumVertices;
  2098. this->dwDP2VertexCountMask = 0;
  2099. }
  2100. }
  2101. //-----------------------------------------------------------------------------
  2102. // This function prepares the batch for new primitive.
  2103. // Called only if vertices from user memory are NOT used for rendering
  2104. //
  2105. // Uses the following data from D3DFE_PROCESSVERTICES:
  2106. // pv->dwVIDOut
  2107. // pv->dwOutputSize
  2108. // pv->dwNumVertices
  2109. //
  2110. #undef DPF_MODNAME
  2111. #define DPF_MODNAME "CD3DDDIDX6::StartPrimVB"
  2112. void
  2113. CD3DDDIDX6::StartPrimVB(D3DFE_PROCESSVERTICES * pv, CVStream* pStream,
  2114. DWORD dwStartVertex)
  2115. {
  2116. CVertexBuffer * lpVBI = pStream->m_pVB;
  2117. // If VID has been changed or new vertex buffer is used we flush the batch
  2118. if (pv->dwVIDOut != dp2data.dwVertexType ||
  2119. lpDP2CurrBatchVBI != lpVBI)
  2120. {
  2121. this->FlushStates();
  2122. dp2data.dwVertexType = pv->dwVIDOut;
  2123. dp2data.dwVertexSize = pv->dwOutputSize;
  2124. dp2data.hDDVertex = lpVBI->DriverAccessibleKernelHandle();
  2125. // Release previously used vertex buffer (if any), because we do not
  2126. // need it any more. We did IncrementUseCount() to TL buffer,
  2127. // so it is safe.
  2128. if (lpDP2CurrBatchVBI)
  2129. {
  2130. lpDP2CurrBatchVBI->DecrementUseCount();
  2131. }
  2132. // If a vertex buffer is used for rendering, make sure that it is no
  2133. // released by user. So do IncrementUseCount().
  2134. lpDP2CurrBatchVBI = lpVBI;
  2135. lpDP2CurrBatchVBI->IncrementUseCount();
  2136. }
  2137. DXGASSERT(dp2data.hDDVertex == lpVBI->DriverAccessibleKernelHandle());
  2138. lpDP2CurrBatchVBI->Batch();
  2139. SetWithinPrimitive( TRUE );
  2140. this->dwVertexBase = dwStartVertex;
  2141. dp2data.dwFlags &= ~D3DHALDP2_SWAPVERTEXBUFFER;
  2142. this->dwDP2VertexCount = max(this->dwDP2VertexCount,
  2143. this->dwVertexBase + pv->dwNumVertices);
  2144. // Prevent modification of dwDP2VertexCount during DrawPrim
  2145. this->dwDP2VertexCountMask = 0;
  2146. }
  2147. //-----------------------------------------------------------------------------
  2148. // This function prepares the batch for new primitive.
  2149. // Called when the runtime needs to output vertices to a TL buffer
  2150. // TL buffer grows if necessary
  2151. //
  2152. // Uses the following global variables:
  2153. // pv->dwVIDOut
  2154. // pv->dwNumVertices
  2155. // this->dp2data
  2156. // this->dwDP2VertexCount;
  2157. // this->lpDP2CurrBatchVBI
  2158. // this->dwDP2Flags
  2159. // pv->dwOutputSize
  2160. // Updates the following variables:
  2161. // this->dwVertexBase
  2162. // this->dwDP2VertexCount;
  2163. // this->lpDP2CurrBatchVBI
  2164. // dp2data.dwFlags
  2165. // Sets "within primitive" to TRUE
  2166. // Returns:
  2167. // TL buffer address
  2168. //
  2169. //
  2170. #undef DPF_MODNAME
  2171. #define DPF_MODNAME "CD3DDDIDX6::StartPrimTL"
  2172. LPVOID
  2173. CD3DDDIDX6::StartPrimTL(D3DFE_PROCESSVERTICES * pv, DWORD dwVertexPoolSize,
  2174. BOOL bWriteOnly)
  2175. {
  2176. if (bWriteOnly)
  2177. {
  2178. if (dwVertexPoolSize > this->GetTLVbufSize())
  2179. {
  2180. this->GrowTLVbuf(dwVertexPoolSize, TRUE);
  2181. }
  2182. }
  2183. else
  2184. {
  2185. if (this->dwDP2Flags & D3DDDI_TLVBUFWRITEONLY ||
  2186. dwVertexPoolSize > this->GetTLVbufSize())
  2187. {
  2188. this->GrowTLVbuf(dwVertexPoolSize, FALSE);
  2189. }
  2190. }
  2191. CVertexBuffer * lpVBI = this->TLVbuf_GetVBI();
  2192. // If VID has been changed or new vertex buffer is used we flush the batch
  2193. if (pv->dwVIDOut != dp2data.dwVertexType ||
  2194. lpDP2CurrBatchVBI != lpVBI ||
  2195. dp2data.hDDVertex != lpVBI->DriverAccessibleKernelHandle())
  2196. {
  2197. this->FlushStates();
  2198. dp2data.dwVertexType = pv->dwVIDOut;
  2199. dp2data.dwVertexSize = pv->dwOutputSize;
  2200. dp2data.hDDVertex = lpVBI->DriverAccessibleKernelHandle();
  2201. // Release previously used vertex buffer (if any), because we do not
  2202. // need it any more. We did IncrementUseCount() to TL buffer,
  2203. // so it is safe.
  2204. if (lpDP2CurrBatchVBI)
  2205. {
  2206. lpDP2CurrBatchVBI->DecrementUseCount();
  2207. }
  2208. // If a vertex buffer is used for rendering, make sure that it is not
  2209. // released by user. So do IncrementUseCount().
  2210. lpDP2CurrBatchVBI = lpVBI;
  2211. lpDP2CurrBatchVBI->IncrementUseCount();
  2212. }
  2213. SetWithinPrimitive( TRUE );
  2214. this->dwVertexBase = this->dwDP2VertexCount;
  2215. DDASSERT(this->dwVertexBase < MAX_DX6_VERTICES);
  2216. dp2data.dwFlags |= D3DHALDP2_SWAPVERTEXBUFFER;
  2217. this->dwDP2VertexCountMask = 0xFFFFFFFF;
  2218. return this->TLVbuf_GetAddress();
  2219. }
  2220. //---------------------------------------------------------------------
  2221. // This function should not be called from DrawVertexBufferVB
  2222. //
  2223. #undef DPF_MODNAME
  2224. #define DPF_MODNAME "CD3DDDIDX6::EndPrim"
  2225. void
  2226. CD3DDDIDX6::EndPrim(UINT vertexSize)
  2227. {
  2228. // Should be called before the FlushStates
  2229. SetWithinPrimitive(FALSE);
  2230. if (this->dwDP2Flags & D3DDDI_USERMEMVERTICES)
  2231. // We can not mix user memory primitive, so flush it.
  2232. {
  2233. FlushStates();
  2234. this->dwDP2Flags &= ~D3DDDI_USERMEMVERTICES;
  2235. }
  2236. else
  2237. if (lpDP2CurrBatchVBI == this->TLVbuf_GetVBI())
  2238. {
  2239. // If TL buffer was used, we have to move its internal base pointer
  2240. this->TLVbuf_Base() = this->dwDP2VertexCount * vertexSize;
  2241. #if DBG
  2242. if (this->TLVbuf_base > this->TLVbuf_size)
  2243. {
  2244. D3D_THROW(D3DERR_INVALIDCALL, "Internal error: TL buffer error");
  2245. }
  2246. #endif
  2247. }
  2248. }
  2249. //----------------------------------------------------------------------
  2250. // Growing aligned vertex buffer implementation.
  2251. //
  2252. #undef DPF_MODNAME
  2253. #define DPF_MODNAME "CD3DDDIDX6::GrowTLVbuf"
  2254. void
  2255. CD3DDDIDX6::GrowTLVbuf(DWORD growSize, BOOL bWriteOnly)
  2256. {
  2257. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  2258. DWORD dwRefCnt = 1;
  2259. // Is ref cnt of TLVbuf 1 or 2 ?
  2260. DWORD bTLVbufIsCurr = this->allocatedBuf == this->lpDP2CurrBatchVBI;
  2261. BOOL bDP2WriteOnly = (dwDP2Flags & D3DDDI_TLVBUFWRITEONLY) != 0;
  2262. // Avoid to many changes. Restrict TLVbuf to sys mem if too many changes
  2263. if (this->dwTLVbufChanges >= D3D_MAX_TLVBUF_CHANGES)
  2264. {
  2265. #if DBG
  2266. if (this->dwTLVbufChanges == D3D_MAX_TLVBUF_CHANGES)
  2267. DPF(1, "Too many changes: Limiting internal VB to sys mem.");
  2268. #endif
  2269. bWriteOnly = FALSE;
  2270. }
  2271. if (this->TLVbuf_base || (bWriteOnly != bDP2WriteOnly))
  2272. {
  2273. FlushStatesReq(growSize);
  2274. this->TLVbuf_base = 0;
  2275. }
  2276. if (growSize <= this->TLVbuf_size)
  2277. {
  2278. if (bWriteOnly == bDP2WriteOnly)
  2279. return;
  2280. else
  2281. this->dwTLVbufChanges++;
  2282. }
  2283. if (this->allocatedBuf)
  2284. {
  2285. this->allocatedBuf->DecrementUseCount();
  2286. this->allocatedBuf = NULL;
  2287. }
  2288. if (bTLVbufIsCurr)
  2289. {
  2290. if (this->lpDP2CurrBatchVBI)
  2291. this->lpDP2CurrBatchVBI->DecrementUseCount();
  2292. this->lpDP2CurrBatchVBI = NULL;
  2293. this->dp2data.lpVertices = NULL;
  2294. }
  2295. DWORD dwNumVerts = (max(growSize, TLVbuf_size) + 31) / sizeof(D3DTLVERTEX);
  2296. this->TLVbuf_size = dwNumVerts * sizeof(D3DTLVERTEX);
  2297. D3DPOOL Pool = D3DPOOL_DEFAULT;
  2298. DWORD dwUsage = D3DUSAGE_INTERNALBUFFER | D3DUSAGE_DYNAMIC;
  2299. if (bWriteOnly)
  2300. {
  2301. dwUsage |= D3DUSAGE_WRITEONLY;
  2302. dwDP2Flags |= D3DDDI_TLVBUFWRITEONLY;
  2303. }
  2304. else
  2305. {
  2306. dwDP2Flags &= ~D3DDDI_TLVBUFWRITEONLY;
  2307. }
  2308. LPDIRECT3DVERTEXBUFFER8 t;
  2309. HRESULT ret = CVertexBuffer::Create(pDevice,
  2310. this->TLVbuf_size,
  2311. dwUsage,
  2312. D3DFVF_TLVERTEX,
  2313. Pool,
  2314. REF_INTERNAL,
  2315. &t); // This should fail duirng ulta-low memory situations.
  2316. if (ret != DD_OK)
  2317. {
  2318. // We set allocatedBuf to a valid VB object since it gets dereferenced many places without
  2319. // checking for it being NULL. WE use the special "NULL" VB created at init time for just
  2320. // this purpose
  2321. allocatedBuf = m_pNullVB;
  2322. if (m_pNullVB) // We do this check because GrowTLVbuf will be called before m_pNullVB is set first time round.
  2323. {
  2324. allocatedBuf->IncrementUseCount();
  2325. // Update lpDP2CurrentBatchVBI if necessary
  2326. if (bTLVbufIsCurr)
  2327. {
  2328. lpDP2CurrBatchVBI = allocatedBuf;
  2329. lpDP2CurrBatchVBI->IncrementUseCount();
  2330. dp2data.hDDVertex = lpDP2CurrBatchVBI->DriverAccessibleKernelHandle();
  2331. }
  2332. }
  2333. this->TLVbuf_size = 0;
  2334. this->alignedBuf = NULL; // Lets see if some one tries to use this...
  2335. D3D_THROW(ret, "Could not allocate internal vertex buffer");
  2336. }
  2337. allocatedBuf = static_cast<CVertexBuffer*>(t);
  2338. ret = allocatedBuf->Lock(0, this->TLVbuf_size, (BYTE**)&alignedBuf, 0);
  2339. if (ret != DD_OK)
  2340. {
  2341. TLVbuf_size = 0;
  2342. alignedBuf = NULL; // Lets see if some one tries to use this...
  2343. D3D_THROW(ret, "Could not lock internal vertex buffer");
  2344. }
  2345. // Update lpDP2CurrentBatchVBI if necessary
  2346. if (bTLVbufIsCurr)
  2347. {
  2348. lpDP2CurrBatchVBI = allocatedBuf;
  2349. lpDP2CurrBatchVBI->IncrementUseCount();
  2350. dp2data.hDDVertex = lpDP2CurrBatchVBI->DriverAccessibleKernelHandle();
  2351. }
  2352. }
  2353. //-----------------------------------------------------------------------------
  2354. #undef DPF_MODNAME
  2355. #define DPF_MODNAME "CD3DDDIDX6::Clear"
  2356. void
  2357. CD3DDDIDX6::Clear(DWORD dwFlags, DWORD clrCount, LPD3DRECT clrRects,
  2358. D3DCOLOR dwColor, D3DVALUE dvZ, DWORD dwStencil)
  2359. {
  2360. HRESULT err;
  2361. // Flush any outstanding geometry to put framebuffer/Zbuffer in a known
  2362. // state for Clears that don't use tris (i.e. HAL Clears and Blts).
  2363. // Note this doesn't work for tiled architectures
  2364. // outside of Begin/EndScene, this will be fixed later
  2365. FlushStates();
  2366. // Clear2 HAL Callback exists
  2367. D3D8_CLEAR2DATA Clear2Data;
  2368. Clear2Data.dwhContext = m_dwhContext;
  2369. Clear2Data.dwFlags = dwFlags;
  2370. // Here I will follow the ClearData.dwFillColor convention that
  2371. // color word is raw 32bit ARGB, unadjusted for surface bit depth
  2372. Clear2Data.dwFillColor = dwColor;
  2373. // depth/stencil values both passed straight from user args
  2374. Clear2Data.dvFillDepth = dvZ;
  2375. Clear2Data.dwFillStencil= dwStencil;
  2376. Clear2Data.lpRects = clrRects;
  2377. Clear2Data.dwNumRects = clrCount;
  2378. Clear2Data.ddrval = D3D_OK;
  2379. Clear2Data.hDDS = m_pDevice->RenderTarget()->KernelHandle();
  2380. if(m_pDevice->ZBuffer() != 0)
  2381. {
  2382. Clear2Data.hDDSZ = m_pDevice->ZBuffer()->KernelHandle();
  2383. }
  2384. else
  2385. {
  2386. Clear2Data.hDDSZ = NULL;
  2387. }
  2388. err = m_pDevice->GetHalCallbacks()->Clear2(&Clear2Data);
  2389. if (err != DDHAL_DRIVER_HANDLED)
  2390. {
  2391. D3D_THROW(E_NOTIMPL, "Driver does not support Clear");
  2392. }
  2393. else if (Clear2Data.ddrval != DD_OK)
  2394. {
  2395. D3D_THROW(Clear2Data.ddrval, "Error in Clear");
  2396. }
  2397. else
  2398. return;
  2399. }
  2400. #undef DPF_MODNAME
  2401. #define DPF_MODNAME "CD3DDDIDX6::LockVB"
  2402. HRESULT __declspec(nothrow) CD3DDDIDX6::LockVB(CDriverVertexBuffer *pVB, DWORD dwFlags)
  2403. {
  2404. if(pVB->GetCachedDataPointer() == 0)
  2405. {
  2406. HRESULT hr = pVB->LockI((dwFlags & D3DLOCK_DISCARD) | D3DLOCK_NOSYSLOCK);
  2407. if(FAILED(hr))
  2408. {
  2409. DPF_ERR("Driver failed to lock a vertex buffer"
  2410. " when attempting to cache the lock.");
  2411. return hr;
  2412. }
  2413. DXGASSERT(pVB->GetCachedDataPointer() != 0);
  2414. }
  2415. else
  2416. {
  2417. DXGASSERT((dwFlags & (D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE)) == 0);
  2418. // We CANNOT use the usual Sync check here (ie Device->BatchNumber <= pVB->BatchNumber)
  2419. // since there are situations in which this condition is true, but the VB is not really
  2420. // batched at all! This is the case for instance, when StartPrimVB calls FlushStates.
  2421. // FlushStates rebatches the current VB but StartPrimVB then switches to a new one. So
  2422. // both new and old "appear" batched, but only one of them is. This would be harmless
  2423. // (as it is for textures), were it not for the fact that we call FlushStatesReq to
  2424. // swap the pointer. When we call FlushStatesReq on an unbatched VB, we pretty much
  2425. // swap a random pointer with very bad effects. This repros in the Unreal driver. (snene)
  2426. if(static_cast<CVertexBuffer*>(pVB) == lpDP2CurrBatchVBI)
  2427. {
  2428. try
  2429. {
  2430. if((dwFlags & D3DLOCK_DISCARD) != 0)
  2431. {
  2432. FlushStatesReq(pVB->GetBufferDesc()->Size);
  2433. }
  2434. else
  2435. {
  2436. FlushStates();
  2437. }
  2438. }
  2439. catch(HRESULT hr)
  2440. {
  2441. DPF_ERR("Driver failed the command batch submitted to it"
  2442. " when attempting to swap the current pointer"
  2443. " in response to D3DLOCK_DISCARDCONTENTS.");
  2444. pVB->SetCachedDataPointer(0);
  2445. return hr;
  2446. }
  2447. DXGASSERT(pVB->GetCachedDataPointer() != 0);
  2448. }
  2449. }
  2450. return D3D_OK;
  2451. }
  2452. #undef DPF_MODNAME
  2453. #define DPF_MODNAME "CD3DDDIDX6::UnlockVB"
  2454. HRESULT __declspec(nothrow) CD3DDDIDX6::UnlockVB(CDriverVertexBuffer *pVB)
  2455. {
  2456. return D3D_OK;
  2457. }
  2458. //---------------------------------------------------------------------
  2459. #undef DPF_MODNAME
  2460. #define DPF_MODNAME "CD3DDDIDX6::EndScene"
  2461. void
  2462. CD3DDDIDX6::EndScene()
  2463. {
  2464. this->dwTLVbufChanges = 0; // reset this every frame
  2465. SceneCapture(FALSE);
  2466. }
  2467. /////////////////////////////////////////////////////////////////////////////
  2468. // //
  2469. // CD3DDDIDX7 //
  2470. // //
  2471. /////////////////////////////////////////////////////////////////////////////
  2472. //-----------------------------------------------------------------------------
  2473. CD3DDDIDX7::CD3DDDIDX7() : CD3DDDIDX6()
  2474. {
  2475. m_ddiType = D3DDDITYPE_DX7;
  2476. }
  2477. //-----------------------------------------------------------------------------
  2478. CD3DDDIDX7::~CD3DDDIDX7()
  2479. {
  2480. return;
  2481. }
  2482. //-----------------------------------------------------------------------------
  2483. #undef DPF_MODNAME
  2484. #define DPF_MODNAME "CD3DDDIDX7::SetRenderTarget"
  2485. void
  2486. CD3DDDIDX7::SetRenderTarget(CBaseSurface *pTarget, CBaseSurface* pZBuffer)
  2487. {
  2488. LPD3DHAL_DP2SETRENDERTARGET pData;
  2489. pData = (LPD3DHAL_DP2SETRENDERTARGET)
  2490. GetHalBufferPointer(D3DDP2OP_SETRENDERTARGET, sizeof(*pData));
  2491. pData->hRenderTarget = pTarget->DrawPrimHandle();
  2492. if (pZBuffer)
  2493. pData->hZBuffer = pZBuffer->DrawPrimHandle();
  2494. else
  2495. pData->hZBuffer = 0;
  2496. }
  2497. //-----------------------------------------------------------------------------
  2498. #undef DPF_MODNAME
  2499. #define DPF_MODNAME "CD3DDDIDX7::TexBlt"
  2500. void
  2501. CD3DDDIDX7::TexBlt(DWORD dwDst, DWORD dwSrc,
  2502. LPPOINT p, RECTL *r)
  2503. {
  2504. if (bDP2CurrCmdOP == D3DDP2OP_TEXBLT)
  2505. { // Last instruction is a tex blt, append this one to it
  2506. if (dwDP2CommandLength + sizeof(D3DHAL_DP2TEXBLT) <= dwDP2CommandBufSize)
  2507. {
  2508. LPD3DHAL_DP2TEXBLT lpTexBlt = (LPD3DHAL_DP2TEXBLT)((LPBYTE)lpvDP2Commands +
  2509. dwDP2CommandLength + dp2data.dwCommandOffset);
  2510. lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
  2511. lpTexBlt->dwDDDestSurface = dwDst;
  2512. lpTexBlt->dwDDSrcSurface = dwSrc;
  2513. lpTexBlt->pDest = *p;
  2514. lpTexBlt->rSrc = *r;
  2515. lpTexBlt->dwFlags = 0;
  2516. dwDP2CommandLength += sizeof(D3DHAL_DP2TEXBLT);
  2517. #ifndef _IA64_
  2518. D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2519. #endif
  2520. return;
  2521. }
  2522. }
  2523. // Check for space
  2524. if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
  2525. sizeof(D3DHAL_DP2TEXBLT) > dwDP2CommandBufSize)
  2526. {
  2527. FlushStates();
  2528. }
  2529. // Add new renderstate instruction
  2530. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  2531. dwDP2CommandLength + dp2data.dwCommandOffset);
  2532. lpDP2CurrCommand->bCommand = D3DDP2OP_TEXBLT;
  2533. bDP2CurrCmdOP = D3DDP2OP_TEXBLT;
  2534. lpDP2CurrCommand->bReserved = 0;
  2535. lpDP2CurrCommand->wStateCount = 1;
  2536. wDP2CurrCmdCnt = 1;
  2537. #ifndef _IA64_
  2538. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2539. #endif
  2540. // Add texture blt data
  2541. LPD3DHAL_DP2TEXBLT lpTexBlt = (LPD3DHAL_DP2TEXBLT)(lpDP2CurrCommand + 1);
  2542. lpTexBlt->dwDDDestSurface = dwDst;
  2543. lpTexBlt->dwDDSrcSurface = dwSrc;
  2544. lpTexBlt->pDest = *p;
  2545. lpTexBlt->rSrc = *r;
  2546. lpTexBlt->dwFlags = 0;
  2547. dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2TEXBLT);
  2548. return;
  2549. }
  2550. //-----------------------------------------------------------------------------
  2551. #undef DPF_MODNAME
  2552. #define DPF_MODNAME "CD3DDDIDX7::InsertStateSetOp"
  2553. void
  2554. CD3DDDIDX7::InsertStateSetOp(DWORD dwOperation, DWORD dwParam,
  2555. D3DSTATEBLOCKTYPE sbt)
  2556. {
  2557. LPD3DHAL_DP2STATESET pData;
  2558. pData = (LPD3DHAL_DP2STATESET)GetHalBufferPointer(D3DDP2OP_STATESET,
  2559. sizeof(*pData));
  2560. pData->dwOperation = dwOperation;
  2561. pData->dwParam = dwParam;
  2562. pData->sbType = sbt;
  2563. }
  2564. //---------------------------------------------------------------------
  2565. #undef DPF_MODNAME
  2566. #define DPF_MODNAME "CD3DDDIDX7::SceneCapture"
  2567. void
  2568. CD3DDDIDX7::SceneCapture(BOOL bState)
  2569. {
  2570. SetRenderState((D3DRENDERSTATETYPE)D3DRENDERSTATE_SCENECAPTURE, bState);
  2571. }
  2572. //-----------------------------------------------------------------------------
  2573. #undef DPF_MODNAME
  2574. #define DPF_MODNAME "CD3DDDIDX7::SetPriority"
  2575. void
  2576. CD3DDDIDX7::SetPriority(CResource *pRes, DWORD dwPriority)
  2577. {
  2578. DXGASSERT(pRes->BaseDrawPrimHandle() == pRes->DriverAccessibleDrawPrimHandle());
  2579. if (bDP2CurrCmdOP == D3DDP2OP_SETPRIORITY)
  2580. { // Last instruction is a set priority, append this one to it
  2581. if (dwDP2CommandLength + sizeof(D3DHAL_DP2SETPRIORITY) <= dwDP2CommandBufSize)
  2582. {
  2583. LPD3DHAL_DP2SETPRIORITY lpSetPriority = (LPD3DHAL_DP2SETPRIORITY)((LPBYTE)lpvDP2Commands +
  2584. dwDP2CommandLength + dp2data.dwCommandOffset);
  2585. lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
  2586. lpSetPriority->dwDDSurface = pRes->BaseDrawPrimHandle();
  2587. lpSetPriority->dwPriority = dwPriority;
  2588. dwDP2CommandLength += sizeof(D3DHAL_DP2SETPRIORITY);
  2589. #ifndef _IA64_
  2590. D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2591. #endif
  2592. pRes->BatchBase();
  2593. return;
  2594. }
  2595. }
  2596. // Check for space
  2597. if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
  2598. sizeof(D3DHAL_DP2SETPRIORITY) > dwDP2CommandBufSize)
  2599. {
  2600. FlushStates();
  2601. }
  2602. // Add new setpriority instruction
  2603. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  2604. dwDP2CommandLength + dp2data.dwCommandOffset);
  2605. lpDP2CurrCommand->bCommand = D3DDP2OP_SETPRIORITY;
  2606. bDP2CurrCmdOP = D3DDP2OP_SETPRIORITY;
  2607. lpDP2CurrCommand->bReserved = 0;
  2608. lpDP2CurrCommand->wStateCount = 1;
  2609. wDP2CurrCmdCnt = 1;
  2610. #ifndef _IA64_
  2611. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2612. #endif
  2613. // Add texture blt data
  2614. LPD3DHAL_DP2SETPRIORITY lpSetPriority = (LPD3DHAL_DP2SETPRIORITY)(lpDP2CurrCommand + 1);
  2615. lpSetPriority->dwDDSurface = pRes->BaseDrawPrimHandle();
  2616. lpSetPriority->dwPriority = dwPriority;
  2617. dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2SETPRIORITY);
  2618. pRes->BatchBase();
  2619. return;
  2620. }
  2621. //-----------------------------------------------------------------------------
  2622. #undef DPF_MODNAME
  2623. #define DPF_MODNAME "CD3DDDIDX7::SetTexLOD"
  2624. void
  2625. CD3DDDIDX7::SetTexLOD(CBaseTexture *pTex, DWORD dwLOD)
  2626. {
  2627. DXGASSERT(pTex->BaseDrawPrimHandle() == pTex->DriverAccessibleDrawPrimHandle());
  2628. if (bDP2CurrCmdOP == D3DDP2OP_SETTEXLOD)
  2629. { // Last instruction is a set LOD, append this one to it
  2630. if (dwDP2CommandLength + sizeof(D3DHAL_DP2SETTEXLOD) <= dwDP2CommandBufSize)
  2631. {
  2632. LPD3DHAL_DP2SETTEXLOD lpSetTexLOD = (LPD3DHAL_DP2SETTEXLOD)((LPBYTE)lpvDP2Commands +
  2633. dwDP2CommandLength + dp2data.dwCommandOffset);
  2634. lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
  2635. lpSetTexLOD->dwDDSurface = pTex->BaseDrawPrimHandle();
  2636. lpSetTexLOD->dwLOD = dwLOD;
  2637. dwDP2CommandLength += sizeof(D3DHAL_DP2SETTEXLOD);
  2638. #ifndef _IA64_
  2639. D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2640. #endif
  2641. pTex->BatchBase();
  2642. return;
  2643. }
  2644. }
  2645. // Check for space
  2646. if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
  2647. sizeof(D3DHAL_DP2SETTEXLOD) > dwDP2CommandBufSize)
  2648. {
  2649. FlushStates();
  2650. }
  2651. // Add new set LOD instruction
  2652. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  2653. dwDP2CommandLength + dp2data.dwCommandOffset);
  2654. lpDP2CurrCommand->bCommand = D3DDP2OP_SETTEXLOD;
  2655. bDP2CurrCmdOP = D3DDP2OP_SETTEXLOD;
  2656. lpDP2CurrCommand->bReserved = 0;
  2657. lpDP2CurrCommand->wStateCount = 1;
  2658. wDP2CurrCmdCnt = 1;
  2659. #ifndef _IA64_
  2660. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2661. #endif
  2662. // Add texture blt data
  2663. LPD3DHAL_DP2SETTEXLOD lpSetTexLOD = (LPD3DHAL_DP2SETTEXLOD)(lpDP2CurrCommand + 1);
  2664. lpSetTexLOD->dwDDSurface = pTex->BaseDrawPrimHandle();
  2665. lpSetTexLOD->dwLOD = dwLOD;
  2666. dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2SETTEXLOD);
  2667. pTex->BatchBase();
  2668. return;
  2669. }
  2670. //-----------------------------------------------------------------------------
  2671. #undef DPF_MODNAME
  2672. #define DPF_MODNAME "CD3DDDIDX7::AddDirtyRect"
  2673. void
  2674. CD3DDDIDX7::AddDirtyRect(DWORD dwHandle, CONST RECTL *pRect)
  2675. {
  2676. if (bDP2CurrCmdOP == D3DDP2OP_ADDDIRTYRECT)
  2677. { // Last instruction is a adddirtyrect, append this one to it
  2678. if (dwDP2CommandLength + sizeof(D3DHAL_DP2ADDDIRTYRECT) <= dwDP2CommandBufSize)
  2679. {
  2680. LPD3DHAL_DP2ADDDIRTYRECT lpDirtyRect = (LPD3DHAL_DP2ADDDIRTYRECT)((LPBYTE)lpvDP2Commands +
  2681. dwDP2CommandLength + dp2data.dwCommandOffset);
  2682. lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
  2683. lpDirtyRect->dwSurface = dwHandle;
  2684. lpDirtyRect->rDirtyArea = *pRect;
  2685. dwDP2CommandLength += sizeof(D3DHAL_DP2ADDDIRTYRECT);
  2686. #ifndef _IA64_
  2687. D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2688. #endif
  2689. return;
  2690. }
  2691. }
  2692. // Check for space
  2693. if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
  2694. sizeof(D3DHAL_DP2ADDDIRTYRECT) > dwDP2CommandBufSize)
  2695. {
  2696. FlushStates();
  2697. }
  2698. // Add new renderstate instruction
  2699. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  2700. dwDP2CommandLength + dp2data.dwCommandOffset);
  2701. lpDP2CurrCommand->bCommand = D3DDP2OP_ADDDIRTYRECT;
  2702. bDP2CurrCmdOP = D3DDP2OP_ADDDIRTYRECT;
  2703. lpDP2CurrCommand->bReserved = 0;
  2704. lpDP2CurrCommand->wStateCount = 1;
  2705. wDP2CurrCmdCnt = 1;
  2706. #ifndef _IA64_
  2707. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2708. #endif
  2709. // Add adddirtyrect data
  2710. LPD3DHAL_DP2ADDDIRTYRECT lpDirtyRect = (LPD3DHAL_DP2ADDDIRTYRECT)(lpDP2CurrCommand + 1);
  2711. lpDirtyRect->dwSurface = dwHandle;
  2712. lpDirtyRect->rDirtyArea = *pRect;
  2713. dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2ADDDIRTYRECT);
  2714. return;
  2715. }
  2716. //-----------------------------------------------------------------------------
  2717. #undef DPF_MODNAME
  2718. #define DPF_MODNAME "CD3DDDIDX7::AddDirtyBox"
  2719. void
  2720. CD3DDDIDX7::AddDirtyBox(DWORD dwHandle, CONST D3DBOX *pBox)
  2721. {
  2722. if (bDP2CurrCmdOP == D3DDP2OP_ADDDIRTYBOX)
  2723. { // Last instruction is a adddirtybox, append this one to it
  2724. if (dwDP2CommandLength + sizeof(D3DHAL_DP2ADDDIRTYBOX) <= dwDP2CommandBufSize)
  2725. {
  2726. LPD3DHAL_DP2ADDDIRTYBOX lpDirtyBox = (LPD3DHAL_DP2ADDDIRTYBOX)((LPBYTE)lpvDP2Commands +
  2727. dwDP2CommandLength + dp2data.dwCommandOffset);
  2728. lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
  2729. lpDirtyBox->dwSurface = dwHandle;
  2730. lpDirtyBox->DirtyBox = *pBox;
  2731. dwDP2CommandLength += sizeof(D3DHAL_DP2ADDDIRTYBOX);
  2732. #ifndef _IA64_
  2733. D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2734. #endif
  2735. return;
  2736. }
  2737. }
  2738. // Check for space
  2739. if (dwDP2CommandLength + sizeof(D3DHAL_DP2COMMAND) +
  2740. sizeof(D3DHAL_DP2ADDDIRTYBOX) > dwDP2CommandBufSize)
  2741. {
  2742. FlushStates();
  2743. }
  2744. // Add new renderstate instruction
  2745. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  2746. dwDP2CommandLength + dp2data.dwCommandOffset);
  2747. lpDP2CurrCommand->bCommand = D3DDP2OP_ADDDIRTYBOX;
  2748. bDP2CurrCmdOP = D3DDP2OP_ADDDIRTYBOX;
  2749. lpDP2CurrCommand->bReserved = 0;
  2750. lpDP2CurrCommand->wStateCount = 1;
  2751. wDP2CurrCmdCnt = 1;
  2752. #ifndef _IA64_
  2753. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2754. #endif
  2755. // Add adddirtybox data
  2756. LPD3DHAL_DP2ADDDIRTYBOX lpDirtyBox = (LPD3DHAL_DP2ADDDIRTYBOX)(lpDP2CurrCommand + 1);
  2757. lpDirtyBox->dwSurface = dwHandle;
  2758. lpDirtyBox->DirtyBox = *pBox;
  2759. dwDP2CommandLength += sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2ADDDIRTYBOX);
  2760. return;
  2761. }
  2762. //-----------------------------------------------------------------------------
  2763. #undef DPF_MODNAME
  2764. #define DPF_MODNAME "CD3DDDIDX7::Clear"
  2765. void
  2766. CD3DDDIDX7::Clear(DWORD dwFlags, DWORD clrCount, LPD3DRECT clrRects,
  2767. D3DCOLOR dwColor, D3DVALUE dvZ, DWORD dwStencil)
  2768. {
  2769. DWORD dwCommandSize = sizeof(D3DHAL_DP2COMMAND) +
  2770. sizeof(D3DHAL_DP2CLEAR) + sizeof(RECT) * (clrCount - 1);
  2771. // Check to see if there is space to add a new command for space
  2772. if (dwCommandSize + dwDP2CommandLength > dwDP2CommandBufSize)
  2773. {
  2774. FlushStates();
  2775. }
  2776. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  2777. dwDP2CommandLength + dp2data.dwCommandOffset);
  2778. lpDP2CurrCommand->bCommand = D3DDP2OP_CLEAR;
  2779. bDP2CurrCmdOP = D3DDP2OP_CLEAR;
  2780. lpDP2CurrCommand->bReserved = 0;
  2781. wDP2CurrCmdCnt = (WORD)clrCount;
  2782. lpDP2CurrCommand->wStateCount = wDP2CurrCmdCnt;
  2783. #ifndef _IA64_
  2784. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2785. #endif
  2786. dwDP2CommandLength += dwCommandSize;
  2787. // Write data
  2788. LPD3DHAL_DP2CLEAR pData = (LPD3DHAL_DP2CLEAR)(lpDP2CurrCommand + 1);
  2789. pData->dwFlags = dwFlags;
  2790. pData->dwFillColor = dwColor;
  2791. pData->dvFillDepth = dvZ;
  2792. pData->dwFillStencil = dwStencil;
  2793. memcpy(pData->Rects, clrRects, clrCount * sizeof(D3DRECT));
  2794. }
  2795. //-----------------------------------------------------------------------------
  2796. // This function should be called from PaletteUpdateNotify
  2797. //
  2798. #undef DPF_MODNAME
  2799. #define DPF_MODNAME "CD3DDDIDX7::UpdatePalette"
  2800. void
  2801. CD3DDDIDX7::UpdatePalette(DWORD dwPaletteHandle,
  2802. DWORD dwStartIndex,
  2803. DWORD dwNumberOfIndices,
  2804. PALETTEENTRY *pFirstIndex)
  2805. {
  2806. DWORD dwSizeChange=sizeof(D3DHAL_DP2COMMAND) +
  2807. sizeof(D3DHAL_DP2UPDATEPALETTE) + dwNumberOfIndices*sizeof(PALETTEENTRY);
  2808. if (bDP2CurrCmdOP == D3DDP2OP_UPDATEPALETTE)
  2809. { // Last instruction is same, append this one to it
  2810. if (dwDP2CommandLength + dwSizeChange <= dwDP2CommandBufSize)
  2811. {
  2812. LPD3DHAL_DP2UPDATEPALETTE lpUpdatePal = (LPD3DHAL_DP2UPDATEPALETTE)((LPBYTE)lpvDP2Commands +
  2813. dwDP2CommandLength + dp2data.dwCommandOffset);
  2814. lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
  2815. lpUpdatePal->dwPaletteHandle=dwPaletteHandle + 1;
  2816. lpUpdatePal->wStartIndex=(WORD)dwStartIndex;
  2817. lpUpdatePal->wNumEntries=(WORD)dwNumberOfIndices;
  2818. memcpy((LPVOID)(lpUpdatePal+1),(LPVOID)pFirstIndex,
  2819. dwNumberOfIndices*sizeof(PALETTEENTRY));
  2820. dwDP2CommandLength += dwSizeChange;
  2821. #ifndef _IA64_
  2822. D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2823. #endif
  2824. return;
  2825. }
  2826. }
  2827. // Check for space
  2828. if (dwDP2CommandLength + dwSizeChange > dwDP2CommandBufSize)
  2829. {
  2830. FlushStates();
  2831. }
  2832. // Add new renderstate instruction
  2833. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  2834. dwDP2CommandLength + dp2data.dwCommandOffset);
  2835. lpDP2CurrCommand->bCommand = D3DDP2OP_UPDATEPALETTE;
  2836. bDP2CurrCmdOP = D3DDP2OP_UPDATEPALETTE;
  2837. lpDP2CurrCommand->bReserved = 0;
  2838. lpDP2CurrCommand->wStateCount = 1;
  2839. wDP2CurrCmdCnt = 1;
  2840. #ifndef _IA64_
  2841. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2842. #endif
  2843. // Add texture blt data
  2844. LPD3DHAL_DP2UPDATEPALETTE lpUpdatePal = (LPD3DHAL_DP2UPDATEPALETTE)(lpDP2CurrCommand + 1);
  2845. lpUpdatePal->dwPaletteHandle=dwPaletteHandle + 1;
  2846. lpUpdatePal->wStartIndex=(WORD)dwStartIndex;
  2847. lpUpdatePal->wNumEntries=(WORD)dwNumberOfIndices;
  2848. memcpy((LPVOID)(lpUpdatePal+1),(LPVOID)pFirstIndex,
  2849. dwNumberOfIndices*sizeof(PALETTEENTRY));
  2850. dwDP2CommandLength += dwSizeChange;
  2851. }
  2852. //-----------------------------------------------------------------------------
  2853. // This function should be called from PaletteAssociateNotify
  2854. //
  2855. #undef DPF_MODNAME
  2856. #define DPF_MODNAME "CD3DDDIDX7::SetPalette"
  2857. void
  2858. CD3DDDIDX7::SetPalette(DWORD dwPaletteHandle,
  2859. DWORD dwPaletteFlags,
  2860. CBaseTexture *pTex )
  2861. {
  2862. if (pTex->IsD3DManaged())
  2863. {
  2864. if (!m_pDevice->ResourceManager()->InVidmem(pTex->RMHandle()))
  2865. {
  2866. // We will hit this return ONLY
  2867. // when for some reason promoting
  2868. // pTex to vidmem failed.
  2869. return;
  2870. }
  2871. }
  2872. pTex->SetPalette(dwPaletteHandle);
  2873. DWORD dwSizeChange=sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2SETPALETTE);
  2874. if (bDP2CurrCmdOP == D3DDP2OP_SETPALETTE)
  2875. { // Last instruction is a tex blt, append this one to it
  2876. if (dwDP2CommandLength + dwSizeChange <= dwDP2CommandBufSize)
  2877. {
  2878. LPD3DHAL_DP2SETPALETTE lpSetPal = (LPD3DHAL_DP2SETPALETTE)((LPBYTE)lpvDP2Commands +
  2879. dwDP2CommandLength + dp2data.dwCommandOffset);
  2880. lpDP2CurrCommand->wStateCount = ++wDP2CurrCmdCnt;
  2881. lpSetPal->dwPaletteHandle=dwPaletteHandle + 1;
  2882. lpSetPal->dwPaletteFlags=dwPaletteFlags;
  2883. lpSetPal->dwSurfaceHandle=pTex->DriverAccessibleDrawPrimHandle();
  2884. dwDP2CommandLength += dwSizeChange;
  2885. #ifndef _IA64_
  2886. D3D_INFO(6, "Modify Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2887. #endif
  2888. pTex->Batch();
  2889. return;
  2890. }
  2891. }
  2892. // Check for space
  2893. if (dwDP2CommandLength + dwSizeChange > dwDP2CommandBufSize)
  2894. {
  2895. FlushStates();
  2896. }
  2897. // Add new renderstate instruction
  2898. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  2899. dwDP2CommandLength + dp2data.dwCommandOffset);
  2900. lpDP2CurrCommand->bCommand = D3DDP2OP_SETPALETTE;
  2901. bDP2CurrCmdOP = D3DDP2OP_SETPALETTE;
  2902. lpDP2CurrCommand->bReserved = 0;
  2903. lpDP2CurrCommand->wStateCount = 1;
  2904. wDP2CurrCmdCnt = 1;
  2905. #ifndef _IA64_
  2906. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2907. #endif
  2908. LPD3DHAL_DP2SETPALETTE lpSetPal = (LPD3DHAL_DP2SETPALETTE)(lpDP2CurrCommand + 1);
  2909. lpSetPal->dwPaletteHandle=dwPaletteHandle + 1;
  2910. lpSetPal->dwPaletteFlags=dwPaletteFlags;
  2911. lpSetPal->dwSurfaceHandle=pTex->DriverAccessibleDrawPrimHandle();
  2912. dwDP2CommandLength += dwSizeChange;
  2913. pTex->Batch();
  2914. return;
  2915. }
  2916. //-----------------------------------------------------------------------------
  2917. #undef DPF_MODNAME
  2918. #define DPF_MODNAME "CD3DDDIDX7::WriteStateSetToDevice"
  2919. void
  2920. CD3DDDIDX7::WriteStateSetToDevice(D3DSTATEBLOCKTYPE sbt)
  2921. {
  2922. DWORD dwDeviceHandle;
  2923. LPVOID pBuffer;
  2924. DWORD dwBufferSize;
  2925. m_pDevice->m_pStateSets->GetDeviceBufferInfo(&dwDeviceHandle, &pBuffer,
  2926. &dwBufferSize);
  2927. // If device buffer is empty we do not create the set state macro in the device
  2928. if (dwBufferSize == 0)
  2929. return;
  2930. DWORD dwByteCount = dwBufferSize + (sizeof(D3DHAL_DP2STATESET) +
  2931. sizeof(D3DHAL_DP2COMMAND)) * 2;
  2932. // Check to see if there is space to add a new command for space
  2933. if (dwByteCount + dwDP2CommandLength > dwDP2CommandBufSize)
  2934. {
  2935. // Request the driver to grow the command buffer upon flush
  2936. FlushStatesCmdBufReq(dwByteCount);
  2937. // Check if the driver did give us what we need or do it ourselves
  2938. GrowCommandBuffer(dwByteCount);
  2939. }
  2940. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)lpvDP2Commands +
  2941. dwDP2CommandLength + dp2data.dwCommandOffset);
  2942. lpDP2CurrCommand->bCommand = D3DDP2OP_STATESET;
  2943. lpDP2CurrCommand->bReserved = 0;
  2944. lpDP2CurrCommand->wStateCount = 1;
  2945. LPD3DHAL_DP2STATESET pData = (LPD3DHAL_DP2STATESET)(lpDP2CurrCommand + 1);
  2946. pData->dwOperation = D3DHAL_STATESETBEGIN;
  2947. pData->dwParam = dwDeviceHandle;
  2948. pData->sbType = sbt;
  2949. #ifndef _IA64_
  2950. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2951. #endif
  2952. // Copy the entire state macro to the DP2 buffer
  2953. memcpy(pData + 1, pBuffer, dwBufferSize);
  2954. if (m_ddiType < D3DDDITYPE_DX8)
  2955. {
  2956. // Translate buffer content to DX7 DDI
  2957. m_pDevice->m_pStateSets->TranslateDeviceBufferToDX7DDI( (DWORD*)(pData + 1), dwBufferSize );
  2958. }
  2959. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)((LPBYTE)(pData + 1) + dwBufferSize);
  2960. lpDP2CurrCommand->bCommand = D3DDP2OP_STATESET;
  2961. lpDP2CurrCommand->bReserved = 0;
  2962. lpDP2CurrCommand->wStateCount = 1;
  2963. pData = (LPD3DHAL_DP2STATESET)(lpDP2CurrCommand + 1);
  2964. pData->dwOperation = D3DHAL_STATESETEND;
  2965. pData->dwParam = dwDeviceHandle;
  2966. pData->sbType = sbt;
  2967. #ifndef _IA64_
  2968. D3D_INFO(6, "Write Ins:%08lx", *(LPDWORD)lpDP2CurrCommand);
  2969. #endif
  2970. dwDP2CommandLength += dwByteCount;
  2971. FlushStates();
  2972. }
  2973. /////////////////////////////////////////////////////////////////////////////
  2974. // //
  2975. // CD3DDDITL //
  2976. // //
  2977. /////////////////////////////////////////////////////////////////////////////
  2978. CD3DDDITL::CD3DDDITL() : CD3DDDIDX7()
  2979. {
  2980. m_ddiType = D3DDDITYPE_DX7TL;
  2981. }
  2982. CD3DDDITL::~CD3DDDITL()
  2983. {
  2984. return;
  2985. }
  2986. //-----------------------------------------------------------------------------
  2987. #undef DPF_MODNAME
  2988. #define DPF_MODNAME "CD3DDDITL::SetTransform"
  2989. void
  2990. CD3DDDITL::SetTransform(D3DTRANSFORMSTATETYPE state, CONST D3DMATRIX* lpMat)
  2991. {
  2992. // Do mapping between new world matrix states and the old ones
  2993. if ((DWORD)state >= __WORLDMATRIXBASE &&
  2994. (DWORD)state < (__WORLDMATRIXBASE + __MAXWORLDMATRICES))
  2995. {
  2996. // World matrix is set
  2997. UINT index = (DWORD)state - __WORLDMATRIXBASE;
  2998. switch (index)
  2999. {
  3000. case 0 : state = (D3DTRANSFORMSTATETYPE)D3DTRANSFORMSTATE_WORLD_DX7; break;
  3001. case 1 : state = (D3DTRANSFORMSTATETYPE)D3DTRANSFORMSTATE_WORLD1_DX7; break;
  3002. case 2 : state = (D3DTRANSFORMSTATETYPE)D3DTRANSFORMSTATE_WORLD2_DX7; break;
  3003. case 3 : state = (D3DTRANSFORMSTATETYPE)D3DTRANSFORMSTATE_WORLD3_DX7; break;
  3004. default : return; // State is not supported
  3005. }
  3006. }
  3007. // Send down the state and the matrix
  3008. LPD3DHAL_DP2SETTRANSFORM pData;
  3009. pData = (LPD3DHAL_DP2SETTRANSFORM)
  3010. GetHalBufferPointer(D3DDP2OP_SETTRANSFORM, sizeof(*pData));
  3011. pData->xfrmType = state;
  3012. pData->matrix = *lpMat;
  3013. // Update W info in case of projection matrix
  3014. if (state == D3DTRANSFORMSTATE_PROJECTION)
  3015. CD3DDDIDX6::SetTransform(state, lpMat);
  3016. }
  3017. //-----------------------------------------------------------------------------
  3018. #undef DPF_MODNAME
  3019. #define DPF_MODNAME "CD3DDDITL::SetViewport"
  3020. void
  3021. CD3DDDITL::SetViewport(CONST D3DVIEWPORT8* lpVwpData)
  3022. {
  3023. // Update viewport size
  3024. CD3DDDIDX6::SetViewport(lpVwpData);
  3025. // Update Z range
  3026. LPD3DHAL_DP2ZRANGE pData;
  3027. pData = (LPD3DHAL_DP2ZRANGE)GetHalBufferPointer(D3DDP2OP_ZRANGE, sizeof(*pData));
  3028. pData->dvMinZ = lpVwpData->MinZ;
  3029. pData->dvMaxZ = lpVwpData->MaxZ;
  3030. }
  3031. //-----------------------------------------------------------------------------
  3032. // This function is called whe software vertex processing is used
  3033. // Handle should be always legacy
  3034. //
  3035. #undef DPF_MODNAME
  3036. #define DPF_MODNAME "CD3DDDITL::SetVertexShader"
  3037. void CD3DDDITL::SetVertexShader(DWORD dwHandle)
  3038. {
  3039. DXGASSERT(D3DVSD_ISLEGACY(dwHandle));
  3040. // Pre-DX8 drivers should not recieve D3DFVF_LASTBETA_UBYTE4 bit
  3041. m_CurrentVertexShader = dwHandle & ~D3DFVF_LASTBETA_UBYTE4;
  3042. #if DBG
  3043. m_VertexSizeFromShader = ComputeVertexSizeFVF(dwHandle);
  3044. #endif
  3045. }
  3046. //-----------------------------------------------------------------------------
  3047. // This function is called whe hardware vertex processing is used
  3048. // Redundant shader check has been done at the API level
  3049. //
  3050. #undef DPF_MODNAME
  3051. #define DPF_MODNAME "CD3DDDITL::SetVertexShaderHW"
  3052. void CD3DDDITL::SetVertexShaderHW(DWORD dwHandle)
  3053. {
  3054. if( D3DVSD_ISLEGACY(dwHandle) )
  3055. {
  3056. // Pre-DX8 drivers should not recieve D3DFVF_LASTBETA_UBYTE4 bit
  3057. m_CurrentVertexShader = dwHandle & ~D3DFVF_LASTBETA_UBYTE4;
  3058. }
  3059. else
  3060. {
  3061. CVShader* pShader =
  3062. (CVShader*)m_pDevice->m_pVShaderArray->GetObject(dwHandle);
  3063. if( pShader == NULL )
  3064. {
  3065. D3D_THROW( D3DERR_INVALIDCALL,
  3066. "Bad handle passed to SetVertexShader DDI" )
  3067. }
  3068. if( pShader->m_Declaration.m_bLegacyFVF == FALSE )
  3069. {
  3070. D3D_THROW( D3DERR_INVALIDCALL, "Declaration is too complex for "
  3071. "the Driver to handle." );
  3072. }
  3073. else
  3074. {
  3075. m_CurrentVertexShader = pShader->m_Declaration.m_dwInputFVF;
  3076. }
  3077. }
  3078. #if DBG
  3079. m_VertexSizeFromShader = ComputeVertexSizeFVF(m_CurrentVertexShader);
  3080. #endif
  3081. }
  3082. //-----------------------------------------------------------------------------
  3083. #undef DPF_MODNAME
  3084. #define DPF_MODNAME "CD3DDDITL::SetMaterial"
  3085. void
  3086. CD3DDDITL::SetMaterial(CONST D3DMATERIAL8* pMat)
  3087. {
  3088. LPD3DHAL_DP2SETMATERIAL pData;
  3089. pData = (LPD3DHAL_DP2SETMATERIAL)GetHalBufferPointer(D3DDP2OP_SETMATERIAL, sizeof(*pData));
  3090. *pData = *((LPD3DHAL_DP2SETMATERIAL)pMat);
  3091. }
  3092. //-----------------------------------------------------------------------------
  3093. #undef DPF_MODNAME
  3094. #define DPF_MODNAME "CD3DDDITL::SetLight"
  3095. void
  3096. CD3DDDITL::SetLight(DWORD dwLightIndex, CONST D3DLIGHT8* pLight)
  3097. {
  3098. LPD3DHAL_DP2SETLIGHT pData;
  3099. pData = (LPD3DHAL_DP2SETLIGHT)
  3100. GetHalBufferPointer(D3DDP2OP_SETLIGHT,
  3101. sizeof(*pData) + sizeof(D3DLIGHT8));
  3102. pData->dwIndex = dwLightIndex;
  3103. pData->dwDataType = D3DHAL_SETLIGHT_DATA;
  3104. D3DLIGHT8* p = (D3DLIGHT8*)((LPBYTE)pData + sizeof(D3DHAL_DP2SETLIGHT));
  3105. *p = *pLight;
  3106. }
  3107. //-----------------------------------------------------------------------------
  3108. #undef DPF_MODNAME
  3109. #define DPF_MODNAME "CD3DDDITL::CreateLight"
  3110. void
  3111. CD3DDDITL::CreateLight(DWORD dwLightIndex)
  3112. {
  3113. LPD3DHAL_DP2CREATELIGHT pData;
  3114. pData = (LPD3DHAL_DP2CREATELIGHT)GetHalBufferPointer(D3DDP2OP_CREATELIGHT, sizeof(*pData));
  3115. pData->dwIndex = dwLightIndex;
  3116. }
  3117. //-----------------------------------------------------------------------------
  3118. #undef DPF_MODNAME
  3119. #define DPF_MODNAME "CD3DDDITL::LightEnable"
  3120. void
  3121. CD3DDDITL::LightEnable(DWORD dwLightIndex, BOOL bEnable)
  3122. {
  3123. LPD3DHAL_DP2SETLIGHT pData;
  3124. pData = (LPD3DHAL_DP2SETLIGHT)GetHalBufferPointer(D3DDP2OP_SETLIGHT, sizeof(*pData));
  3125. pData->dwIndex = dwLightIndex;
  3126. if (bEnable)
  3127. pData->dwDataType = D3DHAL_SETLIGHT_ENABLE;
  3128. else
  3129. pData->dwDataType = D3DHAL_SETLIGHT_DISABLE;
  3130. }
  3131. //-----------------------------------------------------------------------------
  3132. #undef DPF_MODNAME
  3133. #define DPF_MODNAME "CD3DDDITL::SetClipPlane"
  3134. void
  3135. CD3DDDITL::SetClipPlane(DWORD dwPlaneIndex, CONST D3DVALUE* pPlaneEquation)
  3136. {
  3137. LPD3DHAL_DP2SETCLIPPLANE pData;
  3138. pData = (LPD3DHAL_DP2SETCLIPPLANE)
  3139. GetHalBufferPointer(D3DDP2OP_SETCLIPPLANE, sizeof(*pData));
  3140. pData->dwIndex = dwPlaneIndex;
  3141. pData->plane[0] = pPlaneEquation[0];
  3142. pData->plane[1] = pPlaneEquation[1];
  3143. pData->plane[2] = pPlaneEquation[2];
  3144. pData->plane[3] = pPlaneEquation[3];
  3145. }
  3146. //-----------------------------------------------------------------------------
  3147. #undef DPF_MODNAME
  3148. #define DPF_MODNAME "CD3DDDITL::CreateVertexShader"
  3149. void
  3150. CD3DDDITL::CreateVertexShader(CONST DWORD* pdwDeclaration,
  3151. DWORD dwDeclarationSize,
  3152. CONST DWORD* pdwFunction,
  3153. DWORD dwFunctionSize,
  3154. DWORD dwHandle,
  3155. BOOL bLegacyFVF)
  3156. {
  3157. if( bLegacyFVF == FALSE )
  3158. {
  3159. D3D_THROW(D3DERR_INVALIDCALL,
  3160. "The declaration is too complex for the driver to handle");
  3161. }
  3162. }
  3163. //-----------------------------------------------------------------------------
  3164. // Allocates space for the internal clip buffer and sets lpClipFlags pointer
  3165. //
  3166. #undef DPF_MODNAME
  3167. #define DPF_MODNAME "CD3DDDIDX6::PrepareForClipping"
  3168. void
  3169. CD3DDDIDX6::PrepareForClipping(D3DFE_PROCESSVERTICES* pv, UINT StartVertex)
  3170. {
  3171. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  3172. if (!(pv->dwDeviceFlags & D3DDEV_VBPROCVER))
  3173. {
  3174. // Grow clip flags buffer if we need clipping
  3175. DWORD size = pv->dwNumVertices * sizeof(D3DFE_CLIPCODE);
  3176. if (size > pDevice->HVbuf.GetSize())
  3177. {
  3178. if (pDevice->HVbuf.Grow(size) != D3D_OK)
  3179. {
  3180. D3D_THROW(E_OUTOFMEMORY, "Could not grow clip buffer" );
  3181. }
  3182. }
  3183. pv->lpClipFlags = (D3DFE_CLIPCODE*)pDevice->HVbuf.GetAddress();
  3184. }
  3185. else
  3186. {
  3187. // For vertex buffers, which are destination for ProcessVertices
  3188. // clip buffer is already computed
  3189. pv->lpClipFlags = pDevice->m_pStream[0].m_pVB->GetClipCodes();
  3190. #if DBG
  3191. if (pv->lpClipFlags == NULL)
  3192. {
  3193. D3D_THROW_FAIL("Clip codes are not computed for the vertex buffer");
  3194. }
  3195. #endif
  3196. pv->dwClipUnion = 0xFFFFFFFF; // Force clipping
  3197. pv->lpClipFlags += StartVertex;
  3198. }
  3199. }
  3200. //-----------------------------------------------------------------------------
  3201. // Point sprites are drawn as indexed triangle list
  3202. //
  3203. #undef DPF_MODNAME
  3204. #define DPF_MODNAME "CD3DDDIDX6::StartPointSprites"
  3205. void CD3DDDIDX6::StartPointSprites()
  3206. {
  3207. D3DFE_PROCESSVERTICES* pv = static_cast<CD3DHal*>(m_pDevice)->m_pv;
  3208. if(m_pDevice->m_dwRuntimeFlags & D3DRT_NEED_TEXTURE_UPDATE)
  3209. {
  3210. m_pDevice->UpdateTextures();
  3211. m_pDevice->m_dwRuntimeFlags &= ~D3DRT_NEED_TEXTURE_UPDATE;
  3212. }
  3213. // Reserve place for the output vertices
  3214. const UINT size = NUM_SPRITES_IN_BATCH * 4 * m_dwOutputSizePS;
  3215. // We may have a different vertex type for point sprites
  3216. DWORD tmpFVF = pv->dwVIDOut;
  3217. pv->dwVIDOut = m_dwVIDOutPS;
  3218. // For StartPrimTL we should use vertex size, which will go to the driver
  3219. DWORD tmpVertexSize = pv->dwOutputSize;
  3220. pv->dwOutputSize = m_dwOutputSizePS;
  3221. m_pCurSpriteVertex = (BYTE*)StartPrimTL(pv, size, TRUE);
  3222. // Restore vertex size, which is size before point sprite emulation
  3223. pv->dwOutputSize = tmpVertexSize;
  3224. // Vertex base and vertex count could be changed during clipping
  3225. // So we save them here and use in the EndPointSprites
  3226. m_dwVertexBasePS = this->dwVertexBase;
  3227. m_dwVertexCountPS = this->dwDP2VertexCount;
  3228. // Continue processing with the original FVF
  3229. pv->dwVIDOut = tmpFVF;
  3230. // Reserve place for indices
  3231. UINT count = NUM_SPRITES_IN_BATCH * 2 * 6;
  3232. // We change lpDP2CurrCommand here, so to prevent combining multiple driver
  3233. // calls to one token in case when all points are off screen, we clear
  3234. // bDP2CurrCmdOP.
  3235. bDP2CurrCmdOP = 0;
  3236. lpDP2CurrCommand = (LPD3DHAL_DP2COMMAND)ReserveSpaceInCommandBuffer(count);
  3237. m_pCurPointSpriteIndex = (WORD*)((BYTE*)(lpDP2CurrCommand + 1) +
  3238. sizeof(D3DHAL_DP2STARTVERTEX));
  3239. m_CurNumberOfSprites = 0;
  3240. ((LPD3DHAL_DP2STARTVERTEX)(lpDP2CurrCommand+1))->wVStart = (WORD)this->dwVertexBase;
  3241. SetWithinPrimitive(TRUE);
  3242. }
  3243. //-----------------------------------------------------------------------------
  3244. #undef DPF_MODNAME
  3245. #define DPF_MODNAME "CD3DDDIDX6::NextSprite"
  3246. void CD3DDDIDX6::NextSprite(float x, float y, float z, float w, DWORD diffuse,
  3247. DWORD specular, float* pTexture, UINT TextureSize,
  3248. float PointSize)
  3249. {
  3250. D3DFE_PROCESSVERTICES* pv = static_cast<CD3DHal*>(m_pDevice)->m_pv;
  3251. BOOL bTexGen = pv->lpdwRStates[D3DRS_POINTSPRITEENABLE] != 0;
  3252. if (m_CurNumberOfSprites >= NUM_SPRITES_IN_BATCH)
  3253. {
  3254. EndPointSprites();
  3255. StartPointSprites();
  3256. }
  3257. // Compute point size
  3258. PointSize = PointSize * 0.5f;
  3259. // Build sprite vertices
  3260. BYTE* v1 = m_pCurSpriteVertex;
  3261. BYTE* v2 = m_pCurSpriteVertex + m_dwOutputSizePS;
  3262. BYTE* v3 = m_pCurSpriteVertex + m_dwOutputSizePS * 2;
  3263. BYTE* v4 = m_pCurSpriteVertex + m_dwOutputSizePS * 3;
  3264. float x1, y1, x2, y2, x3, y3, x4, y4;
  3265. x1 = x - PointSize;
  3266. y1 = y - PointSize;
  3267. x2 = x + PointSize;
  3268. y2 = y + PointSize;
  3269. float tx1 = 0; // Interpolation coefficient at left plane
  3270. float tx2 = 1; // Interpolation coefficient at right plane
  3271. float ty1 = 0; // Interpolation coefficient at top plane
  3272. float ty2 = 1; // Interpolation coefficient at bottom plane
  3273. if (pv->dwDeviceFlags & D3DDEV_DONOTCLIP)
  3274. {
  3275. ((D3DVECTORH*)v1)->x = x1;
  3276. ((D3DVECTORH*)v1)->y = y1;
  3277. ((D3DVECTORH*)v1)->z = z;
  3278. ((D3DVECTORH*)v1)->w = w;
  3279. ((D3DVECTORH*)v2)->x = x2;
  3280. ((D3DVECTORH*)v2)->y = y1;
  3281. ((D3DVECTORH*)v2)->z = z;
  3282. ((D3DVECTORH*)v2)->w = w;
  3283. ((D3DVECTORH*)v3)->x = x2;
  3284. ((D3DVECTORH*)v3)->y = y2;
  3285. ((D3DVECTORH*)v3)->z = z;
  3286. ((D3DVECTORH*)v3)->w = w;
  3287. ((D3DVECTORH*)v4)->x = x1;
  3288. ((D3DVECTORH*)v4)->y = y2;
  3289. ((D3DVECTORH*)v4)->z = z;
  3290. ((D3DVECTORH*)v4)->w = w;
  3291. }
  3292. else
  3293. {// Do clipping
  3294. // new x and y
  3295. float xnew1 = x1, xnew2 = x2;
  3296. float ynew1 = y1, ynew2 = y2;
  3297. if (x1 < pv->vcache.minX)
  3298. if (x2 < pv->vcache.minX)
  3299. return;
  3300. else
  3301. {
  3302. xnew1 = pv->vcache.minX;
  3303. if (bTexGen)
  3304. tx1 = (xnew1 - x1) / (x2 - x1);
  3305. }
  3306. else
  3307. if (x2 > pv->vcache.maxX)
  3308. if (x1 > pv->vcache.maxX)
  3309. return;
  3310. else
  3311. {
  3312. xnew2 = pv->vcache.maxX;
  3313. if (bTexGen)
  3314. tx2 = (xnew2 - x1) / (x2 - x1);
  3315. }
  3316. if (y1 < pv->vcache.minY)
  3317. if (y2 < pv->vcache.minY)
  3318. return;
  3319. else
  3320. {
  3321. ynew1 = pv->vcache.minY;
  3322. if (bTexGen)
  3323. ty1 = (ynew1 - y1) / (y2 - y1);
  3324. }
  3325. else
  3326. if (y2 > pv->vcache.maxY)
  3327. if (y1 > pv->vcache.maxY)
  3328. return;
  3329. else
  3330. {
  3331. ynew2 = pv->vcache.maxY;
  3332. if (bTexGen)
  3333. ty2 = (ynew2 - y1) / (y2 - y1);
  3334. }
  3335. ((D3DVECTORH*)v1)->x = xnew1;
  3336. ((D3DVECTORH*)v1)->y = ynew1;
  3337. ((D3DVECTORH*)v1)->z = z;
  3338. ((D3DVECTORH*)v1)->w = w;
  3339. ((D3DVECTORH*)v2)->x = xnew2;
  3340. ((D3DVECTORH*)v2)->y = ynew1;
  3341. ((D3DVECTORH*)v2)->z = z;
  3342. ((D3DVECTORH*)v2)->w = w;
  3343. ((D3DVECTORH*)v3)->x = xnew2;
  3344. ((D3DVECTORH*)v3)->y = ynew2;
  3345. ((D3DVECTORH*)v3)->z = z;
  3346. ((D3DVECTORH*)v3)->w = w;
  3347. ((D3DVECTORH*)v4)->x = xnew1;
  3348. ((D3DVECTORH*)v4)->y = ynew2;
  3349. ((D3DVECTORH*)v4)->z = z;
  3350. ((D3DVECTORH*)v4)->w = w;
  3351. }
  3352. UINT offset = 4*4;
  3353. if (m_dwVIDOutPS & D3DFVF_DIFFUSE)
  3354. {
  3355. *(DWORD*)(v1 + offset) = diffuse;
  3356. *(DWORD*)(v2 + offset) = diffuse;
  3357. *(DWORD*)(v3 + offset) = diffuse;
  3358. *(DWORD*)(v4 + offset) = diffuse;
  3359. offset += 4;
  3360. }
  3361. if (m_dwVIDOutPS & D3DFVF_SPECULAR)
  3362. {
  3363. *(DWORD*)(v1 + offset) = specular;
  3364. *(DWORD*)(v2 + offset) = specular;
  3365. *(DWORD*)(v3 + offset) = specular;
  3366. *(DWORD*)(v4 + offset) = specular;
  3367. offset += 4;
  3368. }
  3369. if (bTexGen)
  3370. {
  3371. ((float*)(v1 + offset))[0] = tx1;
  3372. ((float*)(v1 + offset))[1] = ty1;
  3373. ((float*)(v2 + offset))[0] = tx2;
  3374. ((float*)(v2 + offset))[1] = ty1;
  3375. ((float*)(v3 + offset))[0] = tx2;
  3376. ((float*)(v3 + offset))[1] = ty2;
  3377. ((float*)(v4 + offset))[0] = tx1;
  3378. ((float*)(v4 + offset))[1] = ty2;
  3379. }
  3380. else
  3381. {
  3382. // Copy input texture coordinates
  3383. memcpy(v1 + offset, pTexture, TextureSize);
  3384. memcpy(v2 + offset, pTexture, TextureSize);
  3385. memcpy(v3 + offset, pTexture, TextureSize);
  3386. memcpy(v4 + offset, pTexture, TextureSize);
  3387. }
  3388. m_pCurSpriteVertex = v4 + m_dwOutputSizePS;
  3389. // Output indices for 2 triangles
  3390. WORD index = m_CurNumberOfSprites << 2;
  3391. m_pCurPointSpriteIndex[0] = index;
  3392. m_pCurPointSpriteIndex[1] = index + 1;
  3393. m_pCurPointSpriteIndex[2] = index + 2;
  3394. m_pCurPointSpriteIndex[3] = index;
  3395. m_pCurPointSpriteIndex[4] = index + 2;
  3396. m_pCurPointSpriteIndex[5] = index + 3;
  3397. m_pCurPointSpriteIndex += 6;
  3398. m_CurNumberOfSprites++;
  3399. }
  3400. //-----------------------------------------------------------------------------
  3401. #undef DPF_MODNAME
  3402. #define DPF_MODNAME "CD3DDDIDX6::EndPointSprites"
  3403. void CD3DDDIDX6::EndPointSprites()
  3404. {
  3405. if (m_CurNumberOfSprites)
  3406. {
  3407. dwDP2CommandLength += (DWORD) ((BYTE*)this->m_pCurPointSpriteIndex -
  3408. (BYTE*)this->lpDP2CurrCommand);
  3409. this->lpDP2CurrCommand->bCommand = D3DDP2OP_INDEXEDTRIANGLELIST2;
  3410. this->bDP2CurrCmdOP = D3DDP2OP_INDEXEDTRIANGLELIST2;
  3411. this->lpDP2CurrCommand->bReserved = 0;
  3412. this->lpDP2CurrCommand->wPrimitiveCount = m_CurNumberOfSprites * 2;
  3413. #if DBG
  3414. if (m_bValidateCommands)
  3415. ValidateCommand(this->lpDP2CurrCommand);
  3416. #endif
  3417. UINT vertexCount = m_CurNumberOfSprites << 2;
  3418. this->dwVertexBase = m_dwVertexBasePS + vertexCount;
  3419. this->dwDP2VertexCount = m_dwVertexCountPS + vertexCount;
  3420. EndPrim(m_dwOutputSizePS);
  3421. m_CurNumberOfSprites = 0;
  3422. }
  3423. else
  3424. {
  3425. // We need to restore dwVertexBase and dwDP2VertexCount, because
  3426. // they could be changed during clipping of transformed vertices.
  3427. // But they should reflect position in TL buffer, not in user buffer
  3428. this->dwVertexBase = m_dwVertexBasePS;
  3429. this->dwDP2VertexCount = m_dwVertexCountPS;
  3430. EndPrim(m_dwOutputSizePS);
  3431. }
  3432. SetWithinPrimitive(FALSE);
  3433. }
  3434. //-----------------------------------------------------------------------------
  3435. #undef DPF_MODNAME
  3436. #define DPF_MODNAME "CD3DDDIDX6::UpdatePalette"
  3437. void CD3DDDIDX6::UpdatePalette(DWORD dwPaletteHandle,
  3438. DWORD dwStartIndex,
  3439. DWORD dwNumberOfIndices,
  3440. PALETTEENTRY *pFirstIndex)
  3441. {
  3442. D3D8_UPDATEPALETTEDATA Data;
  3443. Data.hDD = m_pDevice->GetHandle();
  3444. Data.Palette = dwPaletteHandle;
  3445. Data.ColorTable = pFirstIndex;
  3446. Data.ddRVal = S_OK;
  3447. HRESULT ret = m_pDevice->GetHalCallbacks()->UpdatePalette(&Data);
  3448. if (ret != DDHAL_DRIVER_HANDLED || Data.ddRVal != S_OK)
  3449. {
  3450. D3D_ERR( "Driver failed UpdatePalette call" );
  3451. throw D3DERR_INVALIDCALL;
  3452. }
  3453. }
  3454. //-----------------------------------------------------------------------------
  3455. #undef DPF_MODNAME
  3456. #define DPF_MODNAME "CD3DDDIDX6::SetPalette"
  3457. void CD3DDDIDX6::SetPalette(DWORD dwPaletteHandle,
  3458. DWORD dwPaletteFlags,
  3459. CBaseTexture *pTex)
  3460. {
  3461. if (pTex->IsD3DManaged())
  3462. {
  3463. if (!m_pDevice->ResourceManager()->InVidmem(pTex->RMHandle()))
  3464. {
  3465. // We will hit this return ONLY
  3466. // when for some reason promoting
  3467. // pTex to vidmem failed.
  3468. return;
  3469. }
  3470. }
  3471. D3D8_SETPALETTEDATA Data;
  3472. Data.hDD = m_pDevice->GetHandle();
  3473. Data.hSurface = pTex->DriverAccessibleKernelHandle();
  3474. Data.Palette = dwPaletteHandle;
  3475. Data.ddRVal = S_OK;
  3476. HRESULT ret = m_pDevice->GetHalCallbacks()->SetPalette(&Data);
  3477. if (ret != DDHAL_DRIVER_HANDLED || Data.ddRVal != S_OK)
  3478. {
  3479. D3D_ERR( "Driver failed SetPalette call" );
  3480. throw D3DERR_INVALIDCALL;
  3481. }
  3482. pTex->SetPalette(dwPaletteHandle);
  3483. }
  3484. //-----------------------------------------------------------------------------
  3485. #if DBG
  3486. #undef DPF_MODNAME
  3487. #define DPF_MODNAME "CD3DDDIDX6::ValidateVertex"
  3488. void CD3DDDIDX6::ValidateVertex(LPDWORD lpdwVertex)
  3489. {
  3490. D3DFE_PROCESSVERTICES* pv = static_cast<CD3DHal*>(m_pDevice)->m_pv;
  3491. DWORD dwFVF = pv->dwVIDOut;
  3492. CD3DHal* pDevice = static_cast<CD3DHal*>(m_pDevice);
  3493. if (FVF_TRANSFORMED(dwFVF))
  3494. {
  3495. float left, right, top, bottom;
  3496. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  3497. {
  3498. left = pv->vcache.minXgb;
  3499. right = pv->vcache.maxXgb;
  3500. top = pv->vcache.minYgb;
  3501. bottom = pv->vcache.maxYgb;
  3502. }
  3503. else
  3504. {
  3505. left = (float)pDevice->m_Viewport.X;
  3506. top = (float)pDevice->m_Viewport.Y;
  3507. right = (float)pDevice->m_Viewport.X + pDevice->m_Viewport.Width;
  3508. bottom = (float)pDevice->m_Viewport.Y + pDevice->m_Viewport.Height;
  3509. }
  3510. float x = ((float*)lpdwVertex)[0];
  3511. float y = ((float*)lpdwVertex)[1];
  3512. float z = ((float*)lpdwVertex)[2];
  3513. float w = ((float*)lpdwVertex)[3];
  3514. if (x < left || x > right)
  3515. {
  3516. D3D_THROW_FAIL("X coordinate out of range!");
  3517. }
  3518. if (y < top || y > bottom)
  3519. {
  3520. D3D_THROW_FAIL("Y coordinate out of range!");
  3521. }
  3522. if (pv->lpdwRStates[D3DRS_ZENABLE] ||
  3523. pv->lpdwRStates[D3DRS_ZWRITEENABLE])
  3524. {
  3525. // Allow a little slack for those generating triangles exactly on the
  3526. // depth limit. Needed for Quake.
  3527. if (z < -0.00015f || z > 1.00015f)
  3528. {
  3529. D3D_THROW_FAIL("Z coordinate out of range!");
  3530. }
  3531. }
  3532. UINT index = 4;
  3533. if (dwFVF & D3DFVF_DIFFUSE)
  3534. index++;
  3535. if (dwFVF & D3DFVF_SPECULAR)
  3536. index++;
  3537. UINT nTex = FVF_TEXCOORD_NUMBER(dwFVF);
  3538. if (nTex > 0)
  3539. {
  3540. if (w <= 0 )
  3541. {
  3542. D3D_THROW_FAIL("RHW out of range!");
  3543. }
  3544. for (UINT i=0; i < nTex; i++)
  3545. {
  3546. float u = ((float*)lpdwVertex)[index];
  3547. float v = ((float*)lpdwVertex)[index+1];
  3548. if (u < -100 || u > 100 || v < -100 || v > 100)
  3549. {
  3550. D3D_THROW_FAIL("Texture coordinate out of range!");
  3551. }
  3552. index += 2;
  3553. }
  3554. }
  3555. }
  3556. }
  3557. //-----------------------------------------------------------------------------
  3558. #undef DPF_MODNAME
  3559. #define DPF_MODNAME "CD3DDDIDX6::ValidateCommand"
  3560. void CD3DDDIDX6::ValidateCommand(LPD3DHAL_DP2COMMAND lpCmd)
  3561. {
  3562. D3DFE_PROCESSVERTICES* pv = static_cast<CD3DHal*>(m_pDevice)->m_pv;
  3563. BYTE* pVertices;
  3564. if (dp2data.dwFlags & D3DHALDP2_USERMEMVERTICES)
  3565. pVertices = (LPBYTE)(dp2data.lpVertices);
  3566. else
  3567. if (!lpDP2CurrBatchVBI->IsLocked())
  3568. {
  3569. lpDP2CurrBatchVBI->Lock(dp2data.dwVertexOffset,
  3570. this->dwDP2VertexCount,
  3571. &pVertices, DDLOCK_READONLY);
  3572. }
  3573. else
  3574. {
  3575. pVertices = lpDP2CurrBatchVBI->Data();
  3576. }
  3577. DWORD dwVertexSize = pv->dwOutputSize;
  3578. WORD wStart, wCount;
  3579. switch (lpCmd->bCommand)
  3580. {
  3581. case D3DDP2OP_TRIANGLELIST:
  3582. {
  3583. LPD3DHAL_DP2TRIANGLELIST pTri = (LPD3DHAL_DP2TRIANGLELIST)(lpCmd + 1);
  3584. wStart = pTri->wVStart;
  3585. wCount =lpCmd->wPrimitiveCount * 3;
  3586. }
  3587. break;
  3588. case D3DDP2OP_TRIANGLESTRIP:
  3589. case D3DDP2OP_TRIANGLEFAN:
  3590. {
  3591. LPD3DHAL_DP2TRIANGLEFAN pFan = (LPD3DHAL_DP2TRIANGLEFAN)(lpCmd + 1);
  3592. wStart = pFan->wVStart;
  3593. wCount = lpCmd->wPrimitiveCount + 2;
  3594. }
  3595. break;
  3596. case D3DDP2OP_TRIANGLEFAN_IMM:
  3597. {
  3598. wCount = lpCmd->wPrimitiveCount + 2;
  3599. BYTE* pVertices = (BYTE*)(lpCmd + 1) + sizeof(D3DHAL_DP2TRIANGLEFAN_IMM);
  3600. pVertices = (BYTE*)(((ULONG_PTR)pVertices + 3) & ~3);
  3601. for (WORD i=0; i < wCount; ++i)
  3602. {
  3603. ValidateVertex((DWORD*)(pVertices + i * dwVertexSize));
  3604. }
  3605. goto l_exit;
  3606. }
  3607. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  3608. {
  3609. wCount = lpCmd->wPrimitiveCount * 3;
  3610. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  3611. (LPD3DHAL_DP2STARTVERTEX)(lpCmd + 1);
  3612. WORD* pIndices = (WORD*)(lpStartVertex + 1);
  3613. wStart = lpStartVertex->wVStart;
  3614. pVertices += wStart * dwVertexSize;
  3615. DWORD dwNumVertices = this->dwDP2VertexCount - wStart;
  3616. for (WORD i = 0; i < wCount; ++i)
  3617. {
  3618. if (pIndices[i] >= dwNumVertices)
  3619. {
  3620. D3D_THROW_FAIL("Invalid index in ValidateCommand");
  3621. }
  3622. ValidateVertex((LPDWORD)(pVertices + pIndices[i] * dwVertexSize));
  3623. }
  3624. }
  3625. goto l_exit;
  3626. // Fall through
  3627. default:
  3628. goto l_exit;
  3629. }
  3630. {
  3631. for (WORD i = wStart; i < wStart + wCount; ++i)
  3632. {
  3633. ValidateVertex((LPDWORD)(pVertices + i * dwVertexSize));
  3634. }
  3635. }
  3636. l_exit:
  3637. if (!(dp2data.dwFlags & D3DHALDP2_USERMEMVERTICES))
  3638. lpDP2CurrBatchVBI->Unlock();
  3639. }
  3640. //-----------------------------------------------------------------------------
  3641. // This function could be used to go through all commands in the command buffer
  3642. // and find failed command at a particular offset
  3643. //
  3644. #undef DPF_MODNAME
  3645. #define DPF_MODNAME "ValidateCommandBuffer"
  3646. HRESULT ValidateCommandBuffer(LPBYTE pBuffer, DWORD dwCommandLength, DWORD dwStride)
  3647. {
  3648. LPD3DHAL_DP2COMMAND pCmd = (LPD3DHAL_DP2COMMAND)pBuffer;
  3649. LPBYTE CmdEnd = pBuffer + dwCommandLength;
  3650. loop:
  3651. UINT CommandOffset = (UINT)((LPBYTE)pCmd - pBuffer);
  3652. switch(pCmd->bCommand)
  3653. {
  3654. case D3DDP2OP_STATESET:
  3655. {
  3656. LPD3DHAL_DP2STATESET pStateSetOp =
  3657. (LPD3DHAL_DP2STATESET)(pCmd + 1);
  3658. switch (pStateSetOp->dwOperation)
  3659. {
  3660. case D3DHAL_STATESETBEGIN :
  3661. break;
  3662. case D3DHAL_STATESETEND :
  3663. break;
  3664. case D3DHAL_STATESETDELETE :
  3665. break;
  3666. case D3DHAL_STATESETEXECUTE:
  3667. break;
  3668. case D3DHAL_STATESETCAPTURE:
  3669. break;
  3670. case D3DHAL_STATESETCREATE:
  3671. break;
  3672. default :
  3673. return DDERR_INVALIDPARAMS;
  3674. }
  3675. pCmd = (LPD3DHAL_DP2COMMAND)(pStateSetOp + pCmd->wStateCount);
  3676. }
  3677. break;
  3678. case D3DDP2OP_VIEWPORTINFO:
  3679. {
  3680. pCmd = (LPD3DHAL_DP2COMMAND)
  3681. ((D3DHAL_DP2VIEWPORTINFO *)(pCmd + 1) + pCmd->wStateCount);
  3682. }
  3683. break;
  3684. case D3DDP2OP_WINFO:
  3685. {
  3686. pCmd = (LPD3DHAL_DP2COMMAND)
  3687. ((D3DHAL_DP2WINFO *)(pCmd + 1) + pCmd->wStateCount);
  3688. }
  3689. break;
  3690. case D3DDP2OP_RENDERSTATE:
  3691. {
  3692. pCmd = (LPD3DHAL_DP2COMMAND)
  3693. ((D3DHAL_DP2RENDERSTATE *)(pCmd + 1) + pCmd->wStateCount);
  3694. }
  3695. break;
  3696. case D3DDP2OP_TEXTURESTAGESTATE:
  3697. {
  3698. pCmd = (LPD3DHAL_DP2COMMAND)
  3699. ((LPD3DHAL_DP2TEXTURESTAGESTATE)(pCmd + 1) + pCmd->wStateCount);
  3700. }
  3701. break;
  3702. case D3DDP2OP_INDEXEDTRIANGLELIST:
  3703. {
  3704. WORD cPrims = pCmd->wPrimitiveCount;
  3705. pCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
  3706. sizeof(D3DHAL_DP2INDEXEDTRIANGLELIST) * cPrims);
  3707. }
  3708. break;
  3709. case D3DDP2OP_INDEXEDLINELIST:
  3710. {
  3711. // Update the command buffer pointer
  3712. pCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
  3713. pCmd->wPrimitiveCount * sizeof(D3DHAL_DP2INDEXEDLINELIST));
  3714. }
  3715. break;
  3716. case D3DDP2OP_POINTS:
  3717. {
  3718. D3DHAL_DP2POINTS *pPt = (D3DHAL_DP2POINTS *)(pCmd + 1);
  3719. pPt += pCmd->wPrimitiveCount;
  3720. pCmd = (LPD3DHAL_DP2COMMAND)pPt;
  3721. }
  3722. break;
  3723. case D3DDP2OP_LINELIST:
  3724. {
  3725. D3DHAL_DP2LINELIST *pLine = (D3DHAL_DP2LINELIST *)(pCmd + 1);
  3726. pCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
  3727. }
  3728. break;
  3729. case D3DDP2OP_INDEXEDLINELIST2:
  3730. {
  3731. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  3732. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  3733. pCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  3734. pCmd->wPrimitiveCount * sizeof(D3DHAL_DP2INDEXEDLINELIST));
  3735. }
  3736. break;
  3737. case D3DDP2OP_LINESTRIP:
  3738. {
  3739. D3DHAL_DP2LINESTRIP *pLine = (D3DHAL_DP2LINESTRIP *)(pCmd + 1);
  3740. pCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
  3741. }
  3742. break;
  3743. case D3DDP2OP_INDEXEDLINESTRIP:
  3744. {
  3745. DWORD dwNumIndices = pCmd->wPrimitiveCount + 1;
  3746. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  3747. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  3748. pCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  3749. dwNumIndices * sizeof(WORD));
  3750. }
  3751. break;
  3752. case D3DDP2OP_TRIANGLELIST:
  3753. {
  3754. D3DHAL_DP2TRIANGLELIST *pTri = (D3DHAL_DP2TRIANGLELIST *)(pCmd + 1);
  3755. pCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
  3756. }
  3757. break;
  3758. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  3759. {
  3760. DWORD dwNumIndices = pCmd->wPrimitiveCount*3;
  3761. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  3762. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  3763. pCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  3764. dwNumIndices * sizeof(WORD));
  3765. }
  3766. break;
  3767. case D3DDP2OP_TRIANGLESTRIP:
  3768. {
  3769. D3DHAL_DP2TRIANGLESTRIP *pTri = (D3DHAL_DP2TRIANGLESTRIP *)(pCmd + 1);
  3770. pCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
  3771. }
  3772. break;
  3773. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  3774. {
  3775. DWORD dwNumIndices = pCmd->wPrimitiveCount+2;
  3776. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  3777. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  3778. pCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  3779. dwNumIndices * sizeof(WORD));
  3780. }
  3781. break;
  3782. case D3DDP2OP_TRIANGLEFAN:
  3783. {
  3784. D3DHAL_DP2TRIANGLEFAN *pTri = (D3DHAL_DP2TRIANGLEFAN *)(pCmd + 1);
  3785. pCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
  3786. }
  3787. break;
  3788. case D3DDP2OP_INDEXEDTRIANGLEFAN:
  3789. {
  3790. DWORD dwNumIndices = pCmd->wPrimitiveCount + 2;
  3791. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  3792. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  3793. pCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  3794. dwNumIndices * sizeof(WORD));
  3795. }
  3796. break;
  3797. case D3DDP2OP_TRIANGLEFAN_IMM:
  3798. {
  3799. DWORD vertexCount = pCmd->wPrimitiveCount + 2;
  3800. // Make sure the pFanVtx pointer is DWORD aligned: (pFanVtx +3) % 4
  3801. PUINT8 pFanVtx = (PUINT8)
  3802. (((ULONG_PTR)(pCmd + 1) +
  3803. sizeof(D3DHAL_DP2TRIANGLEFAN_IMM) + 3) & ~3);
  3804. pCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)pFanVtx +
  3805. vertexCount * dwStride);
  3806. }
  3807. break;
  3808. case D3DDP2OP_LINELIST_IMM:
  3809. {
  3810. DWORD vertexCount = pCmd->wPrimitiveCount * 2;
  3811. // Make sure the pLineVtx pointer is DWORD aligned:
  3812. // (pLineVtx +3) % 4
  3813. PUINT8 pLineVtx = (PUINT8)(((ULONG_PTR)(pCmd + 1) + 3) & ~3);
  3814. pCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)pLineVtx +
  3815. vertexCount * dwStride);
  3816. }
  3817. break;
  3818. case D3DDP2OP_DRAWPRIMITIVE:
  3819. {
  3820. pCmd = (LPD3DHAL_DP2COMMAND)
  3821. ((D3DHAL_DP2DRAWPRIMITIVE *)(pCmd + 1) + pCmd->wStateCount);
  3822. }
  3823. break;
  3824. case D3DDP2OP_DRAWPRIMITIVE2:
  3825. {
  3826. pCmd = (LPD3DHAL_DP2COMMAND)
  3827. ((D3DHAL_DP2DRAWPRIMITIVE2 *)(pCmd + 1) + pCmd->wStateCount);
  3828. }
  3829. break;
  3830. case D3DDP2OP_DRAWRECTPATCH:
  3831. {
  3832. LPD3DHAL_DP2DRAWRECTPATCH pDP =
  3833. (LPD3DHAL_DP2DRAWRECTPATCH)(pCmd + 1);
  3834. for( int i = 0; i < pCmd->wStateCount; i++ )
  3835. {
  3836. bool hassegs = (pDP->Flags & RTPATCHFLAG_HASSEGS) != 0;
  3837. bool hasinfo = (pDP->Flags & RTPATCHFLAG_HASINFO) != 0;
  3838. if(hassegs)
  3839. {
  3840. pDP = (LPD3DHAL_DP2DRAWRECTPATCH)((BYTE*)(pDP + 1) +
  3841. sizeof(FLOAT) * 4);
  3842. }
  3843. else
  3844. {
  3845. ++pDP;
  3846. }
  3847. if(hasinfo)
  3848. {
  3849. pDP = (LPD3DHAL_DP2DRAWRECTPATCH)((BYTE*)pDP + sizeof(D3DRECTPATCH_INFO));
  3850. }
  3851. }
  3852. pCmd = (LPD3DHAL_DP2COMMAND)pDP;
  3853. }
  3854. break;
  3855. case D3DDP2OP_DRAWTRIPATCH:
  3856. {
  3857. LPD3DHAL_DP2DRAWTRIPATCH pDP =
  3858. (LPD3DHAL_DP2DRAWTRIPATCH)(pCmd + 1);
  3859. for( int i = 0; i < pCmd->wStateCount; i++ )
  3860. {
  3861. bool hassegs = (pDP->Flags & RTPATCHFLAG_HASSEGS) != 0;
  3862. bool hasinfo = (pDP->Flags & RTPATCHFLAG_HASINFO) != 0;
  3863. if(hassegs)
  3864. {
  3865. pDP = (LPD3DHAL_DP2DRAWTRIPATCH)((BYTE*)(pDP + 1) +
  3866. sizeof(FLOAT) * 3);
  3867. }
  3868. else
  3869. {
  3870. ++pDP;
  3871. }
  3872. if(hasinfo)
  3873. {
  3874. pDP = (LPD3DHAL_DP2DRAWTRIPATCH)((BYTE*)pDP + sizeof(D3DTRIPATCH_INFO));
  3875. }
  3876. }
  3877. pCmd = (LPD3DHAL_DP2COMMAND)pDP;
  3878. }
  3879. break;
  3880. case D3DDP2OP_DRAWINDEXEDPRIMITIVE:
  3881. {
  3882. pCmd = (LPD3DHAL_DP2COMMAND)
  3883. ((D3DHAL_DP2DRAWINDEXEDPRIMITIVE *)(pCmd + 1) +
  3884. pCmd->wStateCount);
  3885. }
  3886. break;
  3887. case D3DDP2OP_DRAWINDEXEDPRIMITIVE2:
  3888. {
  3889. pCmd = (LPD3DHAL_DP2COMMAND)
  3890. ((D3DHAL_DP2DRAWINDEXEDPRIMITIVE2 *)(pCmd + 1) +
  3891. pCmd->wStateCount);
  3892. }
  3893. break;
  3894. case D3DDP2OP_CLIPPEDTRIANGLEFAN:
  3895. {
  3896. pCmd = (LPD3DHAL_DP2COMMAND)
  3897. ((D3DHAL_CLIPPEDTRIANGLEFAN*)(pCmd + 1) + pCmd->wStateCount);
  3898. }
  3899. break;
  3900. case D3DDP2OP_ZRANGE:
  3901. {
  3902. pCmd = (LPD3DHAL_DP2COMMAND)
  3903. ((D3DHAL_DP2ZRANGE *)(pCmd + 1) + pCmd->wStateCount);
  3904. }
  3905. break;
  3906. case D3DDP2OP_SETMATERIAL:
  3907. {
  3908. pCmd = (LPD3DHAL_DP2COMMAND)
  3909. ((D3DHAL_DP2SETMATERIAL *)(pCmd + 1) + pCmd->wStateCount);
  3910. }
  3911. break;
  3912. case D3DDP2OP_SETLIGHT:
  3913. {
  3914. pCmd = (LPD3DHAL_DP2COMMAND)((LPBYTE)(pCmd + 1) + sizeof(D3DHAL_DP2SETLIGHT));
  3915. }
  3916. break;
  3917. case D3DDP2OP_CREATELIGHT:
  3918. {
  3919. pCmd = (LPD3DHAL_DP2COMMAND)
  3920. ((D3DHAL_DP2CREATELIGHT *)(pCmd + 1) + pCmd->wStateCount);
  3921. }
  3922. break;
  3923. case D3DDP2OP_SETTRANSFORM:
  3924. {
  3925. pCmd = (LPD3DHAL_DP2COMMAND)
  3926. ((D3DHAL_DP2SETTRANSFORM *)(pCmd + 1) + pCmd->wStateCount);
  3927. }
  3928. break;
  3929. case D3DDP2OP_MULTIPLYTRANSFORM:
  3930. {
  3931. pCmd = (LPD3DHAL_DP2COMMAND)
  3932. ((D3DHAL_DP2MULTIPLYTRANSFORM *)(pCmd + 1) + pCmd->wStateCount);
  3933. }
  3934. break;
  3935. case D3DDP2OP_EXT:
  3936. {
  3937. pCmd = (LPD3DHAL_DP2COMMAND)
  3938. ((D3DHAL_DP2EXT *)(pCmd + 1) + pCmd->wStateCount);
  3939. }
  3940. break;
  3941. case D3DDP2OP_SETRENDERTARGET:
  3942. {
  3943. pCmd = (LPD3DHAL_DP2COMMAND)
  3944. ((D3DHAL_DP2SETRENDERTARGET*)(pCmd + 1) + pCmd->wStateCount);
  3945. }
  3946. break;
  3947. case D3DDP2OP_CLEAR:
  3948. {
  3949. pCmd = (LPD3DHAL_DP2COMMAND)((LPBYTE)(pCmd + 1) +
  3950. sizeof(D3DHAL_DP2CLEAR) + (pCmd->wStateCount - 1) * sizeof(RECT));
  3951. }
  3952. break;
  3953. case D3DDP2OP_SETCLIPPLANE:
  3954. {
  3955. pCmd = (LPD3DHAL_DP2COMMAND)
  3956. ((D3DHAL_DP2SETCLIPPLANE *)(pCmd + 1) + pCmd->wStateCount);
  3957. }
  3958. break;
  3959. case D3DOP_SPAN:
  3960. // Skip over
  3961. pCmd = (LPD3DHAL_DP2COMMAND)((LPBYTE)(pCmd + 1) +
  3962. pCmd->wPrimitiveCount * pCmd->bReserved );
  3963. break;
  3964. case D3DDP2OP_CREATEVERTEXSHADER:
  3965. {
  3966. LPD3DHAL_DP2CREATEVERTEXSHADER pCVS =
  3967. (LPD3DHAL_DP2CREATEVERTEXSHADER)(pCmd + 1);
  3968. WORD i;
  3969. for( i = 0; i < pCmd->wStateCount ; i++ )
  3970. {
  3971. LPDWORD pDecl = (LPDWORD)(pCVS + 1);
  3972. LPDWORD pCode = (LPDWORD)((LPBYTE)pDecl + pCVS->dwDeclSize);
  3973. pCVS = (LPD3DHAL_DP2CREATEVERTEXSHADER)((LPBYTE)pCode +
  3974. pCVS->dwCodeSize);
  3975. }
  3976. pCmd = (LPD3DHAL_DP2COMMAND)pCVS;
  3977. break;
  3978. }
  3979. case D3DDP2OP_DELETEVERTEXSHADER:
  3980. pCmd = (LPD3DHAL_DP2COMMAND)
  3981. ((D3DHAL_DP2VERTEXSHADER *)(pCmd + 1) + pCmd->wStateCount);
  3982. break;
  3983. case D3DDP2OP_SETVERTEXSHADER:
  3984. pCmd = (LPD3DHAL_DP2COMMAND)
  3985. ((D3DHAL_DP2VERTEXSHADER *)(pCmd + 1) + pCmd->wStateCount);
  3986. break;
  3987. case D3DDP2OP_SETVERTEXSHADERCONST:
  3988. {
  3989. LPD3DHAL_DP2SETVERTEXSHADERCONST pSVC =
  3990. (LPD3DHAL_DP2SETVERTEXSHADERCONST)(pCmd + 1);
  3991. WORD i;
  3992. for( i = 0; i < pCmd->wStateCount ; i++ )
  3993. {
  3994. LPDWORD pData = (LPDWORD)(pSVC + 1);
  3995. pSVC = (LPD3DHAL_DP2SETVERTEXSHADERCONST)((LPBYTE)pData +
  3996. pSVC->dwCount * 4 *
  3997. sizeof( float ) );
  3998. }
  3999. pCmd = (LPD3DHAL_DP2COMMAND)pSVC;
  4000. break;
  4001. }
  4002. case D3DDP2OP_SETSTREAMSOURCE:
  4003. pCmd = (LPD3DHAL_DP2COMMAND)
  4004. ((D3DHAL_DP2SETSTREAMSOURCE *)(pCmd + 1) + pCmd->wStateCount);
  4005. break;
  4006. case D3DDP2OP_SETSTREAMSOURCEUM:
  4007. pCmd = (LPD3DHAL_DP2COMMAND)
  4008. ((D3DHAL_DP2SETSTREAMSOURCEUM *)(pCmd + 1) + pCmd->wStateCount);
  4009. break;
  4010. case D3DDP2OP_SETINDICES:
  4011. pCmd = (LPD3DHAL_DP2COMMAND)
  4012. ((D3DHAL_DP2SETINDICES *)(pCmd + 1) + pCmd->wStateCount);
  4013. break;
  4014. case D3DDP2OP_CREATEPIXELSHADER:
  4015. {
  4016. LPD3DHAL_DP2CREATEPIXELSHADER pCPS =
  4017. (LPD3DHAL_DP2CREATEPIXELSHADER)(pCmd + 1);
  4018. WORD i;
  4019. for( i = 0; i < pCmd->wStateCount ; i++ )
  4020. {
  4021. LPDWORD pCode = (LPDWORD)(pCPS + 1);
  4022. pCPS = (LPD3DHAL_DP2CREATEPIXELSHADER)((LPBYTE)pCode +
  4023. pCPS->dwCodeSize);
  4024. }
  4025. pCmd = (LPD3DHAL_DP2COMMAND)pCPS;
  4026. break;
  4027. }
  4028. case D3DDP2OP_DELETEPIXELSHADER:
  4029. pCmd = (LPD3DHAL_DP2COMMAND)
  4030. ((D3DHAL_DP2PIXELSHADER *)(pCmd + 1) + pCmd->wStateCount);
  4031. break;
  4032. case D3DDP2OP_SETPIXELSHADER:
  4033. pCmd = (LPD3DHAL_DP2COMMAND)
  4034. ((D3DHAL_DP2PIXELSHADER *)(pCmd + 1) + pCmd->wStateCount);
  4035. break;
  4036. case D3DDP2OP_SETPIXELSHADERCONST:
  4037. {
  4038. LPD3DHAL_DP2SETPIXELSHADERCONST pSVC =
  4039. (LPD3DHAL_DP2SETPIXELSHADERCONST)(pCmd + 1);
  4040. WORD i;
  4041. for( i = 0; i < pCmd->wStateCount ; i++ )
  4042. {
  4043. LPDWORD pData = (LPDWORD)(pSVC + 1);
  4044. pSVC = (LPD3DHAL_DP2SETPIXELSHADERCONST)((LPBYTE)pData +
  4045. pSVC->dwCount * 4 *
  4046. sizeof( float ) );
  4047. }
  4048. pCmd = (LPD3DHAL_DP2COMMAND)pSVC;
  4049. break;
  4050. }
  4051. case D3DDP2OP_SETPALETTE:
  4052. {
  4053. pCmd = (LPD3DHAL_DP2COMMAND)
  4054. ((D3DHAL_DP2SETPALETTE *)(pCmd + 1) + pCmd->wStateCount);
  4055. break;
  4056. }
  4057. case D3DDP2OP_UPDATEPALETTE:
  4058. {
  4059. LPD3DHAL_DP2UPDATEPALETTE pUP = (LPD3DHAL_DP2UPDATEPALETTE)(pCmd + 1);
  4060. WORD i;
  4061. for( i = 0; i < pCmd->wStateCount ; i++ )
  4062. {
  4063. PALETTEENTRY* pEntries = (PALETTEENTRY *)(pUP + 1);
  4064. pUP = (LPD3DHAL_DP2UPDATEPALETTE)(pEntries + pUP->wNumEntries);
  4065. }
  4066. pCmd = (LPD3DHAL_DP2COMMAND)pUP;
  4067. break;
  4068. }
  4069. case D3DDP2OP_SETTEXLOD:
  4070. {
  4071. pCmd = (LPD3DHAL_DP2COMMAND)
  4072. ((D3DHAL_DP2SETTEXLOD *)(pCmd + 1) + pCmd->wStateCount);
  4073. break;
  4074. }
  4075. case D3DDP2OP_SETPRIORITY:
  4076. {
  4077. pCmd = (LPD3DHAL_DP2COMMAND)
  4078. ((D3DHAL_DP2SETPRIORITY *)(pCmd + 1) + pCmd->wStateCount);
  4079. break;
  4080. }
  4081. case D3DDP2OP_TEXBLT:
  4082. {
  4083. LPD3DHAL_DP2TEXBLT pTB = (LPD3DHAL_DP2TEXBLT)(pCmd + 1);
  4084. for( WORD i = 0; i < pCmd->wStateCount ; i++ )
  4085. {
  4086. pTB++;
  4087. }
  4088. pCmd = (LPD3DHAL_DP2COMMAND)pTB;
  4089. break;
  4090. }
  4091. case D3DDP2OP_BUFFERBLT:
  4092. {
  4093. LPD3DHAL_DP2BUFFERBLT pBB = (LPD3DHAL_DP2BUFFERBLT)(pCmd + 1);
  4094. for( WORD i = 0; i < pCmd->wStateCount ; i++ )
  4095. {
  4096. pBB++;
  4097. }
  4098. pCmd = (LPD3DHAL_DP2COMMAND)pBB;
  4099. break;
  4100. }
  4101. case D3DDP2OP_VOLUMEBLT:
  4102. {
  4103. LPD3DHAL_DP2VOLUMEBLT pVB = (LPD3DHAL_DP2VOLUMEBLT)(pCmd + 1);
  4104. for( WORD i = 0; i < pCmd->wStateCount ; i++ )
  4105. {
  4106. pVB++;
  4107. }
  4108. pCmd = (LPD3DHAL_DP2COMMAND)pVB;
  4109. break;
  4110. }
  4111. case D3DOP_MATRIXLOAD:
  4112. case D3DOP_MATRIXMULTIPLY:
  4113. case D3DOP_STATETRANSFORM:
  4114. case D3DOP_STATELIGHT:
  4115. case D3DOP_TEXTURELOAD:
  4116. case D3DOP_BRANCHFORWARD:
  4117. case D3DOP_SETSTATUS:
  4118. case D3DOP_EXIT:
  4119. case D3DOP_PROCESSVERTICES:
  4120. {
  4121. D3D_ERR( "Command is not supported\n" );
  4122. return E_FAIL;
  4123. break;
  4124. }
  4125. default:
  4126. D3D_ERR( "Unknown command encountered" );
  4127. return E_FAIL;
  4128. }
  4129. if ((LPBYTE)pCmd < CmdEnd)
  4130. goto loop;
  4131. return S_OK;
  4132. }
  4133. #endif // DBG