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.

5281 lines
162 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: d3dbase.cpp
  6. * Content: Direct3D base device implementation
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. /*
  12. * Create an api for the Direct3DDevice object
  13. */
  14. extern "C" {
  15. #define this _this
  16. #include "ddrawpr.h"
  17. #undef this
  18. }
  19. #include "drawprim.hpp"
  20. #include "vvm.h"
  21. #include "ddi.h"
  22. #if defined(PROFILE4)
  23. #include <icecap.h>
  24. #elif defined(PROFILE)
  25. #include <icapexp.h>
  26. #endif
  27. // Remove DDraw's type unsafe definition and replace with our C++ friendly def
  28. #ifdef VALIDEX_CODE_PTR
  29. #undef VALIDEX_CODE_PTR
  30. #endif
  31. #define VALIDEX_CODE_PTR(ptr) \
  32. (!IsBadCodePtr((FARPROC) ptr))
  33. #undef DPF_MODNAME
  34. #define DPF_MODNAME "Direct3DDevice"
  35. /////////////////////////////////////////////////////////////////////////////
  36. // //
  37. // CD3DBase //
  38. // //
  39. /////////////////////////////////////////////////////////////////////////////
  40. CD3DBase::CD3DBase()
  41. {
  42. // Shaders are not re-created inside Init()
  43. m_pVShaderArray = NULL;
  44. m_pPShaderArray = NULL;
  45. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  46. // DO NOT PUT INITIALIZATION IN THE CONSTRUCTOR.
  47. // Put it in Init() instead. This is because the device can be
  48. // "Destroy()ed" and "Init()ed" anytime via Reset. In this
  49. // situation, the constructor is never called. (snene 01/00)
  50. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  51. m_qwBatch = 1; // this is ok to put here because we DONT WANT
  52. // it to be reinitialized upon Reset() (snene 02/00)
  53. #ifdef FAST_PATH
  54. m_pOrigVtbl = 0; // This is ok to put here since we DONT want it to
  55. // be touched at Destroy()
  56. #endif
  57. #if DBG
  58. // Enable/disable state of debug monitor should be independent
  59. // of Init()/Destroy() calls, so initialization belongs here.
  60. m_bDbgMonConnectionEnabled = TRUE;
  61. #endif //DBG
  62. }
  63. //---------------------------------------------------------------------
  64. HRESULT CD3DBase::ResetShaders()
  65. {
  66. try
  67. {
  68. // Re-create vertex shaders for after DX8.0 apps only
  69. UINT size = m_pVShaderArray->GetSize();
  70. for (UINT i=0; i < size; i++)
  71. {
  72. UINT Handle = m_pVShaderArray->HandleFromIndex(i);
  73. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(Handle);
  74. if (pShader)
  75. {
  76. if (Enum()->GetAppSdkVersion() != D3D_SDK_VERSION_DX8)
  77. {
  78. CreateVertexShaderI(pShader->m_pOrgDeclaration,
  79. pShader->m_OrgDeclSize,
  80. pShader->m_pOrgFuncCode,
  81. pShader->m_OrgFuncCodeSize,
  82. Handle);
  83. }
  84. }
  85. }
  86. // Re-create pixel shaders for after DX8.0 apps only
  87. size = m_pPShaderArray->GetSize();
  88. for (i=0; i < size; i++)
  89. {
  90. UINT Handle = m_pPShaderArray->HandleFromIndex(i);
  91. CPShader* pShader = (CPShader*)m_pPShaderArray->GetObject(Handle);
  92. if (pShader)
  93. {
  94. if (Enum()->GetAppSdkVersion() != D3D_SDK_VERSION_DX8)
  95. {
  96. m_pDDI->CreatePixelShader(pShader->m_pCode,
  97. pShader->m_dwCodeSize, Handle);
  98. }
  99. }
  100. }
  101. }
  102. catch(HRESULT ret)
  103. {
  104. DPF_ERR("There was some error when resetting shaders");
  105. return ret;
  106. }
  107. return S_OK;
  108. }
  109. //---------------------------------------------------------------------
  110. CD3DBase::~CD3DBase()
  111. {
  112. // Destroy() is called during Reset() and we do not want to delete
  113. // shaders there
  114. try
  115. {
  116. delete m_pPShaderArray;
  117. m_pPShaderArray = NULL;
  118. delete m_pVShaderArray;
  119. m_pVShaderArray = NULL;
  120. }
  121. catch(HRESULT ret)
  122. {
  123. DPF_ERR("There was some error when destroying device");
  124. }
  125. Destroy();
  126. }
  127. //---------------------------------------------------------------------
  128. // This function can be called TWICE, so it is ESSENTIAL that all
  129. // pointers be NULLED out and pointer dereferences be protected.
  130. // This function is capable of cleaning up partial initialization.
  131. void
  132. CD3DBase::Destroy()
  133. {
  134. try // Since Destroy() can be called directly by fw
  135. {
  136. // The DDI layer is about to be be deleted; so
  137. // we need to make sure that if Sync is called for
  138. // any object, we don't try to use the DDI.
  139. //
  140. // So we increment our sync counter
  141. // CONSIDER: should we NULL m_pDDI instead and check
  142. // for that in various places?
  143. DDASSERT(m_qwBatch > 0);
  144. m_qwBatch++;
  145. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  146. // MUST CLEANUP AND RELEASE CURRENTLY SET TEXTURES BEFORE
  147. // DOING ANY OTHER WORK, else we will get into situations
  148. // where we are calling FlushStates or batching DDI tokens.
  149. CleanupTextures();
  150. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  151. delete m_pCreatedLights;
  152. m_pCreatedLights = NULL;
  153. // Delete state sets
  154. if (0 != m_pStateSets)
  155. {
  156. delete m_pStateSets;
  157. m_pStateSets = 0;
  158. }
  159. #if DBG
  160. delete m_pRTPatchValidationInfo;
  161. m_pRTPatchValidationInfo = NULL;
  162. #endif
  163. delete m_pPaletteArray;
  164. m_pPaletteArray = NULL;
  165. delete [] m_pStream;
  166. m_pStream = NULL; // Must NULL out
  167. delete m_pIndexStream;
  168. m_pIndexStream = NULL; // Must NULL out
  169. // NOTE: we must free the DDI last; because releasing Driver
  170. // allocated VBs causes an intrinsic call to Unlock through
  171. // the DDI.
  172. delete m_pDDI;
  173. m_pDDI = NULL; // Must NULL out
  174. #if DBG
  175. if (m_pDbgMon) delete m_pDbgMon; m_pDbgMon = NULL;
  176. m_pDbgMonBase = NULL; // this memory is not owned by this pointer
  177. #endif //DBG
  178. }
  179. catch(HRESULT ret)
  180. {
  181. DPF_ERR("There was some error when Reset()ing the device; as a result some resources may not be freed.");
  182. }
  183. }
  184. //---------------------------------------------------------------------
  185. #undef DPF_MODNAME
  186. #define DPF_MODNAME "CD3DBase::CleanupTextures"
  187. void __declspec(nothrow) CD3DBase::CleanupTextures()
  188. {
  189. if(GetDDIType() < D3DDDITYPE_DX8)
  190. {
  191. // We need to unset currently set textures on DX8 drives since we have
  192. // seen these drivers do bad things when the TextureDestroy DDI is called.
  193. BOOL bNeedFlush = FALSE;
  194. for (DWORD dwStage = 0; dwStage < m_dwMaxTextureBlendStages; dwStage++)
  195. {
  196. if(m_dwDDITexHandle[dwStage] != 0)
  197. {
  198. try
  199. {
  200. m_pDDI->SetTSS(dwStage, (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP, 0);
  201. }
  202. catch(HRESULT ret)
  203. {
  204. }
  205. m_dwDDITexHandle[dwStage] = 0;
  206. bNeedFlush = TRUE;
  207. }
  208. }
  209. // Since flush-states (or any command stream thing) can throw
  210. // we need to catch an error (so we can cleanup
  211. // properly.) This flush here is a best-effort
  212. // attempt for old-drivers; we don't want new drivers to rely on
  213. // it since it can fail for lots of reasons.
  214. try
  215. {
  216. if(bNeedFlush)
  217. {
  218. m_pDDI->FlushStates();
  219. }
  220. }
  221. catch(HRESULT ret)
  222. {
  223. }
  224. }
  225. /*
  226. * We need to do this backwards because we cannot have a texture bound to
  227. * stage i + 1 when there is a texture bound to stage i.
  228. */
  229. for (int i = D3DHAL_TSS_MAXSTAGES - 1; i >= 0; --i)
  230. {
  231. if (m_lpD3DMappedTexI[i])
  232. {
  233. m_lpD3DMappedTexI[i]->DecrementUseCount();
  234. m_lpD3DMappedTexI[i] = NULL; // Must NULL out
  235. }
  236. }
  237. }
  238. //---------------------------------------------------------------------
  239. #undef DPF_MODNAME
  240. #define DPF_MODNAME "CD3DBase::Init"
  241. HRESULT __declspec(nothrow)
  242. CD3DBase::Init()
  243. {
  244. HRESULT ret = S_OK;
  245. //
  246. // FE's Init
  247. //
  248. ret = InitDevice();
  249. if (ret!=D3D_OK)
  250. {
  251. D3D_ERR("Failed to initialize D3DDevice");
  252. Destroy();
  253. return ret;
  254. }
  255. //
  256. // Initialize states
  257. //
  258. try
  259. {
  260. StateInitialize(ZBuffer() != 0);
  261. }
  262. catch (HRESULT ret)
  263. {
  264. D3D_ERR("Failed to initialize device state");
  265. Destroy();
  266. return ret;
  267. }
  268. return ret;
  269. }
  270. //------------------------------------------------------------------------------
  271. #undef DPF_MODNAME
  272. #define DPF_MODNAME "CD3DBase::InitDevice"
  273. HRESULT
  274. CD3DBase::InitDevice()
  275. {
  276. HRESULT ret = D3D_OK;
  277. HKEY hKey = (HKEY) NULL;
  278. m_dwRuntimeFlags = 0;
  279. m_dwHintFlags = 0;
  280. m_pDDI = NULL;
  281. m_dwMaxTextureBlendStages = 0;
  282. m_dwStageDirty = 0;
  283. m_dwStreamDirty = 0;
  284. m_pStateSets = NULL;
  285. m_dwCurrentShaderHandle = 0;
  286. m_dwCurrentPixelShaderHandle = 0;
  287. m_dwNumStreams = 0;
  288. m_dwMaxUserClipPlanes = 0;
  289. m_pStream = NULL;
  290. m_pIndexStream = NULL;
  291. m_dwPalette = __INVALIDPALETTE;
  292. m_pPaletteArray = NULL;
  293. #if DBG
  294. m_pRTPatchValidationInfo = NULL;
  295. m_SceneStamp = 0;
  296. #endif
  297. m_pCreatedLights = NULL;
  298. m_pCreatedLights = new CPackedBitArray;
  299. if( m_pCreatedLights == NULL )
  300. {
  301. D3D_ERR("Could not allocate internal light array m_pCreatedLights");
  302. return E_OUTOFMEMORY;
  303. }
  304. if (FAILED(m_pCreatedLights->Init(64)))
  305. {
  306. D3D_ERR("Could not allocate internal bit vector for m_pCreatedLights");
  307. return E_OUTOFMEMORY;
  308. }
  309. if (m_pVShaderArray == NULL)
  310. m_pVShaderArray = new CVShaderHandleFactory;
  311. if (m_pVShaderArray == NULL)
  312. {
  313. D3D_ERR("Could not allocate internal handle factory m_pVShaderArray");
  314. return E_OUTOFMEMORY;
  315. }
  316. // Allocate the zero'th handle. We use the handle as a flag that no
  317. // shader set.
  318. if (__INVALIDHANDLE == m_pVShaderArray->CreateNewHandle(NULL))
  319. {
  320. D3D_ERR("Vertex shader Zero'th handle allocation failed");
  321. return E_OUTOFMEMORY;
  322. }
  323. if (m_pPShaderArray == NULL)
  324. m_pPShaderArray = new CHandleFactory;
  325. if (m_pPShaderArray == NULL)
  326. {
  327. D3D_ERR("Could not allocate internal handle factory m_pPShaderArray");
  328. return E_OUTOFMEMORY;
  329. }
  330. // Allocate the zero'th handle. We use the handle as a flag that no
  331. // shader set.
  332. if (__INVALIDHANDLE == m_pPShaderArray->CreateNewHandle(NULL))
  333. {
  334. D3D_ERR("Pixel shader Zero'th handle allocation failed");
  335. return E_OUTOFMEMORY;
  336. }
  337. m_pPaletteArray = new CHandleArray;
  338. if (m_pPaletteArray == NULL)
  339. {
  340. D3D_ERR("Could not allocate internal handle array m_pPaletteArray");
  341. return E_OUTOFMEMORY;
  342. }
  343. #if DBG
  344. m_pRTPatchValidationInfo = new CHandleArray;
  345. if (m_pRTPatchValidationInfo == NULL)
  346. {
  347. D3D_ERR("Could not allocate internal handle array m_pRTPatchValidationInfo");
  348. return E_OUTOFMEMORY;
  349. }
  350. #endif
  351. m_MaxVertexShaderConst = GetD3DCaps()->MaxVertexShaderConst;
  352. DWORD value;
  353. if ((GetD3DRegValue(REG_DWORD, "DisableNVPS", &value, 4) &&
  354. value != 0))
  355. {
  356. m_dwRuntimeFlags |= D3DRT_DISALLOWNVPSHADERS;
  357. }
  358. // Figure out the DDI type of the underlying driver
  359. //---------------------------------------------------------------------
  360. // HKEY_LOCAL_MACHINE\Software\Microsoft\Direct3D\DriverStyle
  361. // In DX7 this registry key replaces the host of keys we had before like
  362. // DisableDP, DisableDP2 etc. This stuff is for testing purpose only.
  363. // It is more like a hint, in that, if the requested driver type is
  364. // available, it is used otherwise the latest available driver is used
  365. // The following is the meanings for this dword:
  366. //
  367. // Value: Driver-type:
  368. // 0x0 Latest available
  369. // 0x3 (DX6)
  370. // 0x4 (DX7)
  371. // 0x5 (DX7+TL)
  372. // 0x6 (DX8)
  373. // 0x7 (DX8+TL)
  374. //
  375. // The following are the various cases we need to consider:
  376. // 1) NT Hardware: 4 and above are legal
  377. // 2) W9x Hardware: 3 and above are legal
  378. // 3) Reference: 4 and above
  379. //---------------------------------------------------------------------
  380. WORD wDriverCaps = 0;
  381. D3DDDITYPE LatestDDI = D3DDDITYPE_NULL;
  382. //
  383. // 1) Determine what styles of DDIs the driver is capable of
  384. //
  385. // DX6 ?
  386. if (GetHalCallbacks()->DrawPrimitives2 != 0)
  387. {
  388. wDriverCaps |= (1 << D3DDDITYPE_DX6);
  389. LatestDDI = D3DDDITYPE_DX6;
  390. }
  391. // DX7 ?
  392. if ((wDriverCaps & (1 << D3DDDITYPE_DX6)) &&
  393. (GetHalCallbacks()->GetDriverState != 0))
  394. {
  395. wDriverCaps |= (1 << D3DDDITYPE_DX7);
  396. LatestDDI = D3DDDITYPE_DX7;
  397. }
  398. // DX7&TL ?
  399. if ((wDriverCaps & (1 << D3DDDITYPE_DX7)) &&
  400. (GetD3DCaps()->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT))
  401. {
  402. wDriverCaps |= (1 << D3DDDITYPE_DX7TL);
  403. LatestDDI = D3DDDITYPE_DX7TL;
  404. }
  405. // DX8 ?
  406. if ((wDriverCaps & (1 << D3DDDITYPE_DX7)) &&
  407. (GetD3DCaps()->MaxStreams != 0))
  408. {
  409. wDriverCaps |= (1 << D3DDDITYPE_DX8);
  410. LatestDDI = D3DDDITYPE_DX8;
  411. }
  412. // DX8&TL ?
  413. if ((wDriverCaps & (1 << D3DDDITYPE_DX8)) &&
  414. (GetD3DCaps()->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT))
  415. {
  416. wDriverCaps |= (1 << D3DDDITYPE_DX8TL);
  417. LatestDDI = D3DDDITYPE_DX8TL;
  418. }
  419. //
  420. // 2) Verify if the requested driver is supported
  421. //
  422. if (wDriverCaps == 0)
  423. {
  424. m_ddiType = D3DDDITYPE_NULL; // nothing supported so fail
  425. }
  426. else
  427. {
  428. // use the latest available if not specified or
  429. // incorrectly specified or specified but not available
  430. m_ddiType = LatestDDI;
  431. }
  432. D3D_INFO(1,"HalDevice Driver Style %x", GetDDIType());
  433. // Pure device is available only for DX8+ drivers only (check for cap)
  434. if ( (BehaviorFlags() & D3DCREATE_PUREDEVICE) &&
  435. !(GetD3DCaps()->DevCaps & D3DDEVCAPS_PUREDEVICE) )
  436. {
  437. DPF_ERR("No PUREDEVICE support available on this driver");
  438. return E_NOTIMPL;
  439. }
  440. #ifdef _IA64_
  441. if (GetDDIType() < D3DDDITYPE_DX8)
  442. {
  443. D3D_ERR( "Pre-DX8 drivers are not supported in IA64" );
  444. return E_FAIL;
  445. }
  446. #endif // _IA64_
  447. // Now create the DDI object
  448. // Note: If m_dwDriverStyle == 0x0 here, driver creation will fail
  449. // Something must have been chosen by now
  450. switch (GetDDIType())
  451. {
  452. case D3DDDITYPE_DX6:
  453. m_pDDI = new CD3DDDIDX6();
  454. break;
  455. case D3DDDITYPE_DX7:
  456. m_pDDI = new CD3DDDIDX7();
  457. break;
  458. case D3DDDITYPE_DX7TL:
  459. m_pDDI = new CD3DDDITL();
  460. break;
  461. case D3DDDITYPE_DX8:
  462. m_pDDI = new CD3DDDIDX8();
  463. break;
  464. case D3DDDITYPE_DX8TL:
  465. m_pDDI = new CD3DDDIDX8TL();
  466. break;
  467. default:
  468. D3D_ERR("The currently requested/installed driver is not supported.");
  469. // Change this return value ?
  470. return (E_OUTOFMEMORY);
  471. }
  472. if( m_pDDI == NULL )
  473. {
  474. D3D_ERR( "Could not allocate internal driver interface object" );
  475. return E_OUTOFMEMORY;
  476. }
  477. // Now try to initialize the ddi object
  478. try
  479. {
  480. m_pDDI->Init(this);
  481. m_pfnDrawPrim = m_pDDI->GetDrawPrimFunction();
  482. m_pfnDrawIndexedPrim = m_pDDI->GetDrawIndexedPrimFunction();
  483. m_pfnDrawPrimFromNPatch = m_pDDI->GetDrawPrimFunction();
  484. m_pfnDrawIndexedPrimFromNPatch = m_pDDI->GetDrawIndexedPrimFunction();
  485. }
  486. catch(HRESULT hr)
  487. {
  488. return hr;
  489. }
  490. #if DBG
  491. // Initialize debug monitor
  492. m_pDbgMon = NULL;
  493. m_pDbgMonBase = NULL;
  494. if ( !(BehaviorFlags() & D3DCREATE_INTERNALTEMPDEVICE))
  495. {
  496. if ( GetDeviceType() == D3DDEVTYPE_REF )
  497. {
  498. ULONG_PTR dwhDeviceContext = m_pDDI->GetDeviceContext();
  499. HINSTANCE hLibrary = GetDeviceData()->hLibrary;
  500. typedef HRESULT (WINAPI FNCreateDM)( ULONG_PTR dwContext, BOOL bDbgMonConnectionEnabled, D3DDebugMonitor** ppDbgMon );
  501. FNCreateDM* pfnCreateDM = (FNCreateDM*)GetProcAddress(hLibrary, "D3D8CreateDebugMonitor");
  502. if (NULL != pfnCreateDM)
  503. {
  504. if ( (*pfnCreateDM)( dwhDeviceContext, m_bDbgMonConnectionEnabled, &m_pDbgMonBase ) != S_OK )
  505. {
  506. D3D_ERR("Could not initialize debug monitor for D3DDEVTYPE_REF");
  507. m_pDbgMonBase = NULL;
  508. }
  509. }
  510. }
  511. else if ( ( GetDeviceType() == D3DDEVTYPE_HAL) &&
  512. ( BehaviorFlags() & D3DCREATE_SOFTWARE_VERTEXPROCESSING ) )
  513. {
  514. m_pDbgMon = new RTDebugMonitor( this, m_bDbgMonConnectionEnabled );
  515. if ( m_pDbgMon == NULL )
  516. {
  517. D3D_ERR(" debug monitor object allocation failed ");
  518. return E_OUTOFMEMORY;
  519. }
  520. m_pDbgMonBase = (D3DDebugMonitor*)m_pDbgMon;
  521. m_pDbgMon->AttachToMonitor(1);
  522. }
  523. }
  524. #endif
  525. // Initialize some caps for the Software Vertex Processing
  526. m_dwNumStreams = max(1, GetD3DCaps()->MaxStreams);
  527. m_dwMaxUserClipPlanes = GetD3DCaps()->MaxUserClipPlanes;
  528. #ifdef _X86_
  529. if (!(BehaviorFlags() & D3DCREATE_FPU_PRESERVE))
  530. {
  531. m_dwHintFlags |= D3DDEVBOOL_HINTFLAGS_FPUSETUP;
  532. WORD wSave, wTemp;
  533. __asm {
  534. fstcw wSave
  535. mov ax, wSave
  536. and ax, not 300h ;; single mode
  537. or ax, 3fh ;; disable all exceptions
  538. and ax, not 0C00h ;; round to nearest mode
  539. mov wTemp, ax
  540. fldcw wTemp
  541. }
  542. }
  543. #endif
  544. #ifdef FAST_PATH
  545. if(m_pOrigVtbl == 0)
  546. {
  547. m_pOrigVtbl = *((VOID***)this);
  548. memcpy(m_pVtbl, m_pOrigVtbl, sizeof(VOID*) * NUMVTBLENTRIES);
  549. *((VOID***)this) = m_pVtbl;
  550. }
  551. FastPathSetRenderStateExecute();
  552. FastPathSetTextureStageStateExecute();
  553. FastPathApplyStateBlockExecute();
  554. FastPathSetTextureExecute();
  555. FastPathSetMaterialExecute();
  556. FastPathSetVertexShaderFast();
  557. FastPathSetStreamSourceFast();
  558. FastPathSetIndicesFast();
  559. FastPathSetTransformExecute();
  560. FastPathMultiplyTransformExecute();
  561. FastPathSetPixelShaderExecute();
  562. FastPathSetPixelShaderConstantExecute();
  563. FastPathSetVertexShaderConstantExecute();
  564. #endif
  565. // Setup the viewport
  566. D3DSURFACE_DESC d3ddesc = RenderTarget()->InternalGetDesc();
  567. D3DVIEWPORT8 Viewport;
  568. Viewport.X = 0;
  569. Viewport.Y = 0;
  570. Viewport.Width = d3ddesc.Width;
  571. Viewport.Height = d3ddesc.Height;
  572. Viewport.MinZ = (D3DVALUE)0;
  573. Viewport.MaxZ = (D3DVALUE)1;
  574. if (FAILED(ret = this->SetViewport(&Viewport)))
  575. {
  576. return ret;
  577. }
  578. m_pStream = new CVStream[__NUMSTREAMS];
  579. if( m_pStream == NULL )
  580. {
  581. return E_OUTOFMEMORY;
  582. }
  583. for (UINT i=0; i < __NUMSTREAMS; i++)
  584. {
  585. m_pStream[i].m_dwIndex = i;
  586. }
  587. m_pIndexStream = new CVIndexStream;
  588. if( m_pIndexStream == NULL )
  589. {
  590. return E_OUTOFMEMORY;
  591. }
  592. //
  593. // Initialize the caps
  594. //
  595. const D3DCAPS8 *pCaps = GetD3DCaps();
  596. DDASSERT( pCaps );
  597. if (pCaps && pCaps->FVFCaps)
  598. {
  599. m_dwMaxTextureBlendStages = pCaps->MaxTextureBlendStages;
  600. }
  601. // Setup Statesets
  602. m_pStateSets = new CStateSets;
  603. if (m_pStateSets == NULL)
  604. {
  605. return E_OUTOFMEMORY;
  606. }
  607. m_pStateSets->Init(this);
  608. #if defined(PROFILE4) || defined(PROFILE)
  609. m_dwProfStart = m_dwProfStop = 0;
  610. GetD3DRegValue(REG_DWORD, "ProfileStartFrame", &m_dwProfStart, 4);
  611. GetD3DRegValue(REG_DWORD, "ProfileStopFrame", &m_dwProfStop, 4);
  612. #endif
  613. return D3D_OK;
  614. }
  615. //-----------------------------------------------------------------------------
  616. #undef DPF_MODNAME
  617. #define DPF_MODNAME "CD3DBase::TextureManagerDiscardBytes"
  618. HRESULT D3DAPI
  619. CD3DBase::ResourceManagerDiscardBytes(DWORD cbBytes)
  620. {
  621. API_ENTER(this);
  622. // For driver-management we pass the number of
  623. // bytes needed down through this renderstate. For DX7
  624. // we passed the value "1" which mean EvictAll. Now
  625. // if the app specifices 0 for cbBytes, that means EvictAll.
  626. // So this should make it easy for drivers to support both
  627. // dx7 and dx8+ uses of this renderstate.
  628. if (CanDriverManageResource())
  629. {
  630. try
  631. {
  632. m_pDDI->SetRenderState((D3DRENDERSTATETYPE)D3DRENDERSTATE_EVICTMANAGEDTEXTURES,
  633. cbBytes + 1);
  634. m_pDDI->FlushStates();
  635. }
  636. catch (HRESULT ret)
  637. {
  638. DPF_ERR("ResourceManagerDiscardBytes failed.");
  639. return ret;
  640. }
  641. }
  642. else
  643. {
  644. ResourceManager()->DiscardBytes(cbBytes);
  645. }
  646. return D3D_OK;
  647. }
  648. //-----------------------------------------------------------------------------
  649. #undef DPF_MODNAME
  650. #define DPF_MODNAME "CD3DBase::ValidateDevice"
  651. HRESULT D3DAPI
  652. CD3DBase::ValidateDevice(LPDWORD lpdwNumPasses)
  653. {
  654. API_ENTER(this); // Takes D3D Lock if necessary
  655. #if DBG
  656. // Validate Parameters
  657. if (!VALID_WRITEPTR(lpdwNumPasses, sizeof(DWORD)))
  658. {
  659. D3D_ERR("Invalid NumPasses pointer passed. ValidateDevice failed.");
  660. return D3DERR_INVALIDCALL;
  661. }
  662. #endif
  663. try
  664. {
  665. m_pDDI->ValidateDevice(lpdwNumPasses);
  666. }
  667. catch(HRESULT hr)
  668. {
  669. D3D_INFO(0, "ValidateDevice failed.");
  670. return hr;
  671. }
  672. return S_OK;
  673. }
  674. //-----------------------------------------------------------------------------
  675. #undef DPF_MODNAME
  676. #define DPF_MODNAME "CD3DBase::BeginScene"
  677. HRESULT D3DAPI
  678. CD3DBase::BeginScene()
  679. {
  680. API_ENTER(this); // Takes D3D Lock if necessary
  681. #if defined(PROFILE4) || defined(PROFILE)
  682. static DWORD dwFrameCount = 0;
  683. #endif
  684. DebugEvent(D3DDM_EVENT_BEGINSCENE);
  685. try
  686. {
  687. if (m_dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)
  688. {
  689. D3D_ERR("BeginScene, already in scene. BeginScene failed.");
  690. return (D3DERR_INVALIDCALL);
  691. }
  692. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  693. {
  694. D3D_ERR("Cannot be recording state macros when calling BeginScene. BeginScene failed.");
  695. throw (D3DERR_INVALIDCALL);
  696. }
  697. m_pDDI->BeginScene();
  698. #if defined(PROFILE4)
  699. if (++dwFrameCount == m_dwProfStart)
  700. {
  701. OutputDebugString("Direct3D IM 8.0: Started Profiling...\n");
  702. StartProfile(PROFILE_THREADLEVEL, PROFILE_CURRENTID);
  703. }
  704. else if (dwFrameCount == m_dwProfStop)
  705. {
  706. StopProfile(PROFILE_THREADLEVEL, PROFILE_CURRENTID);
  707. OutputDebugString("Direct3D IM 8.0: Stopped Profiling.\n");
  708. }
  709. #elif defined(PROFILE)
  710. if (++dwFrameCount == m_dwProfStart)
  711. {
  712. OutputDebugString("Direct3D IM 8.0: Started Profiling...\n");
  713. StartCAP();
  714. }
  715. else if (dwFrameCount == m_dwProfStop)
  716. {
  717. StopCAP();
  718. OutputDebugString("Direct3D IM 8.0: Stopped Profiling.\n");
  719. }
  720. #endif
  721. // So that currently bound textures get scene stamped
  722. m_dwStageDirty = (1ul << m_dwMaxTextureBlendStages) - 1ul;
  723. m_dwStreamDirty = (((1ul << m_dwNumStreams) - 1ul) | (1 << __NUMSTREAMS));
  724. m_dwRuntimeFlags |= (D3DRT_NEED_TEXTURE_UPDATE | D3DRT_NEED_VB_UPDATE);
  725. m_dwHintFlags |= D3DDEVBOOL_HINTFLAGS_INSCENE;
  726. return (D3D_OK);
  727. }
  728. catch (HRESULT ret)
  729. {
  730. DPF_ERR("BeginScene failed.");
  731. return ret;
  732. }
  733. }
  734. //-----------------------------------------------------------------------------
  735. #undef DPF_MODNAME
  736. #define DPF_MODNAME "CD3DBase::EndScene"
  737. HRESULT D3DAPI
  738. CD3DBase::EndScene()
  739. {
  740. API_ENTER(this); // Takes D3D Lock if necessary
  741. DebugEvent(D3DDM_EVENT_ENDSCENE);
  742. try
  743. {
  744. if (!(m_dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE))
  745. {
  746. D3D_ERR("EndScene, not in scene. EndScene failed.");
  747. return (D3DERR_INVALIDCALL);
  748. }
  749. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  750. {
  751. D3D_ERR("Cannot be recording state macros when calling EndScene. EndScene failed.");
  752. throw (D3DERR_INVALIDCALL);
  753. }
  754. m_dwHintFlags &= ~D3DDEVBOOL_HINTFLAGS_INSCENE;
  755. m_pDDI->EndScene();
  756. // Update the scene count in texman
  757. ResourceManager()->SceneStamp();
  758. #if DBG
  759. ++m_SceneStamp;
  760. #endif
  761. return (D3D_OK);
  762. }
  763. catch (HRESULT ret)
  764. {
  765. DPF_ERR("EndScene failed.");
  766. return ret;
  767. }
  768. }
  769. //-----------------------------------------------------------------------------
  770. #undef DPF_MODNAME
  771. #define DPF_MODNAME "CD3DBase::MultiplyTransformI"
  772. void
  773. CD3DBase::MultiplyTransformI(D3DTRANSFORMSTATETYPE state, CONST D3DMATRIX* lpMat)
  774. {
  775. m_pDDI->MultiplyTransform(state, lpMat);
  776. }
  777. #ifdef FAST_PATH
  778. //-----------------------------------------------------------------------------
  779. #undef DPF_MODNAME
  780. #define DPF_MODNAME "CD3DBase::MultiplyTransformFast"
  781. HRESULT D3DAPI
  782. CD3DBase::MultiplyTransformFast(D3DTRANSFORMSTATETYPE state, CONST D3DMATRIX* lpMat)
  783. {
  784. #if DBG
  785. if (!VALID_PTR(lpMat, sizeof(D3DMATRIX)))
  786. {
  787. D3D_ERR("Invalid matrix pointer. MultiplyTransform failed.");
  788. return D3DERR_INVALIDCALL;
  789. }
  790. if ((DWORD)state >= __WORLDMATRIXBASE &&
  791. (DWORD)state < __WORLDMATRIXBASE + __MAXWORLDMATRICES)
  792. {
  793. }
  794. else
  795. switch (state)
  796. {
  797. case D3DTS_VIEW :
  798. case D3DTS_PROJECTION :
  799. case D3DTS_TEXTURE0:
  800. case D3DTS_TEXTURE1:
  801. case D3DTS_TEXTURE2:
  802. case D3DTS_TEXTURE3:
  803. case D3DTS_TEXTURE4:
  804. case D3DTS_TEXTURE5:
  805. case D3DTS_TEXTURE6:
  806. case D3DTS_TEXTURE7:
  807. break;
  808. default :
  809. D3D_ERR("Invalid state value passed to MultiplyTransform. MultiplyTransform failed.");
  810. return D3DERR_INVALIDCALL;
  811. }
  812. #endif
  813. DXGASSERT((m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE) == 0 &&
  814. (BehaviorFlags() & D3DCREATE_MULTITHREADED) == 0 &&
  815. (BehaviorFlags() & D3DCREATE_PUREDEVICE) != 0);
  816. try
  817. {
  818. m_pDDI->MultiplyTransform(state, lpMat);
  819. }
  820. catch(HRESULT ret)
  821. {
  822. DPF_ERR("MultiplyTransform failed.");
  823. return ret;
  824. }
  825. return D3D_OK;
  826. }
  827. #endif
  828. //-----------------------------------------------------------------------------
  829. #undef DPF_MODNAME
  830. #define DPF_MODNAME "CD3DBase::MultiplyTransform"
  831. HRESULT D3DAPI
  832. CD3DBase::MultiplyTransform(D3DTRANSFORMSTATETYPE state, CONST D3DMATRIX* lpMat)
  833. {
  834. API_ENTER(this);
  835. #if DBG
  836. if (!VALID_PTR(lpMat, sizeof(D3DMATRIX)))
  837. {
  838. D3D_ERR("Invalid matrix pointer. MultiplyTransform failed.");
  839. return D3DERR_INVALIDCALL;
  840. }
  841. if ((DWORD)state >= __WORLDMATRIXBASE &&
  842. (DWORD)state < __WORLDMATRIXBASE + __MAXWORLDMATRICES)
  843. {
  844. }
  845. else
  846. switch (state)
  847. {
  848. case D3DTS_VIEW :
  849. case D3DTS_PROJECTION :
  850. case D3DTS_TEXTURE0:
  851. case D3DTS_TEXTURE1:
  852. case D3DTS_TEXTURE2:
  853. case D3DTS_TEXTURE3:
  854. case D3DTS_TEXTURE4:
  855. case D3DTS_TEXTURE5:
  856. case D3DTS_TEXTURE6:
  857. case D3DTS_TEXTURE7:
  858. break;
  859. default :
  860. D3D_ERR("Invalid state value passed to MultiplyTransform. MultiplyTransform failed.");
  861. return D3DERR_INVALIDCALL;
  862. }
  863. #endif
  864. try
  865. {
  866. MultiplyTransformI(state, lpMat);
  867. }
  868. catch(HRESULT ret)
  869. {
  870. DPF_ERR("MultiplyTransform failed.");
  871. return ret;
  872. }
  873. return D3D_OK;
  874. }
  875. //-----------------------------------------------------------------------------
  876. #undef DPF_MODNAME
  877. #define DPF_MODNAME "CD3DBase::SetTransformI"
  878. void CD3DBase::SetTransformI(D3DTRANSFORMSTATETYPE state,
  879. CONST D3DMATRIX* lpMat)
  880. {
  881. if( state == D3DTS_PROJECTION )
  882. m_pDDI->UpdateWInfo( lpMat );
  883. m_pDDI->SetTransform(state, lpMat);
  884. }
  885. //-----------------------------------------------------------------------------
  886. #undef DPF_MODNAME
  887. #define DPF_MODNAME "CD3DBase::SetTransform"
  888. HRESULT D3DAPI
  889. CD3DBase::SetTransform(D3DTRANSFORMSTATETYPE state,
  890. CONST D3DMATRIX* lpMat)
  891. {
  892. API_ENTER(this); // Takes D3D Lock if necessary
  893. #if DBG
  894. if (!VALID_PTR(lpMat, sizeof(D3DMATRIX)))
  895. {
  896. D3D_ERR("Invalid matrix pointer. SetTransform failed.");
  897. return D3DERR_INVALIDCALL;
  898. }
  899. if ((DWORD)state >= __WORLDMATRIXBASE &&
  900. (DWORD)state < __WORLDMATRIXBASE + __MAXWORLDMATRICES)
  901. {
  902. }
  903. else
  904. switch (state)
  905. {
  906. case D3DTS_VIEW :
  907. case D3DTS_PROJECTION :
  908. case D3DTS_TEXTURE0:
  909. case D3DTS_TEXTURE1:
  910. case D3DTS_TEXTURE2:
  911. case D3DTS_TEXTURE3:
  912. case D3DTS_TEXTURE4:
  913. case D3DTS_TEXTURE5:
  914. case D3DTS_TEXTURE6:
  915. case D3DTS_TEXTURE7:
  916. break;
  917. default :
  918. D3D_ERR("Invalid state value passed to SetTransform. SetTransform failed.");
  919. return D3DERR_INVALIDCALL;
  920. }
  921. #endif
  922. try
  923. {
  924. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  925. m_pStateSets->InsertTransform(state, lpMat);
  926. else
  927. SetTransformI(state, lpMat);
  928. }
  929. catch(HRESULT ret)
  930. {
  931. DPF_ERR("SetTransform failed.");
  932. return ret;
  933. }
  934. return D3D_OK;
  935. }
  936. #ifdef FAST_PATH
  937. //-----------------------------------------------------------------------------
  938. #undef DPF_MODNAME
  939. #define DPF_MODNAME "CD3DBase::SetTransformFast"
  940. HRESULT D3DAPI
  941. CD3DBase::SetTransformFast(D3DTRANSFORMSTATETYPE state,
  942. CONST D3DMATRIX* lpMat)
  943. {
  944. #if DBG
  945. if (!VALID_PTR(lpMat, sizeof(D3DMATRIX)))
  946. {
  947. D3D_ERR("Invalid matrix pointer. SetTransform failed.");
  948. return D3DERR_INVALIDCALL;
  949. }
  950. if ((DWORD)state >= __WORLDMATRIXBASE &&
  951. (DWORD)state < __WORLDMATRIXBASE + __MAXWORLDMATRICES)
  952. {
  953. }
  954. else
  955. switch (state)
  956. {
  957. case D3DTS_VIEW :
  958. case D3DTS_PROJECTION :
  959. case D3DTS_TEXTURE0:
  960. case D3DTS_TEXTURE1:
  961. case D3DTS_TEXTURE2:
  962. case D3DTS_TEXTURE3:
  963. case D3DTS_TEXTURE4:
  964. case D3DTS_TEXTURE5:
  965. case D3DTS_TEXTURE6:
  966. case D3DTS_TEXTURE7:
  967. break;
  968. default :
  969. D3D_ERR("Invalid state value passed to SetTransform. SetTransform failed.");
  970. return D3DERR_INVALIDCALL;
  971. }
  972. #endif
  973. DXGASSERT((m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE) == 0 &&
  974. (BehaviorFlags() & D3DCREATE_MULTITHREADED) == 0 &&
  975. (BehaviorFlags() & D3DCREATE_PUREDEVICE) != 0);
  976. try
  977. {
  978. m_pDDI->SetTransform(state, lpMat);
  979. }
  980. catch(HRESULT ret)
  981. {
  982. DPF_ERR("SetTransform failed.");
  983. return ret;
  984. }
  985. return S_OK;
  986. }
  987. #endif // FAST_PATH
  988. //---------------------------------------------------------------------
  989. #undef DPF_MODNAME
  990. #define DPF_MODNAME "CD3DBase::SetRenderTarget"
  991. HRESULT D3DAPI
  992. CD3DBase::SetRenderTarget(IDirect3DSurface8 *pRenderTarget,
  993. IDirect3DSurface8 *pZStencil)
  994. {
  995. API_ENTER(this); // Takes D3D Lock if necessary
  996. try
  997. {
  998. CBaseSurface *pTarget;
  999. CBaseSurface *pZ;
  1000. if (pRenderTarget != NULL)
  1001. {
  1002. if (!VALID_D3D_DIRECTDRAWSURFACE8_PTR(pRenderTarget))
  1003. {
  1004. D3D_ERR("Invalid IDirect3DSurface8 pointer passed for RenderTarget. SetRenderTarget failed.");
  1005. return D3DERR_INVALIDCALL;
  1006. }
  1007. pTarget = static_cast<CBaseSurface*>(pRenderTarget);
  1008. if (pTarget->InternalGetDevice() != this)
  1009. {
  1010. D3D_ERR("Render Target wasn't created with this Device. SetRenderTarget fails");
  1011. return D3DERR_INVALIDCALL;
  1012. }
  1013. D3DSURFACE_DESC desc = pTarget->InternalGetDesc();
  1014. if ((desc.Usage & D3DUSAGE_RENDERTARGET) == 0)
  1015. {
  1016. D3D_ERR("**** The D3DUSAGE_RENDERTARGET is not set on this surface.");
  1017. D3D_ERR("**** You need to add D3DUSAGE_RENDERTARGET to the Usage parameter");
  1018. D3D_ERR("**** when creating the surface. SetRenderTarget failed.");
  1019. return (D3DERR_INVALIDCALL);
  1020. }
  1021. }
  1022. else
  1023. {
  1024. pTarget = RenderTarget();
  1025. }
  1026. if (pZStencil != NULL)
  1027. {
  1028. if (!VALID_D3D_DIRECTDRAWSURFACE8_PTR(pZStencil))
  1029. {
  1030. D3D_ERR("Invalid IDirect3DSurface8 pointer passed for ZStencil. SetRenderTarget failed.");
  1031. return D3DERR_INVALIDCALL;
  1032. }
  1033. pZ = static_cast<CBaseSurface*>(pZStencil);
  1034. if (pZ->InternalGetDevice() != this)
  1035. {
  1036. D3D_ERR("Zbuffer wasn't created with this Device. SetRenderTarget fails");
  1037. return D3DERR_INVALIDCALL;
  1038. }
  1039. // We call the external interface because
  1040. // we need to get the Z format that the user
  1041. // specified NOT our internal mapping.
  1042. D3DSURFACE_DESC descZ;
  1043. pZ->GetDesc(&descZ);
  1044. if ((descZ.Usage & D3DUSAGE_DEPTHSTENCIL) == 0)
  1045. {
  1046. D3D_ERR("**** The D3DUSAGE_DEPTHSTENCIL is not set on this surface.");
  1047. D3D_ERR("**** You need to add D3DUSAGE_DEPTHSTENCIL to the Usage parameter");
  1048. D3D_ERR("**** when creating the surface. SetRenderTarget failed.");
  1049. return (D3DERR_INVALIDCALL);
  1050. }
  1051. // Check that RT and Z have matching Multi-Sampleness
  1052. DXGASSERT(pTarget != NULL);
  1053. D3DSURFACE_DESC descTarget = pTarget->InternalGetDesc();
  1054. if (descZ.MultiSampleType != descTarget.MultiSampleType)
  1055. {
  1056. DPF_ERR("MultiSampleType between DepthStencil Buffer and RenderTarget must match. SetRenderTarget failed.");
  1057. return D3DERR_INVALIDCALL;
  1058. }
  1059. // Ensure that the ZBuffer that is being set is atleast as big as the RenderTarget
  1060. if ((descZ.Width < descTarget.Width) ||
  1061. (descZ.Height < descTarget.Height))
  1062. {
  1063. DPF_ERR("DepthStencil Buffer must be atleast as big as the RenderTarget. SetRenderTarget failed.");
  1064. return D3DERR_INVALIDCALL;
  1065. }
  1066. // Need to check whether formats are compatible if
  1067. // the format is the lockable D16 or has Stencil
  1068. if (descZ.Format == D3DFMT_D16_LOCKABLE ||
  1069. CPixel::HasStencilBits(descZ.Format))
  1070. {
  1071. HRESULT hr = CheckDepthStencilMatch(descTarget.Format, descZ.Format);
  1072. if (FAILED(hr))
  1073. {
  1074. DPF_ERR("SetRenderTarget failed; Z Buffer is incompatible with Render Target. See CheckDepthStencilMatch documentation.");
  1075. if (descZ.Format == D3DFMT_D16_LOCKABLE)
  1076. {
  1077. DPF_ERR("If you don't need to lock the z-buffer, then you should use D3DFMT_D16 instead of D3DFMT_D16_LOCKABLE");
  1078. }
  1079. return D3DERR_INVALIDCALL;
  1080. }
  1081. }
  1082. }
  1083. else
  1084. {
  1085. pZ = NULL;
  1086. }
  1087. HRESULT hr = SetRenderTargetI(pTarget, pZ);
  1088. if( FAILED(hr) )
  1089. {
  1090. DPF_ERR("SetRenderTargetI failed because the driver failed a command a batch");
  1091. return hr;
  1092. }
  1093. // Set the viewport to default to the whole render-target
  1094. D3DVIEWPORT8 vp;
  1095. D3DSURFACE_DESC desc = pTarget->InternalGetDesc();
  1096. vp.X = 0;
  1097. vp.Y = 0;
  1098. vp.Width = desc.Width;
  1099. vp.Height = desc.Height;
  1100. vp.MinZ = 0.0f;
  1101. vp.MaxZ = 1.0f;
  1102. SetViewportI( &vp );
  1103. }
  1104. catch (HRESULT ret)
  1105. {
  1106. DPF_ERR("SetRenderTarget failed.");
  1107. return ret;
  1108. }
  1109. return D3D_OK;
  1110. }
  1111. //---------------------------------------------------------------------
  1112. #undef DPF_MODNAME
  1113. #define DPF_MODNAME "CD3DBase::SetRenderTargetI"
  1114. HRESULT __declspec(nothrow)
  1115. CD3DBase::SetRenderTargetI( CBaseSurface* pTarget,
  1116. CBaseSurface* pZ )
  1117. {
  1118. try
  1119. {
  1120. m_pDDI->SetRenderTarget(pTarget, pZ);
  1121. UpdateRenderTarget(pTarget, pZ);
  1122. return D3D_OK;
  1123. }
  1124. catch (HRESULT ret)
  1125. {
  1126. return ret;
  1127. }
  1128. }
  1129. //---------------------------------------------------------------------
  1130. #undef DPF_MODNAME
  1131. #define DPF_MODNAME "CD3DBase::GetRenderTarget"
  1132. HRESULT D3DAPI
  1133. CD3DBase::GetRenderTarget(LPDIRECT3DSURFACE8* lplpDDS)
  1134. {
  1135. API_ENTER(this); // Takes D3D Lock if necessary
  1136. if (!VALID_OUTPTR(lplpDDS))
  1137. {
  1138. D3D_ERR("Invalid ptr to IDirect3DSurface8*. GetRenderTarget failed.");
  1139. return D3DERR_INVALIDCALL;
  1140. }
  1141. *lplpDDS = this->RenderTarget();
  1142. this->RenderTarget()->AddRef();
  1143. return D3D_OK;
  1144. }
  1145. //---------------------------------------------------------------------
  1146. #undef DPF_MODNAME
  1147. #define DPF_MODNAME "CD3DBase::GetZStencilSurface"
  1148. HRESULT D3DAPI
  1149. CD3DBase::GetDepthStencilSurface(LPDIRECT3DSURFACE8* lplpDDS)
  1150. {
  1151. API_ENTER(this); // Takes D3D Lock if necessary
  1152. if (!VALID_OUTPTR(lplpDDS))
  1153. {
  1154. D3D_ERR("Invalid ptr to IDirect3DSurface8*. GetDepthStencilSurface failed.");
  1155. return D3DERR_INVALIDCALL;
  1156. }
  1157. *lplpDDS = this->ZBuffer();
  1158. if (*lplpDDS)
  1159. {
  1160. (*lplpDDS)->AddRef();
  1161. return S_OK;
  1162. }
  1163. else
  1164. {
  1165. D3D_INFO(0, "Device doesn't have a Z Buffer.");
  1166. return D3DERR_NOTFOUND;
  1167. }
  1168. }
  1169. //---------------------------------------------------------------------
  1170. #undef DPF_MODNAME
  1171. #define DPF_MODNAME "CD3DBase::SetViewport"
  1172. HRESULT D3DAPI
  1173. CD3DBase::SetViewport(CONST D3DVIEWPORT8* lpData)
  1174. {
  1175. API_ENTER(this); // Takes D3D Lock if necessary
  1176. if (!VALID_PTR(lpData, sizeof(*lpData)))
  1177. {
  1178. D3D_ERR("Invalid viewport pointer. SetViewport failed.");
  1179. return D3DERR_INVALIDCALL;
  1180. }
  1181. try
  1182. {
  1183. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1184. m_pStateSets->InsertViewport(lpData);
  1185. else
  1186. SetViewportI(lpData);
  1187. }
  1188. catch(HRESULT ret)
  1189. {
  1190. DPF_ERR("SetViewport failed.");
  1191. return ret;
  1192. }
  1193. return D3D_OK;
  1194. }
  1195. //---------------------------------------------------------------------
  1196. #undef DPF_MODNAME
  1197. #define DPF_MODNAME "CD3DBase::SetViewportI"
  1198. void CD3DBase::SetViewportI(CONST D3DVIEWPORT8* lpData)
  1199. {
  1200. #if DBG
  1201. CheckViewport(lpData);
  1202. #endif
  1203. m_pDDI->SetViewport(lpData);
  1204. }
  1205. //---------------------------------------------------------------------
  1206. #undef DPF_MODNAME
  1207. #define DPF_MODNAME "CD3DBase::SetMaterial"
  1208. HRESULT D3DAPI
  1209. CD3DBase::SetMaterial(CONST D3DMATERIAL8* lpData)
  1210. {
  1211. API_ENTER(this); // Takes D3D Lock if necessary
  1212. #if DBG
  1213. if (!VALID_PTR(lpData, sizeof(*lpData)))
  1214. {
  1215. D3D_ERR("Invalid D3DMATERIAL pointer. SetMaterial failed.");
  1216. return D3DERR_INVALIDCALL;
  1217. }
  1218. #endif
  1219. try
  1220. {
  1221. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1222. m_pStateSets->InsertMaterial(lpData);
  1223. else
  1224. this->SetMaterialFast(lpData);
  1225. }
  1226. catch(HRESULT ret)
  1227. {
  1228. DPF_ERR("SetMaterial failed.");
  1229. return ret;
  1230. }
  1231. return D3D_OK;
  1232. }
  1233. //---------------------------------------------------------------------
  1234. #undef DPF_MODNAME
  1235. #define DPF_MODNAME "CD3DBase::SetMaterialFast"
  1236. HRESULT D3DAPI
  1237. CD3DBase::SetMaterialFast(CONST D3DMATERIAL8* lpData)
  1238. {
  1239. #if DBG
  1240. if (!VALID_PTR(lpData, sizeof(*lpData)))
  1241. {
  1242. D3D_ERR("Invalid D3DMATERIAL pointer. SetMaterial failed.");
  1243. return D3DERR_INVALIDCALL;
  1244. }
  1245. #endif
  1246. try
  1247. {
  1248. m_pDDI->SetMaterial(lpData);
  1249. }
  1250. catch(HRESULT ret)
  1251. {
  1252. DPF_ERR("SetMaterial failed.");
  1253. return ret;
  1254. }
  1255. return D3D_OK;
  1256. }
  1257. //---------------------------------------------------------------------
  1258. #undef DPF_MODNAME
  1259. #define DPF_MODNAME "CD3DBase::SetLight"
  1260. extern void CheckLightParams(CONST D3DLIGHT8* lpData);
  1261. HRESULT D3DAPI
  1262. CD3DBase::SetLight(DWORD dwLightIndex,
  1263. CONST D3DLIGHT8* lpData)
  1264. {
  1265. API_ENTER(this); // Takes D3D Lock if necessary
  1266. if (!VALID_PTR(lpData, sizeof(*lpData)))
  1267. {
  1268. D3D_ERR( "Invalid D3DLIGHT pointer. SetLight failed." );
  1269. return D3DERR_INVALIDCALL;
  1270. }
  1271. try
  1272. {
  1273. #if DBG
  1274. CheckLightParams(lpData);
  1275. #endif // DBG
  1276. // If new index greater than allocated array - re-allocate the array
  1277. if (dwLightIndex >= m_pCreatedLights->GetSize())
  1278. m_pCreatedLights->Init(dwLightIndex + 32);
  1279. // If the light if not already created, send command to the DDI to
  1280. // create it.
  1281. if (!m_pCreatedLights->IsBitSet(dwLightIndex))
  1282. {
  1283. m_pDDI->CreateLight(dwLightIndex);
  1284. m_pCreatedLights->SetBit(dwLightIndex);
  1285. // If we are in the record mode, we need to create the light object.
  1286. // Otherwise, if we access the light during capture, we will have
  1287. // access violation.
  1288. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1289. {
  1290. // Set default value to the light
  1291. D3DLIGHT8 light;
  1292. memset(&light, 0, sizeof(light));
  1293. light.Type = D3DLIGHT_DIRECTIONAL;
  1294. light.Direction.x = D3DVAL(0);
  1295. light.Direction.y = D3DVAL(0);
  1296. light.Direction.z = D3DVAL(1);
  1297. light.Diffuse.r = D3DVAL(1);
  1298. light.Diffuse.g = D3DVAL(1);
  1299. light.Diffuse.b = D3DVAL(1);
  1300. this->SetLightI(dwLightIndex, &light);
  1301. }
  1302. }
  1303. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1304. m_pStateSets->InsertLight(dwLightIndex, lpData);
  1305. else
  1306. this->SetLightI(dwLightIndex, lpData);
  1307. return D3D_OK;
  1308. }
  1309. catch(HRESULT ret)
  1310. {
  1311. D3D_ERR("SetLight failed.");
  1312. return ret;
  1313. }
  1314. }
  1315. //---------------------------------------------------------------------
  1316. #undef DPF_MODNAME
  1317. #define DPF_MODNAME "CD3DBase::SetLightI"
  1318. void
  1319. CD3DBase::SetLightI(DWORD dwLightIndex, CONST D3DLIGHT8* lpData)
  1320. {
  1321. m_pDDI->SetLight(dwLightIndex, lpData);
  1322. }
  1323. //---------------------------------------------------------------------
  1324. #undef DPF_MODNAME
  1325. #define DPF_MODNAME "CD3DBase::LightEnableI"
  1326. void
  1327. CD3DBase::LightEnableI(DWORD dwLightIndex, BOOL bEnable)
  1328. {
  1329. m_pDDI->LightEnable(dwLightIndex, bEnable);
  1330. }
  1331. //---------------------------------------------------------------------
  1332. BOOL ValidateRenderState(D3DRENDERSTATETYPE dwState, DWORD value)
  1333. {
  1334. if (dwState >= D3D_MAXRENDERSTATES || dwState == 0)
  1335. {
  1336. D3D_ERR("Invalid render state type. SetRenderState failed.");
  1337. return FALSE;
  1338. }
  1339. switch (dwState)
  1340. {
  1341. case D3DRS_POSITIONORDER:
  1342. if (!((value == D3DORDER_LINEAR) || (value == D3DORDER_CUBIC)))
  1343. {
  1344. D3D_ERR("D3DRS_POSITIONORDER should be D3DORDER_LINEAR or D3DORDER_CUBIC");
  1345. return FALSE;
  1346. }
  1347. break;
  1348. case D3DRS_NORMALORDER:
  1349. if (!((value == D3DORDER_LINEAR) || (value == D3DORDER_QUADRATIC)))
  1350. {
  1351. D3D_ERR("D3DRS_NORMALORDER should be D3DORDER_LINEAR or D3DORDER_QUADRATIC");
  1352. return FALSE;
  1353. }
  1354. break;
  1355. }
  1356. return TRUE;
  1357. }
  1358. //---------------------------------------------------------------------
  1359. #undef DPF_MODNAME
  1360. #define DPF_MODNAME "CD3DBase::SetRenderState"
  1361. HRESULT D3DAPI
  1362. CD3DBase::SetRenderState(D3DRENDERSTATETYPE dwState,
  1363. DWORD value)
  1364. {
  1365. API_ENTER(this); // Takes D3D Lock if necessary
  1366. #if DBG
  1367. if (!ValidateRenderState(dwState, value))
  1368. return D3DERR_INVALIDCALL;
  1369. #endif
  1370. try
  1371. {
  1372. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1373. m_pStateSets->InsertRenderState(dwState, value,
  1374. CanHandleRenderState(dwState));
  1375. else
  1376. m_pDDI->SetRenderState(dwState, value);
  1377. }
  1378. catch(HRESULT ret)
  1379. {
  1380. DPF_ERR("SetRenderState failed.");
  1381. return ret;
  1382. }
  1383. return D3D_OK;
  1384. }
  1385. //---------------------------------------------------------------------
  1386. #undef DPF_MODNAME
  1387. #define DPF_MODNAME "CD3DBase::SetRenderStateFast"
  1388. HRESULT D3DAPI CD3DBase::SetRenderStateFast(D3DRENDERSTATETYPE dwState,
  1389. DWORD value)
  1390. {
  1391. #if DBG
  1392. if (!ValidateRenderState(dwState, value))
  1393. return D3DERR_INVALIDCALL;
  1394. #endif
  1395. DXGASSERT((BehaviorFlags() & D3DCREATE_MULTITHREADED) == 0);
  1396. try
  1397. {
  1398. m_pDDI->SetRenderState(dwState, value);
  1399. }
  1400. catch(HRESULT ret)
  1401. {
  1402. DPF_ERR("SetRenderState failed.");
  1403. return ret;
  1404. }
  1405. return D3D_OK;
  1406. }
  1407. //---------------------------------------------------------------------
  1408. #undef DPF_MODNAME
  1409. #define DPF_MODNAME "CD3DBase::SetClipStatus"
  1410. HRESULT D3DAPI
  1411. CD3DBase::SetClipStatus(CONST D3DCLIPSTATUS8* lpStatus)
  1412. {
  1413. API_ENTER(this); // Takes D3D Lock if necessary
  1414. D3D_ERR("SetClipStatus is not available for D3DCREATE_PUREDEVICE. SetClipStatus failed.");
  1415. return E_NOTIMPL;
  1416. }
  1417. //---------------------------------------------------------------------
  1418. #undef DPF_MODNAME
  1419. #define DPF_MODNAME "CD3DBase::GetClipStatus"
  1420. HRESULT D3DAPI
  1421. CD3DBase::GetClipStatus(D3DCLIPSTATUS8* lpStatus)
  1422. {
  1423. API_ENTER(this); // Takes D3D Lock if necessary
  1424. D3D_ERR("GetClipStatus is not available for D3DCREATE_PUREDEVICE. GetClipStatus failed.");
  1425. return E_NOTIMPL;
  1426. }
  1427. //---------------------------------------------------------------------
  1428. #undef DPF_MODNAME
  1429. #define DPF_MODNAME "CD3DBase::ProcessVertices"
  1430. HRESULT D3DAPI
  1431. CD3DBase::ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount,
  1432. IDirect3DVertexBuffer8 *pDestBuffer,
  1433. DWORD Flags)
  1434. {
  1435. API_ENTER(this); // Takes D3D Lock if necessary
  1436. if (pDestBuffer == NULL)
  1437. {
  1438. D3D_ERR("Invalid vertex buffer pointer. ProcessVertices failed.");
  1439. return D3DERR_INVALIDCALL;
  1440. }
  1441. CVertexBuffer* pVB = static_cast<CVertexBuffer*>(pDestBuffer);
  1442. if (pVB->Device() != this)
  1443. {
  1444. D3D_ERR("VertexBuffer not created with this device. Process Vertices failed.");
  1445. return D3DERR_INVALIDCALL;
  1446. }
  1447. D3D_ERR("ProcessVertices is not available for a PUREDEVICE. ProcessVertices failed.");
  1448. return E_NOTIMPL;
  1449. }
  1450. //---------------------------------------------------------------------
  1451. #undef DPF_MODNAME
  1452. #define DPF_MODNAME "CD3DBase::SetTexture"
  1453. HRESULT D3DAPI
  1454. CD3DBase::SetTexture(DWORD dwStage,
  1455. IDirect3DBaseTexture8 *lpTex)
  1456. {
  1457. API_ENTER(this); // Takes D3D Lock if necessary
  1458. try
  1459. {
  1460. #if DBG
  1461. HRESULT ret = VerifyTexture(dwStage, lpTex);
  1462. if (ret != D3D_OK)
  1463. return ret;
  1464. #endif
  1465. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1466. {
  1467. m_pStateSets->InsertTexture(dwStage, lpTex);
  1468. return D3D_OK;
  1469. }
  1470. return SetTextureFast(dwStage, lpTex);
  1471. }
  1472. catch(HRESULT ret)
  1473. {
  1474. DPF_ERR("SetTexture failed.");
  1475. return ret;
  1476. }
  1477. }
  1478. #undef DPF_MODNAME
  1479. #define DPF_MODNAME "CD3DBase::VerifyTexture"
  1480. HRESULT
  1481. CD3DBase::VerifyTexture(DWORD dwStage,
  1482. IDirect3DBaseTexture8 *lpTex)
  1483. {
  1484. if (dwStage >= D3DHAL_TSS_MAXSTAGES)
  1485. {
  1486. D3D_ERR("Invalid texture stage or state index. SetTexture failed.");
  1487. return D3DERR_INVALIDCALL;
  1488. }
  1489. if (lpTex)
  1490. {
  1491. if (!VALID_DIRECT3DBASETEXTURE8_PTR(lpTex))
  1492. {
  1493. D3D_ERR("Invalid texture pointer. SetTexture failed.");
  1494. return D3DERR_INVALIDCALL;
  1495. }
  1496. CBaseTexture *pTex = CBaseTexture::SafeCast(lpTex);
  1497. if (pTex->Device() != this)
  1498. {
  1499. D3D_ERR("Texture not created with this device. SetTexture failed.");
  1500. return D3DERR_INVALIDCALL;
  1501. }
  1502. if (pTex->GetUserPool() == D3DPOOL_SYSTEMMEM)
  1503. {
  1504. if ((GetD3DCaps()->DevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY) == 0)
  1505. {
  1506. D3D_ERR("Device cannot render using texture surface from system memory. SetTexture failed.");
  1507. return D3DERR_INVALIDCALL;
  1508. }
  1509. }
  1510. if (pTex->GetUserPool() == D3DPOOL_SCRATCH)
  1511. {
  1512. D3D_ERR("D3DPOOL_SCRATCH resources cannot be passed to SetTexture. SetTexture fails.");
  1513. return D3DERR_INVALIDCALL;
  1514. }
  1515. }
  1516. return D3D_OK;
  1517. }
  1518. #undef DPF_MODNAME
  1519. #define DPF_MODNAME "CD3DBase::SetTextureFast"
  1520. HRESULT D3DAPI
  1521. CD3DBase::SetTextureFast(DWORD dwStage,
  1522. IDirect3DBaseTexture8 *lpTex)
  1523. {
  1524. // NOTE: This can become a public API through the
  1525. // v-table hack. This should only happen for
  1526. // single-threaded apps; so we don't need
  1527. // to take the critical section.
  1528. #if DBG
  1529. HRESULT ret = VerifyTexture(dwStage, lpTex);
  1530. if (ret != D3D_OK)
  1531. return ret;
  1532. #endif
  1533. CBaseTexture *lpTexI = CBaseTexture::SafeCast(lpTex);
  1534. if (m_lpD3DMappedTexI[dwStage] == lpTexI)
  1535. {
  1536. return D3D_OK;
  1537. }
  1538. if (m_lpD3DMappedTexI[dwStage])
  1539. {
  1540. m_lpD3DMappedTexI[dwStage]->DecrementUseCount();
  1541. }
  1542. m_lpD3DMappedTexI[dwStage] = lpTexI;
  1543. if (lpTexI)
  1544. {
  1545. lpTexI->IncrementUseCount();
  1546. }
  1547. m_dwStageDirty |= (1 << dwStage);
  1548. // Need to call UpdateTextures()
  1549. m_dwRuntimeFlags |= D3DRT_NEED_TEXTURE_UPDATE;
  1550. return D3D_OK;
  1551. }
  1552. //---------------------------------------------------------------------
  1553. #undef DPF_MODNAME
  1554. #define DPF_MODNAME "CD3DBase::GetTexture"
  1555. HRESULT D3DAPI
  1556. CD3DBase::GetTexture(DWORD dwStage,
  1557. IDirect3DBaseTexture8 **lplpTex)
  1558. {
  1559. API_ENTER(this); // Takes D3D Lock if necessary
  1560. #if DBG
  1561. if (dwStage >= D3DHAL_TSS_MAXSTAGES)
  1562. {
  1563. D3D_ERR("Invalid texture stage or state index. GetTexture failed.");
  1564. return D3DERR_INVALIDCALL;
  1565. }
  1566. #endif
  1567. if (!VALID_WRITEPTR(lplpTex, sizeof(LPVOID)))
  1568. {
  1569. D3D_ERR("Invalid pointer to IDirect3DBaseTexture8*. GetTexture failed.");
  1570. return D3DERR_INVALIDCALL;
  1571. }
  1572. if (m_lpD3DMappedTexI[dwStage])
  1573. {
  1574. switch(m_lpD3DMappedTexI[dwStage]->GetBufferDesc()->Type)
  1575. {
  1576. case D3DRTYPE_TEXTURE:
  1577. *lplpTex = static_cast<IDirect3DTexture8*>(static_cast<CMipMap*>(m_lpD3DMappedTexI[dwStage]));
  1578. break;
  1579. case D3DRTYPE_CUBETEXTURE:
  1580. *lplpTex = static_cast<IDirect3DCubeTexture8*>(static_cast<CCubeMap*>(m_lpD3DMappedTexI[dwStage]));
  1581. break;
  1582. case D3DRTYPE_VOLUMETEXTURE:
  1583. *lplpTex = static_cast<IDirect3DVolumeTexture8*>(static_cast<CMipVolume*>(m_lpD3DMappedTexI[dwStage]));
  1584. break;
  1585. }
  1586. (*lplpTex)->AddRef();
  1587. }
  1588. else
  1589. {
  1590. *lplpTex = NULL;
  1591. }
  1592. return D3D_OK;
  1593. }
  1594. //---------------------------------------------------------------------
  1595. #undef DPF_MODNAME
  1596. #define DPF_MODNAME "CD3DBase::SetTextureStageState"
  1597. HRESULT D3DAPI
  1598. CD3DBase::SetTextureStageState(DWORD dwStage,
  1599. D3DTEXTURESTAGESTATETYPE dwState,
  1600. DWORD dwValue)
  1601. {
  1602. API_ENTER(this); // Takes D3D Lock if necessary
  1603. #if DBG
  1604. if ( (dwStage >= D3DHAL_TSS_MAXSTAGES) ||
  1605. (dwState == 0) ||
  1606. (dwState >= D3DTSS_MAX) ||
  1607. (dwState == 12) ) // D3DTSS_ADDRESS no longer valid
  1608. {
  1609. D3D_ERR("Invalid texture stage or state index. SetTextureStageState failed.");
  1610. return D3DERR_INVALIDCALL;
  1611. }
  1612. #endif //DBG
  1613. try
  1614. {
  1615. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1616. m_pStateSets->InsertTextureStageState(dwStage, dwState, dwValue);
  1617. else
  1618. m_pDDI->SetTSS(dwStage, dwState, dwValue);
  1619. }
  1620. catch(HRESULT ret)
  1621. {
  1622. DPF_ERR("SetTextureStageState failed.");
  1623. return ret;
  1624. }
  1625. return D3D_OK;
  1626. }
  1627. //---------------------------------------------------------------------
  1628. #undef DPF_MODNAME
  1629. #define DPF_MODNAME "CD3DBase::SetTextureStageStateFast"
  1630. HRESULT D3DAPI
  1631. CD3DBase::SetTextureStageStateFast(DWORD dwStage,
  1632. D3DTEXTURESTAGESTATETYPE dwState,
  1633. DWORD dwValue)
  1634. {
  1635. #if DBG
  1636. if ( (dwStage >= D3DHAL_TSS_MAXSTAGES) ||
  1637. (dwState == 0) ||
  1638. (dwState >= D3DTSS_MAX) ||
  1639. (dwState == 12) ) // D3DTSS_ADDRESS no longer valid
  1640. {
  1641. D3D_ERR("Invalid texture stage or state index. SetTextureStageState failed.");
  1642. return D3DERR_INVALIDCALL;
  1643. }
  1644. #endif //DBG
  1645. DXGASSERT((BehaviorFlags() & D3DCREATE_MULTITHREADED) == 0);
  1646. try
  1647. {
  1648. m_pDDI->SetTSS(dwStage, dwState, dwValue);
  1649. }
  1650. catch(HRESULT ret)
  1651. {
  1652. DPF_ERR("SetTextureStageState failed.");
  1653. return ret;
  1654. }
  1655. return D3D_OK;
  1656. }
  1657. //---------------------------------------------------------------------
  1658. #undef DPF_MODNAME
  1659. #define DPF_MODNAME "CD3DBase::LightEnable"
  1660. HRESULT D3DAPI
  1661. CD3DBase::LightEnable(DWORD dwLightIndex,
  1662. BOOL bEnable)
  1663. {
  1664. API_ENTER(this); // Takes D3D Lock if necessary
  1665. try
  1666. {
  1667. // If light was never created, we create a default light
  1668. if (dwLightIndex >= m_pCreatedLights->GetSize() ||
  1669. !m_pCreatedLights->IsBitSet(dwLightIndex))
  1670. {
  1671. // Set default value to the light
  1672. D3DLIGHT8 light;
  1673. memset(&light, 0, sizeof(light));
  1674. light.Type = D3DLIGHT_DIRECTIONAL;
  1675. light.Direction.x = D3DVAL(0);
  1676. light.Direction.y = D3DVAL(0);
  1677. light.Direction.z = D3DVAL(1);
  1678. light.Diffuse.r = D3DVAL(1);
  1679. light.Diffuse.g = D3DVAL(1);
  1680. light.Diffuse.b = D3DVAL(1);
  1681. // When a new light is created we need to actually create it even
  1682. // in the record mode. So we clear record flag, create light and
  1683. // restore the flag.
  1684. DWORD OldBit = m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE;
  1685. m_dwRuntimeFlags &= ~D3DRT_RECORDSTATEMODE;
  1686. HRESULT ret = SetLight(dwLightIndex, &light);
  1687. m_dwRuntimeFlags |= OldBit;
  1688. if (ret != S_OK)
  1689. return ret;
  1690. }
  1691. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1692. m_pStateSets->InsertLightEnable(dwLightIndex, bEnable);
  1693. else
  1694. LightEnableI(dwLightIndex, bEnable);
  1695. }
  1696. catch (HRESULT ret)
  1697. {
  1698. DPF_ERR("LightEnable failed.");
  1699. return ret;
  1700. }
  1701. return D3D_OK;
  1702. }
  1703. //---------------------------------------------------------------------
  1704. #undef DPF_MODNAME
  1705. #define DPF_MODNAME "CD3DBase::GetInfo"
  1706. HRESULT D3DAPI
  1707. CD3DBase::GetInfo(DWORD dwDevInfoID,
  1708. LPVOID pDevInfoStruct,
  1709. DWORD dwSize)
  1710. {
  1711. API_ENTER(this); // Takes D3D Lock if necessary
  1712. if (dwSize == 0 || !VALID_D3DDEVINFOSTRUCT_PTR(pDevInfoStruct, dwSize))
  1713. {
  1714. D3D_ERR("Invalid structure pointer or size. GetInfo failed.");
  1715. return D3DERR_INVALIDCALL;
  1716. }
  1717. memset(pDevInfoStruct, 0, dwSize);
  1718. if (dwDevInfoID < D3DDEVINFOID_VCACHE)
  1719. {
  1720. D3D_ERR("DX7 DevInfo IDs not supported in DX8. GetInfo failed.");
  1721. return E_FAIL;
  1722. }
  1723. #if DBG
  1724. if (m_dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)
  1725. {
  1726. DPF(2, "GetInfo called within a scene");
  1727. }
  1728. #endif
  1729. try
  1730. {
  1731. if( !IS_DX7HAL_DEVICE(this) ) // must be at least DX7
  1732. {
  1733. DPF( 1, "Device information query unsupported" );
  1734. return E_FAIL;
  1735. }
  1736. m_pDDI->FlushStates();
  1737. }
  1738. catch(HRESULT hr)
  1739. {
  1740. DPF_ERR("GetInfo failed.");
  1741. return hr;
  1742. }
  1743. D3D8_GETDRIVERSTATEDATA dsd;
  1744. dsd.dwFlags = dwDevInfoID;
  1745. dsd.dwhContext = m_pDDI->GetDeviceContext();
  1746. dsd.lpdwStates = (LPDWORD)pDevInfoStruct;
  1747. dsd.dwLength = dwSize;
  1748. HRESULT hr;
  1749. hr = GetHalCallbacks()->GetDriverState(&dsd);
  1750. if (hr != DDHAL_DRIVER_HANDLED)
  1751. {
  1752. DPF( 1, "Device information query unsupported" );
  1753. memset(pDevInfoStruct, 0, dwSize);
  1754. return S_FALSE;
  1755. }
  1756. else if (dsd.ddRVal != DD_OK)
  1757. {
  1758. D3D_ERR("Driver failed query. GetInfo failed.");
  1759. memset(pDevInfoStruct, 0, dwSize);
  1760. return E_FAIL;
  1761. }
  1762. return D3D_OK;
  1763. }
  1764. //---------------------------------------------------------------------
  1765. #undef DPF_MODNAME
  1766. #define DPF_MODNAME "CD3DBase::SetCurrentTexturePalette"
  1767. HRESULT D3DAPI
  1768. CD3DBase::SetCurrentTexturePalette(UINT PaletteNumber)
  1769. {
  1770. API_ENTER(this); // Takes D3D Lock if necessary
  1771. try
  1772. {
  1773. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1774. {
  1775. m_pStateSets->InsertCurrentTexturePalette(PaletteNumber);
  1776. }
  1777. else
  1778. {
  1779. #if DBG
  1780. if (PaletteNumber >= m_pPaletteArray->GetSize())
  1781. {
  1782. D3D_ERR("Palette not defined. SetCurrentTexturePalette failed.");
  1783. return D3DERR_INVALIDCALL;
  1784. }
  1785. #endif
  1786. if(PaletteNumber != m_dwPalette)
  1787. {
  1788. m_dwPalette = PaletteNumber;
  1789. // Need to call UpdateTextures()
  1790. m_dwRuntimeFlags |= D3DRT_NEED_TEXTURE_UPDATE;
  1791. }
  1792. }
  1793. }
  1794. catch(HRESULT ret)
  1795. {
  1796. DPF_ERR("SetCurrentTexturePalette failed.");
  1797. return ret;
  1798. }
  1799. return S_OK;
  1800. }
  1801. //---------------------------------------------------------------------
  1802. #undef DPF_MODNAME
  1803. #define DPF_MODNAME "CD3DBase::GetCurrentTexturePalette"
  1804. HRESULT D3DAPI
  1805. CD3DBase::GetCurrentTexturePalette(UINT *PaletteNumber)
  1806. {
  1807. API_ENTER(this); // Takes D3D Lock if necessary
  1808. #if DBG
  1809. if (!VALID_PTR(PaletteNumber, sizeof(UINT)))
  1810. {
  1811. D3D_ERR("Invalid PaletteNumber pointer. GetCurrentTexturePalette failed.");
  1812. return D3DERR_INVALIDCALL;
  1813. }
  1814. #endif
  1815. *PaletteNumber = m_dwPalette;
  1816. return S_OK;
  1817. }
  1818. //---------------------------------------------------------------------
  1819. #undef DPF_MODNAME
  1820. #define DPF_MODNAME "CD3DBase::SetPaletteEntries"
  1821. HRESULT D3DAPI
  1822. CD3DBase::SetPaletteEntries(UINT PaletteNumber, CONST PALETTEENTRY *pEntries)
  1823. {
  1824. API_ENTER(this); // Takes D3D Lock if necessary
  1825. #if DBG
  1826. if (!VALID_PTR(pEntries, sizeof(PALETTEENTRY) * 256))
  1827. {
  1828. D3D_ERR("Invalid Entries pointer. SetPaletteEntries failed.");
  1829. return D3DERR_INVALIDCALL;
  1830. }
  1831. if (PaletteNumber > 0xffff)
  1832. {
  1833. D3D_ERR("Illegal PaletteNumber value. SetPaletteEntries failed.");
  1834. return D3DERR_INVALIDCALL;
  1835. }
  1836. #endif
  1837. if (Enum()->GetAppSdkVersion() > D3D_SDK_VERSION_DX8)
  1838. {
  1839. bool bAlpha=false;
  1840. #if DBG
  1841. bool bAllTransparent = true;
  1842. #endif
  1843. for (int i=0;i<256;i++)
  1844. {
  1845. if (pEntries[i].peFlags != 0xff)
  1846. {
  1847. bAlpha = true;
  1848. }
  1849. #if DBG
  1850. if (pEntries[i].peFlags != 0)
  1851. {
  1852. bAllTransparent = false;
  1853. }
  1854. #endif
  1855. }
  1856. #if DBG
  1857. if (bAllTransparent)
  1858. {
  1859. D3D_WARN(0,"Every entry in palette has alpha (peFlags) == 0. Texture may not appear.");
  1860. }
  1861. #endif
  1862. if (bAlpha && (0 == (GetD3DCaps()->TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)) )
  1863. {
  1864. D3D_ERR("Application cannot set a non-opaque palette alpha value (peFlags other than 0xFF) unless the device exposes D3DPTEXTURECAPS_ALPHAPALETTE. SetPaletteEntries failed.");
  1865. return D3DERR_INVALIDCALL;
  1866. }
  1867. }
  1868. HRESULT hr = m_pPaletteArray->Grow(PaletteNumber);
  1869. if(FAILED(hr))
  1870. {
  1871. D3D_ERR("Failed to set palette entries. SetPaletteEntries failed.");
  1872. return hr;
  1873. }
  1874. CPalette *pal = static_cast<CPalette*>((*m_pPaletteArray)[PaletteNumber].m_pObj);
  1875. if(pal == 0)
  1876. {
  1877. pal = new CPalette;
  1878. (*m_pPaletteArray)[PaletteNumber].m_pObj = pal;
  1879. if(pal == 0)
  1880. {
  1881. D3D_ERR("Could not allocate space to hold palette. SetPaletteEntries failed.");
  1882. return E_OUTOFMEMORY;
  1883. }
  1884. }
  1885. memcpy(pal->m_pEntries, pEntries, sizeof(PALETTEENTRY) * 256);
  1886. pal->m_dirty = TRUE;
  1887. if(m_dwPalette == PaletteNumber)
  1888. {
  1889. // Need to call UpdateTextures()
  1890. m_dwRuntimeFlags |= D3DRT_NEED_TEXTURE_UPDATE;
  1891. }
  1892. return S_OK;
  1893. }
  1894. //---------------------------------------------------------------------
  1895. #undef DPF_MODNAME
  1896. #define DPF_MODNAME "CD3DBase::GetPaletteEntries"
  1897. HRESULT D3DAPI
  1898. CD3DBase::GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY *pEntries)
  1899. {
  1900. API_ENTER(this); // Takes D3D Lock if necessary
  1901. #if DBG
  1902. if (!VALID_WRITEPTR(pEntries, sizeof(PALETTEENTRY) * 256))
  1903. {
  1904. D3D_ERR("Invalid ppEntries pointer. GetPaletteEntries failed.");
  1905. return D3DERR_INVALIDCALL;
  1906. }
  1907. if (PaletteNumber >= m_pPaletteArray->GetSize())
  1908. {
  1909. D3D_ERR("Palette not defined. GetPaletteEntries failed.");
  1910. return D3DERR_INVALIDCALL;
  1911. }
  1912. #endif
  1913. CPalette *pal = static_cast<CPalette*>((*m_pPaletteArray)[PaletteNumber].m_pObj);
  1914. #if DBG
  1915. if(pal == 0)
  1916. {
  1917. D3D_ERR("Palette not defined. GetPaletteEntries failed.");
  1918. return D3DERR_INVALIDCALL;
  1919. }
  1920. #endif
  1921. memcpy(pEntries, pal->m_pEntries, sizeof(PALETTEENTRY) * 256);
  1922. return S_OK;
  1923. }
  1924. //-----------------------------------------------------------------------------
  1925. #undef DPF_MODNAME
  1926. #define DPF_MODNAME "CD3DBase::SetClipPlaneI"
  1927. void CD3DBase::SetClipPlaneI(DWORD dwPlaneIndex,
  1928. CONST D3DVALUE* pPlaneEquation)
  1929. {
  1930. m_pDDI->SetClipPlane(dwPlaneIndex, pPlaneEquation);
  1931. }
  1932. //-----------------------------------------------------------------------------
  1933. #undef DPF_MODNAME
  1934. #define DPF_MODNAME "CD3DBase::SetClipPlane"
  1935. HRESULT D3DAPI
  1936. CD3DBase::SetClipPlane(DWORD dwPlaneIndex,
  1937. CONST D3DVALUE* pPlaneEquation)
  1938. {
  1939. API_ENTER(this); // Takes D3D Lock if necessary
  1940. #if DBG
  1941. if (dwPlaneIndex >= m_dwMaxUserClipPlanes)
  1942. {
  1943. D3D_ERR("Plane index is too big. SetClipPlane failed.");
  1944. return D3DERR_INVALIDCALL;
  1945. }
  1946. if (!VALID_PTR(pPlaneEquation, sizeof(D3DVALUE)*4))
  1947. {
  1948. D3D_ERR("Invalid plane pointer. SetClipPlane failed.");
  1949. return D3DERR_INVALIDCALL;
  1950. }
  1951. #endif
  1952. try
  1953. {
  1954. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1955. m_pStateSets->InsertClipPlane(dwPlaneIndex, pPlaneEquation);
  1956. else
  1957. SetClipPlaneI(dwPlaneIndex, pPlaneEquation);
  1958. }
  1959. catch(HRESULT ret)
  1960. {
  1961. DPF_ERR("SetClipPlane failed.");
  1962. return ret;
  1963. }
  1964. return D3D_OK;
  1965. }
  1966. //-----------------------------------------------------------------------------
  1967. #undef DPF_MODNAME
  1968. #define DPF_MODNAME "CD3DBase::SetStreamSource"
  1969. HRESULT D3DAPI
  1970. CD3DBase::SetStreamSource(UINT StreamNumber,
  1971. IDirect3DVertexBuffer8 *pStreamData,
  1972. UINT Stride)
  1973. {
  1974. API_ENTER(this); // Takes D3D Lock if necessary
  1975. #if DBG
  1976. // Validate Parameters
  1977. if (StreamNumber >= m_dwNumStreams)
  1978. {
  1979. D3D_ERR("Stream number should be less than %d. SetStreamSource failed.", m_dwNumStreams);
  1980. return D3DERR_INVALIDCALL;
  1981. }
  1982. if (Stride > this->GetD3DCaps()->MaxStreamStride)
  1983. {
  1984. D3D_ERR("Stream stride is too big. Check device caps. SetStreamSource failed.");
  1985. return D3DERR_INVALIDCALL;
  1986. }
  1987. // NULL is allowed to be passed
  1988. if (pStreamData)
  1989. {
  1990. CVertexBuffer* pVB = static_cast<CVertexBuffer*>(pStreamData);
  1991. if (pVB->Device() != this)
  1992. {
  1993. D3D_ERR("VertexBuffer not created with this Device. SetStreamSource fails.");
  1994. return D3DERR_INVALIDCALL;
  1995. }
  1996. }
  1997. #endif
  1998. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1999. {
  2000. try
  2001. {
  2002. m_pStateSets->InsertStreamSource(StreamNumber, static_cast<CVertexBuffer *>(pStreamData), Stride);
  2003. }
  2004. catch(HRESULT hr)
  2005. {
  2006. DPF_ERR("SetStreamSource failed.");
  2007. return hr;
  2008. }
  2009. return S_OK;
  2010. }
  2011. CVStream* pStream = &m_pStream[StreamNumber];
  2012. if (pStream->m_pVB == static_cast<CVertexBuffer *>(pStreamData) &&
  2013. Stride == pStream->m_dwStride)
  2014. return D3D_OK;
  2015. // Release previously set vertex buffer
  2016. if (pStream->m_pVB)
  2017. {
  2018. m_pDDI->VBReleased(pStream->m_pVB);
  2019. pStream->m_pVB->DecrementUseCount();
  2020. pStream->m_pVB = NULL;
  2021. }
  2022. pStream->m_pData = NULL;
  2023. pStream->m_pVB = static_cast<CVertexBuffer *>(pStreamData);
  2024. if (pStreamData)
  2025. {
  2026. pStream->m_pVB->IncrementUseCount();
  2027. pStream->m_dwStride = Stride;
  2028. #if DBG
  2029. pStream->m_dwSize = pStream->m_pVB->GetBufferDesc()->Size;
  2030. #endif // DBG
  2031. m_dwStreamDirty |= (1 << StreamNumber);
  2032. m_dwRuntimeFlags |= D3DRT_NEED_VB_UPDATE; // Need to call UpdateDirtyStreams()
  2033. #if DBG
  2034. if (Stride == 0)
  2035. pStream->m_dwNumVertices = 1;
  2036. else
  2037. pStream->m_dwNumVertices = pStream->m_dwSize / Stride;
  2038. #endif
  2039. try
  2040. {
  2041. SetStreamSourceI(pStream);
  2042. }
  2043. catch(HRESULT hr)
  2044. {
  2045. DPF_ERR("SetStreamSource failed.");
  2046. return hr;
  2047. }
  2048. }
  2049. return S_OK;
  2050. }
  2051. //-----------------------------------------------------------------------------
  2052. #undef DPF_MODNAME
  2053. #define DPF_MODNAME "CD3DBase::SetStreamSourceI"
  2054. void
  2055. CD3DBase::SetStreamSourceI(CVStream* pStream)
  2056. {
  2057. }
  2058. #ifdef FAST_PATH
  2059. //-----------------------------------------------------------------------------
  2060. #undef DPF_MODNAME
  2061. #define DPF_MODNAME "CD3DBase::SetStreamSourceFast"
  2062. HRESULT D3DAPI
  2063. CD3DBase::SetStreamSourceFast(UINT StreamNumber,
  2064. IDirect3DVertexBuffer8 *pStreamData,
  2065. UINT Stride)
  2066. {
  2067. #if DBG
  2068. // Validate Parameters
  2069. if (StreamNumber >= m_dwNumStreams)
  2070. {
  2071. D3D_ERR("Stream number should be less than %d. SetStreamSource failed.", m_dwNumStreams);
  2072. return D3DERR_INVALIDCALL;
  2073. }
  2074. if (Stride > this->GetD3DCaps()->MaxStreamStride)
  2075. {
  2076. D3D_ERR("Stream stride is too big. Check device caps. SetStreamSource failed.");
  2077. return D3DERR_INVALIDCALL;
  2078. }
  2079. // NULL is allowed to be passed
  2080. if (pStreamData)
  2081. {
  2082. CVertexBuffer* pVB = static_cast<CVertexBuffer*>(pStreamData);
  2083. if (pVB->Device() != this)
  2084. {
  2085. D3D_ERR("VertexBuffer not created with this Device. SetStreamSource fails.");
  2086. return D3DERR_INVALIDCALL;
  2087. }
  2088. }
  2089. #endif
  2090. DXGASSERT((m_dwRuntimeFlags & (D3DRT_RECORDSTATEMODE | D3DRT_RSSOFTWAREPROCESSING)) == 0 &&
  2091. (BehaviorFlags() & D3DCREATE_MULTITHREADED) == 0);
  2092. CVStream* pStream = &m_pStream[StreamNumber];
  2093. if (pStream->m_pVB == static_cast<CVertexBuffer *>(pStreamData) &&
  2094. Stride == pStream->m_dwStride)
  2095. return D3D_OK;
  2096. // Release previously set vertex buffer
  2097. if (pStream->m_pVB)
  2098. {
  2099. // We don't call VBReleased() here because there is no need to update the DDI object since
  2100. // the fe/PSGP never does the redundant stream set check. This check is done in DrawPrim,
  2101. // DrawIndexPrim and DrawClippedPrim. It is important to call VBReleased whenever fe/PSGP
  2102. // is being used because it is possible that the user freed and recreated the same VB with
  2103. // the same address and then the redundant set check will not work.
  2104. pStream->m_pVB->DecrementUseCount();
  2105. pStream->m_pVB = NULL;
  2106. }
  2107. pStream->m_pData = NULL;
  2108. pStream->m_pVB = static_cast<CVertexBuffer *>(pStreamData);
  2109. if (pStreamData)
  2110. {
  2111. pStream->m_pVB->IncrementUseCount();
  2112. pStream->m_dwStride = Stride;
  2113. #if DBG
  2114. pStream->m_dwSize = pStream->m_pVB->GetBufferDesc()->Size;
  2115. #endif // DBG
  2116. m_dwStreamDirty |= (1 << StreamNumber);
  2117. m_dwRuntimeFlags |= D3DRT_NEED_VB_UPDATE; // Need to call UpdateDirtyStreams()
  2118. #if DBG
  2119. if (Stride == 0)
  2120. pStream->m_dwNumVertices = 1;
  2121. else
  2122. pStream->m_dwNumVertices = pStream->m_dwSize / Stride;
  2123. #endif
  2124. }
  2125. if (!IS_DX8HAL_DEVICE(this))
  2126. {
  2127. PickDrawPrimFn();
  2128. }
  2129. return S_OK;
  2130. }
  2131. #endif // FAST_PATH
  2132. //-----------------------------------------------------------------------------
  2133. #undef DPF_MODNAME
  2134. #define DPF_MODNAME "CD3DBase::GetStreamSource"
  2135. HRESULT
  2136. CD3DBase::GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer8 **ppStreamData,
  2137. UINT* pStride)
  2138. {
  2139. API_ENTER(this); // Takes D3D Lock if necessary
  2140. #if DBG
  2141. if (StreamNumber >= m_dwNumStreams)
  2142. {
  2143. D3D_ERR("Stream number should be less than %d. GetStreamSource failed.", m_dwNumStreams);
  2144. return D3DERR_INVALIDCALL;
  2145. }
  2146. if (!VALID_WRITEPTR(ppStreamData, sizeof(IDirect3DVertexBuffer8*)))
  2147. {
  2148. D3D_ERR("Invalid stream data pointer. GetStreamSource failed.");
  2149. return D3DERR_INVALIDCALL;
  2150. }
  2151. if (!VALID_WRITEPTR(pStride, sizeof(UINT*)))
  2152. {
  2153. D3D_ERR("Invalid stride pointer. GetStreamSource failed.");
  2154. return D3DERR_INVALIDCALL;
  2155. }
  2156. #endif
  2157. CVStream* pStream = &m_pStream[StreamNumber];
  2158. *ppStreamData = (pStream) ? (pStream->m_pVB) : (NULL);
  2159. if (pStream->m_pVB)
  2160. pStream->m_pVB->AddRef();
  2161. *pStride = (pStream) ? (pStream->m_dwStride) : (0);
  2162. return S_OK;
  2163. }
  2164. //-----------------------------------------------------------------------------
  2165. #undef DPF_MODNAME
  2166. #define DPF_MODNAME "CD3DBase::SetIndices"
  2167. HRESULT D3DAPI
  2168. CD3DBase::SetIndices(IDirect3DIndexBuffer8 *pIndexData, UINT BaseVertexIndex)
  2169. {
  2170. API_ENTER(this); // Takes D3D Lock if necessary
  2171. try
  2172. {
  2173. CIndexBuffer * pVB = static_cast<CIndexBuffer*>(pIndexData);
  2174. #if DBG
  2175. if (pVB && pVB->Device() != this)
  2176. {
  2177. D3D_ERR("IndexBuffer not created with this Device. SetIndices fails.");
  2178. return D3DERR_INVALIDCALL;
  2179. }
  2180. #endif
  2181. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  2182. {
  2183. m_pStateSets->InsertIndices(pVB, BaseVertexIndex);
  2184. return S_OK;
  2185. }
  2186. if (m_pIndexStream->m_pVBI == static_cast<CIndexBuffer *>(pIndexData))
  2187. {
  2188. m_pIndexStream->m_dwBaseIndex = BaseVertexIndex;
  2189. return D3D_OK;
  2190. }
  2191. // Release previously set vertex buffer
  2192. if (m_pIndexStream->m_pVBI)
  2193. {
  2194. m_pDDI->VBIReleased(m_pIndexStream->m_pVBI);
  2195. m_pIndexStream->m_pVBI->DecrementUseCount();
  2196. m_pIndexStream->m_pVBI = NULL;
  2197. }
  2198. m_pIndexStream->m_pVBI = static_cast<CIndexBuffer *>(pIndexData);
  2199. if (pVB)
  2200. {
  2201. switch (pVB->GetBufferDesc()->Format)
  2202. {
  2203. case D3DFMT_INDEX16:
  2204. m_pIndexStream->m_dwStride = 2;
  2205. break;
  2206. case D3DFMT_INDEX32:
  2207. #if DBG
  2208. if (GetD3DCaps()->MaxVertexIndex <= 0xFFFF)
  2209. D3D_THROW(D3DERR_INVALIDCALL, "Device does not support 32-bit indices");
  2210. #endif
  2211. m_pIndexStream->m_dwStride = 4;
  2212. break;
  2213. default:
  2214. D3D_THROW(D3DERR_INVALIDCALL, "Invalid index buffer format");
  2215. }
  2216. #if DBG
  2217. m_pIndexStream->m_dwSize = pVB->GetBufferDesc()->Size;
  2218. #endif
  2219. m_pIndexStream->m_dwBaseIndex = BaseVertexIndex;
  2220. m_pIndexStream->m_pData = NULL;
  2221. #if DBG
  2222. m_pIndexStream->m_dwNumVertices = m_pIndexStream->m_dwSize /
  2223. m_pIndexStream->m_dwStride;
  2224. #endif
  2225. m_pIndexStream->m_pVBI->IncrementUseCount();
  2226. m_dwStreamDirty |= (1 << __NUMSTREAMS);
  2227. m_dwRuntimeFlags |= D3DRT_NEED_VB_UPDATE; // Need to call UpdateDirtyStreams()
  2228. SetIndicesI(m_pIndexStream);
  2229. }
  2230. }
  2231. catch(HRESULT hr)
  2232. {
  2233. DPF_ERR("SetIndices failed.");
  2234. return hr;
  2235. }
  2236. return S_OK;
  2237. }
  2238. //-----------------------------------------------------------------------------
  2239. #undef DPF_MODNAME
  2240. #define DPF_MODNAME "CD3DBase::SetIndicesI"
  2241. void
  2242. CD3DBase::SetIndicesI(CVIndexStream* pStream)
  2243. {
  2244. }
  2245. //-----------------------------------------------------------------------------
  2246. #undef DPF_MODNAME
  2247. #define DPF_MODNAME "CD3DBase::GetIndices"
  2248. HRESULT D3DAPI
  2249. CD3DBase::GetIndices(IDirect3DIndexBuffer8 **ppIndexData, UINT* pBaseVertexIndex)
  2250. {
  2251. API_ENTER(this); // Takes D3D Lock if necessary
  2252. #if DBG
  2253. if (!VALID_WRITEPTR(ppIndexData, sizeof(IDirect3DIndexBuffer8*)))
  2254. {
  2255. D3D_ERR("Invalid index data pointer. GetIndices failed.");
  2256. return D3DERR_INVALIDCALL;
  2257. }
  2258. if (!VALID_WRITEPTR(pBaseVertexIndex, sizeof(UINT*)))
  2259. {
  2260. D3D_ERR("Invalid base index pointer. GetIndices failed.");
  2261. return D3DERR_INVALIDCALL;
  2262. }
  2263. #endif //DBG
  2264. *ppIndexData = m_pIndexStream->m_pVBI;
  2265. if (m_pIndexStream->m_pVBI)
  2266. m_pIndexStream->m_pVBI->AddRef();
  2267. *pBaseVertexIndex = m_pIndexStream->m_dwBaseIndex;
  2268. return S_OK;
  2269. }
  2270. #ifdef FAST_PATH
  2271. //-----------------------------------------------------------------------------
  2272. #undef DPF_MODNAME
  2273. #define DPF_MODNAME "CD3DBase::SetIndicesFast"
  2274. HRESULT D3DAPI
  2275. CD3DBase::SetIndicesFast(IDirect3DIndexBuffer8 *pIndexData, UINT BaseVertexIndex)
  2276. {
  2277. CIndexBuffer * pVB = static_cast<CIndexBuffer*>(pIndexData);
  2278. #if DBG
  2279. if (pVB && pVB->Device() != this)
  2280. {
  2281. D3D_ERR("IndexBuffer not created with this device. SetIndices fails.");
  2282. return D3DERR_INVALIDCALL;
  2283. }
  2284. #endif
  2285. DXGASSERT((m_dwRuntimeFlags & (D3DRT_RECORDSTATEMODE | D3DRT_RSSOFTWAREPROCESSING)) == 0 &&
  2286. (BehaviorFlags() & D3DCREATE_MULTITHREADED) == 0);
  2287. if (m_pIndexStream->m_pVBI == pVB)
  2288. {
  2289. m_pIndexStream->m_dwBaseIndex = BaseVertexIndex;
  2290. return D3D_OK;
  2291. }
  2292. // Release previously set index buffer
  2293. if (m_pIndexStream->m_pVBI)
  2294. {
  2295. // We don't call VBReleased() here because there is no need to update the DDI object since
  2296. // the fe/PSGP never does the redundant stream set check. This check is done in DrawPrim,
  2297. // DrawIndexPrim and DrawClippedPrim. It is important to call VBReleased whenever fe/PSGP
  2298. // is being used because it is possible that the user freed and recreated the same VB with
  2299. // the same address and then the redundant set check will not work.
  2300. m_pIndexStream->m_pVBI->DecrementUseCount();
  2301. m_pIndexStream->m_pVBI = NULL;
  2302. }
  2303. m_pIndexStream->m_pVBI = static_cast<CIndexBuffer *>(pIndexData);
  2304. if (pVB)
  2305. {
  2306. switch (pVB->GetBufferDesc()->Format)
  2307. {
  2308. case D3DFMT_INDEX16:
  2309. m_pIndexStream->m_dwStride = 2;
  2310. break;
  2311. case D3DFMT_INDEX32:
  2312. #if DBG
  2313. if (GetD3DCaps()->MaxVertexIndex <= 0xFFFF)
  2314. {
  2315. DPF_ERR("Device does not support 32-bit indices. SetIndices failed.");
  2316. return D3DERR_INVALIDCALL;
  2317. }
  2318. #endif
  2319. m_pIndexStream->m_dwStride = 4;
  2320. break;
  2321. default:
  2322. DPF_ERR("Invalid index buffer format. SetIndices failed.");
  2323. return D3DERR_INVALIDCALL;
  2324. }
  2325. #if DBG
  2326. m_pIndexStream->m_dwSize = pVB->GetBufferDesc()->Size;
  2327. #endif
  2328. m_pIndexStream->m_dwBaseIndex = BaseVertexIndex;
  2329. m_pIndexStream->m_pData = NULL;
  2330. #if DBG
  2331. m_pIndexStream->m_dwNumVertices = m_pIndexStream->m_dwSize /
  2332. m_pIndexStream->m_dwStride;
  2333. #endif
  2334. m_pIndexStream->m_pVBI->IncrementUseCount();
  2335. m_dwStreamDirty |= (1 << __NUMSTREAMS);
  2336. m_dwRuntimeFlags |= D3DRT_NEED_VB_UPDATE; // Need to call UpdateDirtyStreams()
  2337. }
  2338. return S_OK;
  2339. }
  2340. #endif // FAST_PATH
  2341. //-----------------------------------------------------------------------------
  2342. #undef DPF_MODNAME
  2343. #define DPF_MODNAME "CD3DBase::CreateVertexShader"
  2344. HRESULT D3DAPI
  2345. CD3DBase::CreateVertexShader(CONST DWORD* pdwDeclaration,
  2346. CONST DWORD* pdwFunction,
  2347. LPDWORD pdwHandle, DWORD Usage)
  2348. {
  2349. API_ENTER(this); // Takes D3D Lock if necessary
  2350. #if DBG
  2351. // Validate Parameters
  2352. // WARNING!! sizeof(LPVOID) is not good enough
  2353. if (!VALID_PTR(pdwDeclaration, sizeof(LPVOID)))
  2354. {
  2355. D3D_ERR("Invalid shader declaration pointer. CreateVertexShader failed.");
  2356. return D3DERR_INVALIDCALL;
  2357. }
  2358. // WARNING!! sizeof(LPVOID) is not good enough
  2359. if (pdwFunction && !VALID_PTR(pdwFunction, sizeof(LPVOID)))
  2360. {
  2361. D3D_ERR("Invalid shader function pointer. CreateVertexShader failed.");
  2362. return D3DERR_INVALIDCALL;
  2363. }
  2364. if (pdwHandle && !VALID_WRITEPTR(pdwHandle, sizeof(DWORD)))
  2365. {
  2366. D3D_ERR("Invalid shader handle pointer. CreateVertexShader failed.");
  2367. return D3DERR_INVALIDCALL;
  2368. }
  2369. if (Usage & ~D3DUSAGE_SOFTWAREPROCESSING)
  2370. {
  2371. D3D_ERR("Illegal usage value. CreateVertexShader failed.");
  2372. return D3DERR_INVALIDCALL;
  2373. }
  2374. if (pdwHandle == NULL)
  2375. {
  2376. // Temporary vertex shaders are disabled
  2377. D3D_ERR("Output handle pointer cannot be NULL. CreateVertexShader failed.");
  2378. return D3DERR_INVALIDCALL;
  2379. }
  2380. if ((pdwFunction != NULL) &&
  2381. (GetD3DCaps()->VertexShaderVersion == D3DVS_VERSION(0,0)) &&
  2382. (BehaviorFlags() & (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE)))
  2383. {
  2384. D3D_ERR("No programmable vertex shaders are supported by this device. CreateVertexShader failed.");
  2385. return D3DERR_INVALIDCALL;
  2386. }
  2387. #endif // DBG
  2388. DWORD dwHandle = m_pVShaderArray->CreateNewHandle(NULL);
  2389. HRESULT ret = S_OK;
  2390. if (dwHandle == __INVALIDHANDLE)
  2391. {
  2392. D3D_ERR("Error in creating shader handle. CreateVertexShader failed.");
  2393. return E_OUTOFMEMORY;
  2394. }
  2395. CVShader *pShader = new CVShader(m_dwNumStreams);
  2396. if (pShader == NULL)
  2397. {
  2398. D3D_ERR("Cannot allocate memory for internal shader object. CreateVertexShader failed.");
  2399. return E_OUTOFMEMORY;
  2400. }
  2401. if (Usage & D3DUSAGE_SOFTWAREPROCESSING ||
  2402. BehaviorFlags() & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
  2403. {
  2404. pShader->m_dwFlags |= CVShader::SOFTWARE;
  2405. Usage |= D3DUSAGE_SOFTWAREPROCESSING;
  2406. }
  2407. try
  2408. {
  2409. D3DCAPS8 Caps, *pCaps = NULL;
  2410. const D3DCAPS8 *pConstCaps = GetD3DCaps();
  2411. if( pConstCaps )
  2412. {
  2413. pCaps = &Caps;
  2414. memcpy(pCaps,pConstCaps,sizeof(D3DCAPS8));
  2415. pCaps->MaxStreams = m_dwNumStreams;
  2416. if( pShader->m_dwFlags & CVShader::SOFTWARE )
  2417. {
  2418. pCaps->VertexShaderVersion = D3DVS_VERSION(1, 1); // Version 1.1
  2419. pCaps->MaxVertexShaderConst = D3DVS_CONSTREG_MAX_V1_1;
  2420. }
  2421. }
  2422. if( !ValidateVertexShaderInternal(pdwFunction, pdwDeclaration, pCaps) )
  2423. {
  2424. ret = D3DERR_INVALIDCALL;
  2425. goto error;
  2426. }
  2427. // Even for the D3DCREATE_PUREDEVICE we create a shader object for
  2428. // validation
  2429. DWORD dwCodeOnlySize = 0;
  2430. DWORD dwCodeAndCommentSize = 0;
  2431. DWORD dwDeclSize = 0;
  2432. if (pdwFunction == NULL)
  2433. {
  2434. pShader->m_dwFlags |= CVShader::FIXEDFUNCTION;
  2435. pShader->m_Declaration.Parse(this, pdwDeclaration, TRUE, &dwDeclSize, Usage);
  2436. }
  2437. else
  2438. {
  2439. pShader->m_Declaration.Parse(this, pdwDeclaration, FALSE, &dwDeclSize, Usage);
  2440. HRESULT hr = ComputeShaderCodeSize(pdwFunction,
  2441. &dwCodeOnlySize,
  2442. &dwCodeAndCommentSize,
  2443. NULL);
  2444. if (hr != S_OK)
  2445. {
  2446. D3D_THROW(hr, "Unable to compute shader code size.");
  2447. }
  2448. pShader->m_pOrgFuncCode = new DWORD[dwCodeAndCommentSize];
  2449. pShader->m_pStrippedFuncCode = new DWORD[dwCodeOnlySize];
  2450. if (pShader->m_pOrgFuncCode == NULL ||
  2451. pShader->m_pStrippedFuncCode == NULL)
  2452. {
  2453. D3D_THROW(E_OUTOFMEMORY, "Could not allocate space for holding vertex shader");
  2454. }
  2455. pShader->m_OrgFuncCodeSize = dwCodeAndCommentSize;
  2456. memcpy(pShader->m_pOrgFuncCode, pdwFunction, dwCodeAndCommentSize);
  2457. pShader->m_StrippedFuncCodeSize = dwCodeOnlySize;
  2458. // copy and strip comments (instead of memcpy)
  2459. DWORD* pDst = pShader->m_pStrippedFuncCode;
  2460. CONST DWORD* pSrc = pdwFunction;
  2461. *pDst++ = *pSrc++; // copy version
  2462. while (*pSrc != 0x0000FFFF)
  2463. {
  2464. if(IsInstructionToken(*pSrc))
  2465. {
  2466. DWORD opCode = (*pSrc) & D3DSI_OPCODE_MASK;
  2467. if ( opCode == D3DSIO_COMMENT )
  2468. {
  2469. UINT DWordSize = ((*pSrc)&D3DSI_COMMENTSIZE_MASK)>>D3DSI_COMMENTSIZE_SHIFT;
  2470. pSrc += (DWordSize + 1); // comment + instruction token
  2471. }
  2472. else
  2473. {
  2474. *pDst++ = *pSrc++;
  2475. }
  2476. }
  2477. else
  2478. {
  2479. *pDst++ = *pSrc++;
  2480. }
  2481. }
  2482. *pDst++ = *pSrc++; // copy END
  2483. }
  2484. // ALways save the original declaration
  2485. pShader->m_pOrgDeclaration = new DWORD[dwDeclSize];
  2486. if (pShader->m_pOrgDeclaration == NULL)
  2487. {
  2488. D3D_THROW(E_OUTOFMEMORY, "Could not allocate space for holding vertex shader");
  2489. }
  2490. pShader->m_OrgDeclSize = dwDeclSize;
  2491. memcpy(pShader->m_pOrgDeclaration, pdwDeclaration, dwDeclSize);
  2492. m_pVShaderArray->SetObject(dwHandle, pShader);
  2493. CreateVertexShaderI(pdwDeclaration,
  2494. dwDeclSize,
  2495. pdwFunction,
  2496. dwCodeAndCommentSize, dwHandle);
  2497. }
  2498. catch(HRESULT hr)
  2499. {
  2500. ret = hr;
  2501. goto error;
  2502. }
  2503. *pdwHandle = dwHandle;
  2504. return S_OK;
  2505. error:
  2506. D3D_ERR("CreateVertexShader failed.");
  2507. delete pShader;
  2508. m_pVShaderArray->ReleaseHandle(dwHandle, FALSE);
  2509. return ret;
  2510. }
  2511. //-----------------------------------------------------------------------------
  2512. #undef DPF_MODNAME
  2513. #define DPF_MODNAME "CD3DBase::CheckVertexShaderHandle"
  2514. void CD3DBase::CheckVertexShaderHandle(DWORD dwHandle)
  2515. {
  2516. if (dwHandle == 0)
  2517. {
  2518. D3D_THROW(D3DERR_INVALIDCALL, "Invalid vertex shader handle");
  2519. }
  2520. if (D3DVSD_ISLEGACY(dwHandle))
  2521. {
  2522. if (((GetD3DCaps()->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0) &&
  2523. !FVF_TRANSFORMED(dwHandle) &&
  2524. (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING) == 0)
  2525. {
  2526. D3D_THROW(D3DERR_INVALIDCALL,
  2527. "Untransformed data cannot be handles by this device");
  2528. }
  2529. if (FAILED(ValidateFVF(dwHandle)))
  2530. {
  2531. D3D_THROW(D3DERR_INVALIDCALL, "Invalid FVF (or legacy vertex shader handle)");
  2532. }
  2533. }
  2534. else
  2535. {
  2536. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  2537. if (pShader == NULL)
  2538. {
  2539. D3D_THROW(D3DERR_INVALIDCALL, "Invalid vertex shader handle");
  2540. }
  2541. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)
  2542. {
  2543. if (!(pShader->m_dwFlags & CVShader::SOFTWARE))
  2544. {
  2545. D3D_THROW_FAIL("Vertex shader created in hardware mode cannot be used in software mode");
  2546. }
  2547. }
  2548. else
  2549. {
  2550. if (pShader->m_dwFlags & CVShader::SOFTWARE)
  2551. {
  2552. D3D_THROW_FAIL("Vertex shader created in software mode cannot be used in hardware mode");
  2553. }
  2554. }
  2555. }
  2556. }
  2557. //-----------------------------------------------------------------------------
  2558. #undef DPF_MODNAME
  2559. #define DPF_MODNAME "CD3DBase::CheckPixelShaderHandle"
  2560. void CD3DBase::CheckPixelShaderHandle(DWORD dwHandle)
  2561. {
  2562. if (dwHandle != 0)
  2563. {
  2564. CPShader* pShader = (CPShader*)m_pPShaderArray->GetObject(dwHandle);
  2565. if (pShader == NULL)
  2566. {
  2567. D3D_THROW(D3DERR_INVALIDCALL, "Invalid pixel shader handle");
  2568. }
  2569. }
  2570. }
  2571. //-----------------------------------------------------------------------------
  2572. #undef DPF_MODNAME
  2573. #define DPF_MODNAME "CD3DBase::SetVertexShader"
  2574. HRESULT D3DAPI
  2575. CD3DBase::SetVertexShader(DWORD dwHandle)
  2576. {
  2577. API_ENTER(this); // Takes D3D Lock if necessary
  2578. try
  2579. {
  2580. #if DBG
  2581. CheckVertexShaderHandle(dwHandle);
  2582. #endif
  2583. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  2584. {
  2585. if (D3DVSD_ISLEGACY(dwHandle))
  2586. {
  2587. m_pStateSets->InsertVertexShader(dwHandle, TRUE);
  2588. }
  2589. else
  2590. {
  2591. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  2592. if (pShader->m_dwFlags & CVShader::SOFTWARE)
  2593. m_pStateSets->InsertVertexShader(dwHandle, FALSE);
  2594. else
  2595. m_pStateSets->InsertVertexShader(dwHandle, TRUE);
  2596. }
  2597. }
  2598. else
  2599. {
  2600. SetVertexShaderI(dwHandle);
  2601. }
  2602. }
  2603. catch(HRESULT hr)
  2604. {
  2605. DPF_ERR("SetVertexShader failed.");
  2606. ClearVertexShaderHandle();
  2607. return hr;
  2608. }
  2609. return S_OK;
  2610. }
  2611. #ifdef FAST_PATH
  2612. //-----------------------------------------------------------------------------
  2613. #undef DPF_MODNAME
  2614. #define DPF_MODNAME "CD3DBase::SetVertexShaderFast"
  2615. HRESULT D3DAPI
  2616. CD3DBase::SetVertexShaderFast(DWORD dwHandle)
  2617. {
  2618. try
  2619. {
  2620. #if DBG
  2621. CheckVertexShaderHandle(dwHandle);
  2622. if (!D3DVSD_ISLEGACY(dwHandle))
  2623. {
  2624. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  2625. if (pShader->m_dwFlags & CVShader::SOFTWARE)
  2626. {
  2627. D3D_THROW_FAIL("Vertex shader created in software mode cannot be used in hardware mode");
  2628. }
  2629. }
  2630. #endif
  2631. DXGASSERT((m_dwRuntimeFlags & (D3DRT_RECORDSTATEMODE | D3DRT_RSSOFTWAREPROCESSING)) == 0 &&
  2632. (BehaviorFlags() & D3DCREATE_MULTITHREADED) == 0);
  2633. m_pDDI->SetVertexShaderHW(dwHandle);
  2634. }
  2635. catch(HRESULT hr)
  2636. {
  2637. DPF_ERR("SetVertexShader failed.");
  2638. ClearVertexShaderHandle();
  2639. return hr;
  2640. }
  2641. return S_OK;
  2642. }
  2643. #endif // FAST_PATH
  2644. //-----------------------------------------------------------------------------
  2645. #undef DPF_MODNAME
  2646. #define DPF_MODNAME "CD3DBase::GetVertexShader"
  2647. HRESULT D3DAPI
  2648. CD3DBase::GetVertexShader(LPDWORD pdwHandle)
  2649. {
  2650. API_ENTER(this);
  2651. D3D_ERR("GetVertexShader does not work in pure-device. GetVertexShader failed.");
  2652. return D3DERR_INVALIDCALL;
  2653. }
  2654. //-----------------------------------------------------------------------------
  2655. #undef DPF_MODNAME
  2656. #define DPF_MODNAME "CD3DBase::DeleteVertexShader"
  2657. HRESULT D3DAPI
  2658. CD3DBase::DeleteVertexShader(DWORD dwHandle)
  2659. {
  2660. API_ENTER(this); // Takes D3D Lock if necessary
  2661. #if DBG
  2662. // Validate Parameters
  2663. if (dwHandle == 0)
  2664. {
  2665. DPF_ERR( "Cannot delete a NULL vertex shader handle." );
  2666. return D3DERR_INVALIDCALL;
  2667. }
  2668. if (D3DVSD_ISLEGACY(dwHandle))
  2669. {
  2670. DPF_ERR( "Cannot delete a legacy vertex shader handle (FVF ?)." );
  2671. return D3DERR_INVALIDCALL;
  2672. }
  2673. #endif
  2674. if( m_pVShaderArray->GetObject(dwHandle) == NULL )
  2675. {
  2676. DPF_ERR( "Cannot delete a vertex shader handle that does not exist." );
  2677. return D3DERR_INVALIDCALL;
  2678. }
  2679. try
  2680. {
  2681. DeleteVertexShaderI(dwHandle);
  2682. // Release handle and delete shader object
  2683. m_pVShaderArray->ReleaseHandle(dwHandle, TRUE);
  2684. }
  2685. catch(HRESULT hr)
  2686. {
  2687. DPF_ERR("DeleteVertexShader failed.");
  2688. return hr;
  2689. }
  2690. return S_OK;
  2691. }
  2692. //-----------------------------------------------------------------------------
  2693. #undef DPF_MODNAME
  2694. #define DPF_MODNAME "CD3DBase::SetVertexShaderConstant"
  2695. HRESULT D3DAPI
  2696. CD3DBase::SetVertexShaderConstant(DWORD Register,
  2697. CONST VOID* pData,
  2698. DWORD count)
  2699. {
  2700. API_ENTER(this); // Takes D3D Lock if necessary
  2701. #if DBG
  2702. // Validate Parameters
  2703. if (!VALID_PTR(pData, 4* sizeof(DWORD) * count))
  2704. {
  2705. D3D_ERR("Invalid constant data pointer. SetVertexShaderConstant failed.");
  2706. return D3DERR_INVALIDCALL;
  2707. }
  2708. if ((GetD3DCaps()->VertexShaderVersion == D3DVS_VERSION(0,0)) &&
  2709. (BehaviorFlags() & (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE)))
  2710. {
  2711. D3D_ERR("No programmable vertex shaders are supported by this device. SetVertexShaderConstant failed.");
  2712. return D3DERR_INVALIDCALL;
  2713. }
  2714. UINT ValidationCount;
  2715. if (BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING)
  2716. ValidationCount = max(m_MaxVertexShaderConst, D3DVS_CONSTREG_MAX_V1_1);
  2717. else
  2718. if (BehaviorFlags() & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
  2719. ValidationCount = D3DVS_CONSTREG_MAX_V1_1;
  2720. else
  2721. ValidationCount = m_MaxVertexShaderConst;
  2722. if((Register + count) > ValidationCount)
  2723. {
  2724. D3D_ERR("Not that many constant registers in the vertex machine. SetVertexShaderConstant failed.");
  2725. return D3DERR_INVALIDCALL;
  2726. }
  2727. #endif
  2728. try
  2729. {
  2730. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  2731. m_pStateSets->InsertVertexShaderConstant(Register,
  2732. pData,
  2733. count);
  2734. else
  2735. SetVertexShaderConstantI(Register, pData, count);
  2736. }
  2737. catch(HRESULT hr)
  2738. {
  2739. D3D_ERR("SetVertexShaderConstant failed.");
  2740. return hr;
  2741. }
  2742. return S_OK;
  2743. }
  2744. //-----------------------------------------------------------------------------
  2745. #undef DPF_MODNAME
  2746. #define DPF_MODNAME "CD3DBase::SetVertexShaderConstantFast"
  2747. HRESULT D3DAPI
  2748. CD3DBase::SetVertexShaderConstantFast(DWORD Register,
  2749. CONST VOID* pData,
  2750. DWORD count)
  2751. {
  2752. #if DBG
  2753. // Validate Parameters
  2754. if (!VALID_PTR(pData, 4* sizeof(DWORD) * count))
  2755. {
  2756. D3D_ERR("Invalid constant data pointer. SetVertexShaderConstant failed.");
  2757. return D3DERR_INVALIDCALL;
  2758. }
  2759. if ((GetD3DCaps()->VertexShaderVersion == D3DVS_VERSION(0,0)) &&
  2760. (BehaviorFlags() & (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE)))
  2761. {
  2762. D3D_ERR("No programmable vertex shaders are supported by this device. SetVertexShaderConstant failed.");
  2763. return D3DERR_INVALIDCALL;
  2764. }
  2765. UINT ValidationCount;
  2766. if (BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING)
  2767. ValidationCount = max(m_MaxVertexShaderConst, D3DVS_CONSTREG_MAX_V1_1);
  2768. else
  2769. if (BehaviorFlags() & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
  2770. ValidationCount = D3DVS_CONSTREG_MAX_V1_1;
  2771. else
  2772. ValidationCount = m_MaxVertexShaderConst;
  2773. if((Register + count) > ValidationCount)
  2774. {
  2775. D3D_ERR("Not that many constant registers in the vertex machine. SetVertexShaderConstant failed.");
  2776. return D3DERR_INVALIDCALL;
  2777. }
  2778. #endif
  2779. DXGASSERT((m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE) == 0 &&
  2780. (BehaviorFlags() & D3DCREATE_MULTITHREADED) == 0 &&
  2781. (BehaviorFlags() & D3DCREATE_PUREDEVICE) != 0);
  2782. try
  2783. {
  2784. m_pDDI->SetVertexShaderConstant(Register, pData, count);
  2785. }
  2786. catch(HRESULT hr)
  2787. {
  2788. D3D_ERR("SetVertexShaderConstant failed.");
  2789. return hr;
  2790. }
  2791. return S_OK;
  2792. }
  2793. //-----------------------------------------------------------------------------
  2794. #undef DPF_MODNAME
  2795. #define DPF_MODNAME "CD3DBase::SetVertexShaderConstantI"
  2796. void
  2797. CD3DBase::SetVertexShaderConstantI(DWORD dwRegister, CONST VOID* pData, DWORD count)
  2798. {
  2799. m_pDDI->SetVertexShaderConstant(dwRegister, pData, count);
  2800. }
  2801. //-----------------------------------------------------------------------------
  2802. //
  2803. // Pixel Shaders
  2804. //
  2805. #undef DPF_MODNAME
  2806. #define DPF_MODNAME "CD3DBase::CreatePixelShader"
  2807. HRESULT D3DAPI
  2808. CD3DBase::CreatePixelShader(CONST DWORD* pdwFunction, LPDWORD pdwHandle)
  2809. {
  2810. API_ENTER(this); // Takes D3D Lock if necessary
  2811. #if DBG
  2812. // Validate Parameters
  2813. // WARNING!! sizeof(LPVOID) is not good enough
  2814. if (!VALID_PTR(pdwFunction, sizeof(LPVOID)))
  2815. {
  2816. D3D_ERR("Invalid shader function pointer. CreatePixelShader failed.");
  2817. return D3DERR_INVALIDCALL;
  2818. }
  2819. if (!VALID_WRITEPTR(pdwHandle, sizeof(DWORD)))
  2820. {
  2821. D3D_ERR("Invalid handle pointer. CreatePixelShader failed.");
  2822. return D3DERR_INVALIDCALL;
  2823. }
  2824. #endif
  2825. DWORD dwHandle = m_pPShaderArray->CreateNewHandle(NULL);
  2826. HRESULT ret = S_OK;
  2827. if (dwHandle == __INVALIDHANDLE)
  2828. {
  2829. D3D_ERR("Error in creating shader handle. CreatePixelShader failed.");
  2830. return E_OUTOFMEMORY;
  2831. }
  2832. CPShader *pShader = new CPShader();
  2833. if (pShader == NULL)
  2834. {
  2835. D3D_ERR("Cannot allocate memory for internal pixel shader object. CreatePixelShader failed.");
  2836. return E_OUTOFMEMORY;
  2837. }
  2838. try
  2839. {
  2840. if( !ValidatePixelShaderInternal(pdwFunction, GetD3DCaps()) )
  2841. {
  2842. ret = D3DERR_INVALIDCALL;
  2843. goto error;
  2844. }
  2845. DWORD dwVersion = *pdwFunction;
  2846. if ( (0xff == D3DSHADER_VERSION_MAJOR(dwVersion) )
  2847. && (m_dwRuntimeFlags & D3DRT_DISALLOWNVPSHADERS) )
  2848. {
  2849. D3D_ERR("Disallowing non-versioned pixel shader.");
  2850. ret = D3DERR_INVALIDCALL;
  2851. goto error;
  2852. }
  2853. // Even for the D3DCREATE_PUREDEVICE we create a shader object for validation
  2854. pShader->Initialize(pdwFunction, GetDeviceType());
  2855. m_pPShaderArray->SetObject(dwHandle, pShader);
  2856. try
  2857. {
  2858. m_pDDI->CreatePixelShader(pShader->m_pCode,
  2859. pShader->m_dwCodeSize, dwHandle);
  2860. }
  2861. catch(HRESULT hr)
  2862. {
  2863. if( 0xff == D3DSHADER_VERSION_MAJOR(dwVersion) )
  2864. {
  2865. // This is a ff.ff shader. The driver is allowed to fail this.
  2866. D3D_INFO(0, "Driver failed the creation of this non-versioned pixel "
  2867. "shader");
  2868. throw D3DERR_DRIVERINVALIDCALL;
  2869. }
  2870. else
  2871. {
  2872. OutputDebugString( "Driver failed to create the requested "
  2873. "pixel shader. Please contact your "
  2874. "friendly video card manufacturer "
  2875. "to inquire why this problem was "
  2876. "encountered.\n" );
  2877. OutputDebugString( "\n" );
  2878. // NOTE! Prefix will catch this as a bug, but it is entirely
  2879. // intentional
  2880. *(DWORD *)0 = 0;
  2881. }
  2882. }
  2883. }
  2884. catch(HRESULT hr)
  2885. {
  2886. ret = hr;
  2887. goto error;
  2888. }
  2889. *pdwHandle = dwHandle;
  2890. return S_OK;
  2891. error:
  2892. D3D_ERR("CreatePixelShader failed.");
  2893. delete pShader;
  2894. m_pPShaderArray->ReleaseHandle(dwHandle, FALSE);
  2895. return ret;
  2896. }
  2897. //-----------------------------------------------------------------------------
  2898. #undef DPF_MODNAME
  2899. #define DPF_MODNAME "CD3DBase::SetPixelShader"
  2900. HRESULT D3DAPI
  2901. CD3DBase::SetPixelShader(DWORD dwHandle)
  2902. {
  2903. API_ENTER(this); // Takes D3D Lock if necessary
  2904. try
  2905. {
  2906. #if DBG
  2907. CheckPixelShaderHandle(dwHandle);
  2908. #endif
  2909. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  2910. m_pStateSets->InsertPixelShader(dwHandle);
  2911. else
  2912. SetPixelShaderFast(dwHandle);
  2913. }
  2914. catch(HRESULT hr)
  2915. {
  2916. D3D_ERR("SetPixelShader failed.");
  2917. m_dwCurrentPixelShaderHandle = 0;
  2918. return hr;
  2919. }
  2920. return S_OK;
  2921. }
  2922. //-----------------------------------------------------------------------------
  2923. #undef DPF_MODNAME
  2924. #define DPF_MODNAME "CD3DBase::SetPixelShaderFast"
  2925. HRESULT D3DAPI
  2926. CD3DBase::SetPixelShaderFast(DWORD dwHandle)
  2927. {
  2928. try
  2929. {
  2930. #if DBG
  2931. CheckPixelShaderHandle(dwHandle);
  2932. #endif
  2933. // m_dwCurrentPixelShaderHandle is not defined for pure device
  2934. m_pDDI->SetPixelShader(dwHandle);
  2935. }
  2936. catch(HRESULT hr)
  2937. {
  2938. D3D_ERR("SetPixelShader failed.");
  2939. m_dwCurrentPixelShaderHandle = 0;
  2940. return hr;
  2941. }
  2942. return S_OK;
  2943. }
  2944. //-----------------------------------------------------------------------------
  2945. #undef DPF_MODNAME
  2946. #define DPF_MODNAME "CD3DBase::GetPixelShader"
  2947. HRESULT D3DAPI
  2948. CD3DBase::GetPixelShader(LPDWORD pdwHandle)
  2949. {
  2950. API_ENTER(this);
  2951. D3D_ERR("GetPixelShader is not available for PUREDEVICE. GetPixelShader failed.");
  2952. return D3DERR_INVALIDCALL;
  2953. }
  2954. //-----------------------------------------------------------------------------
  2955. #undef DPF_MODNAME
  2956. #define DPF_MODNAME "CD3DBase::DeletePixelShader"
  2957. HRESULT D3DAPI
  2958. CD3DBase::DeletePixelShader(DWORD dwHandle)
  2959. {
  2960. API_ENTER(this); // Takes D3D Lock if necessary
  2961. #if DBG
  2962. // Validate Parameters
  2963. CPShader* pShader = (CPShader*)m_pPShaderArray->GetObject(dwHandle);
  2964. if (pShader == NULL)
  2965. {
  2966. D3D_ERR("Invalid pixel shader handle. DeletePixelShader failed.");
  2967. return D3DERR_INVALIDCALL;
  2968. }
  2969. #endif
  2970. try
  2971. {
  2972. m_pDDI->DeletePixelShader(dwHandle);
  2973. // Release handle and delete shader object
  2974. m_pPShaderArray->ReleaseHandle(dwHandle, TRUE);
  2975. // If the pixel shader is current, set an invalid shader as current
  2976. // This is needed only for non-pure device.
  2977. if (dwHandle == m_dwCurrentPixelShaderHandle)
  2978. {
  2979. m_dwCurrentPixelShaderHandle = 0x0;
  2980. }
  2981. }
  2982. catch(HRESULT hr)
  2983. {
  2984. D3D_ERR("DeletePixelShader failed.");
  2985. return hr;
  2986. }
  2987. return S_OK;
  2988. }
  2989. //-----------------------------------------------------------------------------
  2990. #undef DPF_MODNAME
  2991. #define DPF_MODNAME "CD3DBase::SetPixelShaderConstant"
  2992. HRESULT D3DAPI
  2993. CD3DBase::SetPixelShaderConstant(DWORD Register, CONST VOID* pData,
  2994. DWORD count)
  2995. {
  2996. API_ENTER(this); // Takes D3D Lock if necessary
  2997. #if DBG
  2998. // Validate Parameters
  2999. if (!VALID_PTR(pData, sizeof(DWORD) * count))
  3000. {
  3001. D3D_ERR("Invalid constant data pointer. SetPixelShaderConstant failed.");
  3002. return D3DERR_INVALIDCALL;
  3003. }
  3004. if(Register >= D3DPS_CONSTREG_MAX_DX8)
  3005. {
  3006. D3D_ERR("Invalid Constant Register number. SetPixelShaderConstant failed.");
  3007. return D3DERR_INVALIDCALL;
  3008. }
  3009. if( (Register + count) > D3DPS_CONSTREG_MAX_DX8 )
  3010. {
  3011. D3D_ERR("Not that many constant registers in the pixel machine. SetPixelShaderConstant failed.");
  3012. return D3DERR_INVALIDCALL;
  3013. }
  3014. #endif
  3015. try
  3016. {
  3017. if (m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  3018. m_pStateSets->InsertPixelShaderConstant(Register,
  3019. pData,
  3020. count);
  3021. else
  3022. SetPixelShaderConstantFast(Register, pData, count);
  3023. }
  3024. catch(HRESULT hr)
  3025. {
  3026. D3D_ERR("SetPixelShaderConstant failed.");
  3027. return hr;
  3028. }
  3029. return S_OK;
  3030. }
  3031. //-----------------------------------------------------------------------------
  3032. #undef DPF_MODNAME
  3033. #define DPF_MODNAME "CD3DBase::SetPixelShaderConstantFast"
  3034. HRESULT D3DAPI
  3035. CD3DBase::SetPixelShaderConstantFast(DWORD Register, CONST VOID* pData,
  3036. DWORD count)
  3037. {
  3038. #if DBG
  3039. // Validate Parameters
  3040. if (!VALID_PTR(pData, sizeof(DWORD) * count))
  3041. {
  3042. D3D_ERR("Invalid constant data pointer. SetPixelShaderConstant failed.");
  3043. return D3DERR_INVALIDCALL;
  3044. }
  3045. if(Register >= D3DPS_CONSTREG_MAX_DX8)
  3046. {
  3047. D3D_ERR("Invalid Constant Register number. SetPixelShaderConstant failed.");
  3048. return D3DERR_INVALIDCALL;
  3049. }
  3050. if( (Register + count) > D3DPS_CONSTREG_MAX_DX8 )
  3051. {
  3052. D3D_ERR("Not that many constant registers in the pixel machine. SetPixelShaderConstant failed.");
  3053. return D3DERR_INVALIDCALL;
  3054. }
  3055. #endif
  3056. try
  3057. {
  3058. m_pDDI->SetPixelShaderConstant(Register, pData, count);
  3059. }
  3060. catch(HRESULT hr)
  3061. {
  3062. D3D_ERR("SetPixelShaderConstant failed.");
  3063. return hr;
  3064. }
  3065. return S_OK;
  3066. }
  3067. //-----------------------------------------------------------------------------
  3068. #undef DPF_MODNAME
  3069. #define DPF_MODNAME "CD3DBase::GetPixelShaderConstantI"
  3070. void
  3071. CD3DBase::GetPixelShaderConstantI(DWORD dwRegister, DWORD count, LPVOID pData)
  3072. {
  3073. // Should never be called.
  3074. DDASSERT( FALSE );
  3075. }
  3076. //-----------------------------------------------------------------------------
  3077. #undef DPF_MODNAME
  3078. #define DPF_MODNAME "CD3DBase::ValidateDraw"
  3079. void CD3DBase::ValidateDraw(D3DPRIMITIVETYPE primType,
  3080. UINT StartVertex,
  3081. UINT PrimitiveCount,
  3082. UINT NumVertices,
  3083. BOOL bIndexPrimitive,
  3084. BOOL bUserMemPrimitive)
  3085. {
  3086. #if DBG
  3087. if ((m_dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE) == 0)
  3088. {
  3089. D3D_THROW_FAIL("Need to call BeginScene before rendering.");
  3090. }
  3091. if (primType < D3DPT_POINTLIST || primType > D3DPT_TRIANGLEFAN)
  3092. {
  3093. D3D_THROW_FAIL("Invalid primitive type");
  3094. }
  3095. if (primType == D3DPT_POINTLIST && bIndexPrimitive)
  3096. {
  3097. D3D_THROW_FAIL("Indexed point lists are not supported");
  3098. }
  3099. if (PrimitiveCount == 0)
  3100. {
  3101. D3D_THROW_FAIL("Invalid primitive count");
  3102. }
  3103. // Number of vertices is always greater than or equal number of primitives
  3104. if (max(NumVertices, PrimitiveCount) > this->GetD3DCaps()->MaxPrimitiveCount)
  3105. {
  3106. D3D_THROW_FAIL("Primitive count or vertex count is too big. Check device caps.");
  3107. }
  3108. for (DWORD dwStage = 0; dwStage < m_dwMaxTextureBlendStages; dwStage++)
  3109. {
  3110. if (m_lpD3DMappedTexI[dwStage] != 0)
  3111. {
  3112. if (m_lpD3DMappedTexI[dwStage]->IsTextureLocked())
  3113. {
  3114. D3D_THROW_FAIL("Cannot render when currently set textures are locked.");
  3115. }
  3116. }
  3117. }
  3118. #endif //DBG
  3119. }
  3120. //-----------------------------------------------------------------------------
  3121. // Check if indices are within the range. We do it only for software
  3122. // processing because we do not want to read video memory
  3123. #undef DPF_MODNAME
  3124. #define DPF_MODNAME "CD3DBase::CheckIndices"
  3125. void CD3DBase::CheckIndices(CONST BYTE* pIndices, UINT NumIndices,
  3126. UINT StartIndex,
  3127. UINT MinIndex, UINT NumVertices, UINT IndexStride)
  3128. {
  3129. // Check if indices are within the range. We do it only for software
  3130. // processing because we do not want to read video memory
  3131. if (pIndices == NULL)
  3132. {
  3133. D3D_THROW_FAIL("Invalid index data pointer");
  3134. }
  3135. UINT MaxIndex = MinIndex + NumVertices - 1;
  3136. pIndices += IndexStride * StartIndex;
  3137. for (DWORD i = 0; i < NumIndices; i++)
  3138. {
  3139. DWORD dwIndex = IndexStride == 4?
  3140. *(DWORD*)pIndices : *(WORD*)pIndices;
  3141. pIndices += IndexStride;
  3142. if (dwIndex < MinIndex || dwIndex > MaxIndex)
  3143. {
  3144. D3D_ERR("Invalid index in the index stream: %d", dwIndex);
  3145. D3D_THROW_FAIL("");
  3146. }
  3147. }
  3148. }
  3149. //-----------------------------------------------------------------------------
  3150. #undef DPF_MODNAME
  3151. #define DPF_MODNAME "CD3DBase::DrawPrimitive"
  3152. HRESULT D3DAPI
  3153. CD3DBase::DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,
  3154. UINT StartVertex,
  3155. UINT PrimitiveCount)
  3156. {
  3157. API_ENTER(this); // Takes D3D Lock if necessary
  3158. try
  3159. {
  3160. #if DBG
  3161. UINT nVer = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  3162. try
  3163. {
  3164. ValidateDraw(PrimitiveType, StartVertex, PrimitiveCount, nVer,
  3165. FALSE, FALSE);
  3166. }
  3167. catch (HRESULT ret)
  3168. {
  3169. D3D_ERR("DrawPrimitive failed.");
  3170. return ret;
  3171. }
  3172. #endif // DBG
  3173. if (PrimitiveType != D3DPT_POINTLIST)
  3174. {
  3175. (*m_pfnDrawPrim)(this, PrimitiveType, StartVertex, PrimitiveCount);
  3176. }
  3177. else
  3178. DrawPointsI(PrimitiveType, StartVertex, PrimitiveCount);
  3179. }
  3180. catch (HRESULT ret)
  3181. {
  3182. D3D_ERR("DrawPrimitive failed.");
  3183. m_pDDI->ClearBatch(FALSE);
  3184. return ret;
  3185. }
  3186. return S_OK;
  3187. }
  3188. //-----------------------------------------------------------------------------
  3189. #undef DPF_MODNAME
  3190. #define DPF_MODNAME "CD3DBase::DrawIndexedPrimitive"
  3191. HRESULT D3DAPI
  3192. CD3DBase::DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType,
  3193. UINT MinIndex, UINT NumVertices, UINT StartIndex,
  3194. UINT PrimitiveCount)
  3195. {
  3196. API_ENTER(this); // Takes D3D Lock if necessary
  3197. #if DBG
  3198. try
  3199. {
  3200. if (NumVertices == 0)
  3201. {
  3202. D3D_ERR("Invalid number of vertices. DrawIndexedPrimitive failed.");
  3203. return D3DERR_INVALIDCALL;
  3204. }
  3205. DWORD dwNumIndices = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  3206. if (dwNumIndices + StartIndex > m_pIndexStream->m_dwNumVertices)
  3207. {
  3208. D3D_ERR("Index stream does not have required number of indices. DrawIndexedPrimitive failed.");
  3209. return D3DERR_INVALIDCALL;
  3210. }
  3211. if (m_pIndexStream == NULL)
  3212. {
  3213. D3D_ERR("No index stream object. Perhaps something went wrong at a mode-change. DrawIndexedPrimitive failed.");
  3214. return D3DERR_INVALIDCALL;
  3215. }
  3216. if (m_pIndexStream->m_pVBI == NULL)
  3217. {
  3218. D3D_ERR("No valid index stream currently set. DrawIndexedPrimitive failed.");
  3219. return D3DERR_INVALIDCALL;
  3220. }
  3221. ValidateDraw(PrimitiveType, MinIndex + m_pIndexStream->m_dwBaseIndex,
  3222. PrimitiveCount, NumVertices, TRUE, FALSE);
  3223. if (m_pIndexStream->m_pVBI->GetBufferDesc()->Pool == D3DPOOL_SYSTEMMEM &&
  3224. (m_pIndexStream->m_pVBI->GetBufferDesc()->Usage & D3DUSAGE_SOFTWAREPROCESSING) != 0)
  3225. {
  3226. CheckIndices((BYTE*)m_pIndexStream->m_pVBI->Data(),
  3227. dwNumIndices,
  3228. StartIndex, MinIndex, NumVertices,
  3229. m_pIndexStream->m_dwStride);
  3230. }
  3231. }
  3232. catch(HRESULT hr)
  3233. {
  3234. D3D_ERR("DrawIndexedPrimitive failed.");
  3235. return hr;
  3236. }
  3237. #endif //DBG
  3238. try
  3239. {
  3240. (*m_pfnDrawIndexedPrim)(this, PrimitiveType,
  3241. m_pIndexStream->m_dwBaseIndex,
  3242. MinIndex, NumVertices, StartIndex,
  3243. PrimitiveCount);
  3244. }
  3245. catch (HRESULT ret)
  3246. {
  3247. D3D_ERR("DrawIndexedPrimitive failed.");
  3248. m_pDDI->ClearBatch(FALSE);
  3249. return ret;
  3250. }
  3251. return S_OK;
  3252. }
  3253. //-----------------------------------------------------------------------------
  3254. #undef DPF_MODNAME
  3255. #define DPF_MODNAME "CD3DBase::DrawRectPatch"
  3256. HRESULT D3DAPI CD3DBase::DrawRectPatch(UINT Handle, CONST FLOAT *pNumSegs,
  3257. CONST D3DRECTPATCH_INFO *pSurf)
  3258. {
  3259. API_ENTER(this); // Takes D3D Lock if necessary
  3260. #if DBG
  3261. if ((m_dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE) == 0)
  3262. {
  3263. D3D_ERR("Need to call BeginScene before rendering.");
  3264. return (D3DERR_INVALIDCALL);
  3265. }
  3266. if ((m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING) != 0)
  3267. {
  3268. D3D_ERR("There is no emulation support for RT patches, hence only hardware device or hardware mode is legal. DrawRectPatch failed.");
  3269. return D3DERR_INVALIDCALL;
  3270. }
  3271. if ((BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0)
  3272. {
  3273. CD3DHal* pDevice = static_cast<CD3DHal*>(this);
  3274. if (!D3DVSD_ISLEGACY(pDevice->m_dwCurrentShaderHandle))
  3275. {
  3276. if (pDevice->m_pv->dwDeviceFlags & D3DDEV_VERTEXSHADERS)
  3277. {
  3278. for (DWORD i=0; i < D3DHAL_TSS_MAXSTAGES; i++)
  3279. {
  3280. if (pDevice->tsstates[i][D3DTSS_TEXCOORDINDEX] != i)
  3281. {
  3282. D3D_ERR("Stage %d - Texture coordinate index in the stage "
  3283. "must be equal to the stage index when programmable"
  3284. " vertex pipeline is used", i);
  3285. return D3DERR_INVALIDCALL;
  3286. }
  3287. DWORD TexTransformFlags = pDevice->tsstates[i][D3DTSS_TEXTURETRANSFORMFLAGS];
  3288. if ((TexTransformFlags & ~D3DTTFF_PROJECTED) != D3DTTFF_DISABLE)
  3289. {
  3290. D3D_ERR("Stage %d - Count in D3DTSS_TEXTURETRANSFORMFLAGS "
  3291. "must be 0 when programmable pipeline is used", i);
  3292. return D3DERR_INVALIDCALL;
  3293. }
  3294. }
  3295. }
  3296. }
  3297. }
  3298. if ((GetD3DCaps()->DevCaps & D3DDEVCAPS_RTPATCHES) == 0)
  3299. {
  3300. D3D_ERR("RT patches unsupported on current device. DrawRectPatch failed.");
  3301. return D3DERR_INVALIDCALL;
  3302. }
  3303. if (Handle == 0 && pSurf == 0)
  3304. {
  3305. D3D_ERR("Handle and patch specification cannot be both zero. DrawRectPatch failed.");
  3306. return D3DERR_INVALIDCALL;
  3307. }
  3308. if (pSurf != 0)
  3309. {
  3310. if (!VALID_PTR(pSurf, sizeof(D3DRECTPATCH_INFO)))
  3311. {
  3312. D3D_ERR("Invalid patch information pointer. DrawRectPatch failed.");
  3313. return D3DERR_INVALIDCALL;
  3314. }
  3315. if (pSurf->Order != D3DORDER_LINEAR &&
  3316. pSurf->Order != D3DORDER_CUBIC &&
  3317. pSurf->Order != D3DORDER_QUINTIC)
  3318. {
  3319. D3D_ERR("Order not supported. DrawRectPatch failed.");
  3320. return D3DERR_INVALIDCALL;
  3321. }
  3322. if (pSurf->Order == D3DORDER_QUINTIC && (GetD3DCaps()->DevCaps & D3DDEVCAPS_QUINTICRTPATCHES) == 0)
  3323. {
  3324. D3D_ERR("Quintic patches not supported on this device. DrawRectPatch failed.");
  3325. return D3DERR_INVALIDCALL;
  3326. }
  3327. if (pSurf->Basis != D3DBASIS_BEZIER &&
  3328. pSurf->Basis != D3DBASIS_BSPLINE &&
  3329. pSurf->Basis != D3DBASIS_INTERPOLATE)
  3330. {
  3331. D3D_ERR("Basis not supported. DrawRectPatch failed.");
  3332. return D3DERR_INVALIDCALL;
  3333. }
  3334. if (pSurf->Basis == D3DBASIS_BEZIER)
  3335. {
  3336. if (pSurf->Width != (DWORD)pSurf->Order + 1 ||
  3337. pSurf->Height != (DWORD)pSurf->Order + 1)
  3338. {
  3339. D3D_ERR("Bezier patch must have correct dimensions to match order. DrawRectPatch failed.");
  3340. return D3DERR_INVALIDCALL;
  3341. }
  3342. }
  3343. else
  3344. {
  3345. if (pSurf->Width <= (DWORD)pSurf->Order ||
  3346. pSurf->Height <= (DWORD)pSurf->Order)
  3347. {
  3348. D3D_ERR("Patch dimensions too small for the order. DrawRectPatch failed.");
  3349. return D3DERR_INVALIDCALL;
  3350. }
  3351. if (pSurf->Basis == D3DBASIS_INTERPOLATE && pSurf->Order != D3DORDER_CUBIC)
  3352. {
  3353. D3D_ERR("Only bicubic interpolating splines supported. DrawRectPatch failed.");
  3354. return D3DERR_INVALIDCALL;
  3355. }
  3356. }
  3357. if (pSurf->Stride == 0)
  3358. {
  3359. D3D_ERR("Stride cannot be zero. DrawRectPatch failed.");
  3360. return D3DERR_INVALIDCALL;
  3361. }
  3362. if ((BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0)
  3363. {
  3364. try
  3365. {
  3366. static_cast<CD3DHal*>(this)->ValidateRTPatch();
  3367. }
  3368. catch(HRESULT ret)
  3369. {
  3370. D3D_ERR("DrawRectPatch failed.");
  3371. return ret;
  3372. }
  3373. }
  3374. if ((BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0 && Handle != 0)
  3375. {
  3376. // Need to snapshot current Vshader in the Handle table
  3377. HRESULT hr = m_pRTPatchValidationInfo->Grow(Handle);
  3378. if (FAILED(hr))
  3379. {
  3380. D3D_ERR("Could not grow handle table. DrawRectPatch failed.");
  3381. return hr;
  3382. }
  3383. if ((*m_pRTPatchValidationInfo)[Handle].m_pObj == 0)
  3384. {
  3385. (*m_pRTPatchValidationInfo)[Handle].m_pObj = new CRTPatchValidationInfo;
  3386. if ((*m_pRTPatchValidationInfo)[Handle].m_pObj == 0)
  3387. {
  3388. D3D_ERR("Out of memory growing handle table. DrawRectPatch failed.");
  3389. return E_OUTOFMEMORY;
  3390. }
  3391. }
  3392. static_cast<CRTPatchValidationInfo*>((*m_pRTPatchValidationInfo)[Handle].m_pObj)->m_ShaderHandle = m_dwCurrentShaderHandle;
  3393. }
  3394. }
  3395. else
  3396. {
  3397. if ((BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0 && Handle != 0)
  3398. {
  3399. if (Handle >= m_pRTPatchValidationInfo->GetSize())
  3400. {
  3401. D3D_ERR("Cannot draw a patch without any information. DrawRectPatch failed.");
  3402. return D3DERR_INVALIDCALL;
  3403. }
  3404. if ((*m_pRTPatchValidationInfo)[Handle].m_pObj == 0)
  3405. {
  3406. D3D_ERR("Cannot draw a patch without any information. DrawRectPatch failed.");
  3407. return D3DERR_INVALIDCALL;
  3408. }
  3409. if (static_cast<CRTPatchValidationInfo*>((*m_pRTPatchValidationInfo)[Handle].m_pObj)->m_ShaderHandle != m_dwCurrentShaderHandle)
  3410. {
  3411. D3D_ERR("Cannot set a vertex shader different from the one set when the patch was first created. DrawRectPatch failed.");
  3412. return D3DERR_INVALIDCALL;
  3413. }
  3414. }
  3415. }
  3416. if (pNumSegs != 0)
  3417. {
  3418. if (!VALID_PTR(pNumSegs, sizeof(FLOAT) * 4))
  3419. {
  3420. D3D_ERR("Invalid pointer to array of 4 floats (NumSegs). DrawRectPatch failed.");
  3421. return D3DERR_INVALIDCALL;
  3422. }
  3423. }
  3424. #endif
  3425. try
  3426. {
  3427. m_pDDI->DrawRectPatch(Handle, pSurf, pNumSegs);
  3428. }
  3429. catch(HRESULT ret)
  3430. {
  3431. D3D_ERR("DrawRectPatch failed.");
  3432. return ret;
  3433. }
  3434. return S_OK;
  3435. }
  3436. //-----------------------------------------------------------------------------
  3437. #undef DPF_MODNAME
  3438. #define DPF_MODNAME "CD3DBase::DrawTriPatch"
  3439. HRESULT D3DAPI CD3DBase::DrawTriPatch(UINT Handle, CONST FLOAT *pNumSegs,
  3440. CONST D3DTRIPATCH_INFO *pSurf)
  3441. {
  3442. API_ENTER(this); // Takes D3D Lock if necessary
  3443. #if DBG
  3444. if ((m_dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE) == 0)
  3445. {
  3446. D3D_ERR("Need to call BeginScene before rendering.");
  3447. return (D3DERR_INVALIDCALL);
  3448. }
  3449. if ((m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING) != 0)
  3450. {
  3451. D3D_ERR("There is no emulation support for RT patches, hence only hardware device or hardware mode is legal. DrawTriPatch failed.");
  3452. return D3DERR_INVALIDCALL;
  3453. }
  3454. if ((BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0)
  3455. {
  3456. CD3DHal* pDevice = static_cast<CD3DHal*>(this);
  3457. if (!D3DVSD_ISLEGACY(pDevice->m_dwCurrentShaderHandle))
  3458. {
  3459. if (pDevice->m_pv->dwDeviceFlags & D3DDEV_VERTEXSHADERS)
  3460. {
  3461. for (DWORD i=0; i < D3DHAL_TSS_MAXSTAGES; i++)
  3462. {
  3463. if (pDevice->tsstates[i][D3DTSS_TEXCOORDINDEX] != i)
  3464. {
  3465. D3D_ERR("Stage %d - Texture coordinate index in the stage "
  3466. "must be equal to the stage index when programmable"
  3467. " vertex pipeline is used", i);
  3468. return D3DERR_INVALIDCALL;
  3469. }
  3470. DWORD TexTransformFlags = pDevice->tsstates[i][D3DTSS_TEXTURETRANSFORMFLAGS];
  3471. if ((TexTransformFlags & ~D3DTTFF_PROJECTED) != D3DTTFF_DISABLE)
  3472. {
  3473. D3D_ERR("Stage %d - Count in D3DTSS_TEXTURETRANSFORMFLAGS "
  3474. "must be 0 when programmable pipeline is used", i);
  3475. return D3DERR_INVALIDCALL;
  3476. }
  3477. }
  3478. }
  3479. }
  3480. }
  3481. if ((GetD3DCaps()->DevCaps & D3DDEVCAPS_RTPATCHES) == 0)
  3482. {
  3483. D3D_ERR("RT patches unsupported on current device. DrawTriPatch failed.");
  3484. return D3DERR_INVALIDCALL;
  3485. }
  3486. if (Handle == 0 && pSurf == 0)
  3487. {
  3488. D3D_ERR("Handle and patch specification cannot be both zero. DrawTriPatch failed.");
  3489. return D3DERR_INVALIDCALL;
  3490. }
  3491. if (pSurf != 0)
  3492. {
  3493. if (!VALID_PTR(pSurf, sizeof(D3DTRIPATCH_INFO)))
  3494. {
  3495. D3D_ERR("Invalid patch information pointer. DrawTriPatch failed.");
  3496. return D3DERR_INVALIDCALL;
  3497. }
  3498. if (pSurf->Order != D3DORDER_LINEAR &&
  3499. pSurf->Order != D3DORDER_CUBIC &&
  3500. pSurf->Order != D3DORDER_QUINTIC)
  3501. {
  3502. D3D_ERR("Order not supported. DrawTriPatch failed.");
  3503. return D3DERR_INVALIDCALL;
  3504. }
  3505. if (pSurf->Order == D3DORDER_QUINTIC && (GetD3DCaps()->DevCaps & D3DDEVCAPS_QUINTICRTPATCHES) == 0)
  3506. {
  3507. D3D_ERR("Quintic patches not supported on this device. DrawTriPatch failed.");
  3508. return D3DERR_INVALIDCALL;
  3509. }
  3510. if (pSurf->Basis != D3DBASIS_BEZIER)
  3511. {
  3512. D3D_ERR("Only Bezier basis is supported. DrawTriPatch failed.");
  3513. return D3DERR_INVALIDCALL;
  3514. }
  3515. if (pSurf->Order == D3DORDER_LINEAR && pSurf->NumVertices != 3)
  3516. {
  3517. D3D_ERR("Only three vertices supported with linear order. DrawTriPatch failed.");
  3518. return D3DERR_INVALIDCALL;
  3519. }
  3520. else if (pSurf->Order == D3DORDER_CUBIC && pSurf->NumVertices != 10)
  3521. {
  3522. D3D_ERR("Only ten vertices supported with cubic order. DrawTriPatch failed.");
  3523. return D3DERR_INVALIDCALL;
  3524. }
  3525. else if (pSurf->Order == D3DORDER_QUINTIC && pSurf->NumVertices != 21)
  3526. {
  3527. D3D_ERR("Only 21 vertices supported with quintic order. DrawTriPatch failed.");
  3528. return D3DERR_INVALIDCALL;
  3529. }
  3530. if ((BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0)
  3531. {
  3532. try
  3533. {
  3534. static_cast<CD3DHal*>(this)->ValidateRTPatch();
  3535. }
  3536. catch(HRESULT ret)
  3537. {
  3538. D3D_ERR("DrawTriPatch failed.");
  3539. return ret;
  3540. }
  3541. }
  3542. if ((BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0 && Handle != 0)
  3543. {
  3544. // Need to snapshot current Vshader in the Handle table
  3545. HRESULT hr = m_pRTPatchValidationInfo->Grow(Handle);
  3546. if (FAILED(hr))
  3547. {
  3548. D3D_ERR("Could not grow handle table. DrawTriPatch failed.");
  3549. return hr;
  3550. }
  3551. if ((*m_pRTPatchValidationInfo)[Handle].m_pObj == 0)
  3552. {
  3553. (*m_pRTPatchValidationInfo)[Handle].m_pObj = new CRTPatchValidationInfo;
  3554. if ((*m_pRTPatchValidationInfo)[Handle].m_pObj == 0)
  3555. {
  3556. D3D_ERR("Out of memory growing handle table. DrawTriPatch failed.");
  3557. return E_OUTOFMEMORY;
  3558. }
  3559. }
  3560. static_cast<CRTPatchValidationInfo*>((*m_pRTPatchValidationInfo)[Handle].m_pObj)->m_ShaderHandle = m_dwCurrentShaderHandle;
  3561. }
  3562. }
  3563. else
  3564. {
  3565. if ((BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0 && Handle != 0)
  3566. {
  3567. if (Handle >= m_pRTPatchValidationInfo->GetSize())
  3568. {
  3569. D3D_ERR("Cannot draw a patch without any information. DrawTriPatch failed.");
  3570. return D3DERR_INVALIDCALL;
  3571. }
  3572. if ((*m_pRTPatchValidationInfo)[Handle].m_pObj == 0)
  3573. {
  3574. D3D_ERR("Cannot draw a patch without any information. DrawTriPatch failed.");
  3575. return D3DERR_INVALIDCALL;
  3576. }
  3577. if (static_cast<CRTPatchValidationInfo*>((*m_pRTPatchValidationInfo)[Handle].m_pObj)->m_ShaderHandle != m_dwCurrentShaderHandle)
  3578. {
  3579. D3D_ERR("Cannot set a vertex shader different from the one set when the patch was first created. DrawTriPatch failed.");
  3580. return D3DERR_INVALIDCALL;
  3581. }
  3582. }
  3583. }
  3584. if (pNumSegs != 0)
  3585. {
  3586. if (!VALID_PTR(pNumSegs, sizeof(FLOAT) * 3))
  3587. {
  3588. D3D_ERR("Invalid pointer to array of 3 floats (NumSegs). DrawTriPatch failed.");
  3589. return D3DERR_INVALIDCALL;
  3590. }
  3591. }
  3592. #endif
  3593. try
  3594. {
  3595. m_pDDI->DrawTriPatch(Handle, pSurf, pNumSegs);
  3596. }
  3597. catch(HRESULT ret)
  3598. {
  3599. D3D_ERR("DrawTriPatch failed.");
  3600. return ret;
  3601. }
  3602. return S_OK;
  3603. }
  3604. //-----------------------------------------------------------------------------
  3605. #undef DPF_MODNAME
  3606. #define DPF_MODNAME "CD3DBase::DeletePatch"
  3607. HRESULT D3DAPI CD3DBase::DeletePatch(UINT Handle)
  3608. {
  3609. API_ENTER(this); // Takes D3D Lock if necessary
  3610. if ((GetD3DCaps()->DevCaps & D3DDEVCAPS_RTPATCHES) == 0)
  3611. {
  3612. D3D_ERR("High order surfaces unsupported on current device. DeletePatch failed.");
  3613. return D3DERR_INVALIDCALL;
  3614. }
  3615. if (Handle == 0)
  3616. {
  3617. return S_OK;
  3618. }
  3619. #if DBG
  3620. if ((BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0)
  3621. {
  3622. if (Handle >= m_pRTPatchValidationInfo->GetSize())
  3623. {
  3624. D3D_ERR("Attempt to delete non-existent patch. DeletePatch failed.");
  3625. return D3DERR_INVALIDCALL;
  3626. }
  3627. if ((*m_pRTPatchValidationInfo)[Handle].m_pObj == 0)
  3628. {
  3629. D3D_ERR("Attempt to delete non-existent patch. DeletePatch failed.");
  3630. return D3DERR_INVALIDCALL;
  3631. }
  3632. delete (*m_pRTPatchValidationInfo)[Handle].m_pObj;
  3633. (*m_pRTPatchValidationInfo)[Handle].m_pObj = 0;
  3634. }
  3635. #endif // DBG
  3636. try
  3637. {
  3638. m_pDDI->SetRenderState((D3DRENDERSTATETYPE)D3DRS_DELETERTPATCH, Handle);
  3639. }
  3640. catch(HRESULT ret)
  3641. {
  3642. D3D_ERR("DeletePatch failed.");
  3643. return ret;
  3644. }
  3645. return S_OK;
  3646. }
  3647. //-----------------------------------------------------------------------------
  3648. #undef DPF_MODNAME
  3649. #define DPF_MODNAME "CD3DBase::DrawPrimitiveUP"
  3650. HRESULT D3DAPI
  3651. CD3DBase::DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,
  3652. UINT PrimitiveCount,
  3653. CONST VOID *pVertexStreamZeroData,
  3654. UINT VertexStreamZeroStride)
  3655. {
  3656. API_ENTER(this); // Takes D3D Lock if necessary
  3657. m_dwRuntimeFlags |= D3DRT_USERMEMPRIMITIVE;
  3658. try
  3659. {
  3660. if (m_pStream[0].m_pVB)
  3661. {
  3662. m_pDDI->VBReleased(m_pStream[0].m_pVB);
  3663. m_pStream[0].m_pVB->DecrementUseCount();
  3664. m_pStream[0].m_pVB = NULL;
  3665. }
  3666. m_pStream[0].m_pData = (BYTE*)pVertexStreamZeroData;
  3667. m_pStream[0].m_dwStride = VertexStreamZeroStride;
  3668. #if DBG
  3669. UINT nVer = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  3670. if (!VALID_PTR(pVertexStreamZeroData, nVer*VertexStreamZeroStride))
  3671. {
  3672. D3D_THROW_FAIL("Invalid input vertex stream pointer");
  3673. }
  3674. m_pStream[0].m_dwSize = nVer * VertexStreamZeroStride;
  3675. m_pStream[0].m_dwNumVertices = nVer;
  3676. try
  3677. {
  3678. ValidateDraw(PrimitiveType, 0, PrimitiveCount, nVer, FALSE, TRUE);
  3679. }
  3680. catch (HRESULT ret)
  3681. {
  3682. m_dwRuntimeFlags &= ~D3DRT_USERMEMPRIMITIVE;
  3683. return ret;
  3684. }
  3685. #endif // DBG
  3686. DrawPrimitiveUPI(PrimitiveType, PrimitiveCount);
  3687. // Invalidate stream zero
  3688. m_pStream[0].m_pData = NULL;
  3689. #if DBG
  3690. m_pStream[0].m_dwSize = 0;
  3691. #endif
  3692. m_pStream[0].m_dwStride = 0;
  3693. }
  3694. catch (HRESULT ret)
  3695. {
  3696. D3D_ERR("DrawPrimitiveUP failed.");
  3697. #if DBG
  3698. m_dwRuntimeFlags &= ~D3DRT_USERMEMPRIMITIVE;
  3699. #endif
  3700. m_pDDI->ClearBatch(FALSE);
  3701. return ret;
  3702. }
  3703. m_dwRuntimeFlags &= ~D3DRT_USERMEMPRIMITIVE;
  3704. return S_OK;
  3705. }
  3706. //-----------------------------------------------------------------------------
  3707. #undef DPF_MODNAME
  3708. #define DPF_MODNAME "CD3DBase::DrawPrimitiveUPI"
  3709. void CD3DBase::DrawPrimitiveUPI(D3DPRIMITIVETYPE PrimType, UINT PrimCount)
  3710. {
  3711. m_pDDI->DrawPrimitiveUP(PrimType, PrimCount);
  3712. }
  3713. //-----------------------------------------------------------------------------
  3714. #undef DPF_MODNAME
  3715. #define DPF_MODNAME "CD3DBase::DrawIndexedPrimitiveUPI"
  3716. void
  3717. CD3DBase::DrawIndexedPrimitiveUPI(D3DPRIMITIVETYPE PrimitiveType,
  3718. UINT MinVertexIndex,
  3719. UINT NumVertices,
  3720. UINT PrimitiveCount)
  3721. {
  3722. m_pDDI->DrawIndexedPrimitiveUP(PrimitiveType, MinVertexIndex, NumVertices,
  3723. PrimitiveCount);
  3724. }
  3725. //-----------------------------------------------------------------------------
  3726. #undef DPF_MODNAME
  3727. #define DPF_MODNAME "CD3DBase::DrawIndexedPrimitiveUP"
  3728. HRESULT D3DAPI
  3729. CD3DBase::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType,
  3730. UINT MinIndex, UINT NumVertices,
  3731. UINT PrimitiveCount,
  3732. CONST VOID *pIndexData, D3DFORMAT IndexDataFormat,
  3733. CONST VOID *pVertexStreamZeroData,
  3734. UINT VertexStreamZeroStride)
  3735. {
  3736. API_ENTER(this); // Takes D3D Lock if necessary
  3737. m_dwRuntimeFlags |= D3DRT_USERMEMPRIMITIVE;
  3738. try
  3739. {
  3740. if (m_pStream[0].m_pVB)
  3741. {
  3742. m_pDDI->VBReleased(m_pStream[0].m_pVB);
  3743. m_pStream[0].m_pVB->DecrementUseCount();
  3744. m_pStream[0].m_pVB = NULL;
  3745. }
  3746. if (m_pIndexStream->m_pVBI)
  3747. {
  3748. m_pDDI->VBIReleased(m_pIndexStream->m_pVBI);
  3749. m_pIndexStream->m_pVBI->DecrementUseCount();
  3750. m_pIndexStream->m_pVBI = NULL;
  3751. }
  3752. m_pStream[0].m_pData = (BYTE*)pVertexStreamZeroData;
  3753. m_pStream[0].m_dwStride = VertexStreamZeroStride;
  3754. m_pIndexStream->m_pData = (BYTE*)pIndexData;
  3755. m_pIndexStream->m_dwBaseIndex = 0;
  3756. if (IndexDataFormat == D3DFMT_INDEX16)
  3757. m_pIndexStream->m_dwStride = 2;
  3758. else
  3759. if (IndexDataFormat == D3DFMT_INDEX32)
  3760. {
  3761. #if DBG
  3762. if (GetD3DCaps()->MaxVertexIndex <= 0xFFFF)
  3763. D3D_THROW(D3DERR_INVALIDCALL, "Device does not support 32-bit indices");
  3764. #endif
  3765. m_pIndexStream->m_dwStride = 4;
  3766. }
  3767. else
  3768. {
  3769. D3D_THROW(D3DERR_INVALIDCALL, "Invalid index data format");
  3770. }
  3771. #if DBG
  3772. try
  3773. {
  3774. if (pVertexStreamZeroData == NULL)
  3775. {
  3776. D3D_THROW(D3DERR_INVALIDCALL, "Invalid vertex stream pointer");
  3777. }
  3778. if (pIndexData == NULL)
  3779. {
  3780. D3D_THROW(D3DERR_INVALIDCALL, "Invalid index data pointer");
  3781. }
  3782. if (NumVertices == 0)
  3783. {
  3784. D3D_THROW(D3DERR_INVALIDCALL, "Invalid number of vertices");
  3785. }
  3786. m_pStream[0].m_dwSize = NumVertices * VertexStreamZeroStride;
  3787. m_pStream[0].m_dwNumVertices = NumVertices;
  3788. UINT NumIndices = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  3789. m_pIndexStream[0].m_dwSize = NumIndices * m_pIndexStream[0].m_dwStride;
  3790. m_pIndexStream[0].m_dwNumVertices = NumIndices;
  3791. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)
  3792. {
  3793. CheckIndices((BYTE*)pIndexData, NumIndices, 0, MinIndex,
  3794. NumVertices, m_pIndexStream->m_dwStride);
  3795. }
  3796. ValidateDraw(PrimitiveType, MinIndex, PrimitiveCount, NumVertices,
  3797. TRUE, TRUE);
  3798. }
  3799. catch (HRESULT ret)
  3800. {
  3801. D3D_ERR("DrawIndexedPrimitiveUP failed.");
  3802. m_dwRuntimeFlags &= ~D3DRT_USERMEMPRIMITIVE;
  3803. return ret;
  3804. }
  3805. #endif // DBG
  3806. DrawIndexedPrimitiveUPI(PrimitiveType, MinIndex, NumVertices, PrimitiveCount);
  3807. // Invalidate stream zero
  3808. m_pStream[0].m_pData = NULL;
  3809. #if DBG
  3810. m_pStream[0].m_dwSize = 0;
  3811. #endif
  3812. m_pStream[0].m_dwStride = 0;
  3813. //Invalidate index stream
  3814. m_pIndexStream[0].m_pData = NULL;
  3815. #if DBG
  3816. m_pIndexStream[0].m_dwSize = 0;
  3817. #endif
  3818. m_pIndexStream[0].m_dwStride = 0;
  3819. }
  3820. catch (HRESULT ret)
  3821. {
  3822. D3D_ERR("DrawIndexedPrimitiveUP failed.");
  3823. m_dwRuntimeFlags &= ~D3DRT_USERMEMPRIMITIVE;
  3824. m_pDDI->ClearBatch(FALSE);
  3825. return ret;
  3826. }
  3827. m_dwRuntimeFlags &= ~D3DRT_USERMEMPRIMITIVE;
  3828. return S_OK;
  3829. }
  3830. //-----------------------------------------------------------------------------
  3831. #undef DPF_MODNAME
  3832. #define DPF_MODNAME "CD3DBase::DrawPointsI"
  3833. void
  3834. CD3DBase::DrawPointsI(D3DPRIMITIVETYPE PrimitiveType,
  3835. UINT StartVertex,
  3836. UINT PrimitiveCount)
  3837. {
  3838. (*m_pfnDrawPrim)(this, PrimitiveType, StartVertex, PrimitiveCount);
  3839. }
  3840. //-----------------------------------------------------------------------------
  3841. #undef DPF_MODNAME
  3842. #define DPF_MODNAME "CD3DBase::CreateVertexShaderI"
  3843. void
  3844. CD3DBase::CreateVertexShaderI(CONST DWORD* pdwDeclaration, DWORD dwDeclSize,
  3845. CONST DWORD* pdwFunction, DWORD dwCodeSize,
  3846. DWORD dwHandle)
  3847. {
  3848. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  3849. #if DBG
  3850. if (pShader->m_dwFlags & CVShader::SOFTWARE)
  3851. {
  3852. D3D_THROW_FAIL("Software vertex shader cannot be created with a PUREDEVICE");
  3853. }
  3854. #endif // DBG
  3855. // always pass stripped version for pure hal
  3856. m_pDDI->CreateVertexShader(pdwDeclaration, dwDeclSize,
  3857. pShader->m_pStrippedFuncCode,
  3858. pShader->m_StrippedFuncCodeSize, dwHandle,
  3859. pShader->m_Declaration.m_bLegacyFVF);
  3860. }
  3861. //-----------------------------------------------------------------------------
  3862. #undef DPF_MODNAME
  3863. #define DPF_MODNAME "CD3DBase::SetVertexShaderI"
  3864. void CD3DBase::SetVertexShaderI(DWORD dwHandle)
  3865. {
  3866. #if DBG
  3867. CheckVertexShaderHandle(dwHandle);
  3868. if (!D3DVSD_ISLEGACY(dwHandle))
  3869. {
  3870. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  3871. if (pShader->m_dwFlags & CVShader::SOFTWARE)
  3872. {
  3873. D3D_THROW_FAIL("Vertex shader created in software mode cannot be used in hardware mode");
  3874. }
  3875. }
  3876. #endif // DBG
  3877. m_pDDI->SetVertexShaderHW(dwHandle);
  3878. }
  3879. //-----------------------------------------------------------------------------
  3880. #undef DPF_MODNAME
  3881. #define DPF_MODNAME "CD3DBase::DeleteVertexShaderI"
  3882. void CD3DBase::DeleteVertexShaderI(DWORD dwHandle)
  3883. {
  3884. m_pDDI->DeleteVertexShader(dwHandle);
  3885. }
  3886. //---------------------------------------------------------------------
  3887. #undef DPF_MODNAME
  3888. #define DPF_MODNAME "CD3DBase::Clear"
  3889. #define bDoRGBClear ((dwFlags & D3DCLEAR_TARGET)!=0)
  3890. #define bDoZClear ((dwFlags & D3DCLEAR_ZBUFFER)!=0)
  3891. #define bDoStencilClear ((dwFlags & D3DCLEAR_STENCIL)!=0)
  3892. // Maximum number of clear rectangles considered legal.
  3893. // This limit is set by NT kernel for Clear2 callback
  3894. const DWORD MAX_CLEAR_RECTS = 0x1000;
  3895. //---------------------------------------------------------------------
  3896. #undef DPF_MODNAME
  3897. #define DPF_MODNAME "CD3DBase::ClearI"
  3898. void
  3899. CD3DBase::ClearI(DWORD dwCount,
  3900. CONST D3DRECT* rects,
  3901. DWORD dwFlags,
  3902. D3DCOLOR dwColor,
  3903. D3DVALUE dvZ,
  3904. DWORD dwStencil)
  3905. {
  3906. if (rects == NULL)
  3907. dwCount = 0;
  3908. // We do not cull rects against viewport, so let the driver do it
  3909. dwFlags |= D3DCLEAR_COMPUTERECTS;
  3910. m_pDDI->Clear(dwFlags, dwCount, (LPD3DRECT)rects, dwColor, dvZ, dwStencil);
  3911. }
  3912. //---------------------------------------------------------------------
  3913. #undef DPF_MODNAME
  3914. #define DPF_MODNAME "CD3DBase::Clear"
  3915. HRESULT D3DAPI
  3916. CD3DBase::Clear(DWORD dwCount,
  3917. CONST D3DRECT* rects,
  3918. DWORD dwFlags,
  3919. D3DCOLOR dwColor,
  3920. D3DVALUE dvZ,
  3921. DWORD dwStencil)
  3922. {
  3923. API_ENTER(this); // Takes D3D Lock if necessary
  3924. #if DBG
  3925. if (IsBadReadPtr(rects, dwCount * sizeof(D3DRECT)))
  3926. {
  3927. D3D_ERR("Invalid rects pointer. Clear failed.");
  3928. return D3DERR_INVALIDCALL;
  3929. }
  3930. #endif
  3931. try
  3932. {
  3933. HRESULT err;
  3934. LPDDPIXELFORMAT pZPixFmt=NULL;
  3935. if (dwCount > MAX_CLEAR_RECTS)
  3936. {
  3937. D3D_ERR("Cannot support more than 64K rectangles. Clear failed.");
  3938. return D3DERR_INVALIDCALL;
  3939. }
  3940. if (!(GetD3DCaps()->RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR))
  3941. {
  3942. if (bDoStencilClear||bDoZClear)
  3943. {
  3944. if (this->ZBuffer()==NULL)
  3945. {
  3946. // unlike Clear(), specifying a Zbuffer-clearing flag without a zbuffer will
  3947. // be considered an error
  3948. #if DBG
  3949. if (bDoZClear)
  3950. {
  3951. D3D_ERR("Invalid flag D3DCLEAR_ZBUFFER: no zbuffer is associated with device. Clear failed.");
  3952. }
  3953. if (bDoStencilClear)
  3954. {
  3955. D3D_ERR("Invalid flag D3DCLEAR_STENCIL: no zbuffer is associated with device. Clear failed.");
  3956. }
  3957. #endif
  3958. return D3DERR_INVALIDCALL;
  3959. }
  3960. if (bDoStencilClear)
  3961. {
  3962. D3DSURFACE_DESC desc = (this->ZBuffer())->InternalGetDesc();
  3963. if (!CPixel::IsIHVFormat(desc.Format) &&
  3964. !CPixel::HasStencilBits(desc.Format))
  3965. {
  3966. D3D_ERR("Invalid flag D3DCLEAR_STENCIL; current zbuffer's pixel format doesnt support stencil bits. Clear failed.");
  3967. return D3DERR_INVALIDCALL;
  3968. }
  3969. }
  3970. }
  3971. }
  3972. if (!(dwFlags & (D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL)))
  3973. {
  3974. D3D_ERR("Flags not valid. Clear failed.");
  3975. return D3DERR_INVALIDCALL;
  3976. }
  3977. // bad clear values just cause wacky results but no crashes, so OK to allow in retail bld
  3978. DDASSERT(!bDoZClear || ((dvZ>=0.0) && (dvZ<=1.0)));
  3979. DDASSERT(!bDoStencilClear || !pZPixFmt || (dwStencil <= (DWORD)((1<<pZPixFmt->dwStencilBitDepth)-1)));
  3980. ClearI(dwCount, rects, dwFlags, dwColor, dvZ, dwStencil);
  3981. return D3D_OK;
  3982. }
  3983. catch(HRESULT ret)
  3984. {
  3985. D3D_ERR("Clear failed.");
  3986. return ret;
  3987. }
  3988. }
  3989. //---------------------------------------------------------------------
  3990. #undef DPF_MODNAME
  3991. #define DPF_MODNAME "CD3DBase::FlushStatesNoThrow"
  3992. void __declspec(nothrow) CD3DBase::FlushStatesNoThrow()
  3993. {
  3994. try
  3995. {
  3996. DXGASSERT(m_pDDI);
  3997. m_pDDI->FlushStates();
  3998. }
  3999. catch(HRESULT hr)
  4000. {
  4001. DPF_ERR("Driver failed a command batch will synchronizing a synchronous call with the command stream. (No error will be returned to the app)");
  4002. }
  4003. }
  4004. //---------------------------------------------------------------------
  4005. #undef DPF_MODNAME
  4006. #define DPF_MODNAME "CD3DBase::TexBlt"
  4007. HRESULT __declspec(nothrow) CD3DBase::TexBlt(CBaseTexture *pDst,
  4008. CBaseTexture *pSrc,
  4009. POINT *pPoint,
  4010. RECTL *pRect)
  4011. {
  4012. // Get the draw prim handles
  4013. DWORD dwSrc = pSrc->BaseDrawPrimHandle();
  4014. DWORD dwDst = 0;
  4015. if (pDst)
  4016. {
  4017. dwDst = pDst->DriverAccessibleDrawPrimHandle();
  4018. }
  4019. // Insert the tokens now
  4020. try
  4021. {
  4022. m_pDDI->TexBlt(dwDst, dwSrc, pPoint, pRect);
  4023. }
  4024. catch(HRESULT ret)
  4025. {
  4026. return ret;
  4027. }
  4028. // If successful, batch the source and dest
  4029. // For the source, we want to call BatchBase since
  4030. // we want to batch the backing (or sysmem) texture
  4031. // rather than the promoted one.
  4032. pSrc->BatchBase();
  4033. if (pDst != NULL)
  4034. {
  4035. pDst->Batch();
  4036. }
  4037. return D3D_OK;
  4038. }
  4039. //---------------------------------------------------------------------
  4040. #undef DPF_MODNAME
  4041. #define DPF_MODNAME "CD3DBase::CubeTexBlt"
  4042. // Very similar function to TexBlt except that
  4043. // this is done for cube-maps which are special since we
  4044. // need to send different handles for each face
  4045. HRESULT __declspec(nothrow) CD3DBase::CubeTexBlt(CBaseTexture *pDstParent,
  4046. CBaseTexture *pSrcParent,
  4047. DWORD dwDestFaceHandle,
  4048. DWORD dwSrcFaceHandle,
  4049. POINT *pPoint,
  4050. RECTL *pRect)
  4051. {
  4052. // CubeTexBlt is not overloaded for use with PreLoad semantics
  4053. // so we should always have a source and a dest
  4054. DXGASSERT(pDstParent);
  4055. DXGASSERT(pSrcParent);
  4056. // Insert the tokens now
  4057. try
  4058. {
  4059. m_pDDI->TexBlt(dwDestFaceHandle, dwSrcFaceHandle, pPoint, pRect);
  4060. }
  4061. catch(HRESULT ret)
  4062. {
  4063. return ret;
  4064. }
  4065. // If successful, batch the parents of the source and dest
  4066. // For the source, we want to call BatchBase since
  4067. // we want to batch the backing (or sysmem) texture
  4068. // rather than the promoted one.
  4069. pSrcParent->BatchBase();
  4070. pDstParent->Batch();
  4071. return D3D_OK;
  4072. }
  4073. //---------------------------------------------------------------------
  4074. #undef DPF_MODNAME
  4075. #define DPF_MODNAME "CD3DBase::VolBlt"
  4076. HRESULT __declspec(nothrow)
  4077. CD3DBase::VolBlt(CBaseTexture *lpDst, CBaseTexture* lpSrc, DWORD dwDestX,
  4078. DWORD dwDestY, DWORD dwDestZ, D3DBOX *pBox)
  4079. {
  4080. try
  4081. {
  4082. m_pDDI->VolBlt(lpDst, lpSrc, dwDestX, dwDestY, dwDestZ, pBox);
  4083. return D3D_OK;
  4084. }
  4085. catch(HRESULT ret)
  4086. {
  4087. return ret;
  4088. }
  4089. }
  4090. //---------------------------------------------------------------------
  4091. #undef DPF_MODNAME
  4092. #define DPF_MODNAME "CD3DBase::BufBlt"
  4093. HRESULT __declspec(nothrow)
  4094. CD3DBase::BufBlt(CBuffer *lpDst, CBuffer* lpSrc, DWORD dwOffset,
  4095. D3DRANGE* pRange)
  4096. {
  4097. try
  4098. {
  4099. m_pDDI->BufBlt(lpDst, lpSrc, dwOffset, pRange);
  4100. return D3D_OK;
  4101. }
  4102. catch(HRESULT ret)
  4103. {
  4104. return ret;
  4105. }
  4106. }
  4107. //---------------------------------------------------------------------
  4108. #undef DPF_MODNAME
  4109. #define DPF_MODNAME "CD3DBase::SetPriority"
  4110. HRESULT __declspec(nothrow) CD3DBase::SetPriority(CResource *pRes, DWORD dwPriority)
  4111. {
  4112. try
  4113. {
  4114. m_pDDI->SetPriority(pRes, dwPriority);
  4115. return D3D_OK;
  4116. }
  4117. catch(HRESULT ret)
  4118. {
  4119. return ret;
  4120. }
  4121. }
  4122. //---------------------------------------------------------------------
  4123. #undef DPF_MODNAME
  4124. #define DPF_MODNAME "CD3DBase::SetTexLOD"
  4125. HRESULT __declspec(nothrow) CD3DBase::SetTexLOD(CBaseTexture *pTex, DWORD dwLOD)
  4126. {
  4127. try
  4128. {
  4129. m_pDDI->SetTexLOD(pTex, dwLOD);
  4130. return D3D_OK;
  4131. }
  4132. catch(HRESULT ret)
  4133. {
  4134. return ret;
  4135. }
  4136. }
  4137. //---------------------------------------------------------------------
  4138. #undef DPF_MODNAME
  4139. #define DPF_MODNAME "CD3DBase::AddDirtyRect"
  4140. HRESULT __declspec(nothrow) CD3DBase::AddDirtyRect(CBaseTexture *pTex, CONST RECTL *pRect)
  4141. {
  4142. DXGASSERT(pTex->IsD3DManaged() == 0);
  4143. DXGASSERT(pTex->GetBufferDesc()->Pool == D3DPOOL_MANAGED);
  4144. DXGASSERT((GetD3DCaps()->Caps2 & DDCAPS2_CANMANAGERESOURCE) != 0);
  4145. try
  4146. {
  4147. m_pDDI->AddDirtyRect(pTex->BaseDrawPrimHandle(), pRect);
  4148. }
  4149. catch(HRESULT ret)
  4150. {
  4151. return ret;
  4152. }
  4153. pTex->BatchBase();
  4154. return D3D_OK;
  4155. }
  4156. //---------------------------------------------------------------------
  4157. #undef DPF_MODNAME
  4158. #define DPF_MODNAME "CD3DBase::AddCubeDirtyRect"
  4159. HRESULT __declspec(nothrow) CD3DBase::AddCubeDirtyRect(CBaseTexture *pTex, DWORD dwFaceHandle, CONST RECTL *pRect)
  4160. {
  4161. DXGASSERT(pTex->IsD3DManaged() == 0);
  4162. DXGASSERT(pTex->GetBufferDesc()->Pool == D3DPOOL_MANAGED);
  4163. DXGASSERT((GetD3DCaps()->Caps2 & DDCAPS2_CANMANAGERESOURCE) != 0);
  4164. try
  4165. {
  4166. m_pDDI->AddDirtyRect(dwFaceHandle, pRect);
  4167. }
  4168. catch(HRESULT ret)
  4169. {
  4170. return ret;
  4171. }
  4172. pTex->BatchBase();
  4173. return D3D_OK;
  4174. }
  4175. //---------------------------------------------------------------------
  4176. #undef DPF_MODNAME
  4177. #define DPF_MODNAME "CD3DBase::AddDirtyBox"
  4178. HRESULT __declspec(nothrow) CD3DBase::AddDirtyBox(CBaseTexture *pTex, CONST D3DBOX *pBox)
  4179. {
  4180. DXGASSERT(pTex->IsD3DManaged() == 0);
  4181. DXGASSERT(pTex->GetBufferDesc()->Pool == D3DPOOL_MANAGED);
  4182. DXGASSERT((GetD3DCaps()->Caps2 & DDCAPS2_CANMANAGERESOURCE) != 0);
  4183. try
  4184. {
  4185. m_pDDI->AddDirtyBox(pTex->BaseDrawPrimHandle(), pBox);
  4186. }
  4187. catch(HRESULT ret)
  4188. {
  4189. return ret;
  4190. }
  4191. pTex->BatchBase();
  4192. return D3D_OK;
  4193. }
  4194. //-----------------------------------------------------------------------------
  4195. #undef DPF_MODNAME
  4196. #define DPF_MODNAME "CD3DBase::OnTextureDestroy"
  4197. void __declspec(nothrow) CD3DBase::OnTextureDestroy(CBaseTexture *pTex)
  4198. {
  4199. // On a pre-DX8 driver, the code will ensure that if any
  4200. // texture got unset by an API call, the driver will be
  4201. // informed. This needs to be done before calling the
  4202. // driver to destroy a texture handle as we have seen
  4203. // instances of drivers crashing. (snene - 4/24/00)
  4204. if(GetDDIType() < D3DDDITYPE_DX8)
  4205. {
  4206. D3DTEXTUREHANDLE dwDDIHandle = pTex->DriverAccessibleDrawPrimHandle();
  4207. if(dwDDIHandle != 0)
  4208. {
  4209. try
  4210. {
  4211. BOOL bNeedFlush = FALSE;
  4212. for (DWORD dwStage = 0; dwStage < m_dwMaxTextureBlendStages; dwStage++)
  4213. {
  4214. if(dwDDIHandle == m_dwDDITexHandle[dwStage])
  4215. {
  4216. m_pDDI->SetTSS(dwStage, (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP, 0);
  4217. m_dwDDITexHandle[dwStage] = 0;
  4218. bNeedFlush = TRUE;
  4219. }
  4220. }
  4221. if(bNeedFlush)
  4222. {
  4223. m_pDDI->FlushStates();
  4224. }
  4225. }
  4226. catch(HRESULT ret)
  4227. {
  4228. }
  4229. }
  4230. }
  4231. }
  4232. //---------------------------------------------------------------------
  4233. #undef DPF_MODNAME
  4234. #define DPF_MODNAME "CD3DBase::SetRenderStateInternal"
  4235. void
  4236. CD3DBase::SetRenderStateInternal(D3DRENDERSTATETYPE dwState, DWORD dwValue)
  4237. {
  4238. if (CanHandleRenderState(dwState))
  4239. m_pDDI->SetRenderState(dwState, dwValue);
  4240. }
  4241. //---------------------------------------------------------------------
  4242. #undef DPF_MODNAME
  4243. #define DPF_MODNAME "CD3DBase::StateInitialize"
  4244. void
  4245. CD3DBase::StateInitialize(BOOL bZEnable)
  4246. {
  4247. m_rsMax = m_pDDI->GetMaxRenderState();
  4248. m_tssMax = m_pDDI->GetMaxTSS();
  4249. D3DLINEPATTERN defLPat;
  4250. SetRenderStateInternal(D3DRENDERSTATE_ZENABLE, bZEnable);
  4251. SetRenderStateInternal(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID);
  4252. SetRenderStateInternal(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
  4253. defLPat.wRepeatFactor = 0;
  4254. defLPat.wLinePattern = 0;
  4255. SetRenderStateInternal(D3DRENDERSTATE_LINEPATTERN, *((LPDWORD)&defLPat)); /* 10 */
  4256. float tmpval;
  4257. /*
  4258. ((LPD3DSTATE)lpPointer)->drstRenderStateType =
  4259. (D3DRENDERSTATETYPE)D3DRENDERSTATE_LINEPATTERN;
  4260. memcpy(&(((LPD3DSTATE)lpPointer)->dwArg[0]), &defLPat, sizeof(DWORD));
  4261. lpPointer = (void *)(((LPD3DSTATE)lpPointer) + 1);*/
  4262. SetRenderStateInternal(D3DRENDERSTATE_ZWRITEENABLE, TRUE);
  4263. SetRenderStateInternal(D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
  4264. SetRenderStateInternal(D3DRENDERSTATE_LASTPIXEL, TRUE);
  4265. SetRenderStateInternal(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
  4266. SetRenderStateInternal(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO);
  4267. SetRenderStateInternal(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW); /* 21 */
  4268. SetRenderStateInternal(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
  4269. SetRenderStateInternal(D3DRENDERSTATE_ALPHAREF, 0);
  4270. SetRenderStateInternal(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_ALWAYS);
  4271. SetRenderStateInternal(D3DRENDERSTATE_DITHERENABLE, FALSE);
  4272. SetRenderStateInternal(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
  4273. SetRenderStateInternal(D3DRENDERSTATE_FOGENABLE, FALSE);
  4274. SetRenderStateInternal(D3DRENDERSTATE_SPECULARENABLE, FALSE);
  4275. SetRenderStateInternal(D3DRENDERSTATE_ZVISIBLE, FALSE);
  4276. SetRenderStateInternal(D3DRENDERSTATE_FOGCOLOR, 0);
  4277. SetRenderStateInternal(D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
  4278. tmpval = 0.0f;
  4279. SetRenderStateInternal(D3DRENDERSTATE_FOGSTART, *((DWORD *)&tmpval));
  4280. tmpval = 1.0f;
  4281. SetRenderStateInternal(D3DRENDERSTATE_FOGEND, *((DWORD *)&tmpval));
  4282. tmpval = 1.0f;
  4283. SetRenderStateInternal(D3DRENDERSTATE_FOGDENSITY, *((DWORD *)&tmpval));
  4284. SetRenderStateInternal(D3DRENDERSTATE_EDGEANTIALIAS, FALSE);
  4285. SetRenderStateInternal(D3DRENDERSTATE_ZBIAS, 0);
  4286. SetRenderStateInternal(D3DRENDERSTATE_RANGEFOGENABLE, FALSE);
  4287. // init stencil states to something reasonable
  4288. // stencil enable is OFF by default since stenciling rasterizers will be
  4289. // faster with it disabled, even if stencil states are benign
  4290. SetRenderStateInternal(D3DRENDERSTATE_STENCILENABLE, FALSE);
  4291. SetRenderStateInternal(D3DRENDERSTATE_STENCILFAIL, D3DSTENCILOP_KEEP);
  4292. SetRenderStateInternal(D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_KEEP);
  4293. SetRenderStateInternal(D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_KEEP);
  4294. SetRenderStateInternal(D3DRENDERSTATE_STENCILFUNC, D3DCMP_ALWAYS);
  4295. SetRenderStateInternal(D3DRENDERSTATE_STENCILREF, 0);
  4296. SetRenderStateInternal(D3DRENDERSTATE_STENCILMASK, 0xFFFFFFFF);
  4297. SetRenderStateInternal(D3DRENDERSTATE_STENCILWRITEMASK,0xFFFFFFFF);
  4298. // don't forget about texturefactor (like we did in DX6.0...)
  4299. SetRenderStateInternal(D3DRENDERSTATE_TEXTUREFACTOR, 0xFFFFFFFF);
  4300. for (DWORD i = 0; i < 8; i++)
  4301. {
  4302. SetRenderStateInternal((D3DRENDERSTATETYPE)
  4303. (D3DRENDERSTATE_WRAPBIAS + i), FALSE);
  4304. }
  4305. for (i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
  4306. {
  4307. m_lpD3DMappedTexI[i] = NULL;
  4308. m_dwDDITexHandle[i] = 0;
  4309. }
  4310. m_dwStageDirty = 0;
  4311. for (i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
  4312. {
  4313. SetTexture(i, NULL);
  4314. if (i == 0)
  4315. SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_MODULATE);
  4316. else
  4317. SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
  4318. SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  4319. SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
  4320. if (i == 0)
  4321. SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  4322. else
  4323. SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  4324. SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  4325. SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  4326. SetTextureStageState(i, D3DTSS_BUMPENVMAT00, 0);
  4327. SetTextureStageState(i, D3DTSS_BUMPENVMAT01, 0);
  4328. SetTextureStageState(i, D3DTSS_BUMPENVMAT10, 0);
  4329. SetTextureStageState(i, D3DTSS_BUMPENVMAT11, 0);
  4330. SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i);
  4331. SetTextureStageState(i, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  4332. SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  4333. SetTextureStageState(i, D3DTSS_BORDERCOLOR, 0x00000000);
  4334. SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_POINT);
  4335. SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_POINT);
  4336. SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  4337. SetTextureStageState(i, D3DTSS_MIPMAPLODBIAS, 0);
  4338. SetTextureStageState(i, D3DTSS_MAXMIPLEVEL, 0);
  4339. SetTextureStageState(i, D3DTSS_MAXANISOTROPY, 1);
  4340. SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, 0);
  4341. SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, 0);
  4342. SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  4343. SetTextureStageState(i, D3DTSS_ADDRESSW, D3DTADDRESS_WRAP);
  4344. SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_CURRENT);
  4345. SetTextureStageState(i, D3DTSS_ALPHAARG0, D3DTA_CURRENT);
  4346. SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
  4347. }
  4348. SetRenderStateInternal(D3DRENDERSTATE_CLIPPING, TRUE);
  4349. SetRenderStateInternal(D3DRENDERSTATE_LIGHTING, TRUE);
  4350. SetRenderStateInternal(D3DRENDERSTATE_AMBIENT, 0);
  4351. SetRenderStateInternal(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE);
  4352. SetRenderStateInternal(D3DRENDERSTATE_COLORVERTEX, TRUE);
  4353. SetRenderStateInternal(D3DRENDERSTATE_LOCALVIEWER, TRUE);
  4354. SetRenderStateInternal(D3DRENDERSTATE_NORMALIZENORMALS, FALSE);
  4355. SetRenderStateInternal(D3DRENDERSTATE_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
  4356. SetRenderStateInternal(D3DRENDERSTATE_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
  4357. SetRenderStateInternal(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
  4358. SetRenderStateInternal(D3DRENDERSTATE_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
  4359. SetRenderStateInternal(D3DRENDERSTATE_VERTEXBLEND, D3DVBF_DISABLE);
  4360. SetRenderStateInternal(D3DRENDERSTATE_CLIPPLANEENABLE, 0);
  4361. //
  4362. // new for DX8
  4363. //
  4364. SetRenderStateInternal(D3DRS_SOFTWAREVERTEXPROCESSING, 0);
  4365. tmpval = GetD3DCaps()->MaxPointSize;
  4366. if (tmpval == 0)
  4367. tmpval = __MAX_POINT_SIZE;
  4368. SetRenderStateInternal(D3DRS_POINTSIZE_MAX, *((DWORD *)&tmpval));
  4369. tmpval = 1.F;
  4370. SetRenderStateInternal(D3DRS_POINTSIZE, *((DWORD *)&tmpval));
  4371. SetRenderStateInternal(D3DRS_POINTSIZE_MIN, 0);
  4372. SetRenderStateInternal(D3DRS_POINTSPRITEENABLE, 0);
  4373. SetRenderStateInternal(D3DRS_POINTSCALEENABLE , 0);
  4374. SetRenderStateInternal(D3DRS_POINTSCALE_A, *((DWORD *)&tmpval));
  4375. SetRenderStateInternal(D3DRS_POINTSCALE_B, 0);
  4376. SetRenderStateInternal(D3DRS_POINTSCALE_C, 0);
  4377. SetRenderStateInternal(D3DRS_MULTISAMPLEMASK, 0xffffffff);
  4378. SetRenderStateInternal(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
  4379. SetRenderStateInternal(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
  4380. tmpval = 1.F;
  4381. SetRenderStateInternal(D3DRS_PATCHSEGMENTS, *((DWORD *)&tmpval));
  4382. SetRenderStateInternal(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
  4383. SetRenderStateInternal(D3DRS_COLORWRITEENABLE, 0xF);
  4384. tmpval = 0.F;
  4385. SetRenderStateInternal(D3DRS_TWEENFACTOR, *((DWORD *)&tmpval));
  4386. SetRenderStateInternal(D3DRS_BLENDOP, D3DBLENDOP_ADD);
  4387. // New for DX8.1
  4388. SetRenderStateInternal(D3DRS_POSITIONORDER, D3DORDER_CUBIC);
  4389. SetRenderStateInternal(D3DRS_NORMALORDER, D3DORDER_LINEAR);
  4390. // Initialize the transform state
  4391. D3DMATRIXI m;
  4392. setIdentity(&m);
  4393. this->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&m);
  4394. this->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)&m);
  4395. {
  4396. for (UINT i=0; i < __MAXWORLDMATRICES; i++)
  4397. this->SetTransform(D3DTS_WORLDMATRIX(i), (D3DMATRIX*)&m);
  4398. }
  4399. this->SetTransform(D3DTS_TEXTURE0, (D3DMATRIX*)&m);
  4400. this->SetTransform(D3DTS_TEXTURE1, (D3DMATRIX*)&m);
  4401. this->SetTransform(D3DTS_TEXTURE2, (D3DMATRIX*)&m);
  4402. this->SetTransform(D3DTS_TEXTURE3, (D3DMATRIX*)&m);
  4403. this->SetTransform(D3DTS_TEXTURE4, (D3DMATRIX*)&m);
  4404. this->SetTransform(D3DTS_TEXTURE5, (D3DMATRIX*)&m);
  4405. this->SetTransform(D3DTS_TEXTURE6, (D3DMATRIX*)&m);
  4406. this->SetTransform(D3DTS_TEXTURE7, (D3DMATRIX*)&m);
  4407. }
  4408. //-----------------------------------------------------------------------------
  4409. #undef DPF_MODNAME
  4410. #define DPF_MODNAME "CD3DBase::UpdatePalette"
  4411. void CD3DBase::UpdatePalette(CBaseTexture *pTex, DWORD Palette, DWORD dwStage, BOOL bSavedWithinPrimitive)
  4412. {
  4413. try
  4414. {
  4415. if(Palette == __INVALIDPALETTE)
  4416. {
  4417. D3D_THROW(D3DERR_INVALIDCALL, "Current palette not set");
  4418. }
  4419. if(pTex->GetPalette() != Palette)
  4420. {
  4421. DWORD dwFlags = DDRAWIPAL_256 | DDRAWIPAL_ALLOW256;
  4422. if (Enum()->GetAppSdkVersion() > D3D_SDK_VERSION_DX8)
  4423. {
  4424. if ((GetD3DCaps()->TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE) &&
  4425. (pTex->GetBufferDesc()->Format != D3DFMT_A8P8) )
  4426. {
  4427. dwFlags |= DDRAWIPAL_ALPHA;
  4428. }
  4429. }
  4430. else
  4431. {
  4432. //This odd selection of formats to receive the palette flag
  4433. //is inherited from DX8. It is wrong, but left in for app-compat reasons.
  4434. if (pTex->GetBufferDesc()->Format != D3DFMT_A8P8)
  4435. {
  4436. dwFlags |= DDRAWIPAL_ALPHA;
  4437. }
  4438. }
  4439. m_pDDI->SetPalette(Palette,
  4440. dwFlags,
  4441. pTex);
  4442. }
  4443. CPalette *pal = static_cast<CPalette*>((*m_pPaletteArray)[Palette].m_pObj);
  4444. if(pal->m_dirty)
  4445. {
  4446. m_pDDI->UpdatePalette(Palette, 0, 256, pal->m_pEntries);
  4447. pal->m_dirty = FALSE;
  4448. }
  4449. }
  4450. catch(HRESULT ret)
  4451. {
  4452. try
  4453. {
  4454. m_pDDI->SetTSS(dwStage,
  4455. (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP,
  4456. 0);
  4457. }
  4458. catch(HRESULT ret)
  4459. {
  4460. m_pDDI->SetWithinPrimitive( bSavedWithinPrimitive );
  4461. D3D_THROW(ret, "");
  4462. }
  4463. m_dwDDITexHandle[dwStage] = 0;
  4464. m_pDDI->SetWithinPrimitive( bSavedWithinPrimitive );
  4465. D3D_THROW(ret, "");
  4466. }
  4467. }
  4468. //-----------------------------------------------------------------------------
  4469. #undef DPF_MODNAME
  4470. #define DPF_MODNAME "CD3DBase::UpdateTextures"
  4471. void CD3DBase::UpdateTextures()
  4472. {
  4473. BOOL bSavedWithinPrimitive = m_pDDI->GetWithinPrimitive();
  4474. m_pDDI->SetWithinPrimitive(TRUE);
  4475. for (DWORD dwStage = 0, StageMask = 1; dwStage < m_dwMaxTextureBlendStages; dwStage++, StageMask <<= 1)
  4476. {
  4477. D3DTEXTUREHANDLE dwDDIHandle;
  4478. BOOL bDirty = (m_dwStageDirty & StageMask) != 0;
  4479. m_dwStageDirty &= ~StageMask; // reset stage dirty
  4480. CBaseTexture *lpTexI = m_lpD3DMappedTexI[dwStage];
  4481. if(lpTexI)
  4482. {
  4483. #if DBG
  4484. if (lpTexI->IsTextureLocked())
  4485. {
  4486. DPF_ERR("Cannot update a locked texture. Texture will be disabled.");
  4487. dwDDIHandle = 0; //tell driver to disable this texture
  4488. }
  4489. else
  4490. {
  4491. #endif // DBG
  4492. if (lpTexI->IsD3DManaged())
  4493. {
  4494. HRESULT hr = ResourceManager()->UpdateVideo(lpTexI->RMHandle(), &bDirty);
  4495. if (FAILED(hr))
  4496. {
  4497. DPF_ERR("The resource manager failed to promote or update a dirty texture. The texture will be disabled.");
  4498. dwDDIHandle = 0; //tell driver to disable this texture
  4499. }
  4500. else
  4501. {
  4502. if (lpTexI->IsPaletted())
  4503. {
  4504. // UpdatePalette can THROW but it safely handles bSavedWithinPrimitive
  4505. UpdatePalette(lpTexI, m_dwPalette, dwStage, bSavedWithinPrimitive);
  4506. }
  4507. if (!bDirty)
  4508. {
  4509. continue; // Ok, then nothing needs to be done further
  4510. }
  4511. dwDDIHandle = static_cast<CMgmtInfo*>(lpTexI->RMHandle())->m_pRes->BaseDrawPrimHandle();
  4512. }
  4513. }
  4514. else
  4515. {
  4516. if (lpTexI->IsPaletted())
  4517. {
  4518. // UpdatePalette can THROW but it safely handles bSavedWithinPrimitive
  4519. UpdatePalette(lpTexI, m_dwPalette, dwStage, bSavedWithinPrimitive);
  4520. }
  4521. if (!bDirty)
  4522. {
  4523. continue; // Ok, then nothing needs to be done further
  4524. }
  4525. dwDDIHandle = lpTexI->BaseDrawPrimHandle();
  4526. }
  4527. #if DBG
  4528. }
  4529. #endif // DBG
  4530. }
  4531. else if (bDirty)
  4532. {
  4533. dwDDIHandle = 0; //tell driver to disable this texture
  4534. }
  4535. else
  4536. {
  4537. continue;
  4538. }
  4539. try
  4540. {
  4541. m_pDDI->SetTSS(dwStage,
  4542. (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP,
  4543. dwDDIHandle);
  4544. }
  4545. catch (HRESULT ret)
  4546. {
  4547. m_pDDI->SetWithinPrimitive( bSavedWithinPrimitive );
  4548. D3D_THROW(ret, "");
  4549. }
  4550. m_dwDDITexHandle[dwStage] = dwDDIHandle;
  4551. if (lpTexI != 0)
  4552. {
  4553. lpTexI->Batch();
  4554. }
  4555. }
  4556. m_pDDI->SetWithinPrimitive( bSavedWithinPrimitive );
  4557. }
  4558. //-----------------------------------------------------------------------------
  4559. #undef DPF_MODNAME
  4560. #define DPF_MODNAME "CD3DBase::IncrementBatch"
  4561. void CD3DBase::IncrementBatchCount()
  4562. {
  4563. DXGASSERT(m_qwBatch > 0);
  4564. m_qwBatch++;
  4565. // Also we need to update the
  4566. // batch counts of our currently set
  4567. // render target and z
  4568. // Batch the current RT
  4569. // RT could be gone during Reset()
  4570. if (RenderTarget() != 0)
  4571. {
  4572. RenderTarget()->Batch();
  4573. }
  4574. if (ZBuffer() != 0)
  4575. {
  4576. // Update the batch count for the current Zbuffer
  4577. ZBuffer()->Batch();
  4578. }
  4579. // So that currently bound textures get rebatched
  4580. for (DWORD dwStage = 0; dwStage < m_dwMaxTextureBlendStages; dwStage++)
  4581. {
  4582. CBaseTexture *lpTexI = m_lpD3DMappedTexI[dwStage];
  4583. if (NULL != lpTexI)
  4584. {
  4585. lpTexI->Batch();
  4586. }
  4587. }
  4588. } // IncrementBatch
  4589. //-----------------------------------------------------------------------------
  4590. #undef DPF_MODNAME
  4591. #define DPF_MODNAME "CD3DBase::GetMaterial"
  4592. HRESULT D3DAPI
  4593. CD3DBase::GetMaterial(D3DMATERIAL8*)
  4594. {
  4595. API_ENTER(this);
  4596. D3D_ERR("GetMaterial does not work in pure-device");
  4597. return D3DERR_INVALIDCALL;
  4598. }
  4599. //-----------------------------------------------------------------------------
  4600. #undef DPF_MODNAME
  4601. #define DPF_MODNAME "CD3DBase::GetTransform"
  4602. HRESULT D3DAPI
  4603. CD3DBase::GetTransform(D3DTRANSFORMSTATETYPE, LPD3DMATRIX)
  4604. {
  4605. API_ENTER(this);
  4606. D3D_ERR("GetTransform does not work in pure-device");
  4607. return D3DERR_INVALIDCALL;
  4608. }
  4609. //-----------------------------------------------------------------------------
  4610. #undef DPF_MODNAME
  4611. #define DPF_MODNAME "CD3DBase::GetLight"
  4612. HRESULT D3DAPI
  4613. CD3DBase::GetLight(DWORD, D3DLIGHT8*)
  4614. {
  4615. API_ENTER(this);
  4616. D3D_ERR("GetLight does not work in pure-device");
  4617. return D3DERR_INVALIDCALL;
  4618. }
  4619. //-----------------------------------------------------------------------------
  4620. #undef DPF_MODNAME
  4621. #define DPF_MODNAME "CD3DBase::GetLightEnable"
  4622. HRESULT D3DAPI
  4623. CD3DBase::GetLightEnable(DWORD dwLightIndex, BOOL*)
  4624. {
  4625. API_ENTER(this);
  4626. D3D_ERR("GetLightEnable does not work in pure-device");
  4627. return D3DERR_INVALIDCALL;
  4628. }
  4629. //-----------------------------------------------------------------------------
  4630. #undef DPF_MODNAME
  4631. #define DPF_MODNAME "CD3DBase::GetClipPlane"
  4632. HRESULT D3DAPI
  4633. CD3DBase::GetClipPlane(DWORD dwPlaneIndex, D3DVALUE* pPlaneEquation)
  4634. {
  4635. API_ENTER(this);
  4636. D3D_ERR("GetClipPlane does not work in pure-device");
  4637. return D3DERR_INVALIDCALL;
  4638. }
  4639. //-----------------------------------------------------------------------------
  4640. #undef DPF_MODNAME
  4641. #define DPF_MODNAME "CD3DBase::GetTextureStageState"
  4642. HRESULT D3DAPI
  4643. CD3DBase::GetTextureStageState(DWORD, D3DTEXTURESTAGESTATETYPE, LPDWORD)
  4644. {
  4645. API_ENTER(this);
  4646. D3D_ERR("GetTextureStageState does not work in pure-device");
  4647. return D3DERR_INVALIDCALL;
  4648. }
  4649. //-----------------------------------------------------------------------------
  4650. #undef DPF_MODNAME
  4651. #define DPF_MODNAME "CD3DBase::GetViewport"
  4652. HRESULT D3DAPI
  4653. CD3DBase::GetViewport(D3DVIEWPORT8*)
  4654. {
  4655. API_ENTER(this);
  4656. D3D_ERR("GetViewport does not work in pure-device");
  4657. return D3DERR_INVALIDCALL;
  4658. }
  4659. //-----------------------------------------------------------------------------
  4660. #undef DPF_MODNAME
  4661. #define DPF_MODNAME "CD3DBase::GetRenderState"
  4662. HRESULT D3DAPI
  4663. CD3DBase::GetRenderState(D3DRENDERSTATETYPE, LPDWORD)
  4664. {
  4665. API_ENTER(this);
  4666. D3D_ERR("GetRenderState does not work in pure-device");
  4667. return D3DERR_INVALIDCALL;
  4668. }
  4669. //-----------------------------------------------------------------------------
  4670. #undef DPF_MODNAME
  4671. #define DPF_MODNAME "CD3DBase::GetPixelShaderConstant"
  4672. HRESULT D3DAPI
  4673. CD3DBase::GetPixelShaderConstant(DWORD dwRegisterAddress,
  4674. LPVOID lpvConstantData,
  4675. DWORD dwConstantCount)
  4676. {
  4677. API_ENTER(this);
  4678. D3D_ERR("GetPixelShaderConstant does not work in pure-device");
  4679. return E_NOTIMPL;
  4680. }
  4681. //-----------------------------------------------------------------------------
  4682. #undef DPF_MODNAME
  4683. #define DPF_MODNAME "CD3DBase::GetVertexShaderConstant"
  4684. HRESULT D3DAPI
  4685. CD3DBase::GetVertexShaderConstant(DWORD dwRegisterAddress,
  4686. LPVOID lpvConstantData,
  4687. DWORD dwConstantCount)
  4688. {
  4689. API_ENTER(this);
  4690. D3D_ERR("GetVertexShaderConstant does not work in pure-device");
  4691. return E_NOTIMPL;
  4692. }
  4693. //-----------------------------------------------------------------------------
  4694. #undef DPF_MODNAME
  4695. #define DPF_MODNAME "CD3DBase::GetVertexShaderDeclaration"
  4696. HRESULT D3DAPI
  4697. CD3DBase::GetVertexShaderDeclaration(DWORD dwHandle, void *pData,
  4698. DWORD *pSizeOfData)
  4699. {
  4700. API_ENTER(this);
  4701. try
  4702. {
  4703. #if DBG
  4704. if (!(VALID_WRITEPTR(pSizeOfData, sizeof(*pSizeOfData))))
  4705. {
  4706. D3D_THROW(D3DERR_INVALIDCALL, "Invalid data size pointer");
  4707. }
  4708. if (pData && !(VALID_WRITEPTR(pData, *pSizeOfData)))
  4709. {
  4710. D3D_THROW(D3DERR_INVALIDCALL, "Invalid data pointer");
  4711. }
  4712. #endif
  4713. if (D3DVSD_ISLEGACY(dwHandle))
  4714. {
  4715. *pSizeOfData = 0;
  4716. D3D_THROW(D3DERR_INVALIDCALL, "Legacy vertex shaders do not have declaration");
  4717. }
  4718. else
  4719. {
  4720. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  4721. if (pShader == NULL)
  4722. {
  4723. D3D_THROW(D3DERR_INVALIDCALL, "Invalid vertex shader handle");
  4724. }
  4725. if (pData)
  4726. {
  4727. if (*pSizeOfData < pShader->m_OrgDeclSize)
  4728. {
  4729. D3D_THROW(D3DERR_INVALIDCALL, "Invalid data pointer");
  4730. }
  4731. memcpy(pData, pShader->m_pOrgDeclaration, pShader->m_OrgDeclSize);
  4732. }
  4733. *pSizeOfData = pShader->m_OrgDeclSize;
  4734. }
  4735. }
  4736. catch (HRESULT ret)
  4737. {
  4738. DPF_ERR("GetVertexShaderDeclaration failed.");
  4739. return ret;
  4740. }
  4741. return S_OK;
  4742. }
  4743. //-----------------------------------------------------------------------------
  4744. #undef DPF_MODNAME
  4745. #define DPF_MODNAME "CD3DBase::GetVertexShaderFunction"
  4746. HRESULT D3DAPI
  4747. CD3DBase::GetVertexShaderFunction(DWORD dwHandle, void *pData,
  4748. DWORD *pSizeOfData)
  4749. {
  4750. API_ENTER(this);
  4751. try
  4752. {
  4753. #if DBG
  4754. if (!(VALID_WRITEPTR(pSizeOfData, sizeof(*pSizeOfData))))
  4755. {
  4756. D3D_THROW(D3DERR_INVALIDCALL, "Invalid data size pointer");
  4757. }
  4758. if (pData && !(VALID_WRITEPTR(pData, *pSizeOfData)))
  4759. {
  4760. D3D_THROW(D3DERR_INVALIDCALL, "Invalid data pointer");
  4761. }
  4762. #endif
  4763. if (D3DVSD_ISLEGACY(dwHandle))
  4764. {
  4765. *pSizeOfData = 0;
  4766. D3D_THROW(D3DERR_INVALIDCALL, "Legacy vertex shaders do not have function code");
  4767. }
  4768. else
  4769. {
  4770. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  4771. if (pShader == NULL)
  4772. {
  4773. D3D_THROW(D3DERR_INVALIDCALL, "Invalid vertex shader handle");
  4774. }
  4775. if (pData)
  4776. {
  4777. if (*pSizeOfData < pShader->m_OrgFuncCodeSize)
  4778. {
  4779. D3D_THROW(D3DERR_INVALIDCALL, "Invalid data buffer size");
  4780. }
  4781. memcpy(pData, pShader->m_pOrgFuncCode, pShader->m_OrgFuncCodeSize);
  4782. }
  4783. *pSizeOfData = pShader->m_OrgFuncCodeSize;
  4784. }
  4785. }
  4786. catch (HRESULT ret)
  4787. {
  4788. DPF_ERR("GetVertexShaderFunction failed.");
  4789. return ret;
  4790. }
  4791. return S_OK;
  4792. }
  4793. //-----------------------------------------------------------------------------
  4794. #undef DPF_MODNAME
  4795. #define DPF_MODNAME "CD3DBase::GetPixelShaderFunction"
  4796. HRESULT D3DAPI
  4797. CD3DBase::GetPixelShaderFunction(DWORD dwHandle, void *pData,
  4798. DWORD *pSizeOfData)
  4799. {
  4800. API_ENTER(this);
  4801. try
  4802. {
  4803. #if DBG
  4804. if (!(VALID_WRITEPTR(pSizeOfData, sizeof(*pSizeOfData))))
  4805. {
  4806. D3D_THROW(D3DERR_INVALIDCALL, "Invalid data size pointer");
  4807. }
  4808. if (pData && !(VALID_WRITEPTR(pData, *pSizeOfData)))
  4809. {
  4810. D3D_THROW(D3DERR_INVALIDCALL, "Invalid data pointer");
  4811. }
  4812. #endif
  4813. CPShader* pShader = (CPShader*)m_pPShaderArray->GetObject(dwHandle);
  4814. if (pShader == NULL)
  4815. {
  4816. D3D_THROW(D3DERR_INVALIDCALL, "Invalid pixel shader handle");
  4817. }
  4818. if (pData)
  4819. {
  4820. if (*pSizeOfData < pShader->m_dwCodeSizeOrig)
  4821. {
  4822. D3D_THROW(D3DERR_INVALIDCALL, "Invalid data buffer size");
  4823. }
  4824. memcpy(pData, pShader->m_pCodeOrig, pShader->m_dwCodeSizeOrig);
  4825. }
  4826. *pSizeOfData = pShader->m_dwCodeSizeOrig;
  4827. }
  4828. catch (HRESULT ret)
  4829. {
  4830. DPF_ERR("GetPixelShaderFunction failed");
  4831. return ret;
  4832. }
  4833. return S_OK;
  4834. }