Leaked source code of windows server 2003
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.

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