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.

1365 lines
39 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: vwport.c
  6. * Content: Direct3D viewport functions
  7. *@@BEGIN_MSINTERNAL
  8. *
  9. * $Id: vwport.c,v 1.25 1995/12/04 11:29:49 sjl Exp $
  10. *
  11. * History:
  12. * Date By Reason
  13. * ==== == ======
  14. * 05/11/95 stevela Initial rev with this header.
  15. *@@END_MSINTERNAL
  16. *
  17. ***************************************************************************/
  18. #include "pch.cpp"
  19. #pragma hdrstop
  20. /*
  21. * Create an api for the Direct3DViewport object
  22. */
  23. #include "d3dfei.h"
  24. #include "drawprim.hpp"
  25. extern void UpdateViewportCache(LPDIRECT3DDEVICEI device, D3DVIEWPORT2 *data);
  26. //---------------------------------------------------------------------
  27. //
  28. // Compute inverse Mclip matrix
  29. //
  30. void updateInverseMclip(LPDIRECT3DDEVICEI lpDevI)
  31. {
  32. D3DFE_VIEWPORTCACHE& VPORT = lpDevI->vcache;
  33. VPORT.imclip11 = D3DVAL(1)/VPORT.mclip11;
  34. VPORT.imclip41 = - VPORT.imclip11 * VPORT.mclip41;
  35. VPORT.imclip22 = D3DVAL(1)/VPORT.mclip22;
  36. VPORT.imclip42 = - VPORT.imclip22 * VPORT.mclip42;
  37. VPORT.imclip33 = D3DVAL(1)/VPORT.mclip33;
  38. VPORT.imclip43 = VPORT.imclip33 * VPORT.mclip43;
  39. }
  40. //---------------------------------------------------------------------
  41. HRESULT downloadView(LPDIRECT3DVIEWPORTI lpViewI)
  42. {
  43. HRESULT err;
  44. if (!lpViewI->v_data_is_set)
  45. {
  46. D3D_ERR("SetViewport not called for viewport yet");
  47. return D3DERR_VIEWPORTDATANOTSET;
  48. }
  49. LPDIRECT3DDEVICEI lpDevI = lpViewI->lpDevI;
  50. // Update front-end data
  51. UpdateViewportCache(lpDevI, &lpViewI->v_data);
  52. // Download viewport data
  53. if ((err = lpDevI->UpdateDrvViewInfo(&lpViewI->v_data)) != DD_OK)
  54. {
  55. return err;
  56. }
  57. lpViewI->bLightsChanged = TRUE; // Force setLights call
  58. lpDevI->v_id = lpViewI->v_id;
  59. return (D3D_OK);
  60. }
  61. //---------------------------------------------------------------------
  62. // Viewport ID could be different from Device->v_id, because during Execute call
  63. // Device->v_id is changed to whatever viewport is used as a parameter.
  64. // So we have to make sure that we use the right viewport.
  65. //
  66. inline HRESULT ValidateViewport(LPDIRECT3DDEVICEI lpDevI,
  67. LPDIRECT3DVIEWPORTI lpView)
  68. {
  69. #if DBG
  70. if (!VALID_DIRECT3DDEVICE3_PTR(lpDevI)) {
  71. D3D_ERR( "Viewport not attached to Device" );
  72. return D3DERR_VIEWPORTHASNODEVICE;
  73. }
  74. #endif
  75. if (lpDevI->v_id != lpView->v_id)
  76. {
  77. return downloadView(lpView);
  78. }
  79. else
  80. return D3D_OK;
  81. }
  82. HRESULT hookViewportToD3D(LPDIRECT3DI lpDirect3DI,
  83. LPDIRECT3DVIEWPORTI lpD3DView)
  84. {
  85. LIST_INSERT_ROOT(&lpDirect3DI->viewports, lpD3DView, list);
  86. lpD3DView->lpDirect3DI = lpDirect3DI;
  87. lpDirect3DI->numViewports++;
  88. return (D3D_OK);
  89. }
  90. HRESULT D3DAPI DIRECT3DVIEWPORTI::Initialize(LPDIRECT3D lpD3D)
  91. {
  92. return DDERR_ALREADYINITIALIZED;
  93. }
  94. /*
  95. * Light Management
  96. */
  97. HRESULT hookLightToViewport(LPDIRECT3DVIEWPORTI lpD3DViewI,
  98. LPDIRECT3DLIGHTI lpD3DLight)
  99. {
  100. CIRCLE_QUEUE_INSERT_END(&lpD3DViewI->lights, DIRECT3DLIGHTI, lpD3DLight,
  101. light_list);
  102. lpD3DLight->lpD3DViewportI = lpD3DViewI;
  103. lpD3DViewI->numLights++;
  104. return (D3D_OK);
  105. }
  106. HRESULT setLights(LPDIRECT3DVIEWPORTI lpView)
  107. {
  108. LPDIRECT3DDEVICEI lpDevI;
  109. LPDIRECT3DLIGHTI lpD3DLightI;
  110. int i;
  111. lpDevI = lpView->lpDevI;
  112. lpD3DLightI = (LPDIRECT3DLIGHTI)CIRCLE_QUEUE_FIRST(&lpView->lights);
  113. D3DFE_LIGHTING& LIGHTING = lpDevI->lighting;
  114. LIGHTING.activeLights = NULL;
  115. // Set lights in the device
  116. for (i = 0; i < lpView->numLights; i++)
  117. {
  118. if (lpD3DLightI->diLightData.valid &&
  119. lpD3DLightI->diLightData.flags & D3DLIGHT_ACTIVE)
  120. {
  121. lpD3DLightI->diLightData.next = LIGHTING.activeLights;
  122. LIGHTING.activeLights = &lpD3DLightI->diLightData;
  123. }
  124. lpD3DLightI = CIRCLE_QUEUE_NEXT(&lpView->lights,lpD3DLightI,light_list);
  125. }
  126. lpDevI->dwFEFlags |= (D3DFE_NEED_TRANSFORM_LIGHTS | D3DFE_LIGHTS_DIRTY);
  127. return (D3D_OK);
  128. }
  129. /*
  130. * Create the Viewport
  131. */
  132. #undef DPF_MODNAME
  133. #define DPF_MODNAME "Direct3D::CreateViewport"
  134. HRESULT D3DAPI DIRECT3DI::CreateViewport(LPDIRECT3DVIEWPORT* lplpD3DView,
  135. IUnknown *pUnkOuter)
  136. {
  137. return CreateViewport((LPDIRECT3DVIEWPORT3*)lplpD3DView, NULL);
  138. }
  139. HRESULT D3DAPI DIRECT3DI::CreateViewport(LPDIRECT3DVIEWPORT2* lplpD3DView2,
  140. IUnknown *pUnkOuter)
  141. {
  142. return CreateViewport((LPDIRECT3DVIEWPORT3*)lplpD3DView2, NULL);
  143. }
  144. HRESULT D3DAPI DIRECT3DI::CreateViewport(LPDIRECT3DVIEWPORT3* lplpD3DView,
  145. IUnknown *pUnkOuter)
  146. {
  147. LPDIRECT3DVIEWPORTI lpView;
  148. HRESULT ret = D3D_OK;
  149. if(pUnkOuter != NULL) {
  150. return CLASS_E_NOAGGREGATION;
  151. }
  152. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  153. /*
  154. * validate parms
  155. */
  156. if (!VALID_DIRECT3D3_PTR(this)) {
  157. D3D_ERR( "Invalid Direct3D pointer" );
  158. return DDERR_INVALIDOBJECT;
  159. }
  160. if (!VALID_OUTPTR(lplpD3DView)) {
  161. D3D_ERR( "Invalid pointer to pointer pointer" );
  162. return DDERR_INVALIDPARAMS;
  163. }
  164. *lplpD3DView = NULL;
  165. lpView = new DIRECT3DVIEWPORTI(this);
  166. if (!lpView) {
  167. D3D_ERR("failed to allocate space for object");
  168. return (DDERR_OUTOFMEMORY);
  169. }
  170. /*
  171. * Put this device in the list of those owned by the
  172. * Direct3D object
  173. */
  174. ret = hookViewportToD3D(this, lpView);
  175. if (ret != D3D_OK) {
  176. D3D_ERR("failed to associate viewport to Direct3D");
  177. delete lpView;
  178. return (ret);
  179. }
  180. *lplpD3DView = (LPDIRECT3DVIEWPORT3)lpView;
  181. return (D3D_OK);
  182. }
  183. DIRECT3DVIEWPORTI::DIRECT3DVIEWPORTI(LPDIRECT3DI lpD3DI)
  184. {
  185. /*
  186. * setup the object
  187. */
  188. /*** Object Data ***/
  189. memset(&v_data, 0, sizeof(D3DVIEWPORT2));
  190. v_data_is_set = FALSE;
  191. bHaveBackgndMat=FALSE;
  192. hBackgndMat=NULL;
  193. lpDDSBackgndDepth=NULL;
  194. clrCount=0;
  195. clrRects=NULL;
  196. refCnt = 1;
  197. lpDevI=NULL;
  198. v_id = lpD3DI->v_next++;
  199. /*
  200. * Initialise lights
  201. */
  202. numLights = 0;
  203. CIRCLE_QUEUE_INITIALIZE(&lights, DIRECT3DLIGHTI);
  204. /*
  205. * Make sure that lights are always downloaded the first time
  206. */
  207. bLightsChanged = TRUE;
  208. }
  209. /*
  210. * IDirect3DViewport members
  211. */
  212. /*
  213. * Transform
  214. */
  215. #undef DPF_MODNAME
  216. #define DPF_MODNAME "Direct3DViewport::SetViewport"
  217. HRESULT D3DAPI DIRECT3DVIEWPORTI::SetViewport(LPD3DVIEWPORT lpData)
  218. {
  219. HRESULT ret;
  220. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  221. /*
  222. * validate parms
  223. */
  224. TRY
  225. {
  226. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  227. D3D_ERR( "Invalid Direct3DViewport pointer" );
  228. return DDERR_INVALIDOBJECT;
  229. }
  230. if (!VALID_D3DVIEWPORT_PTR(lpData)) {
  231. D3D_ERR( "Invalid D3DVIEWPORT pointer" );
  232. return DDERR_INVALIDPARAMS;
  233. }
  234. }
  235. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  236. {
  237. D3D_ERR( "Exception encountered validating parameters" );
  238. return DDERR_INVALIDPARAMS;
  239. }
  240. D3DVIEWPORT2 v;
  241. if (lpData->dvScaleX == 0.0f || lpData->dvScaleY == 0.0f)
  242. {
  243. D3D_ERR( "Invalid viewport data" );
  244. v.dvClipWidth = 0.0f;
  245. v.dvClipHeight = 0.0f;
  246. }
  247. else
  248. {
  249. v.dvClipWidth = lpData->dwWidth / lpData->dvScaleX;
  250. v.dvClipHeight = lpData->dwHeight / lpData->dvScaleY;
  251. }
  252. /* Convert D3DVIEWPORT to D3DVIEWPORT2 */
  253. v.dwSize = sizeof(D3DVIEWPORT2);
  254. v.dwX = lpData->dwX;
  255. v.dwY = lpData->dwY;
  256. v.dwWidth = lpData->dwWidth;
  257. v.dwHeight = lpData->dwHeight;
  258. v.dvClipX = -v.dvClipWidth/2.0f;
  259. v.dvClipY = v.dvClipHeight/2.0f;
  260. v.dvMinZ = 0.0f;
  261. v.dvMaxZ = 1.0f;
  262. ret = SetViewport2(&v);
  263. return ret;
  264. }
  265. HRESULT D3DAPI DIRECT3DVIEWPORTI::SetViewport2(LPD3DVIEWPORT2 lpData)
  266. {
  267. HRESULT err;
  268. DWORD uSurfWidth,uSurfHeight;
  269. LPDIRECTDRAWSURFACE lpDDS;
  270. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  271. /*
  272. * validate parms
  273. */
  274. TRY
  275. {
  276. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  277. D3D_ERR( "Invalid Direct3DViewport2 pointer" );
  278. return DDERR_INVALIDOBJECT;
  279. }
  280. if (!VALID_D3DVIEWPORT2_PTR(lpData)) {
  281. D3D_ERR( "Invalid D3DVIEWPORT2 pointer" );
  282. return DDERR_INVALIDPARAMS;
  283. }
  284. }
  285. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  286. {
  287. D3D_ERR( "Exception encountered validating parameters" );
  288. return DDERR_INVALIDPARAMS;
  289. }
  290. if (!VALID_DIRECT3DDEVICE3_PTR(this->lpDevI)) {
  291. D3D_ERR( "Viewport not attached to Device" );
  292. return D3DERR_VIEWPORTHASNODEVICE;
  293. }
  294. if (IS_DX5_COMPATIBLE_DEVICE(this->lpDevI))
  295. { /* we're called directly by dx5 app, so validate params */
  296. if (lpData->dvClipWidth == 0.0f || lpData->dvClipHeight == 0.0f ||
  297. lpData->dvMinZ == lpData->dvMaxZ)
  298. {
  299. D3D_ERR( "Invalid viewport data" );
  300. return DDERR_INVALIDPARAMS;
  301. }
  302. lpDDS = this->lpDevI->lpDDSTarget;
  303. uSurfWidth= ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wWidth;
  304. uSurfHeight= ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wHeight;
  305. if (lpData->dwX > uSurfWidth ||
  306. lpData->dwY > uSurfHeight ||
  307. lpData->dwX + lpData->dwWidth > uSurfWidth ||
  308. lpData->dwY + lpData->dwHeight > uSurfHeight)
  309. {
  310. D3D_ERR("Viewport outside the render target surface");
  311. return DDERR_INVALIDPARAMS;
  312. }
  313. }
  314. this->v_data = *lpData;
  315. this->v_data_is_set = TRUE;
  316. // If this is the last rendered viewport, update its device
  317. if (this->v_id == this->lpDevI->v_id)
  318. {
  319. err = downloadView(this);
  320. if (err != D3D_OK)
  321. {
  322. return err;
  323. }
  324. }
  325. return (D3D_OK);
  326. }
  327. #undef DPF_MODNAME
  328. #define DPF_MODNAME "Direct3DViewport::GetViewport"
  329. HRESULT D3DAPI DIRECT3DVIEWPORTI::GetViewport(LPD3DVIEWPORT lpData)
  330. {
  331. HRESULT ret;
  332. D3DVIEWPORT2 v;
  333. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  334. /*
  335. * validate parms
  336. */
  337. TRY
  338. {
  339. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  340. D3D_ERR( "Invalid Direct3DViewport pointer" );
  341. return DDERR_INVALIDOBJECT;
  342. }
  343. if (!VALID_D3DVIEWPORT_PTR(lpData)) {
  344. D3D_ERR( "Invalid D3DVIEWPORT pointer" );
  345. return DDERR_INVALIDPARAMS;
  346. }
  347. }
  348. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  349. {
  350. D3D_ERR( "Exception encountered validating parameters" );
  351. return DDERR_INVALIDPARAMS;
  352. }
  353. v.dwSize = sizeof(D3DVIEWPORT2);
  354. ret = GetViewport2(&v);
  355. /* Convert D3DVIEWPORT2 to D3DVIEWPORT */
  356. lpData->dwSize = sizeof(D3DVIEWPORT);
  357. lpData->dwX = v.dwX;
  358. lpData->dwY = v.dwY;
  359. lpData->dwWidth = v.dwWidth;
  360. lpData->dwHeight = v.dwHeight;
  361. lpData->dvMinZ = 0.0f;
  362. lpData->dvMaxZ = 1.0f;
  363. lpData->dvScaleX = v.dwWidth / v.dvClipWidth;
  364. lpData->dvScaleY = v.dwHeight / v.dvClipHeight;
  365. lpData->dvMaxX = v.dvClipX + v.dvClipWidth;
  366. lpData->dvMaxY = v.dvClipY;
  367. return ret;
  368. }
  369. HRESULT D3DAPI DIRECT3DVIEWPORTI::GetViewport2(LPD3DVIEWPORT2 lpData)
  370. {
  371. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  372. /*
  373. * validate parms
  374. */
  375. TRY
  376. {
  377. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  378. D3D_ERR( "Invalid Direct3DViewport pointer" );
  379. return DDERR_INVALIDOBJECT;
  380. }
  381. if (!VALID_D3DVIEWPORT2_PTR(lpData)) {
  382. D3D_ERR( "Invalid D3DVIEWPORT2 pointer" );
  383. return DDERR_INVALIDPARAMS;
  384. }
  385. }
  386. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  387. {
  388. D3D_ERR( "Exception encountered validating parameters" );
  389. return DDERR_INVALIDPARAMS;
  390. }
  391. if (!this->v_data_is_set)
  392. {
  393. D3D_ERR("SetViewport not called for viewport yet");
  394. return D3DERR_VIEWPORTDATANOTSET;
  395. }
  396. *lpData = this->v_data;
  397. return (D3D_OK);
  398. }
  399. #undef DPF_MODNAME
  400. #define DPF_MODNAME "Direct3DViewport::TransformVertices"
  401. HRESULT D3DAPI DIRECT3DVIEWPORTI::TransformVertices(DWORD dwVertexCount,
  402. LPD3DTRANSFORMDATA lpData,
  403. DWORD dwFlags,
  404. LPDWORD lpOffScreen)
  405. {
  406. HRESULT err;
  407. D3DTRANSFORMDATAI data;
  408. LPDIRECT3DVIEWPORTI lpViewOld;
  409. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  410. CD3DFPstate D3DFPstate; // Sets optimal FPU state for D3D.
  411. /*
  412. * validate parms
  413. */
  414. TRY
  415. {
  416. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  417. D3D_ERR( "Invalid Direct3DViewport pointer" );
  418. return DDERR_INVALIDOBJECT;
  419. }
  420. if (!VALID_D3DTRANSFORMDATA_PTR(lpData)) {
  421. D3D_ERR( "Invalid D3DTRANSFORMDATA pointer" );
  422. return DDERR_INVALIDPARAMS;
  423. }
  424. if (!VALID_DWORD_PTR(lpOffScreen)) {
  425. D3D_ERR( "Invalid DWORD pointer" );
  426. return DDERR_INVALIDPARAMS;
  427. }
  428. }
  429. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  430. {
  431. D3D_ERR( "Exception encountered validating parameters" );
  432. return DDERR_INVALIDPARAMS;
  433. }
  434. dwFlags &= (D3DTRANSFORM_CLIPPED | D3DTRANSFORM_UNCLIPPED);
  435. if (!dwFlags)
  436. {
  437. D3D_ERR("invalid flags");
  438. return (DDERR_INVALIDPARAMS);
  439. }
  440. /*
  441. * Make sure the correct viewport is set up in the driver.
  442. */
  443. err = ValidateViewport(this->lpDevI, this);
  444. if (err != D3D_OK)
  445. {
  446. D3D_ERR("failed to set viewport");
  447. return err;
  448. }
  449. lpViewOld = this->lpDevI->lpCurrentViewport;
  450. lpDevI->lpCurrentViewport = this;
  451. data = *(LPD3DTRANSFORMDATAI)lpData;
  452. data.drExtent.x1 = D3DVAL(lpData->drExtent.x1);
  453. data.drExtent.y1 = D3DVAL(lpData->drExtent.y1);
  454. data.drExtent.x2 = D3DVAL(lpData->drExtent.x2);
  455. data.drExtent.y2 = D3DVAL(lpData->drExtent.y2);
  456. if (lpDevI->dwFEFlags & D3DFE_TRANSFORM_DIRTY)
  457. updateTransform(lpDevI);
  458. if (dwFlags == D3DTRANSFORM_CLIPPED)
  459. {
  460. if (lpDevI->dwFEFlags & D3DFE_INVERSEMCLIP_DIRTY)
  461. {
  462. updateInverseMclip(lpDevI);
  463. lpDevI->dwFEFlags &= ~D3DFE_INVERSEMCLIP_DIRTY;
  464. }
  465. lpDevI->dwFlags &= ~D3DDP_DONOTCLIP;
  466. }
  467. else
  468. lpDevI->dwFlags |= D3DDP_DONOTCLIP;
  469. *lpOffScreen = lpDevI->pGeometryFuncs->TransformVertices(lpDevI, dwVertexCount, &data);
  470. *lpData = *(D3DTRANSFORMDATA*)&data;
  471. D3DFE_ConvertExtent(this->lpDevI, &data.drExtent, &lpData->drExtent);
  472. this->lpDevI->lpCurrentViewport = lpViewOld;
  473. return (D3D_OK);
  474. }
  475. #undef DPF_MODNAME
  476. #define DPF_MODNAME "Direct3DViewport::LightElements"
  477. HRESULT D3DAPI DIRECT3DVIEWPORTI::LightElements(DWORD dwElementCount,
  478. LPD3DLIGHTDATA lpData)
  479. {
  480. return E_NOTIMPL;
  481. }
  482. #undef DPF_MODNAME
  483. #define DPF_MODNAME "Direct3DViewport::SetBackground"
  484. HRESULT D3DAPI DIRECT3DVIEWPORTI::SetBackground(D3DMATERIALHANDLE hMat)
  485. {
  486. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  487. /*
  488. * validate parms
  489. */
  490. TRY
  491. {
  492. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  493. D3D_ERR( "Invalid Direct3DViewport pointer" );
  494. return DDERR_INVALIDOBJECT;
  495. }
  496. }
  497. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  498. {
  499. D3D_ERR( "Exception encountered validating parameters" );
  500. return DDERR_INVALIDPARAMS;
  501. }
  502. if (!hMat) {
  503. D3D_ERR("invalid material handle");
  504. return (DDERR_INVALIDPARAMS);
  505. }
  506. this->bHaveBackgndMat = (hMat!=0);
  507. this->hBackgndMat = hMat;
  508. return (D3D_OK);
  509. }
  510. #undef DPF_MODNAME
  511. #define DPF_MODNAME "Direct3DViewport::GetBackground"
  512. HRESULT D3DAPI DIRECT3DVIEWPORTI::GetBackground(LPD3DMATERIALHANDLE lphMat,
  513. LPBOOL lpValid)
  514. {
  515. HRESULT err;
  516. err = D3D_OK;
  517. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  518. /*
  519. * validate parms
  520. */
  521. TRY
  522. {
  523. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  524. D3D_ERR( "Invalid Direct3DViewport pointer" );
  525. return DDERR_INVALIDOBJECT;
  526. }
  527. if (!VALID_D3DMATERIALHANDLE_PTR(lphMat)) {
  528. D3D_ERR( "Invalid D3DMATERIALHANDLE pointer" );
  529. return DDERR_INVALIDPARAMS;
  530. }
  531. if (!VALID_BOOL_PTR(lpValid)) {
  532. D3D_ERR( "Invalid BOOL pointer" );
  533. return DDERR_INVALIDPARAMS;
  534. }
  535. }
  536. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  537. {
  538. D3D_ERR( "Exception encountered validating parameters" );
  539. return DDERR_INVALIDPARAMS;
  540. }
  541. if (this->bHaveBackgndMat) {
  542. *lpValid = TRUE;
  543. *lphMat = this->hBackgndMat;
  544. } else {
  545. *lphMat = 0;
  546. *lpValid = FALSE;
  547. }
  548. return (err);
  549. }
  550. #undef DPF_MODNAME
  551. #define DPF_MODNAME "Direct3DViewport::SetBackgroundDepth"
  552. HRESULT D3DAPI DIRECT3DVIEWPORTI::SetBackgroundDepth(LPDIRECTDRAWSURFACE lpDDS) {
  553. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  554. /*
  555. * validate parms
  556. */
  557. TRY
  558. {
  559. if (!VALID_DIRECT3DVIEWPORT2_PTR(this)) {
  560. D3D_ERR( "Invalid Direct3DViewport pointer" );
  561. return DDERR_INVALIDOBJECT;
  562. }
  563. // passing NULL is OK
  564. if ((lpDDS!=NULL) && !VALID_D3D_DIRECTDRAWSURFACE_PTR((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)) {
  565. D3D_ERR( "Invalid DirectDrawSurface pointer" );
  566. return DDERR_INVALIDOBJECT;
  567. }
  568. }
  569. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  570. {
  571. D3D_ERR( "Exception encountered validating parameters" );
  572. return DDERR_INVALIDPARAMS;
  573. }
  574. if(this->lpDDSBackgndDepth!=NULL) {
  575. this->lpDDSBackgndDepth->Release();
  576. }
  577. this->lpDDSBackgndDepth=lpDDS;
  578. return (D3D_OK);
  579. }
  580. #undef DPF_MODNAME
  581. #define DPF_MODNAME "Direct3DViewport::SetBackgroundDepth2"
  582. HRESULT D3DAPI DIRECT3DVIEWPORTI::SetBackgroundDepth2(LPDIRECTDRAWSURFACE4 lpDDS4)
  583. {
  584. LPDIRECTDRAWSURFACE lpDDS;
  585. HRESULT ret;
  586. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  587. /*
  588. * validate parms
  589. */
  590. TRY
  591. {
  592. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  593. D3D_ERR( "Invalid Direct3DViewport pointer" );
  594. return DDERR_INVALIDOBJECT;
  595. }
  596. // passing NULL is OK
  597. if ((lpDDS4!=NULL) && !VALID_D3D_DIRECTDRAWSURFACE4_PTR((LPDDRAWI_DDRAWSURFACE_INT)lpDDS4)) {
  598. D3D_ERR( "Invalid DirectDrawSurface4 pointer" );
  599. return DDERR_INVALIDOBJECT;
  600. }
  601. }
  602. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  603. {
  604. D3D_ERR( "Exception encountered validating parameters" );
  605. return DDERR_INVALIDPARAMS;
  606. }
  607. lpDDS=NULL;
  608. if(lpDDS4!=NULL) {
  609. // QI for DDS interface. This constitutes an AddRef, which is different from previous DX5 behavior
  610. ret = lpDDS4->QueryInterface(IID_IDirectDrawSurface, (LPVOID*)&lpDDS);
  611. if(FAILED(ret))
  612. return ret;
  613. }
  614. if(this->lpDDSBackgndDepth)
  615. this->lpDDSBackgndDepth->Release();
  616. this->lpDDSBackgndDepth = lpDDS;
  617. return (D3D_OK);
  618. }
  619. #undef DPF_MODNAME
  620. #define DPF_MODNAME "Direct3DViewport::GetBackgroundDepth2"
  621. HRESULT D3DAPI DIRECT3DVIEWPORTI::GetBackgroundDepth2(LPDIRECTDRAWSURFACE4* lplpDDS,
  622. LPBOOL lpValid)
  623. {
  624. LPDIRECTDRAWSURFACE lpDDS;
  625. HRESULT ret = D3D_OK;
  626. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  627. /*
  628. * validate parms
  629. */
  630. TRY
  631. {
  632. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  633. D3D_ERR( "Invalid Direct3DViewport pointer" );
  634. return DDERR_INVALIDOBJECT;
  635. }
  636. if (!VALID_OUTPTR(lplpDDS)) {
  637. D3D_ERR( "Invalid ptr to LPDIRECTDRAWSURFACE4" );
  638. return DDERR_INVALIDPARAMS;
  639. }
  640. if (!VALID_BOOL_PTR(lpValid)) {
  641. D3D_ERR( "Invalid BOOL pointer" );
  642. return DDERR_INVALIDPARAMS;
  643. }
  644. }
  645. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  646. {
  647. D3D_ERR( "Exception encountered validating parameters" );
  648. return DDERR_INVALIDPARAMS;
  649. }
  650. *lplpDDS=NULL;
  651. if(this->lpDDSBackgndDepth!=NULL) {
  652. // QI for DDS interface. This constitutes an AddRef, which is different from previous DX5 behavior
  653. ret = this->lpDDSBackgndDepth->QueryInterface(IID_IDirectDrawSurface4, (LPVOID*)lplpDDS);
  654. }
  655. *lpValid = (*lplpDDS!=NULL);
  656. return ret;
  657. }
  658. #undef DPF_MODNAME
  659. #define DPF_MODNAME "Direct3DViewport::GetBackgroundDepth"
  660. HRESULT D3DAPI DIRECT3DVIEWPORTI::GetBackgroundDepth(LPDIRECTDRAWSURFACE* lplpDDS,
  661. LPBOOL lpValid)
  662. {
  663. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  664. /*
  665. * validate parms
  666. */
  667. TRY
  668. {
  669. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  670. D3D_ERR( "Invalid Direct3DViewport pointer" );
  671. return DDERR_INVALIDOBJECT;
  672. }
  673. if (!VALID_OUTPTR(lplpDDS)) {
  674. D3D_ERR( "Invalid ptr to LPDIRECTDRAWSURFACE" );
  675. return DDERR_INVALIDPARAMS;
  676. }
  677. if (!VALID_BOOL_PTR(lpValid)) {
  678. D3D_ERR( "Invalid BOOL pointer" );
  679. return DDERR_INVALIDPARAMS;
  680. }
  681. }
  682. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  683. {
  684. D3D_ERR( "Exception encountered validating parameters" );
  685. return DDERR_INVALIDPARAMS;
  686. }
  687. // no AddRef taken (this was a DX3 bug)
  688. *lplpDDS = this->lpDDSBackgndDepth;
  689. *lpValid = (this->lpDDSBackgndDepth!=NULL);
  690. return D3D_OK;
  691. }
  692. #undef DPF_MODNAME
  693. #define DPF_MODNAME "Direct3DViewport::Clear (ProcessRects)"
  694. HRESULT ProcessRects(DIRECT3DVIEWPORTI *pViewport, DWORD dwCount, LPD3DRECT rects) {
  695. RECT vwport;
  696. DWORD i,j;
  697. /*
  698. * Rip through the rects and validate that they
  699. * are within the viewport.
  700. */
  701. #if DBG
  702. if(dwCount == 0)
  703. {
  704. return D3D_OK;
  705. }
  706. if(rects == NULL)
  707. {
  708. D3D_ERR("invalid clear rectangle parameter rects == NULL");
  709. return DDERR_INVALIDPARAMS;
  710. }
  711. #endif
  712. if (dwCount > pViewport->clrCount) {
  713. if (D3DRealloc((void**)&pViewport->clrRects, dwCount * sizeof(D3DRECT)) != DD_OK) {
  714. pViewport->clrCount = 0;
  715. pViewport->clrRects = NULL;
  716. D3D_ERR("failed to allocate space for rects");
  717. return DDERR_OUTOFMEMORY;
  718. }
  719. }
  720. if (IS_DX5_COMPATIBLE_DEVICE(pViewport->lpDevI))
  721. {
  722. vwport.left = pViewport->v_data.dwX;
  723. vwport.top = pViewport->v_data.dwY;
  724. vwport.right = pViewport->v_data.dwX + pViewport->v_data.dwWidth;
  725. vwport.bottom = pViewport->v_data.dwY + pViewport->v_data.dwHeight;
  726. }
  727. else
  728. {
  729. LPDIRECTDRAWSURFACE lpDDS;
  730. lpDDS = pViewport->lpDevI->lpDDSTarget;
  731. vwport.right = ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wWidth;
  732. vwport.bottom = ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wHeight;
  733. vwport.left = 0;
  734. vwport.top = 0;
  735. }
  736. j=0;
  737. for (i = 0; i < dwCount; i++) {
  738. if (IntersectRect((LPRECT)(pViewport->clrRects + j), &vwport, (LPRECT)(rects + i)))
  739. j++;
  740. }
  741. pViewport->clrCount = j;
  742. return D3D_OK;
  743. }
  744. #undef DPF_MODNAME
  745. #define DPF_MODNAME "Direct3DViewport::Clear2"
  746. HRESULT D3DAPI DIRECT3DVIEWPORTI::Clear2(DWORD dwCount, LPD3DRECT rects, DWORD dwFlags,
  747. D3DCOLOR dwColor, D3DVALUE dvZ, DWORD dwStencil)
  748. {
  749. LPDIRECT3DVIEWPORTI lpTempVwport;
  750. HRESULT err;
  751. BOOL bDoRGBClear,bDoZClear,bDoStencilClear;
  752. LPDDPIXELFORMAT pZPixFmt=NULL;
  753. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  754. /*
  755. * validate parms
  756. */
  757. TRY
  758. {
  759. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  760. D3D_ERR( "Invalid Direct3DViewport pointer" );
  761. return DDERR_INVALIDOBJECT;
  762. }
  763. if (!VALID_DIRECT3DDEVICE3_PTR(this->lpDevI)) {
  764. D3D_ERR( "Viewport not attached to Device" );
  765. return D3DERR_VIEWPORTHASNODEVICE;
  766. }
  767. #if DBG
  768. if (IsBadWritePtr(rects, dwCount * sizeof(D3DRECT))) {
  769. D3D_ERR( "Invalid rects pointer" );
  770. return DDERR_INVALIDPARAMS;
  771. }
  772. #endif
  773. }
  774. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  775. {
  776. D3D_ERR( "Exception encountered validating parameters" );
  777. return DDERR_INVALIDPARAMS;
  778. }
  779. bDoRGBClear=((dwFlags & D3DCLEAR_TARGET)!=0);
  780. bDoZClear=((dwFlags & D3DCLEAR_ZBUFFER)!=0);
  781. bDoStencilClear=((dwFlags & D3DCLEAR_STENCIL)!=0);
  782. if (lpDevI->lpD3DHALGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR)
  783. {
  784. if (!(lpDevI->lpD3DHALCallbacks3->Clear2) &&
  785. !(IS_DX7HAL_DEVICE(lpDevI)))
  786. {
  787. if (bDoStencilClear)
  788. {
  789. D3D_ERR("Invalid flag D3DCLEAR_STENCIL: this ZBUFFERLESSHSR device doesn't support Clear2()");
  790. return D3DERR_ZBUFFER_NOTPRESENT;
  791. }
  792. if (bDoZClear)
  793. {
  794. if (!(lpDevI->lpD3DHALCallbacks2->Clear) || (dvZ!=1.0))
  795. {
  796. D3D_WARN(3,"Ignoring D3DCLEAR_ZBUFFER since this ZBUFFERLESSHSR device doesn't even support Clear() or Z!=1");
  797. dwFlags &= ~(D3DCLEAR_ZBUFFER);
  798. bDoZClear = FALSE;
  799. }
  800. }
  801. }
  802. }
  803. else
  804. {
  805. if((this->lpDevI->lpDDSZBuffer==NULL)&&(bDoStencilClear||bDoZClear)) {
  806. // unlike Clear(), specifying a Zbuffer-clearing flag without a zbuffer will
  807. // be considered an error
  808. if(bDoZClear) {
  809. D3D_ERR("Invalid flag D3DCLEAR_ZBUFFER: no zbuffer is associated with device");
  810. }
  811. if(bDoStencilClear) {
  812. D3D_ERR("Invalid flag D3DCLEAR_STENCIL: no zbuffer is associated with device");
  813. }
  814. return D3DERR_ZBUFFER_NOTPRESENT;
  815. }
  816. if(bDoStencilClear) {
  817. pZPixFmt=&((LPDDRAWI_DDRAWSURFACE_INT) lpDevI->lpDDSZBuffer)->lpLcl->lpGbl->ddpfSurface;
  818. if(!(pZPixFmt->dwFlags & DDPF_STENCILBUFFER)) {
  819. D3D_ERR("Invalid flag D3DCLEAR_STENCIL; current zbuffer's pixel format doesnt support stencil bits");
  820. return D3DERR_STENCILBUFFER_NOTPRESENT;
  821. }
  822. }
  823. }
  824. if (!(dwFlags & (D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL))) {
  825. D3D_ERR("no valid flags passed to Clear2");
  826. err=DDERR_INVALIDPARAMS;
  827. goto early_out;
  828. }
  829. #if DBG
  830. // bad clear values just cause wacky results but no crashes, so OK to allow in retail bld
  831. if(bDoZClear && ((dvZ<0.0) || (dvZ>1.0))) {
  832. D3D_ERR("clear2 Z value outside legal range (0.0-1.0)");
  833. err=DDERR_INVALIDPARAMS;
  834. goto early_out;
  835. }
  836. if(bDoStencilClear && pZPixFmt && (dwStencil > (DWORD)((1<<pZPixFmt->dwStencilBitDepth)-1))) {
  837. D3D_ERR("clear2 stencil value larger than max allowed stencil value for zbuf pixelfmt");
  838. err=DDERR_INVALIDPARAMS;
  839. goto early_out;
  840. }
  841. #endif
  842. // leave this check in retail build since DDFE_Clear keys off lpDDSBackgndDepth to do textured backg. clrs
  843. if(bDoZClear && (this->lpDDSBackgndDepth!=NULL)) {
  844. D3D_ERR("Background Depth Buffer not allowed to be used with Clear2");
  845. err=DDERR_INVALIDPARAMS;
  846. goto early_out;
  847. }
  848. #if DBG
  849. // dont bother with this check for retail, since we can easily ignore existing background material
  850. if(this->bHaveBackgndMat && bDoRGBClear) {
  851. D3DMATERIAL dmMat;
  852. err = D3DHAL_MaterialGetData(this->lpDevI, this->hBackgndMat, &dmMat);
  853. if (err != D3D_OK) {
  854. D3D_ERR("Failed to find material from current viewport background material handle");
  855. goto early_out;
  856. }
  857. if(dmMat.hTexture!=0) {
  858. D3D_ERR("Textured background materials not allowed to be used with Clear2");
  859. err=DDERR_INVALIDPARAMS;
  860. goto early_out;
  861. }
  862. D3D_WARN(3,"Ignoring current Background Material Color, Clear2 dwColor arg overrides it");
  863. }
  864. #endif
  865. // Make sure the correct viewport is set up in the driver.
  866. err = ValidateViewport(this->lpDevI, this);
  867. if (err != D3D_OK)
  868. {
  869. D3D_ERR("failed to set viewport");
  870. goto early_out;
  871. }
  872. if((err=ProcessRects(this,dwCount,rects))!=D3D_OK)
  873. goto early_out;
  874. /* Make sure this viewport is the current viewport for the duration of this call */
  875. lpTempVwport = this->lpDevI->lpCurrentViewport;
  876. this->lpDevI->lpCurrentViewport = this;
  877. if (IS_DX7HAL_DEVICE(lpDevI))
  878. {
  879. static_cast<CDirect3DDeviceIDP2*>(lpDevI)->ClearI(dwFlags, clrCount, clrRects, dwColor, dvZ, dwStencil);
  880. }
  881. else
  882. {
  883. err = D3DFE_Clear2(this->lpDevI, dwFlags, this->clrCount, this->clrRects,
  884. dwColor, dvZ, dwStencil);
  885. }
  886. /* Restore the original current viewport of the device */
  887. this->lpDevI->lpCurrentViewport = lpTempVwport;
  888. early_out:
  889. return err;
  890. }
  891. #undef DPF_MODNAME
  892. #define DPF_MODNAME "Direct3DViewport::Clear"
  893. extern void TriFillRectsTex(LPDIRECT3DDEVICEI lpDevI, DWORD count, LPD3DRECT rect,D3DTEXTUREHANDLE hTex);
  894. HRESULT D3DAPI DIRECT3DVIEWPORTI::Clear(DWORD dwCount,
  895. LPD3DRECT rects,
  896. DWORD dwFlags)
  897. {
  898. LPDIRECT3DVIEWPORTI lpTempVwport;
  899. HRESULT err;
  900. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  901. /*
  902. * validate parms
  903. */
  904. TRY
  905. {
  906. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  907. D3D_ERR( "Invalid Direct3DViewport pointer" );
  908. return DDERR_INVALIDOBJECT;
  909. }
  910. if (!VALID_DIRECT3DDEVICE3_PTR(this->lpDevI)) {
  911. D3D_ERR( "Viewport not attached to Device" );
  912. return D3DERR_VIEWPORTHASNODEVICE;
  913. }
  914. #if DBG
  915. if (IsBadWritePtr(rects, dwCount * sizeof(D3DRECT))) {
  916. D3D_ERR( "Invalid rects pointer" );
  917. return DDERR_INVALIDPARAMS;
  918. }
  919. #endif
  920. }
  921. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  922. {
  923. D3D_ERR( "Exception encountered validating parameters" );
  924. return DDERR_INVALIDPARAMS;
  925. }
  926. if((dwFlags & D3DCLEAR_ZBUFFER) && (this->lpDevI->lpDDSZBuffer==NULL)) {
  927. // this is not an error for legacy app compatibility--DX5 allowed this flag
  928. // to be set even if no ZBuffer exists
  929. if (!(this->lpDevI->lpD3DHALGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR)
  930. || !(this->lpDevI->lpD3DHALCallbacks2->Clear || this->lpDevI->lpD3DHALCallbacks3->Clear2
  931. || (IS_DX7HAL_DEVICE(lpDevI)))
  932. )
  933. {
  934. D3D_WARN(3,"Ignoring D3DCLEAR_ZBUFFER since no zbuffer associated with device");
  935. dwFlags &= ~(D3DCLEAR_ZBUFFER);
  936. if (! dwFlags)
  937. {
  938. D3D_WARN(3, "Viewport::Clear: Nothing to do");
  939. err = D3D_OK;
  940. goto early_out;
  941. }
  942. }
  943. }
  944. #if DBG
  945. if (dwFlags & D3DCLEAR_ZBUFFER)
  946. {
  947. LPDDPIXELFORMAT pZPixFmt =
  948. &((LPDDRAWI_DDRAWSURFACE_INT) lpDevI->lpDDSZBuffer)->lpLcl->lpGbl->ddpfSurface;
  949. if (pZPixFmt->dwFlags & DDPF_STENCILBUFFER) {
  950. D3D_ERR("Can't use Clear() on Z buffer with stencil planes. Use Clear2()");
  951. // No change to execution path.
  952. }
  953. }
  954. #endif
  955. // leave this check until after checks that turn off flags
  956. if (!(dwFlags & (D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER))) {
  957. D3D_ERR("no valid flags were passed to Clear");
  958. err=DDERR_INVALIDPARAMS;
  959. goto early_out;
  960. }
  961. // Make sure the correct viewport is set up in the driver.
  962. err = ValidateViewport(this->lpDevI, this);
  963. if (err != D3D_OK)
  964. {
  965. D3D_ERR("failed to set viewport");
  966. goto early_out;
  967. }
  968. if((err=ProcessRects(this,dwCount,rects))!=D3D_OK)
  969. goto early_out;
  970. D3DMATERIAL dmMat;
  971. if(this->bHaveBackgndMat) {
  972. err = D3DHAL_MaterialGetData(lpDevI, this->hBackgndMat, &dmMat);
  973. if(err != D3D_OK) {
  974. D3D_ERR("Failed to find material from current background material handle");
  975. goto early_out;
  976. }
  977. } else {
  978. // DX5 legacy apps expect to Clear to Black if Background not initialized
  979. dmMat.diffuse.r=dmMat.diffuse.g=dmMat.diffuse.b=dmMat.diffuse.a=0;
  980. dmMat.hTexture=0;
  981. D3D_WARN(3,"Background Material is NULL!! Setting color to black, but please set a valid background");
  982. }
  983. /* Make sure this viewport is the current viewport for the duration of this call */
  984. lpTempVwport = this->lpDevI->lpCurrentViewport;
  985. this->lpDevI->lpCurrentViewport = this;
  986. if (IS_DX7HAL_DEVICE(lpDevI))
  987. {
  988. if (0 != dmMat.hTexture && (D3DCLEAR_TARGET & dwFlags))
  989. {
  990. err = lpDevI->FlushStates();
  991. if (err != D3D_OK)
  992. {
  993. D3D_ERR("Error trying to render batched commands in Clear");
  994. goto early_out;
  995. }
  996. TriFillRectsTex(lpDevI, clrCount, clrRects, dmMat.hTexture);
  997. dwFlags &= ~D3DCLEAR_TARGET;
  998. }
  999. if ((D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER) & dwFlags)
  1000. {
  1001. static_cast<CDirect3DDeviceIDP2*>(lpDevI)->ClearI(dwFlags, clrCount, clrRects, CVAL_TO_RGBA(dmMat.diffuse), 1.0, 0);
  1002. }
  1003. }
  1004. else
  1005. {
  1006. err = D3DFE_Clear(this->lpDevI, dwFlags, this->clrCount, this->clrRects,
  1007. &dmMat.diffuse, dmMat.hTexture);
  1008. }
  1009. /* Restore the original current viewport of the device */
  1010. this->lpDevI->lpCurrentViewport = lpTempVwport;
  1011. early_out:
  1012. return err;
  1013. }
  1014. #undef DPF_MODNAME
  1015. #define DPF_MODNAME "Direct3DViewport::AddLight"
  1016. HRESULT D3DAPI DIRECT3DVIEWPORTI::AddLight(LPDIRECT3DLIGHT lpD3DLight)
  1017. {
  1018. LPDIRECT3DLIGHTI lpLightI;
  1019. HRESULT err = D3D_OK;
  1020. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1021. /*
  1022. * validate parms
  1023. */
  1024. TRY
  1025. {
  1026. lpLightI = (LPDIRECT3DLIGHTI)lpD3DLight;
  1027. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  1028. D3D_ERR( "Invalid Direct3DViewport pointer" );
  1029. return DDERR_INVALIDOBJECT;
  1030. }
  1031. if (!VALID_DIRECT3DLIGHT_PTR(lpLightI)) {
  1032. D3D_ERR( "Invalid DIRECT3DLIGHT pointer" );
  1033. return DDERR_INVALIDPARAMS;
  1034. }
  1035. }
  1036. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1037. {
  1038. D3D_ERR( "Exception encountered validating parameters" );
  1039. return DDERR_INVALIDPARAMS;
  1040. }
  1041. if (lpLightI->lpD3DViewportI) {
  1042. D3D_ERR("light already associated with a viewport");
  1043. return (D3DERR_LIGHTHASVIEWPORT);
  1044. }
  1045. err = hookLightToViewport(this, lpLightI);
  1046. if (err != D3D_OK) {
  1047. D3D_ERR("failed to add light to viewport");
  1048. return (err);
  1049. }
  1050. this->bLightsChanged = TRUE;
  1051. /*
  1052. * AddRef the light
  1053. */
  1054. lpD3DLight->AddRef();
  1055. return (err);
  1056. }
  1057. #undef DPF_MODNAME
  1058. #define DPF_MODNAME "Direct3DViewport::DeleteLight"
  1059. HRESULT D3DAPI DIRECT3DVIEWPORTI::DeleteLight(LPDIRECT3DLIGHT lpD3DLight)
  1060. {
  1061. LPDIRECT3DLIGHTI lpLightI;
  1062. HRESULT err = D3D_OK;
  1063. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1064. /*
  1065. * validate parms
  1066. */
  1067. TRY
  1068. {
  1069. lpLightI = (LPDIRECT3DLIGHTI)lpD3DLight;
  1070. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  1071. D3D_ERR( "Invalid Direct3DViewport pointer" );
  1072. return DDERR_INVALIDOBJECT;
  1073. }
  1074. if (!VALID_DIRECT3DLIGHT_PTR(lpLightI)) {
  1075. D3D_ERR( "Invalid DIRECT3DLIGHT pointer" );
  1076. return DDERR_INVALIDPARAMS;
  1077. }
  1078. }
  1079. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1080. {
  1081. D3D_ERR( "Exception encountered validating parameters" );
  1082. return DDERR_INVALIDPARAMS;
  1083. }
  1084. if (lpLightI->lpD3DViewportI != this) {
  1085. D3D_ERR("Light is not associated with this viewport");
  1086. return (D3DERR_LIGHTNOTINTHISVIEWPORT);
  1087. }
  1088. /*
  1089. * Remove this light from the viewport.
  1090. */
  1091. CIRCLE_QUEUE_DELETE(&this->lights, lpLightI, light_list);
  1092. this->numLights--;
  1093. lpLightI->lpD3DViewportI = NULL;
  1094. this->bLightsChanged = TRUE;
  1095. /*
  1096. * Release the light
  1097. */
  1098. lpD3DLight->Release();
  1099. return (err);
  1100. }
  1101. #undef DPF_MODNAME
  1102. #define DPF_MODNAME "Direct3DViewport::NextLight"
  1103. HRESULT D3DAPI DIRECT3DVIEWPORTI::NextLight(LPDIRECT3DLIGHT lpD3DLight,
  1104. LPDIRECT3DLIGHT* lplpLight,
  1105. DWORD dwFlags)
  1106. {
  1107. LPDIRECT3DLIGHTI lpLightI;
  1108. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1109. /*
  1110. * validate parms
  1111. */
  1112. TRY
  1113. {
  1114. if (!VALID_OUTPTR(lplpLight)) {
  1115. D3D_ERR( "Invalid output pointer to LPDIRECT3DLIGHT" );
  1116. return DDERR_INVALIDPARAMS;
  1117. }
  1118. *lplpLight = NULL;
  1119. lpLightI = (LPDIRECT3DLIGHTI)lpD3DLight;
  1120. if (!VALID_DIRECT3DVIEWPORT3_PTR(this)) {
  1121. D3D_ERR( "Invalid Direct3DViewport pointer" );
  1122. return DDERR_INVALIDOBJECT;
  1123. }
  1124. if (dwFlags & D3DNEXT_NEXT) {
  1125. if (!VALID_DIRECT3DLIGHT_PTR(lpLightI)) {
  1126. D3D_ERR( "Invalid Direct3DLight pointer" );
  1127. return DDERR_INVALIDPARAMS;
  1128. }
  1129. if (lpLightI && lpLightI->lpD3DViewportI != this) {
  1130. D3D_ERR("light not associated with this viewport");
  1131. return (D3DERR_LIGHTNOTINTHISVIEWPORT);
  1132. }
  1133. }
  1134. }
  1135. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1136. {
  1137. D3D_ERR( "Exception encountered validating parameters" );
  1138. return DDERR_INVALIDPARAMS;
  1139. }
  1140. switch (dwFlags) {
  1141. case D3DNEXT_NEXT:
  1142. *lplpLight = (LPDIRECT3DLIGHT)CIRCLE_QUEUE_NEXT(this,lpLightI,light_list);
  1143. break;
  1144. case D3DNEXT_HEAD:
  1145. *lplpLight = (LPDIRECT3DLIGHT)CIRCLE_QUEUE_FIRST(&this->lights);
  1146. break;
  1147. case D3DNEXT_TAIL:
  1148. *lplpLight = (LPDIRECT3DLIGHT)CIRCLE_QUEUE_LAST(&this->lights);
  1149. break;
  1150. default:
  1151. D3D_ERR("invalid flags");
  1152. return (DDERR_INVALIDPARAMS);
  1153. }
  1154. if (*lplpLight == (LPDIRECT3DLIGHT)&this->lights) {
  1155. *lplpLight = NULL;
  1156. }
  1157. /*
  1158. * Must AddRef the returned object
  1159. */
  1160. if (*lplpLight)
  1161. (*lplpLight)->AddRef();
  1162. return (D3D_OK);
  1163. }