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.

1694 lines
52 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: devstate.c
  6. * Content: device state management
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "drawprim.hpp"
  12. extern HRESULT checkDeviceSurface(LPDIRECT3DDEVICEI lpD3DDev,
  13. LPDIRECTDRAWSURFACE lpDDS);
  14. extern HRESULT CalcDDSurfInfo(LPDIRECT3DDEVICEI lpDevI, BOOL bUpdateZBufferFields);
  15. extern HRESULT downloadView(LPDIRECT3DVIEWPORTI lpViewI);
  16. #undef DPF_MODNAME
  17. #define DPF_MODNAME "Direct3DDevice::SetCurrentViewport"
  18. HRESULT D3DAPI DIRECT3DDEVICEI::SetCurrentViewport(LPDIRECT3DVIEWPORT2 lpViewport)
  19. {
  20. return SetCurrentViewport((LPDIRECT3DVIEWPORT3)lpViewport);
  21. }
  22. HRESULT D3DAPI DIRECT3DDEVICEI::SetCurrentViewport(LPDIRECT3DVIEWPORT3 lpViewport)
  23. {
  24. LPDIRECT3DVIEWPORTI lpD3DViewI,lpOldViewportI;
  25. HRESULT err;
  26. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  27. // Release in the destructor
  28. /*
  29. * validate parms
  30. */
  31. TRY
  32. {
  33. lpD3DViewI = (LPDIRECT3DVIEWPORTI)lpViewport;
  34. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  35. {
  36. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  37. return DDERR_INVALIDOBJECT;
  38. }
  39. if (!VALID_DIRECT3DVIEWPORT3_PTR(lpViewport))
  40. {
  41. D3D_ERR( "Invalid viewport pointer passed to SetCurrentViewport" );
  42. return DDERR_INVALIDPARAMS;
  43. }
  44. }
  45. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  46. {
  47. D3D_ERR( "Exception encountered validating parameters in SetCurrentViewport" );
  48. return DDERR_INVALIDPARAMS;
  49. }
  50. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  51. {
  52. D3D_ERR( "SetCurrentViewport in Begin" );
  53. return D3DERR_INBEGIN;
  54. }
  55. /*
  56. * The viewport must be associated with this device
  57. */
  58. if (lpD3DViewI->lpDevI != this)
  59. {
  60. D3D_ERR( "Viewport not associated with this device" );
  61. return (DDERR_INVALIDPARAMS);
  62. }
  63. lpOldViewportI=this->lpCurrentViewport;
  64. this->lpCurrentViewport = lpD3DViewI;
  65. if (lpD3DViewI->v_id != v_id && lpD3DViewI->v_data_is_set)
  66. {
  67. err = downloadView(lpD3DViewI);
  68. if (err != D3D_OK)
  69. {
  70. this->lpCurrentViewport = lpOldViewportI;
  71. return err;
  72. }
  73. }
  74. if(lpOldViewportI!=NULL)
  75. lpOldViewportI->Release();
  76. this->lpCurrentViewport->AddRef();
  77. return D3D_OK;
  78. }
  79. #undef DPF_MODNAME
  80. #define DPF_MODNAME "Direct3DDevice::GetCurrentViewport"
  81. HRESULT D3DAPI DIRECT3DDEVICEI::GetCurrentViewport(LPDIRECT3DVIEWPORT2 *lpViewport)
  82. {
  83. return GetCurrentViewport((LPDIRECT3DVIEWPORT3*)lpViewport);
  84. }
  85. HRESULT D3DAPI DIRECT3DDEVICEI::GetCurrentViewport(LPDIRECT3DVIEWPORT3 *lpViewport)
  86. {
  87. LPDIRECT3DVIEWPORTI lpD3DViewI;
  88. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  89. // Release in the destructor
  90. /*
  91. * validate parms
  92. */
  93. TRY
  94. {
  95. lpD3DViewI = (LPDIRECT3DVIEWPORTI)lpViewport;
  96. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  97. {
  98. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  99. return DDERR_INVALIDOBJECT;
  100. }
  101. if (!VALID_PTR_PTR(lpViewport))
  102. {
  103. D3D_ERR( "Invalid viewport pointer passed to GetCurrentViewport" );
  104. return DDERR_INVALIDPARAMS;
  105. }
  106. }
  107. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  108. {
  109. D3D_ERR( "Exception encountered validating parameters in GetCurrentViewport" );
  110. return DDERR_INVALIDPARAMS;
  111. }
  112. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  113. {
  114. D3D_ERR( "GetCurrentViewport in Begin" );
  115. return D3DERR_INBEGIN;
  116. }
  117. if (VALID_DIRECT3DVIEWPORT3_PTR(this->lpCurrentViewport))
  118. {
  119. this->lpCurrentViewport->AddRef();
  120. *lpViewport = (LPDIRECT3DVIEWPORT3)this->lpCurrentViewport;
  121. return D3D_OK;
  122. }
  123. else
  124. {
  125. return D3DERR_NOCURRENTVIEWPORT;
  126. }
  127. }
  128. #undef DPF_MODNAME
  129. #define DPF_MODNAME "Direct3DDevice::SetRenderState"
  130. HRESULT D3DAPI
  131. DIRECT3DDEVICEI::SetRenderState(D3DRENDERSTATETYPE dwState, DWORD value)
  132. {
  133. // Takes D3D lock (MT only).
  134. // Lock released in the destructor.
  135. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  136. #if DBG
  137. #ifdef DEBUG_PIPELINE
  138. extern void SetDebugRenderState(DWORD value);
  139. if (dwState == (D3DRENDERSTATETYPE)0xFFFFFFFF)
  140. {
  141. SetDebugRenderState(value);
  142. return D3D_OK;
  143. }
  144. #endif
  145. #endif //DBG range check below is needed for backward comp with DX5
  146. if (dwState >= D3DHAL_MAX_RSTATES || dwState == 0)
  147. {
  148. D3D_ERR( "Invalid render state type" );
  149. return DDERR_INVALIDPARAMS;
  150. }
  151. #if DBG
  152. TRY
  153. {
  154. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  155. {
  156. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  157. return DDERR_INVALIDOBJECT;
  158. }
  159. }
  160. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  161. {
  162. D3D_ERR( "Exception encountered validating parameters in SetRenderState" );
  163. return DDERR_INVALIDPARAMS;
  164. }
  165. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  166. {
  167. D3D_ERR( "SetRenderState in Begin" );
  168. return D3DERR_INBEGIN;
  169. }
  170. #endif
  171. if (D3DRENDERSTATE_FLUSHBATCH == dwState)
  172. {
  173. CLockD3DST lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (ST only).
  174. // Release in the destructor
  175. HRESULT ret;
  176. ret = FlushStates();
  177. if (ret != D3D_OK)
  178. {
  179. D3D_ERR("Error trying to render batched commands in SetRenderState");
  180. return ret;
  181. }
  182. return D3D_OK;
  183. }
  184. // map legacy renderstate into WRAP0 - needed for clipping if nothing else
  185. if ( (D3DRENDERSTATE_WRAPU == dwState) || (D3DRENDERSTATE_WRAPV == dwState) )
  186. {
  187. DWORD dwWRAP0State = this->rstates[D3DRENDERSTATE_WRAP0];
  188. DWORD dwWrapFlag = (D3DRENDERSTATE_WRAPU == dwState) ? (D3DWRAP_U) : (D3DWRAP_V);
  189. if (value) dwWRAP0State |= dwWrapFlag;
  190. else dwWRAP0State &= ~dwWrapFlag;
  191. if ( dwWRAP0State != this->rstates[D3DRENDERSTATE_WRAP0] )
  192. {
  193. SetDeviceRenderState(this, D3DRENDERSTATE_WRAP0, dwWRAP0State);
  194. // send new RS's to DX6 aware drivers only
  195. if (IS_DP2HAL_DEVICE(this))
  196. {
  197. SetRenderStateI(D3DRENDERSTATE_WRAP0, dwWRAP0State);
  198. }
  199. }
  200. }
  201. // map WRAP0 into legacy renderstate
  202. if (D3DRENDERSTATE_WRAP0 == dwState)
  203. {
  204. if (!(IS_DP2HAL_DEVICE(this)))
  205. {
  206. BOOLEAN ustate = (value & D3DWRAP_U) ? TRUE : FALSE;
  207. BOOLEAN vstate = (value & D3DWRAP_V) ? TRUE : FALSE;
  208. if (this->rstates[D3DRENDERSTATE_WRAPU] == ustate &&
  209. this->rstates[D3DRENDERSTATE_WRAPV] == vstate)
  210. {
  211. D3D_WARN(4,"Ignoring redundant SetRenderState");
  212. }
  213. else
  214. {
  215. SetDeviceRenderState(this, D3DRENDERSTATE_WRAPU, ustate);
  216. SetRenderStateI(D3DRENDERSTATE_WRAPU, ustate);
  217. SetDeviceRenderState(this, D3DRENDERSTATE_WRAPV, vstate);
  218. SetRenderStateI(D3DRENDERSTATE_WRAPV, vstate);
  219. }
  220. }
  221. }
  222. if (this->rstates[dwState] == value && IS_DP2HAL_DEVICE(this))
  223. {
  224. D3D_WARN(4,"Ignoring redundant SetRenderState");
  225. return D3D_OK;
  226. }
  227. /* Save latest state for GetRenderState() */
  228. SetDeviceRenderState(this, dwState, value);
  229. return SetRenderStateI(dwState, value);
  230. }
  231. #undef DPF_MODNAME
  232. #define DPF_MODNAME "CDirect3DDeviceIHW::SetRenderStateI"
  233. HRESULT D3DAPI
  234. CDirect3DDeviceIHW::SetRenderStateI(D3DRENDERSTATETYPE dwState, DWORD value)
  235. {
  236. LPDWORD lpRS;
  237. if (dwState > D3DRENDERSTATE_STIPPLEPATTERN31)
  238. {
  239. D3D_WARN(4,"Trying to send invalid state %d to legacy driver",dwState);
  240. return D3D_OK;
  241. }
  242. if (dwState > D3DRENDERSTATE_FLUSHBATCH && dwState < D3DRENDERSTATE_STIPPLEPATTERN00)
  243. {
  244. D3D_WARN(4,"Trying to send invalid state %d to legacy driver",dwState);
  245. return D3D_OK;
  246. }
  247. if ( this->dwHWOffset + 8 >= dwHWBufferSize )
  248. {
  249. CLockD3DST lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (ST only).
  250. // Release in the destructor
  251. HRESULT ret;
  252. ret = FlushStates();
  253. if (ret != D3D_OK)
  254. {
  255. D3D_ERR("Error trying to render batched commands in BeginIndexed");
  256. return ret;
  257. }
  258. }
  259. if (this->lpHWCounts[this->dwHWNumCounts].wNumVertices)
  260. {
  261. this->dwHWNumCounts += 1;
  262. memset(&this->lpHWCounts[this->dwHWNumCounts], 0, sizeof(D3DI_HWCOUNTS) );
  263. }
  264. lpRS = (LPDWORD) (((char *) this->lpHWVertices) + this->dwHWOffset);
  265. lpRS[0] = dwState;
  266. lpRS[1] = value;
  267. this->lpHWCounts[this->dwHWNumCounts].wNumStateChanges += 1;
  268. this->dwHWOffset += 8;
  269. return D3D_OK;
  270. }
  271. #undef DPF_MODNAME
  272. #define DPF_MODNAME "Direct3DDevice::GetRenderState"
  273. HRESULT D3DAPI
  274. DIRECT3DDEVICEI::GetRenderState(D3DRENDERSTATETYPE dwState, LPDWORD lpdwValue)
  275. {
  276. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  277. // Release in the destructor
  278. if (dwState >= D3DHAL_MAX_RSTATES || dwState == 0) {
  279. D3D_ERR( "Invalid render state value" );
  280. return DDERR_INVALIDPARAMS;
  281. }
  282. TRY
  283. {
  284. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  285. {
  286. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  287. return DDERR_INVALIDOBJECT;
  288. }
  289. if (!VALID_PTR(lpdwValue, sizeof(DWORD)))
  290. {
  291. D3D_ERR( "Invalid DWORD pointer" );
  292. return DDERR_INVALIDPARAMS;
  293. }
  294. }
  295. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  296. {
  297. D3D_ERR( "Exception encountered validating parameters" );
  298. return DDERR_INVALIDPARAMS;
  299. }
  300. *lpdwValue = this->rstates[dwState];
  301. return D3D_OK;
  302. }
  303. #undef DPF_MODNAME
  304. #define DPF_MODNAME "Direct3DDevice::GetTexture"
  305. HRESULT D3DAPI
  306. DIRECT3DDEVICEI::GetTexture(DWORD dwStage, LPDIRECT3DTEXTURE2 *lplpTex)
  307. {
  308. // Takes D3D lock (MT only).
  309. // Lock released in the destructor.
  310. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  311. #if DBG
  312. if (dwStage >= D3DHAL_TSS_MAXSTAGES)
  313. {
  314. D3D_ERR( "Invalid texture stage or state index" );
  315. return DDERR_INVALIDPARAMS;
  316. }
  317. #endif
  318. TRY
  319. {
  320. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  321. {
  322. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  323. return DDERR_INVALIDOBJECT;
  324. }
  325. if (!VALID_PTR(lplpTex, sizeof(DWORD)))
  326. {
  327. D3D_ERR( "Invalid DWORD pointer" );
  328. return DDERR_INVALIDPARAMS;
  329. }
  330. }
  331. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  332. {
  333. D3D_ERR( "Exception encountered validating parameters" );
  334. return DDERR_INVALIDPARAMS;
  335. }
  336. // Don't bother to check for DX6 support, just return the
  337. // cached value.
  338. *lplpTex = lpD3DMappedTexI[dwStage];
  339. if (*lplpTex) (*lplpTex)->AddRef();
  340. return D3D_OK;
  341. }
  342. #undef DPF_MODNAME
  343. #define DPF_MODNAME "Direct3DDevice::SetTexture"
  344. HRESULT D3DAPI
  345. DIRECT3DDEVICEI::SetTexture(DWORD dwStage, LPDIRECT3DTEXTURE2 lpTex)
  346. {
  347. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  348. #if DBG
  349. if (dwStage >= D3DHAL_TSS_MAXSTAGES)
  350. {
  351. D3D_ERR( "Invalid texture stage or state index" );
  352. return DDERR_INVALIDPARAMS;
  353. }
  354. TRY
  355. {
  356. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  357. {
  358. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  359. return DDERR_INVALIDOBJECT;
  360. }
  361. }
  362. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  363. {
  364. D3D_ERR( "Exception encountered validating parameters" );
  365. return DDERR_INVALIDPARAMS;
  366. }
  367. #endif
  368. if (lpD3DMappedTexI[dwStage] == (LPDIRECT3DTEXTUREI)lpTex)
  369. {
  370. return D3D_OK;
  371. }
  372. #if DBG
  373. if (lpTex)
  374. {
  375. LPDIRECT3DTEXTUREI lpTexI= (LPDIRECT3DTEXTUREI)lpTex;
  376. HRESULT ret;
  377. if (
  378. (!lpTexI->lpDDSSys)
  379. && (lpTexI->DDSInt4.lpLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  380. && (!(lpD3DHALGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY))
  381. )
  382. {
  383. D3D_ERR( "Device cannot render using texture surface from system memory" );
  384. return DDERR_INVALIDPARAMS;
  385. }
  386. ret=VerifyTextureCaps(this, &lpTexI->DDSInt4);
  387. if (D3D_OK != ret)
  388. {
  389. return ret;
  390. }
  391. }
  392. #endif
  393. LPDDRAWI_DDRAWSURFACE_INT surf_int;
  394. LPDDRAWI_DDRAWSURFACE_LCL surf_lcl;
  395. LPDDRAWI_DDRAWSURFACE_GBL surf_gbl;
  396. // we are ssumeing lpTex->lpOwningIUnknown is always a LPDDRAWI_DDRAWSURFACE_INT
  397. // if in the future when texture is not aggregated on ddraw surface, change is needed here
  398. if (lpD3DMappedTexI[dwStage])
  399. { //the following is a hack of Surface Release() for perf reason
  400. surf_int=(LPDDRAWI_DDRAWSURFACE_INT)lpD3DMappedTexI[dwStage]->lpOwningIUnknown;
  401. if (surf_int->dwIntRefCnt > 1) // only do this short way when it's not going away
  402. {
  403. surf_lcl=surf_int->lpLcl;
  404. surf_gbl=surf_lcl->lpGbl;
  405. surf_gbl->dwRefCnt--;
  406. surf_lcl->dwLocalRefCnt--;
  407. surf_int->dwIntRefCnt--;
  408. }
  409. else
  410. lpD3DMappedTexI[dwStage]->Release();
  411. }
  412. lpD3DMappedTexI[dwStage] = (LPDIRECT3DTEXTUREI)lpTex;
  413. if (lpTex)
  414. { //the following is a hack of lpTex->AddRef() for perf reason
  415. surf_int=(LPDDRAWI_DDRAWSURFACE_INT)((LPDIRECT3DTEXTUREI)lpTex)->lpOwningIUnknown;
  416. surf_lcl=surf_int->lpLcl;
  417. surf_gbl=surf_lcl->lpGbl;
  418. surf_gbl->dwRefCnt++;
  419. surf_lcl->dwLocalRefCnt++;
  420. surf_int->dwIntRefCnt++;
  421. lpD3DMappedBlock[dwStage] = NULL;
  422. }
  423. else
  424. {
  425. lpD3DMappedBlock[dwStage] = (LPD3DI_TEXTUREBLOCK)TRUE; //indicate a dirty if lpTex==NULL
  426. }
  427. if (this->tsstates[dwStage][D3DTSS_COLOROP] != D3DTOP_DISABLE)
  428. {
  429. this->dwFVFLastIn = 0; // Force to recompute outputVID
  430. this->dwFEFlags |= D3DFE_TSSINDEX_DIRTY;
  431. }
  432. return D3D_OK;
  433. }
  434. #undef DPF_MODNAME
  435. #define DPF_MODNAME "Direct3DDevice::GetTextureStageState"
  436. HRESULT D3DAPI
  437. DIRECT3DDEVICEI::GetTextureStageState(DWORD dwStage,
  438. D3DTEXTURESTAGESTATETYPE dwState,
  439. LPDWORD pdwValue)
  440. {
  441. // Takes D3D lock (MT only).
  442. // Lock released in the destructor.
  443. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  444. #if DBG
  445. if (dwStage >= D3DHAL_TSS_MAXSTAGES ||
  446. dwState == 0 || dwState >= D3DTSS_MAX)
  447. {
  448. D3D_ERR( "Invalid texture stage or state index" );
  449. return DDERR_INVALIDPARAMS;
  450. }
  451. #endif //DBG
  452. TRY
  453. {
  454. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  455. {
  456. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  457. return DDERR_INVALIDOBJECT;
  458. }
  459. if (!VALID_PTR(pdwValue, sizeof(DWORD)))
  460. {
  461. D3D_ERR( "Invalid DWORD pointer" );
  462. return DDERR_INVALIDPARAMS;
  463. }
  464. }
  465. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  466. {
  467. D3D_ERR( "Exception encountered validating parameters" );
  468. return DDERR_INVALIDPARAMS;
  469. }
  470. // Don't bother to check for DX6 support, just return the
  471. // cached value.
  472. *pdwValue = tsstates[dwStage][dwState];
  473. return D3D_OK;
  474. }
  475. #undef DPF_MODNAME
  476. #define DPF_MODNAME "Direct3D::CreateDevice"
  477. extern HRESULT WINAPI Direct3DCreateDevice(REFCLSID riid,
  478. LPUNKNOWN lpDirect3D,
  479. LPDIRECTDRAWSURFACE lpDDSTarget,
  480. LPUNKNOWN* lplpD3DDevice,
  481. IUnknown* pUnkOuter,
  482. DWORD dwVersion);
  483. HRESULT D3DAPI DIRECT3DI::CreateDevice(REFCLSID devType,
  484. LPDIRECTDRAWSURFACE4 lpDDS4,
  485. LPDIRECT3DDEVICE3 *lplpDirect3DDevice3,
  486. LPUNKNOWN pUnkOuter) {
  487. HRESULT ret;
  488. LPUNKNOWN lpUnkDevice;
  489. LPDIRECTDRAWSURFACE lpDDS;
  490. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  491. // Release in the destructor
  492. TRY
  493. {
  494. if (!VALID_DIRECT3D3_PTR(this)) {
  495. D3D_ERR( "Invalid Direct3D pointer" );
  496. return DDERR_INVALIDOBJECT;
  497. }
  498. if (!VALID_OUTPTR(lplpDirect3DDevice3)) {
  499. D3D_ERR( "Invalid pointer to Device object pointer" );
  500. return DDERR_INVALIDPARAMS;
  501. }
  502. if (!VALID_D3D_DIRECTDRAWSURFACE4_PTR(((LPDDRAWI_DDRAWSURFACE_INT)lpDDS4)))
  503. {
  504. D3D_ERR( "Invalid DirectDrawSurface4 pointer" );
  505. return DDERR_INVALIDOBJECT;
  506. }
  507. }
  508. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  509. {
  510. D3D_ERR( "Exception encountered validating parameters in CreateDevice" );
  511. return DDERR_INVALIDPARAMS;
  512. }
  513. if (pUnkOuter != NULL)
  514. {
  515. return CLASS_E_NOAGGREGATION;
  516. }
  517. *lplpDirect3DDevice3=NULL;
  518. // QI lpDDS4 for lpDDS interface
  519. ret = lpDDS4->QueryInterface(IID_IDirectDrawSurface, (LPVOID*)&lpDDS);
  520. if (FAILED(ret))
  521. return ret;
  522. lpDDS->Release();
  523. ret = Direct3DCreateDevice(devType, &this->mD3DUnk, lpDDS, (LPUNKNOWN *) &lpUnkDevice, NULL, 3);
  524. if(FAILED(ret) || (lpUnkDevice==NULL))
  525. return ret;
  526. // QI device1 for a device3 interface
  527. ret = lpUnkDevice->QueryInterface(IID_IDirect3DDevice3, (LPVOID*)lplpDirect3DDevice3);
  528. lpUnkDevice->Release(); // release unneeded interface
  529. return ret;
  530. }
  531. HRESULT D3DAPI DIRECT3DI::CreateDevice(REFCLSID devType,
  532. LPDIRECTDRAWSURFACE lpDDS,
  533. LPDIRECT3DDEVICE2 *lplpDirect3DDevice2)
  534. {
  535. HRESULT ret;
  536. LPUNKNOWN lpUnkDevice;
  537. ULONG refcnt;
  538. TRY
  539. {
  540. if (!VALID_DIRECT3D3_PTR(this)) {
  541. D3D_ERR( "Invalid Direct3D pointer" );
  542. return DDERR_INVALIDOBJECT;
  543. }
  544. if (!VALID_OUTPTR(lplpDirect3DDevice2)) {
  545. D3D_ERR( "Invalid pointer to Device object pointer" );
  546. return DDERR_INVALIDPARAMS;
  547. }
  548. if (!VALID_D3D_DIRECTDRAWSURFACE_PTR(((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)))
  549. {
  550. D3D_ERR( "Invalid DirectDrawSurface pointer" );
  551. return DDERR_INVALIDOBJECT;
  552. }
  553. }
  554. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  555. {
  556. D3D_ERR( "Exception encountered validating parameters in CreateDevice" );
  557. return DDERR_INVALIDPARAMS;
  558. }
  559. *lplpDirect3DDevice2=NULL;
  560. // Create a device3 object
  561. ret = Direct3DCreateDevice(devType, &this->mD3DUnk, lpDDS, (LPUNKNOWN *) &lpUnkDevice, NULL, 2);
  562. if(FAILED(ret) || (lpUnkDevice==NULL)) {
  563. return ret;
  564. }
  565. // QI it for a device2 interface
  566. ret = lpUnkDevice->QueryInterface(IID_IDirect3DDevice2, (LPVOID*)lplpDirect3DDevice2);
  567. lpUnkDevice->Release(); // releasing unneeded interface
  568. return ret;
  569. }
  570. #undef DPF_MODNAME
  571. #define DPF_MODNAME "Direct3DDevice::SetLightState"
  572. HRESULT D3DAPI
  573. DIRECT3DDEVICEI::SetLightState(D3DLIGHTSTATETYPE dwState, DWORD value)
  574. {
  575. HRESULT ret = D3D_OK;
  576. D3DSTATE state;
  577. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock.
  578. // Release in the destructor
  579. state.dlstLightStateType = dwState;
  580. state.dwArg[0] = value;
  581. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  582. {
  583. D3D_ERR( "SetLightState in Begin" );
  584. return D3DERR_INBEGIN;
  585. }
  586. return D3DHELInst_D3DOP_STATELIGHT(this, 1, &state);
  587. }
  588. #undef DPF_MODNAME
  589. #define DPF_MODNAME "Direct3DDevice::GetLightState"
  590. HRESULT D3DAPI
  591. DIRECT3DDEVICEI::GetLightState(D3DLIGHTSTATETYPE dwState, LPDWORD lpValue)
  592. {
  593. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock.
  594. // Release in the destructor
  595. float* lpfValue = (float*)lpValue;
  596. #if DBG
  597. /*
  598. * validate parms
  599. */
  600. TRY
  601. {
  602. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  603. {
  604. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  605. return DDERR_INVALIDOBJECT;
  606. }
  607. if (!VALID_PTR(lpValue, sizeof(DWORD)))
  608. {
  609. D3D_ERR( "Invalid DWORD pointer" );
  610. return DDERR_INVALIDPARAMS;
  611. }
  612. }
  613. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  614. {
  615. D3D_ERR( "Exception encountered validating parameters in GetLightState" );
  616. return DDERR_INVALIDPARAMS;
  617. }
  618. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  619. {
  620. D3D_ERR( "GetLightState in Begin" );
  621. return D3DERR_INBEGIN;
  622. }
  623. #endif
  624. switch (dwState)
  625. {
  626. case D3DLIGHTSTATE_MATERIAL:
  627. *lpValue = (DWORD)this->lighting.hMat;
  628. break;
  629. case D3DLIGHTSTATE_AMBIENT:
  630. *lpValue = this->lighting.ambient_save;
  631. break;
  632. case D3DLIGHTSTATE_FOGMODE:
  633. *lpValue = this->lighting.fog_mode;
  634. break;
  635. case D3DLIGHTSTATE_FOGSTART:
  636. *lpfValue = this->lighting.fog_start;
  637. break;
  638. case D3DLIGHTSTATE_FOGEND:
  639. *lpfValue = this->lighting.fog_end;
  640. break;
  641. case D3DLIGHTSTATE_FOGDENSITY:
  642. *lpfValue = this->lighting.fog_density;
  643. break;
  644. case D3DLIGHTSTATE_COLORMODEL:
  645. *lpValue = this->lighting.color_model;
  646. break;
  647. case D3DLIGHTSTATE_COLORVERTEX:
  648. // return value for Device3 only
  649. if (dwVersion == 3)
  650. {
  651. *lpValue = (0x0 != (dwFEFlags & D3DFE_COLORVERTEX));
  652. break;
  653. }
  654. // else fall through to error return
  655. default:
  656. D3D_ERR( "Invalid state value passed to GetLightState" );
  657. return DDERR_INVALIDPARAMS; /* Do we return an error code or should we just ignore ? */
  658. }
  659. return D3D_OK;
  660. }
  661. /*
  662. transform matrix functions
  663. */
  664. #undef DPF_MODNAME
  665. #define DPF_MODNAME "Direct3DDevice::SetTransform"
  666. HRESULT D3DAPI
  667. DIRECT3DDEVICEI::SetTransform(D3DTRANSFORMSTATETYPE dtsTransformState, LPD3DMATRIX lpMat)
  668. {
  669. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  670. // Release in the destructor
  671. HRESULT ret = D3D_OK;
  672. D3DFE_TRANSFORM *lpHelTransform = &this->transform;
  673. #if DBG
  674. if (!lpMat) {
  675. D3D_ERR( "NULL matrix pointer passed to SetTransform" );
  676. return DDERR_INVALIDPARAMS;
  677. }
  678. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  679. {
  680. D3D_ERR( "SetTransform in Begin" );
  681. return D3DERR_INBEGIN;
  682. }
  683. #endif
  684. switch (dtsTransformState)
  685. {
  686. case D3DTRANSFORMSTATE_WORLD : D3DFE_SetMatrixWorld(this, lpMat); break;
  687. case D3DTRANSFORMSTATE_VIEW : D3DFE_SetMatrixView(this, lpMat); break;
  688. case D3DTRANSFORMSTATE_PROJECTION :
  689. D3DFE_SetMatrixProj(this, lpMat);
  690. if ((ret = this->UpdateDrvWInfo()) != DD_OK)
  691. {
  692. return ret;
  693. }
  694. break;
  695. default :
  696. D3D_ERR( "Invalid state value passed to SetTransform" );
  697. ret = DDERR_INVALIDPARAMS; /* Work Item: Generate new meaningful return code */
  698. break;
  699. }
  700. return ret;
  701. } // end of D3DDev_SetTransform()
  702. #undef DPF_MODNAME
  703. #define DPF_MODNAME "Direct3DDevice::GetTransform"
  704. HRESULT D3DAPI
  705. DIRECT3DDEVICEI::GetTransform(D3DTRANSFORMSTATETYPE dtsTransformState, LPD3DMATRIX lpMat)
  706. {
  707. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  708. // Release in the destructor
  709. HRESULT ret = D3D_OK;
  710. D3DFE_TRANSFORM *lpHelTransform;
  711. #if DBG
  712. if (!lpMat) {
  713. D3D_ERR( "NULL matrix pointer" );
  714. return DDERR_INVALIDPARAMS;
  715. }
  716. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  717. {
  718. D3D_ERR( "GetTransform in Begin" );
  719. return D3DERR_INBEGIN;
  720. }
  721. #endif
  722. lpHelTransform = &this->transform;
  723. switch (dtsTransformState) {
  724. case D3DTRANSFORMSTATE_WORLD :
  725. *lpMat = *(LPD3DMATRIX)&lpHelTransform->world._11;
  726. break;
  727. case D3DTRANSFORMSTATE_VIEW :
  728. *lpMat = *(LPD3DMATRIX)&lpHelTransform->view._11;
  729. break;
  730. case D3DTRANSFORMSTATE_PROJECTION :
  731. *lpMat = *(LPD3DMATRIX)&lpHelTransform->proj._11;
  732. break;
  733. default :
  734. D3D_ERR( "Invalid state value passed to GetTransform" );
  735. ret = DDERR_INVALIDPARAMS; /* Work Item: Generate new meaningful return code */
  736. break;
  737. }
  738. return ret;
  739. } // end of D3DDev2_GetTransform()
  740. #undef DPF_MODNAME
  741. #define DPF_MODNAME "Direct3DDevice::MultiplyTransform"
  742. /*
  743. MultiplyTransform -- this preconcatenates the new matrix to the specified transform matrix
  744. this really screams for overloaded matrix ops...
  745. */
  746. HRESULT D3DAPI
  747. DIRECT3DDEVICEI::MultiplyTransform(D3DTRANSFORMSTATETYPE dtsTransformState, LPD3DMATRIX lpMat)
  748. {
  749. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  750. // Release in the destructor
  751. HRESULT ret = D3D_OK;
  752. D3DFE_TRANSFORM *lpHelTransform;
  753. #if DBG
  754. if (!lpMat) {
  755. D3D_ERR( "NULL matrix pointer passed to MultiplyTransform" );
  756. return DDERR_INVALIDPARAMS;
  757. }
  758. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  759. {
  760. D3D_ERR( "MultiplyTransform in Begin" );
  761. return D3DERR_INBEGIN;
  762. }
  763. #endif
  764. lpHelTransform = &this->transform;
  765. switch (dtsTransformState)
  766. {
  767. case D3DTRANSFORMSTATE_WORLD : D3DFE_MultMatrixWorld(this, lpMat); break;
  768. case D3DTRANSFORMSTATE_VIEW : D3DFE_MultMatrixView(this, lpMat); break;
  769. case D3DTRANSFORMSTATE_PROJECTION : D3DFE_MultMatrixProj(this, lpMat); break;
  770. default :
  771. D3D_ERR( "Invalid state value passed to MultiplyTransform" );
  772. ret = DDERR_INVALIDPARAMS; /* Work Item: Generate new meaningful return code */
  773. return ret;
  774. }
  775. return ret;
  776. } // end of D3DDev2_MultiplyTransform()
  777. void InvalidateHandles(LPDIRECT3DDEVICEI lpDevI)
  778. {
  779. /* free up all textures created by this object */
  780. LPD3DI_TEXTUREBLOCK tBlock=LIST_FIRST(&lpDevI->texBlocks);
  781. while (tBlock)
  782. {
  783. D3DI_RemoveTextureHandle(tBlock);
  784. tBlock=LIST_NEXT(tBlock,devList);
  785. }
  786. }
  787. #undef DPF_MODNAME
  788. #define DPF_MODNAME "Direct3DDevice::SetRenderTarget"
  789. HRESULT D3DAPI
  790. DIRECT3DDEVICEI::SetRenderTarget(LPDIRECTDRAWSURFACE lpDDS, DWORD dwFlags) {
  791. LPDIRECTDRAWSURFACE4 lpDDS4;
  792. HRESULT ret;
  793. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  794. // Release in the destructor
  795. TRY
  796. {
  797. if (!VALID_DIRECT3DDEVICE2_PTR(this))
  798. {
  799. D3D_ERR( "Invalid Direct3DDevice2 pointer" );
  800. return DDERR_INVALIDOBJECT;
  801. }
  802. if (!VALID_D3D_DIRECTDRAWSURFACE_PTR((LPDDRAWI_DDRAWSURFACE_INT)lpDDS))
  803. {
  804. D3D_ERR( "Invalid DirectDrawSurface pointer" );
  805. return DDERR_INVALIDOBJECT;
  806. }
  807. }
  808. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  809. {
  810. D3D_ERR( "Exception encountered validating parameters in SetRenderTarget" );
  811. return DDERR_INVALIDPARAMS;
  812. }
  813. /* Make sure this device was not aggregated from DDS (DX3-style) */
  814. if ((LPDIRECTDRAWSURFACE)this->lpOwningIUnknown==this->lpDDSTarget)
  815. {
  816. D3D_ERR("Cannot change render target on old device (those QI'ed from a ddraw-surface");
  817. return D3DERR_DEVICEAGGREGATED;
  818. }
  819. // QI lpDDS for lpDDS4 interface, which will be used internally by D3D
  820. ret = lpDDS->QueryInterface(IID_IDirectDrawSurface4, (LPVOID*)&lpDDS4);
  821. if(FAILED(ret))
  822. return ret;
  823. // SetRenderTarget AddRef'd the DDS4 interface, so it's safe to release it here and decrmt the refcnt
  824. lpDDS4->Release();
  825. ret=this->SetRenderTarget(lpDDS4,dwFlags);
  826. return ret;
  827. }
  828. HRESULT D3DAPI
  829. DIRECT3DDEVICEI::SetRenderTarget(LPDIRECTDRAWSURFACE4 lpDDS4, DWORD dwFlags)
  830. {
  831. DDSCAPS2 ddscaps;
  832. DDSURFACEDESC2 ddsd;
  833. HRESULT ret, ddrval;
  834. LPDIRECTDRAWSURFACE lpZ=NULL,lpDDS=NULL;
  835. LPDIRECTDRAWSURFACE4 lpZ_DDS4=NULL;
  836. LPDIRECTDRAWPALETTE lpPal=NULL;
  837. DWORD i, j;
  838. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  839. // Release in the destructor
  840. TRY
  841. {
  842. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  843. {
  844. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  845. return DDERR_INVALIDOBJECT;
  846. }
  847. if (!VALID_D3D_DIRECTDRAWSURFACE4_PTR(((LPDDRAWI_DDRAWSURFACE_INT)lpDDS4)))
  848. {
  849. D3D_ERR( "Invalid DirectDrawSurface4 pointer" );
  850. return DDERR_INVALIDOBJECT;
  851. }
  852. }
  853. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  854. {
  855. D3D_ERR( "Exception encountered validating parameters in SetRenderTarget" );
  856. return DDERR_INVALIDPARAMS;
  857. }
  858. // Flush before switching RenderTarget..
  859. ret = FlushStates();
  860. if (ret != D3D_OK)
  861. {
  862. D3D_ERR("Error trying to FlushStates in SetRenderTarget");
  863. return ret;
  864. }
  865. /* Make sure this device was not aggregated from DDS (DX3-style) */
  866. if ((LPDIRECTDRAWSURFACE)this->lpOwningIUnknown==this->lpDDSTarget)
  867. {
  868. D3D_ERR("Cannot change render target on device QI'ed from DDS");
  869. return D3DERR_DEVICEAGGREGATED;
  870. }
  871. /*
  872. * Check if the 3D cap is set on the surface.
  873. */
  874. memset(&ddsd, 0, sizeof ddsd);
  875. ddsd.dwSize = sizeof ddsd;
  876. ddrval = lpDDS4->GetSurfaceDesc(&ddsd);
  877. if (ddrval != DD_OK)
  878. {
  879. D3D_ERR("Failed to get surface description of device's surface.");
  880. return (ddrval);
  881. }
  882. if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
  883. {
  884. D3D_ERR("**** The DDSCAPS_3DDEVICE is not set on this surface.");
  885. D3D_ERR("**** You need to add DDSCAPS_3DDEVICE to ddsCaps.dwCaps");
  886. D3D_ERR("**** when creating the surface.");
  887. return (DDERR_INVALIDCAPS);
  888. }
  889. if (!(this->lpD3DHALGlobalDriverData->hwCaps.dwDeviceRenderBitDepth & BitDepthToDDBD(ddsd.ddpfPixelFormat.dwRGBBitCount))) {
  890. D3D_ERR("Rendering surface's RGB bit count not supported by hardware device");
  891. return (DDERR_INVALIDCAPS);
  892. }
  893. if (ddsd.dwWidth > 2048 || ddsd.dwHeight > 2048)
  894. {
  895. D3D_ERR("Surface dimension > 2048");
  896. return DDERR_INVALIDPARAMS;
  897. }
  898. /* The z-buffer... */
  899. ddscaps.dwCaps = DDSCAPS_ZBUFFER;
  900. ret = lpDDS4->GetAttachedSurface(&ddscaps, &lpZ_DDS4);
  901. if ((ret != DD_OK) && (ret != DDERR_NOTFOUND))
  902. {
  903. /*
  904. * NOTE: Not an error if the z-buffer is not found. We will let the
  905. * dirver handle that (it might fail or create its own z-buffer).
  906. */
  907. D3D_ERR("Supplied DirectDraw Z-Buffer is invalid - can't set render target");
  908. ret=DDERR_INVALIDPARAMS;
  909. goto handle_error;
  910. }
  911. if (lpZ_DDS4)
  912. lpZ_DDS4->Release(); // We do not need to addref this one;
  913. // QI lpDDS4 for lpDDS interface, which will be used internally by D3D
  914. ret = lpDDS4->QueryInterface(IID_IDirectDrawSurface, (LPVOID*)&lpDDS);
  915. if(FAILED(ret))
  916. goto handle_error;
  917. /* The palette... */
  918. ret = lpDDS->GetPalette(&lpPal);
  919. if ((ret != DD_OK) && (ret != DDERR_NOPALETTEATTACHED))
  920. {
  921. /*
  922. * NOTE: Again, not an error (yet) if there is no palette attached.
  923. * But if there is palette and we can't get at it for some reason
  924. * - fail.
  925. */
  926. D3D_ERR("Supplied DirectDraw Palette is invalid - can't create device");
  927. ret=DDERR_INVALIDPARAMS;
  928. goto handle_error;
  929. }
  930. /*
  931. * We're going to check now whether we should have got a palette.
  932. */
  933. if (ret == DDERR_NOPALETTEATTACHED)
  934. {
  935. if (ddsd.ddpfPixelFormat.dwRGBBitCount < 16)
  936. {
  937. D3D_ERR("No palette supplied for palettized surface");
  938. ret=DDERR_NOPALETTEATTACHED;
  939. goto handle_error;
  940. }
  941. }
  942. /* Verify Z buffer */
  943. if (lpZ_DDS4!=NULL)
  944. {
  945. memset(&ddsd, 0, sizeof(ddsd));
  946. ddsd.dwSize = sizeof(ddsd);
  947. if ((ret=lpZ_DDS4->GetSurfaceDesc(&ddsd)) != DD_OK)
  948. {
  949. D3D_ERR("Failed to getsurfacedesc on Z");
  950. goto handle_error;
  951. }
  952. // QI lpDDS4 for lpDDS interface, which will be used internally by D3D
  953. ret = lpZ_DDS4->QueryInterface(IID_IDirectDrawSurface, (LPVOID*)&lpZ);
  954. if(FAILED(ret))
  955. goto handle_error;
  956. }
  957. else
  958. {
  959. if (this->lpDDSZBuffer)
  960. {
  961. D3D_ERR("Current rendertarget contains ZBuffer, but new one does not!");
  962. ret=DDERR_INVALIDPARAMS;
  963. goto handle_error;
  964. }
  965. }
  966. if (IS_DX7HAL_DEVICE(this))
  967. {
  968. static_cast<CDirect3DDeviceIDP2*>(this)->SetRenderTargetI(lpDDS, lpZ);
  969. }
  970. else
  971. if (this->lpD3DHALCallbacks2->SetRenderTarget)
  972. {
  973. D3DHAL_SETRENDERTARGETDATA rtData;
  974. rtData.dwhContext = this->dwhContext;
  975. #ifndef WIN95
  976. if (dwFEFlags & D3DFE_REALHAL)
  977. {
  978. if (lpDDS)
  979. rtData.lpDDSLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl;
  980. else
  981. rtData.lpDDSLcl = NULL;
  982. if (lpZ)
  983. rtData.lpDDSZLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpZ)->lpLcl;
  984. else
  985. rtData.lpDDSZLcl = NULL;
  986. }
  987. else
  988. #endif //WIN95
  989. {
  990. rtData.lpDDS = lpDDS;
  991. rtData.lpDDSZ = lpZ;
  992. }
  993. rtData.ddrval = 0;
  994. CALL_HAL2ONLY(ret, this, SetRenderTarget, &rtData);
  995. if ((ret != DDHAL_DRIVER_HANDLED) || (rtData.ddrval != DD_OK))
  996. {
  997. D3D_ERR( "Driver call failed in SetRenderTarget" );
  998. // Need sensible return value in this case,
  999. // currently we return whatever the driver stuck in here.
  1000. ret = rtData.ddrval;
  1001. goto handle_error;
  1002. }
  1003. }
  1004. else
  1005. {
  1006. D3DHAL_CONTEXTCREATEDATA cdata;
  1007. D3DHAL_CONTEXTDESTROYDATA ddata;
  1008. /* Destroy old context */
  1009. memset(&ddata, 0, sizeof(D3DHAL_CONTEXTDESTROYDATA));
  1010. ddata.dwhContext = this->dwhContext;
  1011. CALL_HALONLY(ret, this, ContextDestroy, &ddata);
  1012. if (ret != DDHAL_DRIVER_HANDLED || ddata.ddrval != DD_OK)
  1013. {
  1014. DPF(0, "(ERROR) ContextDestroy. Failed. dwhContext = %d", ddata.dwhContext);
  1015. // Need sensible return value in this case,
  1016. // currently we return whatever the driver stuck in here.
  1017. ret = ddata.ddrval;
  1018. goto handle_error;
  1019. }
  1020. /* Create new context */
  1021. memset(&cdata, 0, sizeof(D3DHAL_CONTEXTCREATEDATA));
  1022. #ifndef WIN95
  1023. if (dwFEFlags & D3DFE_REALHAL)
  1024. {
  1025. if (this->lpDD)
  1026. cdata.lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)(this->lpDD))->lpLcl;
  1027. else
  1028. cdata.lpDDLcl = NULL;
  1029. if (lpDDS)
  1030. cdata.lpDDSLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl;
  1031. else
  1032. cdata.lpDDSLcl = NULL;
  1033. if (lpZ)
  1034. cdata.lpDDSZLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpZ)->lpLcl;
  1035. else
  1036. cdata.lpDDSZLcl = NULL;
  1037. }
  1038. else
  1039. #endif //WIN95
  1040. {
  1041. cdata.lpDDGbl = this->lpDDGbl;
  1042. cdata.lpDDS = lpDDS;
  1043. cdata.lpDDSZ = lpZ;
  1044. }
  1045. cdata.dwPID = GetCurrentProcessId();
  1046. CALL_HALONLY(ret, this, ContextCreate, &cdata);
  1047. if (ret != DDHAL_DRIVER_HANDLED || cdata.ddrval != DD_OK)
  1048. {
  1049. D3D_ERR("HAL call to ContextCreate failed in SetRenderTarget");
  1050. // Need sensible return value in this case,
  1051. // currently we return whatever the driver stuck in here.
  1052. return cdata.ddrval;
  1053. }
  1054. this->dwhContext = cdata.dwhContext;
  1055. D3D_INFO(9, "in halCreateContext. Succeeded. dwhContext = %d", cdata.dwhContext);
  1056. /* Set up renderstates */
  1057. // note we can't do a loop from 1 to D3DHAL_MAX_RSTATES(256) as some of rstates are not
  1058. // valid states, passin them down to drivers(like voodoo2 DX6 driver) will crash.
  1059. for (i= 1 ; i< D3DRENDERSTATE_WRAPBIAS+8; ++i)
  1060. {
  1061. this->SetRenderStateI((D3DRENDERSTATETYPE)i, this->rstates[i]);
  1062. }
  1063. if ( IS_DP2HAL_DEVICE(this) ) {
  1064. CDirect3DDeviceIDP2 *dp2dev = static_cast<CDirect3DDeviceIDP2 *>(this);
  1065. for (i=0; i<dwMaxTextureBlendStages; ++i)
  1066. for (j=0; j<D3DTSS_MAX; ++j)
  1067. {
  1068. D3D_INFO(6,"Calling SetTSSI(%d,%d,%08lx)",i,j,this->tsstates[i][j]);
  1069. dp2dev->SetTSSI(i, (D3DTEXTURESTAGESTATETYPE)j, this->tsstates[i][j]);
  1070. }
  1071. }
  1072. }
  1073. if (this->lpDDSTarget)
  1074. UnHookD3DDeviceFromSurface(this,((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSTarget)->lpLcl); //unhook previous surfaces if any
  1075. if (this->lpDDSZBuffer)
  1076. UnHookD3DDeviceFromSurface(this,((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSZBuffer)->lpLcl); //unhook previous surfaces if any
  1077. if (DDERR_OUTOFMEMORY == (ret=HookD3DDeviceToSurface(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS4)->lpLcl)))
  1078. {
  1079. goto handle_error;
  1080. }
  1081. if (lpZ_DDS4 && (DDERR_OUTOFMEMORY == (ret=HookD3DDeviceToSurface(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpZ_DDS4)->lpLcl))))
  1082. {
  1083. UnHookD3DDeviceFromSurface(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS4)->lpLcl);
  1084. goto handle_error;
  1085. }
  1086. // release old device DDS/DDS4 interfaces and replace with the new ones,
  1087. // which are mostly already AddRef'd (except for lpDDS4)
  1088. /// DDSZBuffer ///
  1089. if(this->lpDDSZBuffer)
  1090. this->lpDDSZBuffer->Release();
  1091. // lpZ AddRef'd by QI
  1092. this->lpDDSZBuffer = lpZ;
  1093. /// DDSZBuffer DDS4 ///
  1094. this->lpDDSZBuffer_DDS4=lpZ_DDS4; // This needs no AddRef or Release
  1095. /// DDSTarget ///
  1096. if (this->dwVersion == 2)
  1097. {
  1098. this->lpDDSTarget->Release();
  1099. // lpDDS AddRef'd by QI
  1100. this->lpDDSTarget = lpDDS;
  1101. }
  1102. else
  1103. {
  1104. this->lpDDSTarget = lpDDS;
  1105. // lpDDS AddRef'd by QI so release it
  1106. this->lpDDSTarget->Release();
  1107. }
  1108. #ifndef WIN95
  1109. hSurfaceTarget = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl->hDDSurface;
  1110. D3D_INFO(6,"in SetRenderTarget hSurfaceTarget=%08lx lpDDSTarget=%08lx",hSurfaceTarget,lpDDSTarget);
  1111. #else
  1112. hSurfaceTarget = (unsigned long)((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl->lpSurfMore->dwSurfaceHandle;
  1113. D3D_INFO(6,"in SetRenderTarget hSurfaceTarget=%08lx lpDDSTarget=%08lx",hSurfaceTarget,lpDDSTarget);
  1114. #endif
  1115. /// DDSTarget DDS4 ///
  1116. if (this->dwVersion == 3)
  1117. {
  1118. this->lpDDSTarget_DDS4->Release();
  1119. lpDDS4->AddRef(); // ensure lpDDS4 (which was an argument) doesnt disappear
  1120. }
  1121. this->lpDDSTarget_DDS4=lpDDS4;
  1122. if (this->lpDDPalTarget)
  1123. this->lpDDPalTarget->Release();
  1124. // already AddRef'd by GetPalette()
  1125. this->lpDDPalTarget = lpPal;
  1126. InvalidateHandles(this);
  1127. if( FAILED( ret=CalcDDSurfInfo(this,FALSE) ) )
  1128. goto handle_error;
  1129. return ret;
  1130. handle_error:
  1131. if(lpPal)
  1132. lpPal->Release();
  1133. if(lpZ)
  1134. lpZ->Release();
  1135. if(lpZ_DDS4)
  1136. lpZ_DDS4->Release();
  1137. if(lpDDS)
  1138. lpDDS->Release();
  1139. return ret;
  1140. }
  1141. #undef DPF_MODNAME
  1142. #define DPF_MODNAME "Direct3DDevice::GetRenderTarget"
  1143. HRESULT D3DAPI
  1144. DIRECT3DDEVICEI::GetRenderTarget(LPDIRECTDRAWSURFACE* lplpDDS) {
  1145. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1146. // Release in the destructor
  1147. TRY
  1148. {
  1149. if (!VALID_DIRECT3DDEVICE2_PTR(this))
  1150. {
  1151. D3D_ERR( "Invalid Direct3DDevice2 pointer" );
  1152. return DDERR_INVALIDOBJECT;
  1153. }
  1154. if ( !VALID_OUTPTR( lplpDDS ) )
  1155. {
  1156. D3D_ERR( "Invalid ptr to DDS ptr" );
  1157. return DDERR_INVALIDPARAMS;
  1158. }
  1159. }
  1160. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1161. {
  1162. D3D_ERR( "Exception encountered validating parameters" );
  1163. return DDERR_INVALIDPARAMS;
  1164. }
  1165. *lplpDDS = this->lpDDSTarget;
  1166. this->lpDDSTarget->AddRef();
  1167. return D3D_OK;
  1168. }
  1169. HRESULT D3DAPI
  1170. DIRECT3DDEVICEI::GetRenderTarget(LPDIRECTDRAWSURFACE4* lplpDDS)
  1171. {
  1172. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1173. // Release in the destructor
  1174. TRY
  1175. {
  1176. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  1177. {
  1178. D3D_ERR( "Invalid Direct3DDevice3 pointer" );
  1179. return DDERR_INVALIDOBJECT;
  1180. }
  1181. if ( !VALID_OUTPTR( lplpDDS ) )
  1182. {
  1183. D3D_ERR( "Invalid ptr to DDS ptr" );
  1184. return DDERR_INVALIDPARAMS;
  1185. }
  1186. }
  1187. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1188. {
  1189. D3D_ERR( "Exception encountered validating parameters" );
  1190. return DDERR_INVALIDPARAMS;
  1191. }
  1192. *lplpDDS = this->lpDDSTarget_DDS4;
  1193. this->lpDDSTarget_DDS4->AddRef();
  1194. return D3D_OK;
  1195. }
  1196. #undef DPF_MODNAME
  1197. #define DPF_MODNAME "Direct3DDevice::SetClipStatus"
  1198. #define D3DSTATUS_VALID 0x80000000L /* Reserved Status flag to indicate SetClipStatus is called */
  1199. HRESULT D3DAPI DIRECT3DDEVICEI::SetClipStatus(LPD3DCLIPSTATUS status)
  1200. {
  1201. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  1202. // Release in the destructor
  1203. #if DBG
  1204. TRY
  1205. {
  1206. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  1207. {
  1208. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1209. return DDERR_INVALIDOBJECT;
  1210. }
  1211. if (! VALID_PTR(status, sizeof(D3DCLIPSTATUS)) )
  1212. {
  1213. D3D_ERR( "Invalid status pointer" );
  1214. return DDERR_INVALIDPARAMS;
  1215. }
  1216. }
  1217. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1218. {
  1219. D3D_ERR( "Exception encountered validating parameters" );
  1220. return DDERR_INVALIDPARAMS;
  1221. }
  1222. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  1223. {
  1224. D3D_ERR( "SetClipStatus in Begin" );
  1225. return D3DERR_INBEGIN;
  1226. }
  1227. #endif
  1228. // D3DCLIPSTATUS_EXTENTS3 not supported in Device3
  1229. if (dwVersion == 3 && status->dwFlags & D3DCLIPSTATUS_EXTENTS3)
  1230. {
  1231. D3D_ERR( "D3DCLIPSTATUS_EXTENTS3 not supported for Device3" );
  1232. return DDERR_INVALIDPARAMS;
  1233. }
  1234. if (status->dwFlags & D3DCLIPSTATUS_STATUS)
  1235. this->iClipStatus = status->dwStatus;
  1236. if (status->dwFlags & (D3DCLIPSTATUS_EXTENTS2 | D3DCLIPSTATUS_EXTENTS3))
  1237. {
  1238. this->rExtents.x1 = status->minx;
  1239. this->rExtents.y1 = status->miny;
  1240. this->rExtents.x2 = status->maxx;
  1241. this->rExtents.y2 = status->maxy;
  1242. }
  1243. return D3D_OK;
  1244. }
  1245. #undef DPF_MODNAME
  1246. #define DPF_MODNAME "Direct3DDevice::GetClipStatus"
  1247. HRESULT D3DAPI DIRECT3DDEVICEI::GetClipStatus(LPD3DCLIPSTATUS status)
  1248. {
  1249. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  1250. // Release in the destructor
  1251. #if DBG
  1252. TRY
  1253. {
  1254. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  1255. {
  1256. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1257. return DDERR_INVALIDOBJECT;
  1258. }
  1259. if (! VALID_PTR(status, sizeof(D3DCLIPSTATUS)) )
  1260. {
  1261. D3D_ERR( "Invalid status pointer" );
  1262. return DDERR_INVALIDPARAMS;
  1263. }
  1264. }
  1265. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1266. {
  1267. D3D_ERR( "Exception encountered validating parameters" );
  1268. return DDERR_INVALIDPARAMS;
  1269. }
  1270. if (dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  1271. {
  1272. D3D_ERR( "GetClipStatus in Begin" );
  1273. return D3DERR_INBEGIN;
  1274. }
  1275. #endif
  1276. status->dwStatus = iClipStatus;
  1277. status->dwFlags = D3DCLIPSTATUS_EXTENTS2;
  1278. status->minx = this->rExtents.x1;
  1279. status->miny = this->rExtents.y1;
  1280. status->maxx = this->rExtents.x2;
  1281. status->maxy = this->rExtents.y2;
  1282. return D3D_OK;
  1283. }
  1284. #undef DPF_MODNAME
  1285. #define DPF_MODNAME "Direct3DDevice::UpdateTextures"
  1286. HRESULT DIRECT3DDEVICEI::UpdateTextures()
  1287. {
  1288. BOOL bFlushed=FALSE;
  1289. DWORD dwStage;
  1290. D3DTEXTUREHANDLE dwDDIHandle;
  1291. LPDIRECT3DTEXTUREI lpTexI;
  1292. LPD3DI_TEXTUREBLOCK lpBlock;
  1293. for (dwStage=0;dwStage < this->dwMaxTextureBlendStages; dwStage++)
  1294. {
  1295. lpTexI=this->lpD3DMappedTexI[dwStage];
  1296. lpBlock=this->lpD3DMappedBlock[dwStage];
  1297. if(lpTexI)
  1298. {
  1299. if (lpTexI->lpTMBucket)
  1300. {
  1301. if (lpTexI->bDirty)
  1302. {
  1303. FlushD3DStates(((LPDDRAWI_DDRAWSURFACE_INT)(lpTexI->lpDDS))->lpLcl);
  1304. if (DD_OK != CopySurface(lpTexI->lpDDS,lpTexI->lpDDSSys,this->lpClipper))
  1305. {
  1306. D3D_ERR("Error copying surface while updating textures");
  1307. }
  1308. else
  1309. {
  1310. lpTexI->bDirty=FALSE;
  1311. D3D_INFO(4,"UpdateTextures: Dirty texture updated");
  1312. }
  1313. }
  1314. }
  1315. if (lpBlock)
  1316. {
  1317. if (lpBlock->hTex)
  1318. {
  1319. continue; //nothing need to be done further
  1320. }
  1321. }
  1322. GetTextureDDIHandle(lpTexI, this, &lpBlock);
  1323. this->lpD3DMappedBlock[dwStage]=lpBlock;
  1324. if (lpBlock)
  1325. {
  1326. dwDDIHandle = lpBlock->hTex;
  1327. if (dwDDIHandle)
  1328. {
  1329. if(lpTexI->lpDDS != NULL)
  1330. {
  1331. BatchTextureToDevice(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpTexI->lpDDS)->lpLcl);
  1332. }
  1333. else
  1334. {
  1335. BatchTextureToDevice(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpTexI->lpDDSSys)->lpLcl);
  1336. }
  1337. }
  1338. }
  1339. else
  1340. {
  1341. dwDDIHandle = 0; //something is wrong we disable this texture
  1342. }
  1343. }
  1344. else if (lpBlock)
  1345. {
  1346. this->lpD3DMappedBlock[dwStage]=NULL; //a SetTexture(Stage,NULL) issued
  1347. dwDDIHandle = 0; //tell driver to disable this texture
  1348. }
  1349. else
  1350. {
  1351. continue; //both zero, no action needed
  1352. }
  1353. if (IS_DP2HAL_DEVICE(this))
  1354. {
  1355. CDirect3DDeviceIDP2 *dp2dev = static_cast<CDirect3DDeviceIDP2 *>(this);
  1356. dp2dev->SetTSSI(dwStage, (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP, dwDDIHandle);
  1357. // Update runtime copy of state.
  1358. dp2dev->tsstates[dwStage][D3DTSS_TEXTUREMAP] = dwDDIHandle;
  1359. }
  1360. else
  1361. {
  1362. if(this->dwFEFlags & D3DFE_DISABLE_TEXTURES)
  1363. break;
  1364. CDirect3DDeviceIHW *dev = static_cast<CDirect3DDeviceIHW *>(this);
  1365. (void)dev->SetRenderStateI(D3DRENDERSTATE_TEXTUREHANDLE, dwDDIHandle);
  1366. // Update runtime copy of state.
  1367. dev->rstates[D3DRENDERSTATE_TEXTUREHANDLE] = dwDDIHandle;
  1368. }
  1369. }
  1370. return D3D_OK;
  1371. }
  1372. //---------------------------------------------------------------------
  1373. // This function is called from HALEXE.CPP, from device::SetRenderState and
  1374. // from device::SetTexture.
  1375. // Always use this function to update RSTATES.
  1376. //
  1377. HRESULT
  1378. SetDeviceRenderState(LPDIRECT3DDEVICEI lpDevI, D3DRENDERSTATETYPE type,
  1379. DWORD value)
  1380. {
  1381. DWORD *rstates = lpDevI->rstates;
  1382. switch (type)
  1383. {
  1384. case D3DRENDERSTATE_FOGENABLE:
  1385. rstates[type] = value; // set rstates BEFORE calling SetFogFlags
  1386. SetFogFlags(lpDevI);
  1387. break;
  1388. case D3DRENDERSTATE_SPECULARENABLE:
  1389. lpDevI->dwFEFlags |= D3DFE_MATERIAL_DIRTY | D3DFE_LIGHTS_DIRTY;
  1390. lpDevI->dwFVFLastIn = 0; // Force re-computing of FVF id
  1391. break;
  1392. case D3DRENDERSTATE_TEXTUREHANDLE:
  1393. if ((rstates[D3DRENDERSTATE_TEXTUREHANDLE] == 0) != (value == 0))
  1394. lpDevI->dwFVFLastIn = 0;
  1395. if (value)
  1396. lpDevI->dwDeviceFlags |= D3DDEV_LEGACYTEXTURE;
  1397. else
  1398. lpDevI->dwDeviceFlags &= ~D3DDEV_LEGACYTEXTURE;
  1399. break;
  1400. }
  1401. rstates[type] = value; // set rstates for all other cases
  1402. return D3D_OK;
  1403. }
  1404. #if DBG
  1405. static char ProfileStr[PROF_DRAWINDEXEDPRIMITIVEVB+1][32]=
  1406. {
  1407. "Execute",
  1408. "Begin",
  1409. "BeginIndexed",
  1410. "DrawPrimitive(Device2)",
  1411. "DrawIndexedPrimitive(Device2)",
  1412. "DrawPrimitiveStrided",
  1413. "DrawIndexedPrimitiveStrided",
  1414. "DrawPrimitive(Device3)",
  1415. "DrawIndexedPrimitive(Device3)",
  1416. "DrawPrimitiveVB",
  1417. "DrawIndexedPrimitiveVB",
  1418. };
  1419. static char PrimitiveStr[D3DPT_TRIANGLEFAN][16]=
  1420. {
  1421. "POINTLIST",
  1422. "LINELIST",
  1423. "LINESTRIP",
  1424. "TRIANGLELIST",
  1425. "TRIANGLESTRIP",
  1426. "TRIANGLEFAN",
  1427. };
  1428. static char VertexStr[D3DVT_TLVERTEX][16]=
  1429. {
  1430. "D3DVERTEX",
  1431. "D3DLVERTEX",
  1432. "D3DTLVERTEX",
  1433. };
  1434. #define PROFILE_LEVEL 1
  1435. void DIRECT3DDEVICEI::Profile(DWORD caller, D3DPRIMITIVETYPE dwPrimitive, DWORD dwVertex)
  1436. {
  1437. DWORD bitwisecaller= 1 << caller;
  1438. DWORD bitwisePrimitive = 1 << (DWORD)dwPrimitive;
  1439. DWORD bitwiseVertex1 = 1 << (dwVertex & 0x001F);
  1440. DWORD bitwiseVertex2 = 1 << ((dwVertex & 0x03E0) >> 5);
  1441. char str[256];
  1442. DDASSERT(PROF_DRAWINDEXEDPRIMITIVEVB >= caller);
  1443. DDASSERT(D3DPT_TRIANGLEFAN >= dwPrimitive && D3DPT_POINTLIST<= dwPrimitive);
  1444. if (dwCaller & bitwisecaller)
  1445. {
  1446. if (dwPrimitiveType[caller] & bitwisePrimitive)
  1447. {
  1448. if ((dwVertexType1[caller] & bitwiseVertex1) &&
  1449. (dwVertexType2[caller] & bitwiseVertex2))
  1450. {
  1451. return; //matching a previous api call, no spew, could count stat though
  1452. }
  1453. else
  1454. {
  1455. dwVertexType1[caller] |= bitwiseVertex1;
  1456. dwVertexType2[caller] |= bitwiseVertex2;
  1457. }
  1458. }
  1459. else
  1460. {
  1461. dwPrimitiveType[caller] |= bitwisePrimitive;
  1462. dwVertexType1[caller] |= bitwiseVertex1;
  1463. dwVertexType2[caller] |= bitwiseVertex2;
  1464. }
  1465. }
  1466. else
  1467. {
  1468. this->dwCaller |= bitwisecaller;
  1469. dwPrimitiveType[caller] |= bitwisePrimitive;
  1470. dwVertexType1[caller] |= bitwiseVertex1;
  1471. dwVertexType2[caller] |= bitwiseVertex2;
  1472. }
  1473. wsprintf( (LPSTR) str, ProfileStr[caller]);
  1474. strcat(str,":");
  1475. strcat(str,PrimitiveStr[dwPrimitive-1]);
  1476. if (dwVertex > D3DVT_TLVERTEX)
  1477. {
  1478. if (dwVertex == D3DFVF_VERTEX)
  1479. {
  1480. dwVertex = D3DVT_VERTEX;
  1481. }
  1482. else
  1483. if (dwVertex == D3DFVF_LVERTEX)
  1484. {
  1485. dwVertex = D3DVT_LVERTEX;
  1486. }
  1487. else
  1488. if (dwVertex == D3DFVF_TLVERTEX)
  1489. {
  1490. dwVertex = D3DVT_TLVERTEX;
  1491. }
  1492. else
  1493. {
  1494. D3D_INFO(PROFILE_LEVEL,"Profile:%s FVFType=%08lx",str,dwVertex);
  1495. return;
  1496. }
  1497. }
  1498. else
  1499. {
  1500. DDASSERT(dwVertex >= D3DVT_VERTEX);
  1501. }
  1502. strcat(str,":");
  1503. strcat(str,VertexStr[dwVertex-1]);
  1504. D3D_INFO(PROFILE_LEVEL,"Profile:%s",str);
  1505. }
  1506. #endif