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.

3241 lines
109 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1998 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: d3ddev.cpp
  6. * Content: Direct3D device implementation
  7. *@@BEGIN_MSINTERNAL
  8. *
  9. * $Id: device.c,v 1.26 1995/12/04 11:29:47 sjl Exp $
  10. *
  11. * History:
  12. * Date By Reason
  13. * ==== == ======
  14. * 05/11/95 stevela Initial rev with this header.
  15. * 11/11/95 stevela Light code changed.
  16. * 23/11/95 colinmc Modifications to support aggregatable interfaces
  17. * 07/12/95 stevela Merged Colin's changes.
  18. * 10/12/95 stevela Removed AGGREGATE_D3D.
  19. * 18/12/95 stevela Added GetMatrix, GetState.
  20. * 15/07/96 andyhird Initialise Render state on devices
  21. * 13/08/96 andyhird Check surface and device are compatible
  22. * 18/08/96 colinmc Fixed z-buffer leak
  23. *@@END_MSINTERNAL
  24. *
  25. ***************************************************************************/
  26. #include "pch.cpp"
  27. #pragma hdrstop
  28. /*
  29. * Create an api for the Direct3DDevice object
  30. */
  31. extern "C" {
  32. #define this _this
  33. #include "ddrawpr.h"
  34. #undef this
  35. }
  36. #include "commdrv.hpp"
  37. #include "drawprim.hpp"
  38. //#ifdef DEBUG_PIPELINE
  39. #include "testprov.h"
  40. //#endif //DEBUG_PIPELINE
  41. // Remove DDraw's type unsafe definition and replace with our C++ friendly def
  42. #ifdef VALIDEX_CODE_PTR
  43. #undef VALIDEX_CODE_PTR
  44. #endif
  45. #define VALIDEX_CODE_PTR( ptr ) \
  46. (!IsBadCodePtr( (FARPROC) ptr ) )
  47. #undef DPF_MODNAME
  48. #define DPF_MODNAME "Direct3DDevice"
  49. extern BOOL isMMXprocessor(void);
  50. extern HRESULT GenGetPickRecords(LPDIRECT3DDEVICEI, D3DI_PICKDATA *);
  51. extern BOOL IsValidD3DDeviceGuid(REFCLSID riid);
  52. BOOL D3DI_isHALValid(LPD3DHAL_CALLBACKS halTable)
  53. {
  54. if(halTable==NULL) {
  55. D3D_WARN(0, "HAL callbacks is NULL. HAL will not be enumerated.");
  56. return FALSE;
  57. }
  58. if (halTable->dwSize != D3DHAL_SIZE_V1) {
  59. D3D_WARN(0, "HAL callbacks invalid - size = %d, wanted %d. HAL will not be enumerated.",
  60. halTable->dwSize, D3DHAL_SIZE_V1);
  61. return FALSE;
  62. }
  63. if (halTable->dwReserved ||
  64. halTable->dwReserved0 ||
  65. halTable->dwReserved1 ||
  66. halTable->dwReserved2 ||
  67. halTable->dwReserved3 ||
  68. halTable->dwReserved4 ||
  69. halTable->dwReserved5 ||
  70. halTable->dwReserved6 ||
  71. halTable->dwReserved7 ||
  72. halTable->dwReserved8 ||
  73. halTable->dwReserved9 ||
  74. halTable->lpReserved10 ||
  75. halTable->lpReserved11 ||
  76. halTable->lpReserved12 ||
  77. halTable->lpReserved13 ||
  78. halTable->lpReserved14 ||
  79. halTable->lpReserved15 ||
  80. halTable->lpReserved16 ||
  81. halTable->lpReserved17 ||
  82. halTable->lpReserved18 ||
  83. halTable->lpReserved19 ||
  84. halTable->lpReserved20 ||
  85. halTable->lpReserved21) {
  86. D3D_WARN(0, "HAL callbacks invalid - has non-zero reserved fields, HAL will not be enumerated.");
  87. return FALSE;
  88. }
  89. return TRUE;
  90. }
  91. HRESULT DIRECT3DDEVICEI::stateInitialize(BOOL bZEnable)
  92. {
  93. D3DDEVICEDESC hwDesc, helDesc;
  94. D3DLINEPATTERN defLPat;
  95. HRESULT ret;
  96. float tmpval;
  97. BOOL ckeyenable = FALSE;
  98. /* Get the device caps for MONOENABLE */
  99. memset(&hwDesc, 0, sizeof(D3DDEVICEDESC));
  100. hwDesc.dwSize = sizeof(D3DDEVICEDESC);
  101. memset(&helDesc, 0, sizeof(D3DDEVICEDESC));
  102. helDesc.dwSize = sizeof(D3DDEVICEDESC);
  103. ret = GetCapsI(&hwDesc, &helDesc);
  104. if (FAILED(ret)) {
  105. D3D_ERR("stateInitialise: GetCaps failed");
  106. return(ret);
  107. }
  108. /* If we run on (HAL OR RefRast) AND this is a DX3 app
  109. then we need to initialize colorkey to TRUE so that the old HW driver (except s3 virge) behavior
  110. is exhibited. */
  111. if ( (this->dwVersion < 2) &&
  112. ( (IS_HW_DEVICE(this)) || (IsEqualIID(this->guid, IID_IDirect3DRefDevice)) ) )
  113. {
  114. ckeyenable = TRUE;
  115. }
  116. // Obviate SetRenderState filtering 'redundant' render state settings
  117. // since this is the init step.
  118. memset( this->rstates, 0xff, sizeof(DWORD)*D3DHAL_MAX_RSTATES );
  119. this->rstates[D3DRENDERSTATE_PLANEMASK] = 0;
  120. this->rstates[D3DRENDERSTATE_STENCILMASK] = 0;
  121. this->rstates[D3DRENDERSTATE_STENCILWRITEMASK] = 0;
  122. this->rstates[D3DRENDERSTATE_PLANEMASK] = 0;
  123. SetRenderState( D3DRENDERSTATE_TEXTUREHANDLE, (DWORD)NULL);
  124. SetRenderState( D3DRENDERSTATE_ANTIALIAS, FALSE);
  125. SetRenderState( D3DRENDERSTATE_TEXTUREADDRESS, D3DTADDRESS_WRAP);
  126. if (this->dwVersion <= 2)
  127. {
  128. SetRenderState( D3DRENDERSTATE_TEXTUREPERSPECTIVE, FALSE);
  129. SetRenderState( D3DRENDERSTATE_SPECULARENABLE, TRUE);
  130. }
  131. else
  132. {
  133. // perspective enabled by default for Device3 and later
  134. SetRenderState( D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE);
  135. // specular disabled by default for Device3 and later
  136. SetRenderState( D3DRENDERSTATE_SPECULARENABLE, FALSE);
  137. }
  138. SetRenderState( D3DRENDERSTATE_WRAPU, FALSE);
  139. SetRenderState( D3DRENDERSTATE_WRAPV, FALSE);
  140. SetRenderState( D3DRENDERSTATE_ZENABLE, bZEnable);
  141. SetRenderState( D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID);
  142. SetRenderState( D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
  143. defLPat.wRepeatFactor = 0;
  144. defLPat.wLinePattern = 0;
  145. SetRenderState( D3DRENDERSTATE_LINEPATTERN, *((LPDWORD)&defLPat)); /* 10 */
  146. /*
  147. ((LPD3DSTATE)lpPointer)->drstRenderStateType =
  148. (D3DRENDERSTATETYPE)D3DRENDERSTATE_LINEPATTERN;
  149. memcpy(&(((LPD3DSTATE)lpPointer)->dwArg[0]), &defLPat, sizeof(DWORD));
  150. lpPointer = (void *)(((LPD3DSTATE)lpPointer) + 1);*/
  151. SetRenderState( D3DRENDERSTATE_ROP2, R2_COPYPEN);
  152. SetRenderState( D3DRENDERSTATE_PLANEMASK, (DWORD)~0);
  153. SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE);
  154. SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
  155. SetRenderState( D3DRENDERSTATE_LASTPIXEL, TRUE);
  156. SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
  157. SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO);
  158. SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW); /* 21 */
  159. SetRenderState( D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
  160. SetRenderState( D3DRENDERSTATE_ALPHAREF, 0);
  161. SetRenderState( D3DRENDERSTATE_ALPHAFUNC, D3DCMP_ALWAYS);
  162. SetRenderState( D3DRENDERSTATE_DITHERENABLE, FALSE);
  163. SetRenderState( D3DRENDERSTATE_BLENDENABLE, FALSE);
  164. SetRenderState( D3DRENDERSTATE_FOGENABLE, FALSE);
  165. SetRenderState( D3DRENDERSTATE_ZVISIBLE, FALSE);
  166. SetRenderState( D3DRENDERSTATE_SUBPIXEL, FALSE); /* 30 */
  167. SetRenderState( D3DRENDERSTATE_SUBPIXELX, FALSE);
  168. SetRenderState( D3DRENDERSTATE_STIPPLEDALPHA, FALSE);
  169. SetRenderState( D3DRENDERSTATE_FOGCOLOR, 0);
  170. SetRenderState( D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
  171. /* Initialise these - although they may not need doing */
  172. tmpval = 0.0f;
  173. SetRenderState( D3DRENDERSTATE_FOGTABLESTART, *((DWORD *)&tmpval));
  174. tmpval = 1.0f;
  175. SetRenderState( D3DRENDERSTATE_FOGTABLEEND, *((DWORD *)&tmpval));
  176. tmpval = 1.0f;
  177. SetRenderState( D3DRENDERSTATE_FOGTABLEDENSITY, *((DWORD *)&tmpval));
  178. SetRenderState( D3DRENDERSTATE_STIPPLEENABLE, FALSE);
  179. SetRenderState( D3DRENDERSTATE_EDGEANTIALIAS, FALSE);
  180. SetRenderState( D3DRENDERSTATE_COLORKEYENABLE, ckeyenable);
  181. SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
  182. SetRenderState( D3DRENDERSTATE_BORDERCOLOR, 0);
  183. SetRenderState( D3DRENDERSTATE_TEXTUREADDRESSU, D3DTADDRESS_WRAP);
  184. SetRenderState( D3DRENDERSTATE_TEXTUREADDRESSV, D3DTADDRESS_WRAP);
  185. SetRenderState( D3DRENDERSTATE_MIPMAPLODBIAS, 0);
  186. SetRenderState( D3DRENDERSTATE_ZBIAS, 0);
  187. SetRenderState( D3DRENDERSTATE_RANGEFOGENABLE, FALSE);
  188. SetRenderState( D3DRENDERSTATE_ANISOTROPY, 1);
  189. /* Again - all these probably don't need doing */
  190. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN00, 0);
  191. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN01, 0); /* 40 */
  192. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN02, 0);
  193. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN03, 0);
  194. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN04, 0);
  195. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN05, 0);
  196. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN06, 0);
  197. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN07, 0);
  198. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN08, 0);
  199. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN09, 0);
  200. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN10, 0);
  201. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN11, 0); /* 50 */
  202. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN12, 0);
  203. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN13, 0);
  204. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN14, 0);
  205. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN15, 0);
  206. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN16, 0);
  207. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN17, 0);
  208. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN18, 0);
  209. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN19, 0);
  210. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN20, 0);
  211. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN21, 0); /* 60 */
  212. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN22, 0);
  213. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN23, 0);
  214. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN24, 0);
  215. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN25, 0);
  216. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN26, 0);
  217. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN27, 0);
  218. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN28, 0);
  219. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN29, 0);
  220. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN30, 0);
  221. SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN31, 0); /* 70 */
  222. // init stencil states to something reasonable
  223. // stencil enable is OFF by default since stenciling rasterizers will be
  224. // faster with it disabled, even if stencil states are benign
  225. SetRenderState( D3DRENDERSTATE_STENCILENABLE, FALSE);
  226. SetRenderState( D3DRENDERSTATE_STENCILFAIL, D3DSTENCILOP_KEEP);
  227. SetRenderState( D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_KEEP);
  228. SetRenderState( D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_KEEP);
  229. SetRenderState( D3DRENDERSTATE_STENCILFUNC, D3DCMP_ALWAYS);
  230. SetRenderState( D3DRENDERSTATE_STENCILREF, 0);
  231. SetRenderState( D3DRENDERSTATE_STENCILMASK, 0xFFFFFFFF);
  232. SetRenderState( D3DRENDERSTATE_STENCILWRITEMASK,0xFFFFFFFF);
  233. // don't forget about texturefactor (like we did in DX6.0...)
  234. SetRenderState( D3DRENDERSTATE_TEXTUREFACTOR, 0xFFFFFFFF);
  235. /* Check to see if the driver can do RGB - if not set MONOENABLE to
  236. true otherwise false (ie. RGB) by default */
  237. if (hwDesc.dwFlags & D3DDD_COLORMODEL) {
  238. if ((hwDesc.dcmColorModel & D3DCOLOR_RGB)) {
  239. D3D_INFO(3, "hw and RGB. MONOENABLE = FALSE");
  240. SetRenderState( D3DRENDERSTATE_MONOENABLE, FALSE);
  241. } else {
  242. D3D_INFO(3, "hw and !RGB. MONOENABLE = TRUE");
  243. SetRenderState( D3DRENDERSTATE_MONOENABLE, TRUE);
  244. }
  245. } else if (helDesc.dwFlags & D3DDD_COLORMODEL) {
  246. if ((helDesc.dcmColorModel & D3DCOLOR_RGB)) {
  247. D3D_INFO(3, "hel and RGB. MONOENABLE = FALSE");
  248. SetRenderState( D3DRENDERSTATE_MONOENABLE, FALSE);
  249. } else {
  250. D3D_INFO(3, "hel and !RGB. MONOENABLE = TRUE");
  251. SetRenderState( D3DRENDERSTATE_MONOENABLE, TRUE);
  252. }
  253. } else {
  254. /* Hmm, something bad has happened if we get here! */
  255. D3D_ERR("stateInitialise: neither hw or hel caps set");
  256. return(DDERR_GENERIC);
  257. }
  258. for (unsigned i = 0; i < 8; i++)
  259. {
  260. SetRenderState( (D3DRENDERSTATETYPE)
  261. (D3DRENDERSTATE_WRAPBIAS + i), FALSE );
  262. }
  263. for (i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
  264. {
  265. lpD3DMappedTexI[i] = NULL;
  266. lpD3DMappedBlock[i] = NULL;
  267. }
  268. SetLightState( D3DLIGHTSTATE_COLORVERTEX, TRUE);
  269. // Obviate SetTextureStageState/Settexture filtering 'redundant' render state
  270. // settings since this is the init step.
  271. memset( this->tsstates, 0xff, sizeof(DWORD)*D3DHAL_TSS_MAXSTAGES*D3DHAL_TSS_STATESPERSTAGE );
  272. for (i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
  273. {
  274. SetTexture(i, NULL);
  275. if(i == 0)
  276. SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_MODULATE);
  277. else
  278. SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
  279. SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  280. SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
  281. if(i == 0)
  282. SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  283. else
  284. SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  285. SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  286. SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  287. SetTextureStageState(i, D3DTSS_BUMPENVMAT00, 0);
  288. SetTextureStageState(i, D3DTSS_BUMPENVMAT01, 0);
  289. SetTextureStageState(i, D3DTSS_BUMPENVMAT10, 0);
  290. SetTextureStageState(i, D3DTSS_BUMPENVMAT11, 0);
  291. SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, 0);
  292. SetTextureStageState(i, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
  293. SetTextureStageState(i, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  294. SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  295. SetTextureStageState(i, D3DTSS_BORDERCOLOR, 0x00000000);
  296. SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTFG_POINT);
  297. SetTextureStageState(i, D3DTSS_MINFILTER, D3DTFN_POINT);
  298. SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTFP_NONE);
  299. SetTextureStageState(i, D3DTSS_MIPMAPLODBIAS, 0);
  300. SetTextureStageState(i, D3DTSS_MAXMIPLEVEL, 0);
  301. SetTextureStageState(i, D3DTSS_MAXANISOTROPY, 1);
  302. SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, 0);
  303. SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, 0);
  304. }
  305. // need to set legacy blend and filtering states after per-stage initialization
  306. // to properly set defaults in device
  307. SetRenderState( D3DRENDERSTATE_TEXTUREMAG, D3DFILTER_NEAREST);
  308. SetRenderState( D3DRENDERSTATE_TEXTUREMIN, D3DFILTER_NEAREST);
  309. SetRenderState( D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
  310. // Reset request bit as legacy renderstates have been already initialized
  311. // and no mapping is needed
  312. this->dwFEFlags &= ~D3DFE_MAP_TSS_TO_RS;
  313. return(D3D_OK);
  314. }
  315. DWORD BitDepthToDDBD(int bpp)
  316. {
  317. switch(bpp)
  318. {
  319. case 1:
  320. return DDBD_1;
  321. case 2:
  322. return DDBD_2;
  323. case 4:
  324. return DDBD_4;
  325. case 8:
  326. return DDBD_8;
  327. case 16:
  328. return DDBD_16;
  329. case 24:
  330. return DDBD_24;
  331. case 32:
  332. return DDBD_32;
  333. default:
  334. D3D_ERR("Invalid bit depth");
  335. return 0;
  336. }
  337. }
  338. HRESULT DIRECT3DDEVICEI::checkDeviceSurface(LPDIRECTDRAWSURFACE lpDDS, LPDIRECTDRAWSURFACE lpZbuffer, LPGUID pGuid)
  339. {
  340. D3DDEVICEDESC hwDesc, helDesc;
  341. DDPIXELFORMAT surfPF;
  342. DDSCAPS surfCaps;
  343. HRESULT ret;
  344. DWORD bpp;
  345. /* Get caps bits - check whether device and surface are:
  346. - video/system memory and depth compatible */
  347. if (FAILED(ret = lpDDS->GetCaps(&surfCaps))) {
  348. D3D_ERR("Failed to get render-target surface caps");
  349. return(ret);
  350. }
  351. memset(&surfPF, 0, sizeof(DDPIXELFORMAT));
  352. surfPF.dwSize = sizeof(DDPIXELFORMAT);
  353. if (FAILED(ret = lpDDS->GetPixelFormat(&surfPF))) {
  354. D3D_ERR("Failed to get render-target surface pixel format");
  355. return(ret);
  356. }
  357. memset(&hwDesc, 0, sizeof(D3DDEVICEDESC));
  358. hwDesc.dwSize = sizeof(D3DDEVICEDESC);
  359. memset(&helDesc, 0, sizeof(D3DDEVICEDESC));
  360. helDesc.dwSize = sizeof(D3DDEVICEDESC);
  361. // ATTENTION - Why doesn't this just look at the DEVICEI fields?
  362. ret = GetCapsI(&hwDesc, &helDesc);
  363. if (FAILED(ret)) {
  364. D3D_ERR("GetCaps failed");
  365. return(ret);
  366. }
  367. if (hwDesc.dwFlags) {
  368. /* I'm taking this as evidence that its running on hardware - therefore
  369. the surface should be in video memory */
  370. D3D_INFO(3, "Hardware device being used");
  371. if (!(surfCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) {
  372. D3D_ERR("Render-target surface not in video memory for hw device");
  373. return(D3DERR_SURFACENOTINVIDMEM);
  374. }
  375. }
  376. /* A surface can only have one bit depth - whereas a device can support
  377. multiple bit depths */
  378. if (surfPF.dwFlags & DDPF_RGB) {
  379. D3D_INFO(3, "Render-target surface is RGB");
  380. bpp = BitDepthToDDBD(surfPF.dwRGBBitCount);
  381. if (!bpp) {
  382. D3D_ERR("Bogus render-target surface pixel depth");
  383. return(DDERR_INVALIDPIXELFORMAT);
  384. }
  385. if((surfPF.dwRGBBitCount<16) && (IsEqualIID(*pGuid, IID_IDirect3DRefDevice) || IsEqualIID(*pGuid, IID_IDirect3DNullDevice))) {
  386. // this is actually subsumed by the following test, but whatever
  387. D3D_ERR("Reference rasterizer and null device dont support render targets with bitdepth < 16");
  388. return(DDERR_INVALIDPIXELFORMAT);
  389. }
  390. if (!(bpp & helDesc.dwDeviceRenderBitDepth) &&
  391. !(bpp & hwDesc.dwDeviceRenderBitDepth)) {
  392. D3D_ERR("Render-target surface bitdepth is not supported by HEL or HW for this device");
  393. return(DDERR_INVALIDPIXELFORMAT);
  394. }
  395. }
  396. if(lpZbuffer==NULL)
  397. return D3D_OK;
  398. memset(&surfPF, 0, sizeof(DDPIXELFORMAT));
  399. surfPF.dwSize = sizeof(DDPIXELFORMAT);
  400. if (FAILED(ret = lpZbuffer->GetPixelFormat(&surfPF))) {
  401. D3D_ERR("Failed to get zbuffer pixel format");
  402. return(ret);
  403. }
  404. if (FAILED(ret = lpZbuffer->GetCaps(&surfCaps))) {
  405. D3D_ERR("Failed to get Zbuffer caps");
  406. return(ret);
  407. }
  408. if (hwDesc.dwFlags) {
  409. if (!(surfCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) {
  410. D3D_ERR("Zbuffer not in video memory for hw device");
  411. return(D3DERR_ZBUFF_NEEDS_VIDEOMEMORY);
  412. }
  413. D3D_INFO(3, "Hw device, zbuffer in video memory");
  414. } else if (helDesc.dwFlags) {
  415. if (!(surfCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) {
  416. D3D_ERR("Zbuffer not in system memory for HEL device");
  417. return(D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY);
  418. }
  419. D3D_INFO(3, "Hel device, zbuffer in system memory");
  420. // have to hack in a check to make sure ramp isn't used with stencil zbuffer
  421. // cant do this validation until device creation time (instead of at zbuffer creation in
  422. // ddhel.c) because rgb vs. ramp isn't known until now
  423. if(IsEqualIID(*pGuid, IID_IDirect3DRampDevice)) {
  424. if(surfPF.dwFlags & DDPF_STENCILBUFFER) {
  425. D3D_ERR("Z-Buffer with stencil is invalid with RAMP software rasterizer");
  426. return DDERR_INVALIDPARAMS;
  427. }
  428. }
  429. }
  430. if (surfPF.dwFlags & DDPF_ZBUFFER) {
  431. bpp = BitDepthToDDBD(surfPF.dwZBufferBitDepth);
  432. if (!bpp) {
  433. D3D_ERR("Bogus Zbuffer surface pixel depth");
  434. return(DDERR_INVALIDPIXELFORMAT);
  435. }
  436. }
  437. return(D3D_OK);
  438. }
  439. /*
  440. * Initialisation - class part and device part
  441. */
  442. /*
  443. * Generic class part initialisation
  444. */
  445. HRESULT InitDeviceI(LPDIRECT3DDEVICEI lpDevI, LPDIRECT3DI lpD3DI)
  446. {
  447. LPDDRAWI_DIRECTDRAW_GBL lpDDI;
  448. HRESULT error;
  449. lpDDI = ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl;
  450. //
  451. // Retrieve HAL information from provider.
  452. //
  453. error = lpDevI->pHalProv->GetCaps(lpDDI,
  454. &lpDevI->d3dHWDevDesc,
  455. &lpDevI->d3dHELDevDesc,
  456. lpDevI->dwVersion);
  457. if (error != S_OK)
  458. {
  459. return (error);
  460. }
  461. D3DHALPROVIDER_INTERFACEDATA HalProviderIData;
  462. memset(&HalProviderIData,0,sizeof(HalProviderIData));
  463. HalProviderIData.dwSize = sizeof(HalProviderIData);
  464. if ((error = lpDevI->pHalProv->GetInterface(lpDDI,
  465. &HalProviderIData,
  466. lpDevI->dwVersion)) != S_OK)
  467. {
  468. return error;
  469. }
  470. // interface data for <=DX5 HAL
  471. lpDevI->lpD3DHALGlobalDriverData = HalProviderIData.pGlobalData;
  472. lpDevI->lpD3DExtendedCaps = HalProviderIData.pExtCaps;
  473. lpDevI->lpD3DHALCallbacks = HalProviderIData.pCallbacks;
  474. lpDevI->lpD3DHALCallbacks2 = HalProviderIData.pCallbacks2;
  475. // interface data for DX6 HAL
  476. lpDevI->lpD3DHALCallbacks3 = HalProviderIData.pCallbacks3;
  477. lpDevI->pfnRampService = HalProviderIData.pfnRampService;
  478. lpDevI->pfnRastService = HalProviderIData.pfnRastService;
  479. lpDevI->dwHintFlags = 0;
  480. // Zero out 8 bpp render target caps for real hardware.
  481. if (lpDevI->d3dHWDevDesc.dwFlags != 0)
  482. {
  483. lpDevI->lpD3DHALGlobalDriverData->hwCaps.dwDeviceRenderBitDepth &=
  484. (~DDBD_8);
  485. }
  486. if (!D3DI_isHALValid(lpDevI->lpD3DHALCallbacks))
  487. {
  488. return D3DERR_INITFAILED;
  489. }
  490. if (lpDevI->lpD3DExtendedCaps && lpDevI->lpD3DExtendedCaps->dwFVFCaps)
  491. {
  492. lpDevI->dwMaxTextureIndices =
  493. lpDevI->lpD3DExtendedCaps->dwFVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK;
  494. lpDevI->dwMaxTextureBlendStages =
  495. lpDevI->lpD3DExtendedCaps->wMaxTextureBlendStages;
  496. lpDevI->dwDeviceFlags |= D3DDEV_FVF;
  497. if (lpDevI->lpD3DExtendedCaps->dwFVFCaps & D3DFVFCAPS_DONOTSTRIPELEMENTS)
  498. lpDevI->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS;
  499. DWORD value;
  500. if ((lpDevI->dwDebugFlags & D3DDEBUG_DISABLEDP ||
  501. lpDevI->dwDebugFlags & D3DDEBUG_DISABLEDP2 ||
  502. (GetD3DRegValue(REG_DWORD, "DisableFVF", &value, 4) &&
  503. value != 0)) &&
  504. FVF_DRIVERSUPPORTED(lpDevI))
  505. {
  506. lpDevI->dwMaxTextureIndices = 1;
  507. lpDevI->dwMaxTextureBlendStages = 1;
  508. lpDevI->dwDeviceFlags &= ~D3DDEV_FVF;
  509. lpDevI->dwDebugFlags |= D3DDEBUG_DISABLEFVF;
  510. }
  511. if ((GetD3DRegValue(REG_DWORD, "DisableStripFVF", &value, 4) &&
  512. value != 0))
  513. {
  514. lpDevI->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS;
  515. }
  516. }
  517. else
  518. {
  519. lpDevI->dwMaxTextureIndices = 1;
  520. lpDevI->dwMaxTextureBlendStages = 1;
  521. }
  522. lpDevI->pfnDrawPrim = &DIRECT3DDEVICEI::DrawPrim;
  523. lpDevI->pfnDrawIndexedPrim = &DIRECT3DDEVICEI::DrawIndexPrim;
  524. #if DBG
  525. lpDevI->dwCaller=0;
  526. memset(lpDevI->dwPrimitiveType,0,sizeof(lpDevI->dwPrimitiveType));
  527. memset(lpDevI->dwVertexType1,0,sizeof(lpDevI->dwVertexType1));
  528. memset(lpDevI->dwVertexType2,0,sizeof(lpDevI->dwVertexType2));
  529. #endif
  530. return D3D_OK;
  531. }
  532. HRESULT D3DMallocBucket(LPDIRECT3DI lpD3DI, LPD3DBUCKET *lplpBucket)
  533. {
  534. if (lpD3DI->lpFreeList == NULL ){
  535. lpD3DI->lpTextureManager->cleanup(); //free unused nodes it may have
  536. if (lpD3DI->lpFreeList == NULL )
  537. {
  538. LPD3DBUCKET lpBufferList;
  539. LPVOID lpBuffer;
  540. int i;
  541. *lplpBucket=NULL;
  542. if (D3DMalloc(&lpBuffer, D3DBUCKETBUFFERSIZE*sizeof(D3DBUCKET)) != D3D_OK)
  543. return DDERR_OUTOFMEMORY;
  544. D3D_INFO(9, "D3DMallocBucket %d Bytes allocated for %d free Buckets",
  545. D3DBUCKETBUFFERSIZE*sizeof(D3DBUCKET),D3DBUCKETBUFFERSIZE-1);
  546. lpBufferList=(LPD3DBUCKET)lpBuffer;
  547. for (i=0;i<D3DBUCKETBUFFERSIZE-2;i++)
  548. lpBufferList[i].next=&lpBufferList[i+1];
  549. lpBufferList[D3DBUCKETBUFFERSIZE-2].next=NULL;
  550. lpD3DI->lpFreeList=(LPD3DBUCKET)lpBuffer; //new free list
  551. lpBufferList[D3DBUCKETBUFFERSIZE-1].next=lpD3DI->lpBufferList;//add to lpBufferList
  552. lpBufferList[D3DBUCKETBUFFERSIZE-1].lpBuffer=lpBuffer;
  553. lpD3DI->lpBufferList=&lpBufferList[D3DBUCKETBUFFERSIZE-1];
  554. }
  555. }
  556. *lplpBucket=lpD3DI->lpFreeList;
  557. lpD3DI->lpFreeList=lpD3DI->lpFreeList->next;
  558. return D3D_OK;
  559. }
  560. void D3DFreeBucket(LPDIRECT3DI lpD3DI, LPD3DBUCKET lpBucket)
  561. {
  562. lpBucket->next=lpD3DI->lpFreeList;
  563. lpD3DI->lpFreeList=lpBucket;
  564. }
  565. /*
  566. * Generic device part destroy
  567. */
  568. void DIRECT3DDEVICEI::DestroyDevice()
  569. {
  570. LPDIRECT3DVIEWPORTI lpViewI;
  571. LPDIRECTDRAWSURFACE lpDDS=NULL, lpDDSZ=NULL;
  572. LPDIRECTDRAWSURFACE4 lpDDS_DDS4=NULL;
  573. LPDIRECTDRAWPALETTE lpDDPal=NULL;
  574. BOOL bIsDX3Device;
  575. /* Clear flags that could prohibit cleanup */
  576. this->dwHintFlags &= ~(D3DDEVBOOL_HINTFLAGS_INBEGIN_ALL | D3DDEVBOOL_HINTFLAGS_INSCENE);
  577. /*
  578. * Remove all viewports attached to this device.
  579. */
  580. while ((lpViewI = CIRCLE_QUEUE_FIRST(&this->viewports)) &&
  581. (lpViewI != (LPDIRECT3DVIEWPORTI)&this->viewports)) {
  582. DeleteViewport((LPDIRECT3DVIEWPORT3)lpViewI);
  583. }
  584. /*
  585. * free up all textures created by this object - this also frees up Textures
  586. * We need to do this backwards because we cannot have a texture bound to
  587. * stage i + 1 when there is a texture bound to stage i.
  588. */
  589. for (int i = D3DHAL_TSS_MAXSTAGES - 1; i >= 0; --i)
  590. {
  591. if (lpD3DMappedTexI[i])
  592. {
  593. lpD3DMappedTexI[i]->Release();
  594. lpD3DMappedTexI[i] = NULL;
  595. lpD3DMappedBlock[i] = NULL;
  596. }
  597. }
  598. // The following code can result in D3DHAL_TextureDestroy() being called.
  599. // This BATCHES NEW INSTRUCTIONS in the instruction stream. So we must
  600. // make sure that at this point, the device is still able to accept
  601. // instructions.
  602. while (LIST_FIRST(&this->texBlocks)) {
  603. LPD3DI_TEXTUREBLOCK tBlock = LIST_FIRST(&this->texBlocks);
  604. D3DI_RemoveTextureHandle(tBlock);
  605. // Remove from device
  606. LIST_DELETE(tBlock, devList);
  607. // Remove from texture
  608. LIST_DELETE(tBlock, list);
  609. D3DFree(tBlock);
  610. }
  611. /*
  612. * free up all execute buffers created by this object
  613. */
  614. while (LIST_FIRST(&this->buffers)) {
  615. LPDIRECT3DEXECUTEBUFFERI lpBufI =
  616. LIST_FIRST(&this->buffers);
  617. lpBufI->Release();
  618. }
  619. /*
  620. * All materials associated with this device must be disassocited
  621. */
  622. while (LIST_FIRST(&this->matBlocks)) {
  623. LPD3DI_MATERIALBLOCK mBlock =
  624. LIST_FIRST(&this->matBlocks);
  625. D3DI_RemoveMaterialBlock(mBlock);
  626. }
  627. // In DX3, d3d device is aggregated and doesnt keep references to
  628. // rendertarget surfaces, so they shouldnt be "released"
  629. bIsDX3Device=(this->lpDDSTarget == (LPDIRECTDRAWSURFACE)(this->lpOwningIUnknown));
  630. if(!bIsDX3Device)
  631. {
  632. // Hold pointers into ddraw object for release after driver is destroyed
  633. lpDDSZ = this->lpDDSZBuffer;
  634. lpDDPal = this->lpDDPalTarget;
  635. if (this->dwVersion == 2)
  636. lpDDS = this->lpDDSTarget;
  637. else
  638. lpDDS_DDS4 = this->lpDDSTarget_DDS4;
  639. }
  640. //Unhook so that DDRAW surfaces won't try to flush the dead device
  641. if (this->lpDDSTarget)
  642. UnHookD3DDeviceFromSurface(this,((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSTarget)->lpLcl);
  643. if (this->lpDDSZBuffer)
  644. UnHookD3DDeviceFromSurface(this,((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSZBuffer)->lpLcl);
  645. if (pGeometryFuncs != &GeometryFuncsGuaranteed)
  646. delete pGeometryFuncs;
  647. D3DFE_Destroy(this);
  648. if (this->lpDirect3DI)
  649. unhookDeviceFromD3D();
  650. if (this->wTriIndex)
  651. D3DFree(this->wTriIndex);
  652. // Free the rstates that was allocated
  653. if(!(IS_HW_DEVICE(this) && IS_DP2HAL_DEVICE(this)))
  654. {
  655. delete rstates;
  656. }
  657. if (this->lpwDPBufferAlloced)
  658. D3DFree(this->lpwDPBufferAlloced);
  659. if (this->lpvVertexBatch)
  660. D3DFree(this->lpvVertexBatch);
  661. if (this->lpIndexBatch)
  662. D3DFree(this->lpIndexBatch);
  663. if (this->lpHWCounts)
  664. D3DFree(this->lpHWCounts);
  665. if (this->lpHWTris)
  666. D3DFree(this->lpHWTris);
  667. DeleteCriticalSection(&this->BeginEndCSect);
  668. if (this->pHalProv != NULL)
  669. {
  670. this->pHalProv->Release();
  671. }
  672. if (this->hDllProv != NULL)
  673. {
  674. FreeLibrary(this->hDllProv);
  675. }
  676. /* Now that the class has been destroyed, we should be able to release
  677. any DDraw object that might need to be released */
  678. if(!bIsDX3Device) {
  679. if (lpDDS)
  680. lpDDS->Release();
  681. if (lpDDSZ)
  682. lpDDSZ->Release();
  683. if (lpDDPal)
  684. lpDDPal->Release();
  685. if (lpDDS_DDS4)
  686. lpDDS_DDS4->Release();
  687. }
  688. }
  689. HRESULT DIRECT3DDEVICEI::hookDeviceToD3D(LPDIRECT3DI lpD3DI)
  690. {
  691. LIST_INSERT_ROOT(&lpD3DI->devices, this, list);
  692. this->lpDirect3DI = lpD3DI;
  693. lpD3DI->numDevs++;
  694. return (D3D_OK);
  695. }
  696. HRESULT DIRECT3DDEVICEI::unhookDeviceFromD3D()
  697. {
  698. LIST_DELETE(this, list);
  699. this->lpDirect3DI->numDevs--;
  700. this->lpDirect3DI = NULL;
  701. return (D3D_OK);
  702. }
  703. HRESULT D3DAPI DIRECT3DDEVICEI::Initialize(LPDIRECT3D lpD3D, LPGUID lpGuid, LPD3DDEVICEDESC lpD3Ddd)
  704. {
  705. return DDERR_ALREADYINITIALIZED;
  706. }
  707. HRESULT HookD3DDeviceToSurface( LPDIRECT3DDEVICEI pd3ddev,
  708. LPDDRAWI_DDRAWSURFACE_LCL lpLcl)
  709. {
  710. LPD3DBUCKET lpD3DDevIList;
  711. LPDDRAWI_DDRAWSURFACE_MORE this_more;
  712. // we only batch with DRAWPRIMITIVE aware HAL, so don't bother otherwise
  713. if (!lpLcl) return DDERR_ALREADYINITIALIZED;
  714. this_more = lpLcl->lpSurfMore;
  715. for(lpD3DDevIList=(LPD3DBUCKET)this_more->lpD3DDevIList;
  716. lpD3DDevIList;lpD3DDevIList=lpD3DDevIList->next) {
  717. if ((LPDIRECT3DDEVICEI)lpD3DDevIList->lpD3DDevI==pd3ddev)
  718. return DDERR_ALREADYINITIALIZED; // this device is already hooked to the surface
  719. }
  720. if (D3DMallocBucket(pd3ddev->lpDirect3DI,&lpD3DDevIList) != D3D_OK) {
  721. D3D_ERR("HookD3DDeviceToSurface: Out of memory");
  722. return DDERR_OUTOFMEMORY;
  723. }
  724. D3D_INFO(8,"adding lpd3ddev=%08lx to surface %08lx",pd3ddev,lpLcl);
  725. //Link a node to the DDRAW surface
  726. lpD3DDevIList->lpD3DDevI=(LPVOID)pd3ddev;
  727. lpD3DDevIList->next=(LPD3DBUCKET)this_more->lpD3DDevIList;
  728. this_more->lpD3DDevIList=lpD3DDevIList;
  729. if (DDSCAPS_ZBUFFER & lpLcl->ddsCaps.dwCaps)
  730. {
  731. if (pd3ddev->dwVersion==1)
  732. {
  733. lpD3DDevIList->lplpDDSZBuffer=(LPDIRECTDRAWSURFACE*)&pd3ddev->lpDDSZBuffer_DDS4;
  734. }
  735. else
  736. {
  737. lpD3DDevIList->lplpDDSZBuffer=NULL;
  738. }
  739. }
  740. return D3D_OK;
  741. }
  742. void UnHookD3DDeviceFromSurface( LPDIRECT3DDEVICEI pd3ddev,
  743. LPDDRAWI_DDRAWSURFACE_LCL lpLcl)
  744. {
  745. LPD3DBUCKET last,current,temp;
  746. LPDDRAWI_DDRAWSURFACE_MORE this_more;
  747. // we only batch with DRAWPRIMITIVE aware HAL, so don't bother otherwise
  748. if (!lpLcl) return;
  749. this_more = lpLcl->lpSurfMore;
  750. last=NULL;
  751. current=(LPD3DBUCKET)this_more->lpD3DDevIList;
  752. while(current){
  753. if ((LPDIRECT3DDEVICEI)current->lpD3DDevI==pd3ddev){
  754. temp=current;
  755. current=current->next;
  756. if (last)
  757. last->next=current;
  758. else
  759. this_more->lpD3DDevIList=current;
  760. D3DFreeBucket(pd3ddev->lpDirect3DI,temp);
  761. D3D_INFO(8,"removed lpd3ddev=%08lx from surface %08lx",pd3ddev,lpLcl);
  762. return; // end of search as this is only one pd3ddev in the list
  763. }
  764. else{
  765. last=current;
  766. current=current->next;
  767. }
  768. }
  769. return;
  770. }
  771. HRESULT D3DFlushStates(LPDIRECT3DDEVICEI lpDevI)
  772. {
  773. return lpDevI->FlushStates();
  774. }
  775. /*
  776. * Create a device.
  777. *
  778. * NOTE: Radical modifications to support the aggregatable device
  779. * interface (so devices can be queried off DirectDraw surfaces):
  780. *
  781. * 1) This call is no longer a member of the Direct3D device interface.
  782. * It is now an API function exported from the Direct3D DLL. Its
  783. * a hidden API function - only DirectDraw will ever invoke it.
  784. *
  785. * 2) This call is, in effect, the class factory for Direct3DDevice
  786. * objects. This function will be invoked to create the aggregated
  787. * device object hanging off the DirectDraw surface.
  788. *
  789. * NOTE: So the Direct3DDevice knows which DirectDraw surface is
  790. * its rendering target this function is passed an interface pointer
  791. * for that DirectDraw surface. I suspect this blows a nice big
  792. * hole in the COM model as the DirectDraw surface is also the
  793. * owning interface of the device and I don't think aggregated
  794. * objects should know about thier owning interfaces. However, to
  795. * make this thing work this is what we have to do.
  796. *
  797. * EXTRA BIG NOTE: Because of the above don't take a reference to
  798. * the DirectDraw surface passed in. If you do you will get a circular
  799. * reference and the bloody thing will never die. When aggregated
  800. * the device interface's lifetime is entirely defined by the
  801. * lifetime of its owning interface (the DirectDraw surface) so the
  802. * DirectDraw surface can never go away before the texture.
  803. *
  804. * EXTRA EXTRA BIG NOTE: No device description is passed in any more.
  805. * The only things that can get passed in are things that DirectDraw
  806. * knows about (which does not include stuff like dither and color
  807. * model). Therefore, any input parameters must come in via a
  808. * different IID for the device. The data returned by the device
  809. * description must now be retrieved by another call.
  810. */
  811. #undef DPF_MODNAME
  812. #define DPF_MODNAME "Direct3DCreateDevice"
  813. HRESULT WINAPI Direct3DCreateDevice(REFCLSID riid,
  814. LPUNKNOWN lpDirect3D,
  815. LPDIRECTDRAWSURFACE lpDDSTarget,
  816. LPUNKNOWN* lplpD3DDevice,
  817. IUnknown* pUnkOuter,
  818. DWORD dwVersion)
  819. {
  820. LPDIRECT3DI lpD3DI;
  821. LPDIRECT3DDEVICEI pd3ddev;
  822. D3DCOLORMODEL cm = D3DCOLOR_MONO;
  823. HRESULT ret = D3D_OK;
  824. HKEY hKey = (HKEY) NULL;
  825. bool bDisableDP = false;
  826. bool bDisableST = false;
  827. bool bDisableDP2 = false;
  828. #if _D3D_FORCEDOUBLE
  829. bool bForceDouble = true;
  830. #endif //_D3D_FORCEDOUBLE
  831. /* No need to validate params as they are passed to us by DirectDraw */
  832. /* CreateDevice member of IDirect3D2 will cause this function to be called
  833. * from within Direct3D. The parameters from the application level must be
  834. * validated. Need a way to validate the surface pointer from outside DDraw.
  835. */
  836. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  837. TRY
  838. {
  839. if( ! VALID_PTR_PTR( lplpD3DDevice) )
  840. {
  841. D3D_ERR( "Invalid ptr to device pointer in Direct3DCreateDevice" );
  842. return DDERR_INVALIDPARAMS;
  843. }
  844. if(!IsValidD3DDeviceGuid(riid)) {
  845. D3D_ERR( "Unrecognized Device GUID!");
  846. return DDERR_INVALIDPARAMS;
  847. }
  848. }
  849. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  850. {
  851. D3D_ERR( "Exception encountered validating parameters in Direct3DCreateDevice" );
  852. return DDERR_INVALIDPARAMS;
  853. }
  854. *lplpD3DDevice = NULL;
  855. // Might be safer to use dynamic_cast<> if RTTI is enabled
  856. lpD3DI = reinterpret_cast<CDirect3DUnk*>(lpDirect3D)->pD3DI;
  857. #ifndef _X86_
  858. if(IsEqualIID(riid, IID_IDirect3DRampDevice)) {
  859. // quietly fail if trying to create a RampDevice on a non-x86 platform
  860. return DDERR_INVALIDPARAMS;
  861. }
  862. #endif
  863. if((dwVersion>=3) && IsEqualIID(riid, IID_IDirect3DRampDevice)) {
  864. // Ramp not available in Device3. No more old-style texture handles.
  865. D3D_ERR( "RAMP Device is incompatible with IDirect3DDevice3 and so cannot be created from IDirect3D3");
  866. return DDERR_INVALIDPARAMS;
  867. }
  868. if (IsEqualIID(riid, IID_IDirect3DMMXDevice) && !isMMXprocessor()) {
  869. D3D_ERR("Can't create MMX Device on non-MMX machine");
  870. return DDERR_INVALIDPARAMS;
  871. }
  872. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey) )
  873. {
  874. DWORD dwType;
  875. DWORD dwValue;
  876. DWORD dwSize = 4;
  877. #ifdef WIN95
  878. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "DisableDP", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  879. dwType == REG_DWORD &&
  880. dwValue != 0)
  881. {
  882. bDisableDP = true;
  883. bDisableDP2 = true;
  884. }
  885. #endif //WIN95
  886. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "DisableST", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  887. dwType == REG_DWORD &&
  888. dwValue != 0)
  889. {
  890. bDisableST = true;
  891. }
  892. #ifdef WIN95
  893. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "DisableDP2", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  894. dwType == REG_DWORD &&
  895. dwValue != 0)
  896. {
  897. bDisableDP2 = true;
  898. }
  899. #endif //WIN95
  900. D3D_INFO(2,"EnableDP2: %d",!bDisableDP2);
  901. #if _D3D_FORCEDOUBLE
  902. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "ForceDouble", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  903. dwType == REG_DWORD &&
  904. dwValue == 0)
  905. {
  906. bForceDouble = false;
  907. }
  908. D3D_INFO(2,"ForceDouble: %d",bForceDouble);
  909. #endif //_D3D_FORCEDOUBLE
  910. RegCloseKey( hKey );
  911. }
  912. LPD3DHAL_GLOBALDRIVERDATA lpD3DHALGlobalDriverData=((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DGlobalDriverData;
  913. #ifdef WIN95
  914. /* Test for presence of CB HAL */
  915. if (IsEqualIID(riid, IID_IDirect3DHALDevice) )
  916. {
  917. /* Test for presence of DP2 DDI */
  918. if ((lpD3DHALGlobalDriverData)
  919. && (lpD3DHALGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX)
  920. )
  921. {
  922. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP2());
  923. if (pd3ddev) pd3ddev->deviceType = D3DDEVTYPE_DX7HAL;
  924. }
  925. else if ((!bDisableDP2) &&
  926. ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DHALCallbacks3 &&
  927. ((LPD3DHAL_CALLBACKS3)((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DHALCallbacks3)->DrawPrimitives2)
  928. {
  929. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP2());
  930. }
  931. /* Test for presence DP HAL */
  932. else if ((!bDisableDP) &&
  933. ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DHALCallbacks2 &&
  934. ((LPD3DHAL_CALLBACKS2)((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DHALCallbacks2)->DrawOnePrimitive)
  935. {
  936. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP());
  937. }
  938. else
  939. {
  940. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIHW());
  941. }
  942. }
  943. else // all software rasterizers are DP-enabled
  944. #endif // WIN95
  945. if (!bDisableDP2)
  946. {
  947. if ((lpD3DHALGlobalDriverData)
  948. && (IsEqualIID(riid, IID_IDirect3DHALDevice) )
  949. && (lpD3DHALGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX)
  950. )
  951. {
  952. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP2());
  953. if (pd3ddev) pd3ddev->deviceType = D3DDEVTYPE_DX7HAL;
  954. }
  955. else
  956. {
  957. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP2());
  958. }
  959. }
  960. else if (!bDisableDP)
  961. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP());
  962. else
  963. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIHW());
  964. if (!pd3ddev) {
  965. D3D_ERR("Failed to allocate space for D3DDevice. Quitting.");
  966. return (DDERR_OUTOFMEMORY);
  967. }
  968. // If we have lost managed textures, we need to cleanup
  969. // since CheckSurfaces() would fail which would cause
  970. // FlushStates() to fail, which would result in the
  971. // current batch being abandoned (along with any device initialization)
  972. if(lpD3DI->lpTextureManager->CheckIfLost())
  973. {
  974. D3D_INFO(2, "Found lost managed textures. Evicting...");
  975. lpD3DI->lpTextureManager->EvictTextures();
  976. }
  977. if (bDisableDP)
  978. pd3ddev->dwDebugFlags |= D3DDEBUG_DISABLEDP;
  979. if (bDisableDP2)
  980. pd3ddev->dwDebugFlags |= D3DDEBUG_DISABLEDP2;
  981. ret = pd3ddev->Init(riid, lpD3DI, lpDDSTarget, pUnkOuter, lplpD3DDevice, dwVersion);
  982. if (ret!=D3D_OK)
  983. {
  984. delete pd3ddev;
  985. D3D_ERR("Failed to intilialize D3DDevice");
  986. return ret;
  987. }
  988. if (bDisableST)
  989. pd3ddev->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_MULTITHREADED;
  990. #ifdef _X86_
  991. if (((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->dwLocalFlags & DDRAWILCL_FPUSETUP &&
  992. IS_DP2HAL_DEVICE(pd3ddev))
  993. {
  994. WORD wSave, wTemp;
  995. __asm {
  996. fstcw wSave
  997. mov ax, wSave
  998. and ax, not 300h ;; single mode
  999. or ax, 3fh ;; disable all exceptions
  1000. and ax, not 0C00h ;; round to nearest mode
  1001. mov wTemp, ax
  1002. fldcw wTemp
  1003. }
  1004. }
  1005. #if _D3D_FORCEDOUBLE
  1006. if (bForceDouble && (pd3ddev->deviceType <= D3DDEVTYPE_DPHAL))
  1007. {
  1008. pd3ddev->dwDebugFlags |= D3DDEBUG_FORCEDOUBLE;
  1009. }
  1010. else
  1011. {
  1012. pd3ddev->dwDebugFlags &= ~D3DDEBUG_FORCEDOUBLE;
  1013. }
  1014. #endif //_D3D_FORCEDOUBLE
  1015. #endif
  1016. return (ret);
  1017. }
  1018. HRESULT DIRECT3DDEVICEI::Init(REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS,
  1019. IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice, DWORD dwVersion)
  1020. {
  1021. DDSCAPS ddscaps;
  1022. DDSURFACEDESC ddsd;
  1023. HRESULT ret, ddrval;
  1024. LPDIRECTDRAWSURFACE lpDDSZ=NULL;
  1025. LPDIRECTDRAWPALETTE lpDDPal=NULL;
  1026. LPGUID pGuid;
  1027. BOOL bIsDX3Device;
  1028. DDSCAPS surfCaps;
  1029. this->dwFVFLastIn = this->dwFVFLastOut = 0;
  1030. this->mDevUnk.refCnt = 1;
  1031. this->dwVersion = dwVersion;
  1032. this->mDevUnk.pDevI = this;
  1033. pD3DMappedTexI = (LPVOID*)(this->lpD3DMappedTexI);
  1034. pfnFlushStates = D3DFlushStates;
  1035. this->dwFEFlags |= D3DFE_TSSINDEX_DIRTY;
  1036. /* Single threaded or Multi threaded app ? */
  1037. if (((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->dwLocalFlags & DDRAWILCL_MULTITHREADED)
  1038. this->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_MULTITHREADED;
  1039. /*
  1040. * Are we really being aggregated?
  1041. */
  1042. bIsDX3Device=(pUnkOuter!=NULL);
  1043. if (bIsDX3Device)
  1044. {
  1045. /*
  1046. * Yup - we are being aggregated. Store the supplied
  1047. * IUnknown so we can punt to that.
  1048. * NOTE: We explicitly DO NOT AddRef here.
  1049. */
  1050. this->lpOwningIUnknown = pUnkOuter;
  1051. DDASSERT(dwVersion==1);
  1052. }
  1053. else
  1054. {
  1055. /*
  1056. * Nope - but we pretend we are anyway by storing our
  1057. * own IUnknown as the parent IUnknown. This makes the
  1058. * code much neater.
  1059. */
  1060. this->lpOwningIUnknown = (LPUNKNOWN)&this->mDevUnk;
  1061. }
  1062. // create the begin/end critical section
  1063. InitializeCriticalSection(&this->BeginEndCSect);
  1064. /*
  1065. * Initialise textures
  1066. */
  1067. LIST_INITIALIZE(&this->texBlocks);
  1068. /*
  1069. * Initialise buffers
  1070. */
  1071. LIST_INITIALIZE(&this->buffers);
  1072. /*
  1073. * Initialise viewports
  1074. */
  1075. CIRCLE_QUEUE_INITIALIZE(&this->viewports, DIRECT3DVIEWPORTI);
  1076. this->lpCurrentViewport = NULL;
  1077. this->v_id = 0;
  1078. /*
  1079. * Initialise materials
  1080. */
  1081. LIST_INITIALIZE(&this->matBlocks);
  1082. this->lpvVertexBatch = this->lpIndexBatch = NULL;
  1083. this->dwHWNumCounts = 0;
  1084. this->dwHWOffset = 0;
  1085. this->dwHWTriIndex = 0;
  1086. this->lpTextureBatched = NULL;
  1087. this->dwVertexBase = 0;
  1088. pGeometryFuncs = &GeometryFuncsGuaranteed;
  1089. /*-----------------------------------------------------------------------------------------
  1090. * Up till now we have done the easy part of the initialization. This is the stuff that
  1091. * cannot fail. It initializes the object so that the destructor can be safely called if
  1092. * any of the further initialization does not succeed.
  1093. *---------------------------------------------------------------------------------------*/
  1094. /*
  1095. * Ensure the riid is one we understand.
  1096. *
  1097. * Query the registry.
  1098. */
  1099. pGuid = (GUID *)&riid;
  1100. #if DBG
  1101. if (IsEqualIID(*pGuid, IID_IDirect3DRampDevice))
  1102. {
  1103. D3D_INFO(1, "======================= Ramp device selected");
  1104. }
  1105. if (IsEqualIID(*pGuid, IID_IDirect3DRGBDevice))
  1106. {
  1107. D3D_INFO(1, "======================= RGB device selected");
  1108. }
  1109. if (IsEqualIID(*pGuid, IID_IDirect3DMMXDevice))
  1110. {
  1111. D3D_INFO(1, "======================= RGB(MMX) device selected");
  1112. }
  1113. if (IsEqualIID(*pGuid, IID_IDirect3DHALDevice))
  1114. {
  1115. D3D_INFO(1, "======================= HAL device selected");
  1116. }
  1117. if (IsEqualIID(*pGuid, IID_IDirect3DRefDevice))
  1118. {
  1119. D3D_INFO(1, "======================= Reference Rasterizer device selected");
  1120. }
  1121. if (IsEqualIID(*pGuid, IID_IDirect3DNullDevice))
  1122. {
  1123. D3D_INFO(1, "======================= Null device selected");
  1124. }
  1125. if (IsEqualIID(*pGuid, IID_IDirect3DNewRGBDevice))
  1126. {
  1127. D3D_INFO(1, "======================= New RGB device selected");
  1128. }
  1129. D3D_INFO(1,"with HAL deviceType=%d",deviceType);
  1130. #endif
  1131. // set up flag to use MMX when requested RGB
  1132. BOOL bUseMMXAsRGBDevice = FALSE;
  1133. if (IsEqualIID(*pGuid, IID_IDirect3DRGBDevice) && isMMXprocessor())
  1134. {
  1135. bUseMMXAsRGBDevice = TRUE;
  1136. // read reg key to override use of MMX for RGB
  1137. HKEY hKey = (HKEY) NULL;
  1138. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH, &hKey) )
  1139. {
  1140. DWORD dwType;
  1141. DWORD dwValue;
  1142. DWORD dwSize = 4;
  1143. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "UseMMXForRGB", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  1144. dwType == REG_DWORD &&
  1145. dwValue == 0)
  1146. {
  1147. bUseMMXAsRGBDevice = FALSE;
  1148. }
  1149. RegCloseKey( hKey );
  1150. }
  1151. if (bUseMMXAsRGBDevice)
  1152. {
  1153. D3D_INFO(1, " using MMX in RGB device");
  1154. }
  1155. }
  1156. BOOL bIsRamp = FALSE;
  1157. if (IsEqualIID(*pGuid, IID_IDirect3DRampDevice))
  1158. {
  1159. bIsRamp = TRUE;
  1160. }
  1161. if (IsEqualIID(*pGuid, IID_IDirect3DRGBDevice) &&
  1162. isMMXprocessor())
  1163. {
  1164. // Check for whether this app is one of the Intel ones
  1165. // that want the MMX rasterizer
  1166. LPDDRAWI_DIRECTDRAW_LCL lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl;
  1167. // 0x4 corresponds to the "Intel app that wants MMX"
  1168. // flag defined in ddrawpr.h
  1169. if ( lpDDLcl->dwAppHackFlags & 0x4 )
  1170. {
  1171. pGuid = (GUID *)&IID_IDirect3DMMXDevice;
  1172. }
  1173. }
  1174. /*
  1175. * Check if the 3D cap is set on the surface.
  1176. */
  1177. memset(&ddsd, 0, sizeof ddsd);
  1178. ddsd.dwSize = sizeof ddsd;
  1179. ddrval = lpDDS->GetSurfaceDesc(&ddsd);
  1180. if (ddrval != DD_OK) {
  1181. D3D_ERR("Failed to get surface description of device's surface.");
  1182. return (ddrval);
  1183. }
  1184. if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)) {
  1185. D3D_ERR("**** The DDSCAPS_3DDEVICE is not set on this surface.");
  1186. D3D_ERR("**** You need to add DDSCAPS_3DDEVICE to ddsCaps.dwCaps");
  1187. D3D_ERR("**** when creating the surface.");
  1188. return (DDERR_INVALIDCAPS);
  1189. }
  1190. if (ddsd.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) {
  1191. D3D_ERR("**** DDSCAPS_ZBUFFER is set on this surface.");
  1192. D3D_ERR("**** Rendering into Z buffer surfaces is not");
  1193. D3D_ERR("**** currently supported by Direct3D.");
  1194. return (DDERR_INVALIDCAPS);
  1195. }
  1196. if (ddsd.dwWidth > 2048 || ddsd.dwHeight > 2048)
  1197. {
  1198. D3D_ERR("**** Surface too large - must be <= 2048 in width & height.");
  1199. return (DDERR_INVALIDOBJECT);
  1200. }
  1201. /* Check for palette... */
  1202. ret = lpDDS->GetPalette(&lpDDPal);
  1203. if ((ret != DD_OK) && (ret != DDERR_NOPALETTEATTACHED))
  1204. {
  1205. /*
  1206. * NOTE: Again, not an error (yet) if there is no palette attached.
  1207. * But if there is palette and we can't get at it for some reason
  1208. * - fail.
  1209. */
  1210. D3D_ERR("Supplied DirectDraw Palette is invalid - can't create device");
  1211. return (DDERR_INVALIDPARAMS);
  1212. }
  1213. /*
  1214. * We're going to check now whether we should have got a palette.
  1215. */
  1216. if (ret == DDERR_NOPALETTEATTACHED) {
  1217. if (ddsd.ddpfPixelFormat.dwRGBBitCount < 16) {
  1218. D3D_ERR("No palette supplied for palettized surface - can't create device");
  1219. return (DDERR_NOPALETTEATTACHED);
  1220. }
  1221. }
  1222. // For DX3, we must not keep references to Palette and ZBuffer to avoid
  1223. // circular references in the aggregation model. But for DX5+, we want
  1224. // to keep references to both to ensure they dont disappear.
  1225. if(bIsDX3Device && (lpDDPal != NULL))
  1226. lpDDPal->Release(); // release the reference GetPalette created
  1227. this->lpDDPalTarget = lpDDPal;
  1228. // Check for ZBuffer
  1229. memset(&surfCaps, 0, sizeof(DDSCAPS));
  1230. surfCaps.dwCaps = DDSCAPS_ZBUFFER;
  1231. if (FAILED(ret = lpDDS->GetAttachedSurface(&surfCaps, &lpDDSZ))) {
  1232. if (ret != DDERR_NOTFOUND) {
  1233. D3D_ERR("Failed GetAttachedSurface for ZBuffer");
  1234. goto handle_err;
  1235. }
  1236. D3D_INFO(2, "No zbuffer is attached to rendertarget surface (which is OK)");
  1237. }
  1238. if(bIsDX3Device && (lpDDSZ != NULL))
  1239. lpDDSZ->Release(); // release the reference GetAttachedSurface created
  1240. this->lpDDSZBuffer = lpDDSZ;
  1241. this->guid = *pGuid;
  1242. // Try to get a HAL provider for this driver (may need to use MMX guid if
  1243. // using MMX for RGB requested device)
  1244. ret = GetSwHalProvider(
  1245. bUseMMXAsRGBDevice ? IID_IDirect3DMMXAsRGBDevice : riid,
  1246. &this->pHalProv, &this->hDllProv);
  1247. if (ret == S_OK)
  1248. {
  1249. // Got a software provider.
  1250. }
  1251. else if (ret == E_NOINTERFACE &&
  1252. ((ret = GetHwHalProvider(riid, &this->pHalProv,
  1253. &this->hDllProv,
  1254. ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl)) == S_OK))
  1255. {
  1256. // Got a hardware provider.
  1257. }
  1258. else
  1259. {
  1260. if(IsEqualIID(riid, IID_IDirect3DHALDevice)) {
  1261. D3D_ERR("Requested HAL Device non-existent or invalid");
  1262. } else {
  1263. D3D_ERR("Unable to get D3D Device provider for requested GUID");
  1264. }
  1265. goto handle_err;
  1266. }
  1267. {
  1268. // Initialize test HAL provider to drop HAL calls (sort of a Null device)
  1269. //
  1270. DWORD value = 0;
  1271. if (GetD3DRegValue(REG_DWORD, "DisableRendering", &value, sizeof(DWORD)) &&
  1272. value != 0)
  1273. {
  1274. ret = GetTestHalProvider(
  1275. riid, ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl,
  1276. &this->pHalProv, this->pHalProv, 0);
  1277. if (ret != D3D_OK)
  1278. {
  1279. D3D_ERR("Unable to set up 'DisableRendering' mode");
  1280. goto handle_err;
  1281. }
  1282. }
  1283. }
  1284. // Initialise general DEVICEI information.
  1285. if ((ret = InitDeviceI(this, lpD3DI)) != D3D_OK)
  1286. {
  1287. D3D_ERR("Failed to initialise device");
  1288. goto handle_err;
  1289. }
  1290. // Check the surface and device to see if they're compatible
  1291. if (FAILED(ret = checkDeviceSurface(lpDDS,lpDDSZ,pGuid))) {
  1292. D3D_ERR("Device and surface aren't compatible");
  1293. goto handle_err;
  1294. }
  1295. // Create front-end support structures.
  1296. // ATTENTION - We probably want to avoid doing this if the driver
  1297. // does its own front end. Software fallbacks complicate the issue,
  1298. // though.
  1299. ret = D3DFE_Create(this, lpD3DI->lpDD, lpDDS, lpDDSZ, lpDDPal);
  1300. if (ret != D3D_OK)
  1301. {
  1302. D3D_ERR("Failed to create front-end data-structures.");
  1303. goto handle_err;
  1304. }
  1305. // Figure out place for rstates
  1306. if (IS_HW_DEVICE(this) && IS_DP2HAL_DEVICE(this))
  1307. {
  1308. // In case of HW DP2 HAL we reuse the kernel allocated
  1309. // memory for RStates since we need the driver to update
  1310. // it
  1311. rstates = (LPDWORD)lpwDPBuffer;
  1312. }
  1313. else
  1314. {
  1315. // In all other cases we simply allocate memory for rstates
  1316. rstates = new DWORD[D3DHAL_MAX_RSTATES];
  1317. }
  1318. D3DFE_PROCESSVERTICES::lpdwRStates = this->rstates;
  1319. // Check if we have a processor specific implementation available
  1320. // only use if DisablePSGP is not in registry or set to zero
  1321. DWORD value;
  1322. if (!GetD3DRegValue(REG_DWORD, "DisablePSGP", &value, sizeof(DWORD)))
  1323. {
  1324. value = 0;
  1325. }
  1326. #ifdef _X86_
  1327. extern HRESULT D3DAPI pii_FEContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs);
  1328. if (pfnFEContextCreate == pii_FEContextCreate)
  1329. {
  1330. // here if this is PentiumII PSGP
  1331. // regkey disable for PII PSGP - default is ENABLED
  1332. DWORD dwValue2; // disable if this is TRUE
  1333. if (!GetD3DRegValue(REG_DWORD, "DisablePIIPSGP", &dwValue2, sizeof(DWORD)))
  1334. {
  1335. dwValue2 = 0;
  1336. }
  1337. else
  1338. {
  1339. D3D_INFO(2, "DisablePIIPSGP %d",dwValue2);
  1340. }
  1341. // do disable
  1342. if ( dwValue2 )
  1343. {
  1344. pfnFEContextCreate = NULL;
  1345. }
  1346. }
  1347. #endif
  1348. if (pfnFEContextCreate && ( value == 0) && (!bIsRamp) )
  1349. {
  1350. D3D_INFO(2, "PSGP enabled for device");
  1351. // Ask the PV implementation to create a device specific "context"
  1352. LPD3DFE_PVFUNCS pOptGeoFuncs = pGeometryFuncs;
  1353. ret = pfnFEContextCreate(dwDeviceFlags, &pOptGeoFuncs);
  1354. if ((ret == D3D_OK) && pOptGeoFuncs)
  1355. {
  1356. D3D_INFO(2, "using PSGP");
  1357. pGeometryFuncs = pOptGeoFuncs;
  1358. }
  1359. }
  1360. /*
  1361. * put this device in the list of those owned by the Direct3D object
  1362. */
  1363. ret = hookDeviceToD3D(lpD3DI);
  1364. if (ret != D3D_OK)
  1365. {
  1366. D3D_ERR("Failed to associate device with Direct3D");
  1367. goto handle_err;
  1368. }
  1369. {
  1370. if(lpD3DHALGlobalDriverData->hwCaps.dwMaxVertexCount == 0)
  1371. {
  1372. lpD3DHALGlobalDriverData->hwCaps.dwMaxVertexCount = __INIT_VERTEX_NUMBER;
  1373. }
  1374. if (TLVbuf.Grow(this, (__INIT_VERTEX_NUMBER*2)*sizeof(D3DTLVERTEX)) != DD_OK)
  1375. {
  1376. D3D_ERR( "Out of memory in DeviceCreate (TLVbuf)" );
  1377. ret = DDERR_OUTOFMEMORY;
  1378. goto handle_err;
  1379. }
  1380. if (HVbuf.Grow((__INIT_VERTEX_NUMBER*2)*sizeof(D3DFE_CLIPCODE)) != DD_OK)
  1381. {
  1382. D3D_ERR( "Out of memory in DeviceCreate (HVBuf)" );
  1383. ret = DDERR_OUTOFMEMORY;
  1384. goto handle_err;
  1385. }
  1386. ret = this->ClipperState.clipBuf.Grow
  1387. (this, MAX_CLIP_VERTICES*__MAX_VERTEX_SIZE);
  1388. if (ret != D3D_OK)
  1389. {
  1390. D3D_ERR( "Out of memory in DeviceCreate (ClipBuf)" );
  1391. ret = DDERR_OUTOFMEMORY;
  1392. goto handle_err;
  1393. }
  1394. ret = this->ClipperState.clipBufPrim.Grow
  1395. (this, MAX_CLIP_TRIANGLES*sizeof(D3DTRIANGLE));
  1396. if (ret != D3D_OK)
  1397. {
  1398. D3D_ERR( "Out of memory in DeviceCreate (ClipBufPrim)" );
  1399. ret = DDERR_OUTOFMEMORY;
  1400. goto handle_err;
  1401. }
  1402. }
  1403. /*
  1404. * IDirect3DDevice2 specific initialization
  1405. */
  1406. if (D3DMalloc((void**)&this->wTriIndex, dwD3DTriBatchSize*4*sizeof(WORD)) != DD_OK) {
  1407. D3D_ERR( "Out of memory in DeviceCreate (wTriIndex)" );
  1408. ret = DDERR_OUTOFMEMORY;
  1409. goto handle_err;
  1410. }
  1411. if (D3DMalloc((void**)&this->lpHWCounts, dwHWBufferSize*sizeof(D3DI_HWCOUNTS)/32 ) != DD_OK)
  1412. {
  1413. D3D_ERR( "Out of memory in DeviceCreate (HWCounts)" );
  1414. ret = DDERR_OUTOFMEMORY;
  1415. goto handle_err;
  1416. }
  1417. memset(this->lpHWCounts, 0, sizeof(D3DI_HWCOUNTS) );
  1418. this->lpHWVertices = (LPD3DTLVERTEX) this->lpwDPBuffer;
  1419. if (D3DMalloc((void**)&this->lpHWTris, dwHWMaxTris*sizeof(D3DTRIANGLE) ) != DD_OK)
  1420. {
  1421. D3D_ERR( "Out of memory in DeviceCreate (HWVertices)" );
  1422. ret = DDERR_OUTOFMEMORY;
  1423. goto handle_err;
  1424. }
  1425. if (DDERR_OUTOFMEMORY == (ret=HookD3DDeviceToSurface(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl)))
  1426. goto handle_err;
  1427. if (lpDDSZ && (DDERR_OUTOFMEMORY == (ret=HookD3DDeviceToSurface(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpDDSZ)->lpLcl))))
  1428. {
  1429. UnHookD3DDeviceFromSurface(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl);
  1430. goto handle_err;
  1431. }
  1432. /* Set the initial render state of the device */
  1433. if (FAILED(ret = stateInitialize(lpDDSZ!=NULL))) {
  1434. D3D_ERR("Failed to set initial state for device");
  1435. goto handle_err;
  1436. }
  1437. /*
  1438. * NOTE: We don't return the actual device interface. We
  1439. * return the device's special IUnknown interface which
  1440. * will be used in a QueryInterface to get the actual
  1441. * Direct3D device interface.
  1442. */
  1443. *lplpD3DDevice = static_cast<LPUNKNOWN>(&(this->mDevUnk));
  1444. return (D3D_OK);
  1445. handle_err:
  1446. // might be able to simplify if this fn and not D3DFE_Create sets this->lpDDSZBuffer/this->lpDDPalette
  1447. if(lpDDSZ!=NULL) {
  1448. if(!bIsDX3Device) {
  1449. lpDDSZ->Release(); // release the reference GetAttachedSurface created
  1450. }
  1451. this->lpDDSZBuffer=NULL; // make sure the device destructor doesn't try to re-release this
  1452. // I'd let device destructor handle this, but errors can occur before D3DFE_Create is called
  1453. }
  1454. if(lpDDPal!=NULL) {
  1455. if(!bIsDX3Device) {
  1456. lpDDPal->Release(); // release the reference GetPalette created
  1457. }
  1458. this->lpDDPalTarget=NULL; // make sure the device destructor doesn't try to re-release this
  1459. }
  1460. D3D_ERR("Device creation failed!!");
  1461. return(ret);
  1462. }
  1463. #undef DPF_MODNAME
  1464. #define DPF_MODNAME "DIRECT3DDEVICEI::GetStats"
  1465. HRESULT D3DAPI DIRECT3DDEVICEI::GetStats(LPD3DSTATS lpStats)
  1466. {
  1467. // not implemented for Device3 (and newer) interfaces
  1468. if (this->dwVersion >= 3)
  1469. {
  1470. D3D_INFO(3, "GetStats not implemented for Device3 interface");
  1471. return E_NOTIMPL;
  1472. }
  1473. D3DSTATS stats;
  1474. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1475. /*
  1476. * validate parms
  1477. */
  1478. TRY
  1479. {
  1480. if (!VALID_D3DSTATS_PTR(lpStats)) {
  1481. D3D_ERR( "Invalid D3DSTATS pointer" );
  1482. return DDERR_INVALIDPARAMS;
  1483. }
  1484. }
  1485. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1486. {
  1487. D3D_ERR( "Exception encountered validating parameters in GetStats" );
  1488. return DDERR_INVALIDPARAMS;
  1489. }
  1490. stats = this->D3DStats;
  1491. *lpStats = stats;
  1492. lpStats->dwSize = sizeof(D3DSTATS);
  1493. return DD_OK;
  1494. }
  1495. /**
  1496. ** Viewport Management
  1497. **/
  1498. HRESULT DIRECT3DDEVICEI::hookViewportToDevice(LPDIRECT3DVIEWPORTI lpD3DView)
  1499. {
  1500. CIRCLE_QUEUE_INSERT_END(&this->viewports, DIRECT3DVIEWPORTI,
  1501. lpD3DView, vw_list);
  1502. lpD3DView->lpDevI = this;
  1503. this->numViewports++;
  1504. return (D3D_OK);
  1505. }
  1506. #undef DPF_MODNAME
  1507. #define DPF_MODNAME "DIRECT3DDEVICEI::AddViewport"
  1508. HRESULT D3DAPI DIRECT3DDEVICEI::AddViewport(LPDIRECT3DVIEWPORT lpD3DView)
  1509. {
  1510. return AddViewport((LPDIRECT3DVIEWPORT3)lpD3DView);
  1511. }
  1512. HRESULT D3DAPI DIRECT3DDEVICEI::AddViewport(LPDIRECT3DVIEWPORT2 lpD3DView)
  1513. {
  1514. return AddViewport((LPDIRECT3DVIEWPORT3)lpD3DView);
  1515. }
  1516. HRESULT D3DAPI DIRECT3DDEVICEI::AddViewport(LPDIRECT3DVIEWPORT3 lpD3DView)
  1517. {
  1518. LPDIRECT3DVIEWPORTI lpViewI;
  1519. HRESULT err = D3D_OK;
  1520. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1521. lpViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
  1522. if (lpViewI->lpDevI) {
  1523. D3D_ERR("viewport already associated with a device");
  1524. return (DDERR_INVALIDPARAMS);
  1525. }
  1526. err = hookViewportToDevice(lpViewI);
  1527. /*
  1528. * AddRef the viewport.
  1529. */
  1530. lpD3DView->AddRef();
  1531. return (err);
  1532. }
  1533. #undef DPF_MODNAME
  1534. #define DPF_MODNAME "Direct3DDevice::DeleteViewport"
  1535. HRESULT D3DAPI DIRECT3DDEVICEI::DeleteViewport(LPDIRECT3DVIEWPORT lpD3DView)
  1536. {
  1537. return DeleteViewport((LPDIRECT3DVIEWPORT3)lpD3DView);
  1538. }
  1539. HRESULT D3DAPI DIRECT3DDEVICEI::DeleteViewport(LPDIRECT3DVIEWPORT2 lpD3DView)
  1540. {
  1541. return DeleteViewport((LPDIRECT3DVIEWPORT3)lpD3DView);
  1542. }
  1543. HRESULT D3DAPI DIRECT3DDEVICEI::DeleteViewport(LPDIRECT3DVIEWPORT3 lpD3DView)
  1544. {
  1545. LPDIRECT3DVIEWPORTI lpViewI;
  1546. HRESULT err = D3D_OK;
  1547. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1548. /*
  1549. * validate parms
  1550. */
  1551. TRY
  1552. {
  1553. if (!VALID_DIRECT3DVIEWPORT3_PTR(lpD3DView)) {
  1554. D3D_ERR( "Invalid Direct3DViewport pointer" );
  1555. return DDERR_INVALIDPARAMS;
  1556. }
  1557. }
  1558. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1559. {
  1560. D3D_ERR( "Exception encountered validating parameters in DeleteViewport" );
  1561. return DDERR_INVALIDPARAMS;
  1562. }
  1563. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  1564. {
  1565. D3D_ERR( "DeleteViewport in Begin" );
  1566. return D3DERR_INBEGIN;
  1567. }
  1568. lpViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
  1569. if (lpViewI->lpDevI != this) {
  1570. D3D_ERR("This Viewport is not associated with this device");
  1571. return (DDERR_INVALIDPARAMS);
  1572. }
  1573. /*
  1574. * Remove this viewport from the device.
  1575. */
  1576. CIRCLE_QUEUE_DELETE(&this->viewports, lpViewI, vw_list);
  1577. this->numViewports--;
  1578. lpViewI->lpDevI = NULL;
  1579. if (lpViewI == lpCurrentViewport)
  1580. {
  1581. // AnanKan (6/10/98):
  1582. // Apparently this release needs to be done for proper COM
  1583. // implementation, since we do lpCurrentViewport->AddRef() when
  1584. // we make a viewport the current viewport of the device. But this
  1585. // breaks some old apps (pplane.exe)
  1586. if(!(this->dwDeviceFlags & D3DDEV_PREDX6DEVICE))
  1587. lpCurrentViewport->Release();
  1588. lpCurrentViewport = NULL;
  1589. v_id = 0;
  1590. }
  1591. /*
  1592. * Release the viewport.
  1593. */
  1594. lpD3DView->Release();
  1595. return (err);
  1596. }
  1597. #undef DPF_MODNAME
  1598. #define DPF_MODNAME "Direct3DDevice::NextViewport"
  1599. HRESULT D3DAPI DIRECT3DDEVICEI::NextViewport(LPDIRECT3DVIEWPORT lpD3DView,
  1600. LPDIRECT3DVIEWPORT* lplpView,
  1601. DWORD dwFlags)
  1602. {
  1603. return NextViewport((LPDIRECT3DVIEWPORT3)lpD3DView,
  1604. (LPDIRECT3DVIEWPORT3*)lplpView, dwFlags);
  1605. }
  1606. HRESULT D3DAPI DIRECT3DDEVICEI::NextViewport(LPDIRECT3DVIEWPORT2 lpD3DView,
  1607. LPDIRECT3DVIEWPORT2* lplpView,
  1608. DWORD dwFlags)
  1609. {
  1610. return NextViewport((LPDIRECT3DVIEWPORT3)lpD3DView,
  1611. (LPDIRECT3DVIEWPORT3*)lplpView, dwFlags);
  1612. }
  1613. HRESULT D3DAPI DIRECT3DDEVICEI::NextViewport(LPDIRECT3DVIEWPORT3 lpD3DView,
  1614. LPDIRECT3DVIEWPORT3* lplpView,
  1615. DWORD dwFlags)
  1616. {
  1617. LPDIRECT3DVIEWPORTI lpViewI;
  1618. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1619. /*
  1620. * validate parms
  1621. */
  1622. TRY
  1623. {
  1624. if (!VALID_OUTPTR(lplpView)) {
  1625. D3D_ERR( "Invalid pointer to viewport object pointer" );
  1626. return DDERR_INVALIDPARAMS;
  1627. }
  1628. *lplpView = NULL;
  1629. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  1630. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1631. return DDERR_INVALIDOBJECT;
  1632. }
  1633. if (dwFlags == D3DNEXT_NEXT) {
  1634. if (!VALID_DIRECT3DVIEWPORT3_PTR(lpD3DView)) {
  1635. D3D_ERR( "Invalid Direct3DViewport pointer" );
  1636. return DDERR_INVALIDPARAMS;
  1637. }
  1638. lpViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
  1639. if (lpViewI->lpDevI != this) {
  1640. D3D_ERR("This Viewport is not associated with this device");
  1641. return (DDERR_INVALIDPARAMS);
  1642. }
  1643. }
  1644. }
  1645. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1646. {
  1647. D3D_ERR("Exception encountered validating parameters in NextViewport");
  1648. return DDERR_INVALIDPARAMS;
  1649. }
  1650. if (this->numViewports <= 0) {
  1651. D3D_ERR( "No viewport has been added to the device yet." );
  1652. return D3DERR_NOVIEWPORTS;
  1653. }
  1654. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
  1655. {
  1656. D3D_ERR( "NextViewport called in Begin" );
  1657. return D3DERR_INBEGIN;
  1658. }
  1659. switch (dwFlags) {
  1660. case D3DNEXT_NEXT:
  1661. *lplpView = (LPDIRECT3DVIEWPORT3)
  1662. CIRCLE_QUEUE_NEXT(&this->viewports,lpViewI,vw_list);
  1663. break;
  1664. case D3DNEXT_HEAD:
  1665. *lplpView = (LPDIRECT3DVIEWPORT3)
  1666. CIRCLE_QUEUE_FIRST(&this->viewports);
  1667. break;
  1668. case D3DNEXT_TAIL:
  1669. *lplpView = (LPDIRECT3DVIEWPORT3)
  1670. CIRCLE_QUEUE_LAST(&this->viewports);
  1671. break;
  1672. default:
  1673. D3D_ERR("invalid dwFlags in NextViewport");
  1674. return (DDERR_INVALIDPARAMS);
  1675. }
  1676. if (*lplpView == (LPDIRECT3DVIEWPORT3)&this->viewports) {
  1677. *lplpView = NULL;
  1678. }
  1679. /*
  1680. * Must AddRef the returned object
  1681. */
  1682. if (*lplpView) {
  1683. (*lplpView)->AddRef();
  1684. }
  1685. return (D3D_OK);
  1686. }
  1687. //---------------------------------------------------------------------
  1688. #undef DPF_MODNAME
  1689. #define DPF_MODNAME "DIRECT3DDEVICEI::Execute"
  1690. HRESULT D3DAPI DIRECT3DDEVICEI::Execute(LPDIRECT3DEXECUTEBUFFER lpBuffer,
  1691. LPDIRECT3DVIEWPORT lpD3DView,
  1692. DWORD dwInpFlags)
  1693. {
  1694. HRESULT ret;
  1695. LPDIRECT3DVIEWPORTI lpD3DViewI;
  1696. LPDIRECT3DVIEWPORTI lpD3DOldViewI;
  1697. BOOL viewportChanged;
  1698. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1699. /*
  1700. * validate parms
  1701. */
  1702. TRY
  1703. {
  1704. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  1705. {
  1706. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1707. return DDERR_INVALIDOBJECT;
  1708. }
  1709. if (!VALID_DIRECT3DEXECUTEBUFFER_PTR(lpBuffer))
  1710. {
  1711. D3D_ERR( "Invalid Direct3DExecuteBuffer pointer" );
  1712. return DDERR_INVALIDOBJECT;
  1713. }
  1714. if (lpD3DView && (!VALID_DIRECT3DVIEWPORT_PTR(lpD3DView)) )
  1715. {
  1716. D3D_ERR( "Invalid Direct3DViewport pointer" );
  1717. return DDERR_INVALIDOBJECT;
  1718. }
  1719. }
  1720. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1721. {
  1722. D3D_ERR( "Exception encountered validating parameters in Execute" );
  1723. return DDERR_INVALIDPARAMS;
  1724. }
  1725. lpD3DOldViewI = lpCurrentViewport;
  1726. if (lpD3DView)
  1727. lpD3DViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
  1728. else
  1729. lpD3DViewI = lpCurrentViewport;
  1730. // The viewport must be associated with lpDev device
  1731. //
  1732. if (lpD3DViewI->lpDevI != this)
  1733. {
  1734. return (DDERR_INVALIDPARAMS);
  1735. }
  1736. lpCurrentViewport = lpD3DViewI;
  1737. ret = CheckDeviceSettings(this);
  1738. if (ret != D3D_OK)
  1739. {
  1740. lpCurrentViewport = lpD3DOldViewI;
  1741. D3D_ERR("Bad Device settings");
  1742. return (ret);
  1743. }
  1744. /*
  1745. * Save existing fp state and then disable divide-by-zero exceptions.
  1746. * XXX need a better way for non-intel platforms.
  1747. */
  1748. LPDIRECT3DEXECUTEBUFFERI lpBufferI;
  1749. D3DI_EXECUTEDATA exData;
  1750. lpBufferI = (LPDIRECT3DEXECUTEBUFFERI)lpBuffer;
  1751. /* Make sure this buffer is associated with the correct device */
  1752. if (lpBufferI->lpDevI != this)
  1753. {
  1754. D3D_ERR("Exe-buffer not associated with this device");
  1755. return (DDERR_INVALIDPARAMS);
  1756. }
  1757. if (lpBufferI->locked)
  1758. {
  1759. D3D_ERR("Exe-buffer is locked");
  1760. return (D3DERR_EXECUTE_LOCKED);
  1761. }
  1762. /* Apply any cached render states */
  1763. if ((ret=this->FlushStates()) != D3D_OK)
  1764. {
  1765. D3D_ERR("Error trying to flush batched commands");
  1766. return ret;
  1767. }
  1768. /*
  1769. * Create an execute data structure
  1770. */
  1771. memset(&exData, 0, sizeof(exData));
  1772. exData.dwSize = sizeof(D3DI_EXECUTEDATA);
  1773. exData.dwHandle = lpBufferI->hBuf;
  1774. exData.dwVertexOffset = lpBufferI->exData.dwVertexOffset;
  1775. exData.dwVertexCount = lpBufferI->exData.dwVertexCount;
  1776. exData.dwInstructionOffset = lpBufferI->exData.dwInstructionOffset;
  1777. exData.dwInstructionLength = lpBufferI->exData.dwInstructionLength;
  1778. exData.dwHVertexOffset = lpBufferI->exData.dwHVertexOffset;
  1779. #if DBG
  1780. // Validation
  1781. if (exData.dwVertexOffset > exData.dwInstructionOffset ||
  1782. (exData.dwVertexCount * sizeof(D3DVERTEX) + exData.dwVertexOffset) >
  1783. exData.dwInstructionOffset)
  1784. {
  1785. D3D_WARN(1, "Execute: Instruction and vertex areas overlap");
  1786. }
  1787. #endif
  1788. this->dwFlags = D3DPV_INSIDEEXECUTE;
  1789. this->dwVIDOut = D3DFVF_TLVERTEX;
  1790. ret = this->ExecuteI(&exData, dwInpFlags);
  1791. if (ret != D3D_OK)
  1792. {
  1793. D3D_ERR("Error trying to Execute");
  1794. return ret;
  1795. }
  1796. this->dwFEFlags &= ~D3DFE_TLVERTEX; // This flag could be set inside
  1797. // Flush immediately since we cannot batch across EB calls (for DP2)
  1798. if ((ret=this->FlushStates()) != D3D_OK)
  1799. {
  1800. D3D_ERR("Error trying to flush batched commands");
  1801. return ret;
  1802. }
  1803. lpBufferI->exData.dsStatus = exData.dsStatus;
  1804. lpCurrentViewport = lpD3DOldViewI;
  1805. return (ret);
  1806. }
  1807. #undef DPF_MODNAME
  1808. #define DPF_MODNAME "Direct3DDevice::GetCaps"
  1809. HRESULT D3DAPI CDirect3DDevice::GetCaps(LPD3DDEVICEDESC lpD3DHWDevDesc,
  1810. LPD3DDEVICEDESC lpD3DHELDevDesc)
  1811. {
  1812. HRESULT ret;
  1813. ret = GetCapsI(lpD3DHWDevDesc, lpD3DHELDevDesc);
  1814. if ((ret == D3D_OK) && IS_PRE_DX5_DEVICE(this))
  1815. {
  1816. lpD3DHELDevDesc->dpcLineCaps.dwTextureFilterCaps &= ~(D3DPTFILTERCAPS_MIPNEAREST |
  1817. D3DPTFILTERCAPS_MIPLINEAR |
  1818. D3DPTFILTERCAPS_LINEARMIPNEAREST);
  1819. lpD3DHELDevDesc->dpcTriCaps.dwTextureFilterCaps &= ~(D3DPTFILTERCAPS_MIPNEAREST |
  1820. D3DPTFILTERCAPS_MIPLINEAR |
  1821. D3DPTFILTERCAPS_LINEARMIPNEAREST);
  1822. }
  1823. return ret;
  1824. }
  1825. HRESULT D3DAPI D3DAPI DIRECT3DDEVICEI::GetCaps(LPD3DDEVICEDESC lpD3DHWDevDesc,
  1826. LPD3DDEVICEDESC lpD3DHELDevDesc)
  1827. {
  1828. return GetCapsI(lpD3DHWDevDesc, lpD3DHELDevDesc);
  1829. }
  1830. HRESULT DIRECT3DDEVICEI::GetCapsI(LPD3DDEVICEDESC lpD3DHWDevDesc,
  1831. LPD3DDEVICEDESC lpD3DHELDevDesc)
  1832. {
  1833. HRESULT ret;
  1834. ret = D3D_OK;
  1835. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1836. /*
  1837. * validate parms
  1838. */
  1839. TRY
  1840. {
  1841. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  1842. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1843. return DDERR_INVALIDOBJECT;
  1844. }
  1845. if (!VALID_D3DDEVICEDESC_PTR(lpD3DHWDevDesc)) {
  1846. D3D_ERR( "Invalid D3DDEVICEDESC pointer" );
  1847. return DDERR_INVALIDPARAMS;
  1848. }
  1849. if (!VALID_D3DDEVICEDESC_PTR(lpD3DHELDevDesc)) {
  1850. D3D_ERR( "Invalid D3DDEVICEDESC pointer" );
  1851. return DDERR_INVALIDPARAMS;
  1852. }
  1853. }
  1854. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1855. {
  1856. D3D_ERR( "Exception encountered validating parameters in GetCaps" );
  1857. return DDERR_INVALIDPARAMS;
  1858. }
  1859. memcpy(lpD3DHWDevDesc, &this->d3dHWDevDesc, lpD3DHWDevDesc->dwSize);
  1860. memcpy(lpD3DHELDevDesc, &this->d3dHELDevDesc, lpD3DHELDevDesc->dwSize);
  1861. return (ret);
  1862. }
  1863. #undef DPF_MODNAME
  1864. #define DPF_MODNAME "Direct3DDevice::Pick"
  1865. HRESULT D3DAPI DIRECT3DDEVICEI::Pick(LPDIRECT3DEXECUTEBUFFER lpD3DExBuf,
  1866. LPDIRECT3DVIEWPORT lpD3DView,
  1867. DWORD dwFlags,
  1868. LPD3DRECT lpRect)
  1869. {
  1870. HRESULT ret;
  1871. LPDIRECT3DVIEWPORTI lpD3DViewI;
  1872. LPDIRECT3DVIEWPORTI lpD3DOldViewI;
  1873. LPDIRECT3DEXECUTEBUFFERI lpBufferI;
  1874. D3DI_PICKDATA pdata;
  1875. D3DI_EXECUTEDATA exData;
  1876. ret = D3D_OK;
  1877. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1878. /*
  1879. * validate parms
  1880. */
  1881. TRY
  1882. {
  1883. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  1884. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1885. return DDERR_INVALIDOBJECT;
  1886. }
  1887. if (!VALID_DIRECT3DEXECUTEBUFFER_PTR(lpD3DExBuf)) {
  1888. D3D_ERR( "Invalid Direct3DExecuteBuffer pointer" );
  1889. return DDERR_INVALIDOBJECT;
  1890. }
  1891. if (!VALID_DIRECT3DVIEWPORT_PTR(lpD3DView)) {
  1892. D3D_ERR( "Invalid Direct3DViewport pointer" );
  1893. return DDERR_INVALIDOBJECT;
  1894. }
  1895. if (!VALID_D3DRECT_PTR(lpRect)) {
  1896. D3D_ERR( "Invalid D3DRECT pointer" );
  1897. return DDERR_INVALIDOBJECT;
  1898. }
  1899. }
  1900. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1901. {
  1902. D3D_ERR( "Exception encountered validating parameters" );
  1903. return DDERR_INVALIDPARAMS;
  1904. }
  1905. lpD3DViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
  1906. /*
  1907. * The viewport must be associated with this device
  1908. */
  1909. if (lpD3DViewI->lpDevI != this) {
  1910. D3D_ERR("viewport not associated with this device");
  1911. return (DDERR_INVALIDPARAMS);
  1912. }
  1913. lpBufferI = (LPDIRECT3DEXECUTEBUFFERI)lpD3DExBuf;
  1914. /* Make sure this buffer is associated with the correct device */
  1915. if (lpBufferI->lpDevI != this) {
  1916. D3D_ERR("Exe-buffer not associated with this device");
  1917. return (DDERR_INVALIDPARAMS);
  1918. }
  1919. if (lpBufferI->locked) {
  1920. D3D_ERR("Exe-buffer is locked");
  1921. return (D3DERR_EXECUTE_LOCKED);
  1922. }
  1923. lpD3DOldViewI = lpCurrentViewport;
  1924. lpCurrentViewport = lpD3DViewI;
  1925. ret = CheckDeviceSettings(this);
  1926. if (ret != D3D_OK)
  1927. {
  1928. D3D_ERR("Bad Device settings");
  1929. lpCurrentViewport = lpD3DOldViewI;
  1930. return (ret);
  1931. }
  1932. /*
  1933. * Create an execute data structure
  1934. */
  1935. memset(&exData, 0, sizeof(exData));
  1936. exData.dwSize = sizeof(D3DI_EXECUTEDATA);
  1937. exData.dwHandle = lpBufferI->hBuf;
  1938. memcpy((LPBYTE)(&exData.dwVertexOffset),
  1939. (LPBYTE)(&lpBufferI->exData.dwVertexOffset),
  1940. sizeof(D3DEXECUTEDATA) - sizeof(DWORD));
  1941. pdata.exe = &exData;
  1942. pdata.pick.x1 = lpRect->x1;
  1943. pdata.pick.y1 = lpRect->y1;
  1944. pdata.pick.x2 = lpRect->x2;
  1945. pdata.pick.y2 = lpRect->y2;
  1946. this->dwFlags = D3DPV_INSIDEEXECUTE;
  1947. this->dwVIDOut = D3DFVF_TLVERTEX;
  1948. D3DHAL_ExecutePick(this, &pdata);
  1949. this->dwFEFlags &= ~D3DFE_TLVERTEX; // This flag could be set inside
  1950. lpCurrentViewport = lpD3DOldViewI;
  1951. return ret;
  1952. }
  1953. #undef DPF_MODNAME
  1954. #define DPF_MODNAME "Direct3DDevice::GetPickRecords"
  1955. HRESULT D3DAPI DIRECT3DDEVICEI::GetPickRecords(LPDWORD count,
  1956. LPD3DPICKRECORD records)
  1957. {
  1958. HRESULT ret;
  1959. D3DI_PICKDATA pdata;
  1960. D3DPICKRECORD* tmpBuff;
  1961. ret = D3D_OK;
  1962. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1963. /*
  1964. * validate parms
  1965. */
  1966. TRY
  1967. {
  1968. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  1969. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1970. return DDERR_INVALIDOBJECT;
  1971. }
  1972. if (!VALID_DWORD_PTR(count)) {
  1973. D3D_ERR( "Invalid DWORD pointer" );
  1974. return DDERR_INVALIDPARAMS;
  1975. }
  1976. #if DBG
  1977. if (*count && records && IsBadWritePtr(records, *count * sizeof(D3DPICKRECORD))) {
  1978. D3D_ERR( "Invalid D3DPICKRECORD pointer" );
  1979. return DDERR_INVALIDPARAMS;
  1980. }
  1981. #endif
  1982. }
  1983. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1984. {
  1985. D3D_ERR( "Exception encountered validating parameters" );
  1986. return DDERR_INVALIDPARAMS;
  1987. }
  1988. pdata.records = NULL;
  1989. GenGetPickRecords(this, &pdata);
  1990. if (count && records && *count >= (unsigned long)pdata.pick_count)
  1991. {
  1992. int picked_size = pdata.pick_count * sizeof(D3DPICKRECORD);
  1993. if (D3DMalloc((void**)&tmpBuff, picked_size) != DD_OK)
  1994. {
  1995. return (DDERR_OUTOFMEMORY);
  1996. }
  1997. pdata.records = tmpBuff;
  1998. GenGetPickRecords(this, &pdata);
  1999. memcpy((char*)records, (char*)tmpBuff, picked_size);
  2000. D3DFree(tmpBuff);
  2001. }
  2002. *count = pdata.pick_count;
  2003. return (D3D_OK);
  2004. }
  2005. #undef DPF_MODNAME
  2006. #define DPF_MODNAME "Direct3DDevice::EnumTextureFormats"
  2007. #define DEFINEPF(flags, fourcc, bpp, rMask, gMask, bMask, aMask) \
  2008. { sizeof(DDPIXELFORMAT), (flags), (fourcc), (bpp), (rMask), (gMask), (bMask), (aMask) }
  2009. static DDPIXELFORMAT g_DX5TexEnumIncListStatic[] = {
  2010. DEFINEPF(DDPF_RGB, 0UL, 16UL, 0x00007c00UL, 0x000003e0UL, 0x0000001fUL, 0x00000000), // 16bit 555
  2011. DEFINEPF(DDPF_RGB|DDPF_ALPHAPIXELS, 0UL, 16UL, 0x00007c00UL, 0x000003e0UL, 0x0000001fUL, 0x00008000), // 16bit 1555
  2012. DEFINEPF(DDPF_RGB, 0UL, 16UL, 0x0000f800UL, 0x000007e0UL, 0x0000001fUL, 0x00000000), // 16bit 565
  2013. DEFINEPF(DDPF_RGB|DDPF_ALPHAPIXELS, 0UL, 16UL, 0x00000f00UL, 0x000000f0UL, 0x0000000fUL, 0x0000f000), // 16bit 4444
  2014. DEFINEPF(DDPF_RGB|DDPF_ALPHAPIXELS, 0UL, 32UL, 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL, 0xff000000), // 32bit 8888
  2015. DEFINEPF(DDPF_RGB, 0UL, 32UL, 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL, 0x00000000), // 32bit 888
  2016. DEFINEPF(DDPF_RGB, 0UL, 8UL, 0x000000e0UL, 0x0000001cUL, 0x00000003UL, 0x00000000), // 8bit 332
  2017. DEFINEPF(DDPF_RGB|DDPF_PALETTEINDEXED4, 0UL, 4UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000), // 4bit pal
  2018. DEFINEPF(DDPF_RGB|DDPF_PALETTEINDEXED8, 0UL, 8UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000), // 8bit pal
  2019. };
  2020. DWORD g_cDX5TexEnumIncListStatic = sizeof(g_DX5TexEnumIncListStatic)/sizeof(DDPIXELFORMAT);
  2021. BOOL
  2022. MatchDDPIXELFORMAT( DDPIXELFORMAT* pddpfA, DDPIXELFORMAT* pddpfB )
  2023. {
  2024. if ( pddpfA->dwFlags != pddpfB->dwFlags ) return FALSE;
  2025. if ( pddpfA->dwRGBBitCount != pddpfB->dwRGBBitCount ) return FALSE;
  2026. if ( pddpfA->dwRBitMask != pddpfB->dwRBitMask ) return FALSE;
  2027. if ( pddpfA->dwGBitMask != pddpfB->dwGBitMask ) return FALSE;
  2028. if ( pddpfA->dwBBitMask != pddpfB->dwBBitMask ) return FALSE;
  2029. if ( pddpfA->dwRGBAlphaBitMask != pddpfB->dwRGBAlphaBitMask ) return FALSE;
  2030. if ( pddpfA->dwFourCC != pddpfB->dwFourCC ) return FALSE;
  2031. return TRUE;
  2032. }
  2033. void
  2034. LoadTexEnumInclList( char* pResPath, DDPIXELFORMAT*& pddpfInclList, DWORD& cInclList)
  2035. {
  2036. HKEY hKey = (HKEY)NULL;
  2037. if (ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE,
  2038. pResPath, &hKey))
  2039. {
  2040. DWORD cSubKeys = 0;
  2041. if ( ERROR_SUCCESS == RegQueryInfoKey ( hKey,
  2042. NULL,NULL,NULL, &cSubKeys, NULL,
  2043. NULL,NULL,NULL,NULL,NULL,NULL ) )
  2044. {
  2045. D3D_INFO(3,"LoadTexEnumInclList: cSubKeys = %d",cSubKeys);
  2046. if (cSubKeys == 0) return;
  2047. // allocate space for ddpf inclusion list
  2048. cInclList = cSubKeys;
  2049. if (D3DMalloc((void**)&pddpfInclList, cInclList*sizeof(DDPIXELFORMAT)) != D3D_OK) {
  2050. D3D_ERR("malloc failed on texture enum inclusion list");
  2051. pddpfInclList = NULL;
  2052. cInclList = 0;
  2053. }
  2054. memset( pddpfInclList, 0, cInclList*sizeof(DDPIXELFORMAT) );
  2055. for (DWORD i=0; i<cSubKeys; i++)
  2056. {
  2057. char pName[128] = "";
  2058. DWORD cbName = 128;
  2059. if (ERROR_SUCCESS == RegEnumKeyEx( hKey, i, pName, &cbName,
  2060. NULL,NULL,NULL,NULL ) )
  2061. {
  2062. HKEY hTexKey = (HKEY)NULL;
  2063. if (ERROR_SUCCESS == RegOpenKey( hKey, pName, &hTexKey))
  2064. {
  2065. DWORD dwType; DWORD dwSize;
  2066. // get string of full ddpf
  2067. char pDDPFStr[128] = ""; DWORD cbDDPFStr = 128;
  2068. if (ERROR_SUCCESS == RegQueryValueEx(hTexKey, "ddpf",
  2069. NULL, &dwType, (LPBYTE)pDDPFStr, &cbDDPFStr) )
  2070. {
  2071. sscanf(pDDPFStr, "%x %x %d %x %x %x %x",
  2072. &pddpfInclList[i].dwFlags,&pddpfInclList[i].dwFourCC,&pddpfInclList[i].dwRGBBitCount,
  2073. &pddpfInclList[i].dwRBitMask,&pddpfInclList[i].dwGBitMask,&pddpfInclList[i].dwBBitMask,
  2074. &pddpfInclList[i].dwRGBAlphaBitMask);
  2075. }
  2076. D3D_INFO(3,"LoadTexEnumInclList: <%s> %08x %08x %2d %08x %08x %08x %08x",
  2077. pName,
  2078. pddpfInclList[i].dwFlags,
  2079. pddpfInclList[i].dwFourCC,
  2080. pddpfInclList[i].dwRGBBitCount,
  2081. pddpfInclList[i].dwRBitMask,
  2082. pddpfInclList[i].dwGBitMask,
  2083. pddpfInclList[i].dwBBitMask,
  2084. pddpfInclList[i].dwRGBAlphaBitMask);
  2085. }
  2086. else
  2087. {
  2088. D3D_INFO(3,"LoadTexEnumInclList: failed to open subkey %s",pName);
  2089. }
  2090. }
  2091. else
  2092. {
  2093. D3D_INFO(3,"LoadTexEnumInclList: failed to enumerate subkey %d",i);
  2094. }
  2095. }
  2096. }
  2097. }
  2098. }
  2099. HRESULT
  2100. DoEnumTextureFormats(
  2101. DIRECT3DDEVICEI* lpDevI,
  2102. LPD3DENUMTEXTUREFORMATSCALLBACK lpEnumCallbackDX5, // DX5 version
  2103. LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallbackDX6, // DX6 version
  2104. LPVOID lpContext)
  2105. {
  2106. HRESULT ret, userRet;
  2107. LPDDSURFACEDESC lpDescs, lpRetDescs;
  2108. DWORD num_descs;
  2109. DWORD i;
  2110. ret = D3D_OK;
  2111. num_descs = lpDevI->lpD3DHALGlobalDriverData->dwNumTextureFormats;
  2112. lpDescs = lpDevI->lpD3DHALGlobalDriverData->lpTextureFormats;
  2113. if (!num_descs)
  2114. {
  2115. D3D_ERR("no texture formats supported");
  2116. return (D3DERR_TEXTURE_NO_SUPPORT);
  2117. }
  2118. if (D3DMalloc((void**)&lpRetDescs, sizeof(DDSURFACEDESC) * num_descs) != D3D_OK)
  2119. {
  2120. D3D_ERR("failed to alloc space for return descriptions");
  2121. return (DDERR_OUTOFMEMORY);
  2122. }
  2123. memcpy(lpRetDescs, lpDescs, sizeof(DDSURFACEDESC) * num_descs);
  2124. // get apphack flags
  2125. LPDDRAWI_DIRECTDRAW_LCL lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)(lpDevI->lpDD))->lpLcl;
  2126. DWORD dwEnumInclAppHack =
  2127. ((lpDDLcl->dwAppHackFlags & DDRAW_APPCOMPAT_TEXENUMINCL_0)?1:0) |
  2128. ((lpDDLcl->dwAppHackFlags & DDRAW_APPCOMPAT_TEXENUMINCL_1)?2:0);
  2129. // two bit field:
  2130. // 0 - no apphack (default behavior)
  2131. // 1 - use no inclusion list
  2132. // 2 - use DX5 inclusion list
  2133. // 3 - use DX6 inclusion list
  2134. D3D_INFO(3, "APPCOMPAT_TEXENUMINCL: %d",dwEnumInclAppHack);
  2135. // enumeration limit defaults true for <DX6 interfaces, and can be disabled by apphack
  2136. BOOL bEnumLimit = (lpDevI->dwVersion < 3) ? TRUE : FALSE;
  2137. if (lpDDLcl->dwAppHackFlags & DDRAW_APPCOMPAT_TEXENUMLIMIT) { bEnumLimit = FALSE; }
  2138. D3D_INFO(3, "EnumTextureFormats: bEnumLimit %d",bEnumLimit);
  2139. #if DBG
  2140. // debug capability to eliminate enumeration of any subset of first 32 textures
  2141. DWORD dwEnumDisable = 0x0;
  2142. GetD3DRegValue(REG_DWORD, "TextureEnumDisable", &dwEnumDisable, sizeof(DWORD));
  2143. D3D_INFO(3, "TextureEnumDisable: %08x",dwEnumDisable);
  2144. #endif
  2145. DDPIXELFORMAT* pDX5TexEnumIncList = NULL;
  2146. DWORD cDX5TexEnumIncList = 0;
  2147. // load DX5 inclusion list from registry
  2148. LoadTexEnumInclList( RESPATH_D3D "\\DX5TextureEnumInclusionList",
  2149. pDX5TexEnumIncList, cDX5TexEnumIncList );
  2150. DDPIXELFORMAT* pDX6TexEnumIncList = NULL;
  2151. DWORD cDX6TexEnumIncList = 0;
  2152. // load DX6 list only for DX6 interface or apphack
  2153. if ((lpDevI->dwVersion == 3) || (dwEnumInclAppHack >= 3))
  2154. {
  2155. LoadTexEnumInclList( RESPATH_D3D "\\DX6TextureEnumInclusionList",
  2156. pDX6TexEnumIncList, cDX6TexEnumIncList );
  2157. }
  2158. userRet = D3DENUMRET_OK;
  2159. int cEnumLimit = 0;
  2160. for (i = 0; i < num_descs && userRet == D3DENUMRET_OK; i++)
  2161. {
  2162. D3D_INFO(3,"EnumTextureFormats: %2d %08x %08x %2d %08x %08x %08x %08x",i,
  2163. lpRetDescs[i].ddpfPixelFormat.dwFlags,
  2164. lpRetDescs[i].ddpfPixelFormat.dwFourCC,
  2165. lpRetDescs[i].ddpfPixelFormat.dwRGBBitCount,
  2166. lpRetDescs[i].ddpfPixelFormat.dwRBitMask,
  2167. lpRetDescs[i].ddpfPixelFormat.dwGBitMask,
  2168. lpRetDescs[i].ddpfPixelFormat.dwBBitMask,
  2169. lpRetDescs[i].ddpfPixelFormat.dwRGBAlphaBitMask);
  2170. #if DBG
  2171. if ( (i < 32) && (dwEnumDisable & (1<<i)) )
  2172. {
  2173. D3D_INFO(3, "EnumTextureFormats: filtering texture %d",i);
  2174. continue;
  2175. }
  2176. #endif
  2177. // Filtering out texture formats which are not on inclusion list -
  2178. if ( (dwEnumInclAppHack != 1) && // inclusion list not disabled by apphack
  2179. !(lpRetDescs[i].ddpfPixelFormat.dwFlags == DDPF_FOURCC) ) // not FourCC
  2180. {
  2181. BOOL bMatched = FALSE;
  2182. // match against DX5 base (static) inclusion list
  2183. for (DWORD j=0; j<g_cDX5TexEnumIncListStatic; j++)
  2184. {
  2185. if (MatchDDPIXELFORMAT( &(g_DX5TexEnumIncListStatic[j]), &(lpRetDescs[i].ddpfPixelFormat)))
  2186. {
  2187. bMatched = TRUE; break;
  2188. }
  2189. }
  2190. // match against DX5 extended (regkey) inclusion list
  2191. if (!bMatched && cDX5TexEnumIncList)
  2192. {
  2193. for (DWORD j=0; j<cDX5TexEnumIncList; j++)
  2194. {
  2195. if (MatchDDPIXELFORMAT( &(pDX5TexEnumIncList[j]), &(lpRetDescs[i].ddpfPixelFormat)))
  2196. {
  2197. bMatched = TRUE; break;
  2198. }
  2199. }
  2200. }
  2201. // match against DX6 regkey list for:
  2202. // (DX6 interface AND apphack not forcing DX5 inclusion list only) OR
  2203. // (apphack forcing DX6 inclusion list)
  2204. if ( ((lpDevI->dwVersion == 3) && (dwEnumInclAppHack != 2)) ||
  2205. (dwEnumInclAppHack == 3) )
  2206. {
  2207. for (DWORD j=0; j<cDX6TexEnumIncList; j++)
  2208. {
  2209. if (MatchDDPIXELFORMAT( &(pDX6TexEnumIncList[j]), &(lpRetDescs[i].ddpfPixelFormat)))
  2210. {
  2211. bMatched = TRUE; break;
  2212. }
  2213. }
  2214. }
  2215. if (!bMatched) {
  2216. D3D_INFO(3, "EnumTextureFormats: filtering non-included texture %d",i);
  2217. continue;
  2218. }
  2219. }
  2220. // exclude DXT1..5 for <DX6 interfaces
  2221. if ( (lpDevI->dwVersion < 3) && (lpRetDescs[i].ddpfPixelFormat.dwFlags == DDPF_FOURCC) )
  2222. {
  2223. if ( (lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1')) ||
  2224. (lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '2')) ||
  2225. (lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3')) ||
  2226. (lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '4')) ||
  2227. (lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5')) )
  2228. {
  2229. D3D_INFO(3, "EnumTextureFormats: filtering DXT1..5 format for DX3/5 interfaces");
  2230. continue;
  2231. }
  2232. }
  2233. // exclude all FourCC code formats for <DX6 interfaces on DX7 drivers
  2234. if ( (lpDevI->dwVersion < 3) && IS_DX7HAL_DEVICE(lpDevI) &&
  2235. (lpRetDescs[i].ddpfPixelFormat.dwFlags == DDPF_FOURCC) )
  2236. {
  2237. D3D_INFO(3, "EnumTextureFormats: filtering all FOURCC formats for DX3/5 interfaces on DX7 HALs");
  2238. continue;
  2239. }
  2240. // do enumeration if not ('limit enabled' && 'limit exceeded')
  2241. if ( !(bEnumLimit && (++cEnumLimit > 10)) )
  2242. {
  2243. if (lpEnumCallbackDX5)
  2244. {
  2245. userRet = (*lpEnumCallbackDX5)(&lpRetDescs[i], lpContext);
  2246. }
  2247. if (lpEnumCallbackDX6)
  2248. {
  2249. userRet = (*lpEnumCallbackDX6)(&(lpRetDescs[i].ddpfPixelFormat), lpContext);
  2250. }
  2251. }
  2252. else
  2253. {
  2254. D3D_INFO(3, "EnumTextureFormats: enumeration limit exceeded");
  2255. }
  2256. }
  2257. D3DFree(lpRetDescs);
  2258. if (pDX5TexEnumIncList) D3DFree(pDX5TexEnumIncList);
  2259. if (pDX6TexEnumIncList) D3DFree(pDX6TexEnumIncList);
  2260. return (D3D_OK);
  2261. }
  2262. // Device/Device2 version
  2263. HRESULT D3DAPI DIRECT3DDEVICEI::EnumTextureFormats(
  2264. LPD3DENUMTEXTUREFORMATSCALLBACK lpEnumCallback,
  2265. LPVOID lpContext)
  2266. {
  2267. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2268. /*
  2269. * validate parms
  2270. */
  2271. TRY
  2272. {
  2273. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2274. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2275. return DDERR_INVALIDOBJECT;
  2276. }
  2277. if (!VALIDEX_CODE_PTR(lpEnumCallback)) {
  2278. D3D_ERR( "Invalid callback pointer" );
  2279. return DDERR_INVALIDPARAMS;
  2280. }
  2281. }
  2282. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2283. {
  2284. D3D_ERR( "Exception encountered validating parameters" );
  2285. return DDERR_INVALIDPARAMS;
  2286. }
  2287. return DoEnumTextureFormats(this, lpEnumCallback, NULL, lpContext);
  2288. }
  2289. #undef DPF_MODNAME
  2290. #define DPF_MODNAME "Direct3DDevice::EnumTextureFormats"
  2291. // Device3 version
  2292. HRESULT D3DAPI DIRECT3DDEVICEI::EnumTextureFormats(
  2293. LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
  2294. LPVOID lpContext)
  2295. {
  2296. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2297. /*
  2298. * validate parms
  2299. */
  2300. TRY
  2301. {
  2302. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2303. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2304. return DDERR_INVALIDOBJECT;
  2305. }
  2306. if (!VALIDEX_CODE_PTR(lpEnumCallback)) {
  2307. D3D_ERR( "Invalid callback pointer" );
  2308. return DDERR_INVALIDPARAMS;
  2309. }
  2310. }
  2311. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2312. {
  2313. D3D_ERR( "Exception encountered validating parameters" );
  2314. return DDERR_INVALIDPARAMS;
  2315. }
  2316. return DoEnumTextureFormats(this, NULL, lpEnumCallback, lpContext);
  2317. }
  2318. #undef DPF_MODNAME
  2319. #define DPF_MODNAME "Direct3DDevice::SwapTextureHandles"
  2320. HRESULT D3DAPI DIRECT3DDEVICEI::SwapTextureHandles(LPDIRECT3DTEXTURE lpTex1,
  2321. LPDIRECT3DTEXTURE lpTex2)
  2322. {
  2323. LPDIRECT3DTEXTUREI lpTex1I;
  2324. LPDIRECT3DTEXTUREI lpTex2I;
  2325. HRESULT ret;
  2326. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2327. /*
  2328. * validate parms
  2329. */
  2330. TRY
  2331. {
  2332. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2333. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2334. return DDERR_INVALIDOBJECT;
  2335. }
  2336. if (!VALID_DIRECT3DTEXTURE_PTR(lpTex1)) {
  2337. D3D_ERR( "Invalid Direct3DTexture pointer" );
  2338. return DDERR_INVALIDOBJECT;
  2339. }
  2340. if (!VALID_DIRECT3DTEXTURE_PTR(lpTex2)) {
  2341. D3D_ERR( "Invalid Direct3DTexture pointer" );
  2342. return DDERR_INVALIDOBJECT;
  2343. }
  2344. lpTex1I = static_cast<LPDIRECT3DTEXTUREI>(lpTex1);
  2345. lpTex2I = static_cast<LPDIRECT3DTEXTUREI>(lpTex2);
  2346. }
  2347. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2348. {
  2349. D3D_ERR( "Exception encountered validating parameters" );
  2350. return DDERR_INVALIDPARAMS;
  2351. }
  2352. ret = SwapTextureHandles((LPDIRECT3DTEXTURE2)lpTex1I,
  2353. (LPDIRECT3DTEXTURE2)lpTex2I);
  2354. return ret;
  2355. }
  2356. HRESULT D3DAPI DIRECT3DDEVICEI::SwapTextureHandles(LPDIRECT3DTEXTURE2 lpTex1,
  2357. LPDIRECT3DTEXTURE2 lpTex2)
  2358. {
  2359. LPDIRECT3DTEXTUREI lpTex1I;
  2360. LPDIRECT3DTEXTUREI lpTex2I;
  2361. HRESULT servRet;
  2362. D3DTEXTUREHANDLE hTex;
  2363. LPD3DI_TEXTUREBLOCK lptBlock1,lptBlock2;
  2364. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2365. /*
  2366. * validate parms
  2367. */
  2368. TRY
  2369. {
  2370. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2371. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2372. return DDERR_INVALIDOBJECT;
  2373. }
  2374. if (!VALID_DIRECT3DTEXTURE2_PTR(lpTex1)) {
  2375. D3D_ERR( "Invalid Direct3DTexture pointer" );
  2376. return DDERR_INVALIDOBJECT;
  2377. }
  2378. if (!VALID_DIRECT3DTEXTURE2_PTR(lpTex2)) {
  2379. D3D_ERR( "Invalid Direct3DTexture pointer" );
  2380. return DDERR_INVALIDOBJECT;
  2381. }
  2382. lpTex1I = static_cast<LPDIRECT3DTEXTUREI>(lpTex1);
  2383. lpTex2I = static_cast<LPDIRECT3DTEXTUREI>(lpTex2);
  2384. }
  2385. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2386. {
  2387. D3D_ERR( "Exception encountered validating parameters" );
  2388. return DDERR_INVALIDPARAMS;
  2389. }
  2390. if (lpTex1I->lpDDSSys || lpTex2I->lpDDSSys)
  2391. {
  2392. D3D_ERR("Can't Swap Managed textures. Returning DDERR_INVALIDPARAMS");
  2393. return DDERR_INVALIDPARAMS;
  2394. }
  2395. if (!(lptBlock1=D3DI_FindTextureBlock(lpTex1I,this)))
  2396. {
  2397. D3D_ERR("lpTex1 is an invalid texture handle.");
  2398. return DDERR_INVALIDPARAMS;
  2399. }
  2400. if (!(lptBlock2=D3DI_FindTextureBlock(lpTex2I,this)))
  2401. {
  2402. D3D_ERR("lpTex2 is an invalid texture handle.");
  2403. return DDERR_INVALIDPARAMS;
  2404. }
  2405. if (D3D_OK != (servRet=FlushStates()))
  2406. {
  2407. D3D_ERR("Error trying to flush batched commands during TextureSwap");
  2408. return servRet;
  2409. }
  2410. if (IS_DX7HAL_DEVICE(this))
  2411. {
  2412. LPDDRAWI_DDRAWSURFACE_LCL surf1 = ((LPDDRAWI_DDRAWSURFACE_INT)lpTex1I->lpDDS)->lpLcl;
  2413. LPDDRAWI_DDRAWSURFACE_LCL surf2 = ((LPDDRAWI_DDRAWSURFACE_INT)lpTex2I->lpDDS)->lpLcl;
  2414. LPDDRAWI_DIRECTDRAW_LCL pDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)lpDirect3DI->lpDD)->lpLcl;
  2415. DDASSERT(pDDLcl != NULL);
  2416. // Update DDraw handle in driver GBL object.
  2417. pDDLcl->lpGbl->hDD = pDDLcl->hDD;
  2418. // Swap the handles stored in the surface locals
  2419. surf1->lpSurfMore->dwSurfaceHandle = lptBlock2->hTex;
  2420. surf2->lpSurfMore->dwSurfaceHandle = lptBlock1->hTex;
  2421. // Swap the surface pointers stored in the handle table stored in
  2422. // ddraw local
  2423. SURFACEHANDLELIST(pDDLcl).dwList[lptBlock1->hTex].lpSurface = surf2;
  2424. SURFACEHANDLELIST(pDDLcl).dwList[lptBlock2->hTex].lpSurface = surf1;
  2425. // call the driver to switch the textures mapped to the handles in
  2426. // the driver
  2427. DDASSERT(NULL != pDDLcl->lpGbl->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx);
  2428. DDHAL_CREATESURFACEEXDATA csdex;
  2429. DWORD rc;
  2430. csdex.ddRVal = DDERR_GENERIC;
  2431. csdex.dwFlags = 0;
  2432. csdex.lpDDLcl = pDDLcl;
  2433. csdex.lpDDSLcl = surf1;
  2434. rc = pDDLcl->lpGbl->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx(&csdex);
  2435. if( DDHAL_DRIVER_HANDLED == rc && DD_OK != csdex.ddRVal)
  2436. {
  2437. // Driver call failed
  2438. D3D_ERR("DdSwapTextureHandles failed!");
  2439. return D3DERR_TEXTURE_SWAP_FAILED;
  2440. }
  2441. csdex.lpDDSLcl = surf2;
  2442. rc = pDDLcl->lpGbl->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx(&csdex);
  2443. if( DDHAL_DRIVER_HANDLED == rc && DD_OK != csdex.ddRVal)
  2444. {
  2445. // Driver call failed
  2446. D3D_ERR("DdSwapTextureHandles failed!");
  2447. return D3DERR_TEXTURE_SWAP_FAILED;
  2448. }
  2449. }
  2450. else
  2451. {
  2452. servRet=D3DHAL_TextureSwap(this,lptBlock1->hTex,lptBlock2->hTex);
  2453. if (D3D_OK != servRet)
  2454. {
  2455. D3D_ERR("SwapTextureHandles HAL call failed");
  2456. return D3DERR_TEXTURE_SWAP_FAILED;
  2457. }
  2458. }
  2459. hTex=lptBlock1->hTex;
  2460. lptBlock1->hTex=lptBlock2->hTex;
  2461. lptBlock2->hTex=hTex;
  2462. return (D3D_OK);
  2463. }
  2464. #undef DPF_MODNAME
  2465. #define DPF_MODNAME "Direct3DDevice::CreateMatrix"
  2466. HRESULT D3DAPI DIRECT3DDEVICEI::CreateMatrix(LPD3DMATRIXHANDLE lphMatrix)
  2467. {
  2468. HRESULT servRet;
  2469. D3DMATRIXHANDLE hMat;
  2470. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2471. /*
  2472. * validate parms
  2473. */
  2474. TRY
  2475. {
  2476. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2477. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2478. return DDERR_INVALIDOBJECT;
  2479. }
  2480. if (!VALID_D3DMATRIXHANDLE_PTR(lphMatrix)) {
  2481. D3D_ERR( "Invalid D3DMATRIXHANDLE pointer" );
  2482. return DDERR_INVALIDPARAMS;
  2483. }
  2484. }
  2485. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2486. {
  2487. D3D_ERR( "Exception encountered validating parameters" );
  2488. return DDERR_INVALIDPARAMS;
  2489. }
  2490. *lphMatrix = 0;
  2491. servRet = D3DHAL_MatrixCreate(this, &hMat);
  2492. if (servRet != D3D_OK)
  2493. {
  2494. D3D_ERR("Could not create matrix.");
  2495. return (DDERR_OUTOFMEMORY);
  2496. }
  2497. D3D_INFO(4, "CreateMatrix, Matrix created. handle = %d", hMat);
  2498. *lphMatrix = hMat;
  2499. return (D3D_OK);
  2500. }
  2501. #undef DPF_MODNAME
  2502. #define DPF_MODNAME "Direct3DDevice::SetMatrix"
  2503. HRESULT D3DAPI DIRECT3DDEVICEI::SetMatrix(D3DMATRIXHANDLE hMatrix,
  2504. const LPD3DMATRIX lpdmMatrix)
  2505. {
  2506. HRESULT servRet;
  2507. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2508. /*
  2509. * validate parms
  2510. */
  2511. TRY
  2512. {
  2513. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2514. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2515. return DDERR_INVALIDOBJECT;
  2516. }
  2517. if (!VALID_D3DMATRIX_PTR(lpdmMatrix)) {
  2518. D3D_ERR( "Invalid D3DMATRIX pointer" );
  2519. return DDERR_INVALIDPARAMS;
  2520. }
  2521. }
  2522. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2523. {
  2524. D3D_ERR( "Exception encountered validating parameters" );
  2525. return DDERR_INVALIDPARAMS;
  2526. }
  2527. if (!hMatrix) {
  2528. D3D_ERR("NULL hMatrix passed");
  2529. return (DDERR_INVALIDPARAMS);
  2530. }
  2531. servRet = D3DHAL_MatrixSetData(this, hMatrix, lpdmMatrix);
  2532. if (servRet != D3D_OK)
  2533. {
  2534. D3D_ERR("Could not set matrix");
  2535. return (DDERR_INVALIDPARAMS);
  2536. }
  2537. return (D3D_OK);
  2538. }
  2539. #undef DPF_MODNAME
  2540. #define DPF_MODNAME "Direct3DDevice::GetMatrix"
  2541. HRESULT D3DAPI DIRECT3DDEVICEI::GetMatrix(D3DMATRIXHANDLE hMatrix,
  2542. LPD3DMATRIX lpdmMatrix)
  2543. {
  2544. HRESULT servRet;
  2545. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2546. /*
  2547. * validate parms
  2548. */
  2549. TRY
  2550. {
  2551. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2552. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2553. return DDERR_INVALIDOBJECT;
  2554. }
  2555. if (!VALID_D3DMATRIX_PTR(lpdmMatrix)) {
  2556. D3D_ERR( "Invalid D3DMATRIX pointer" );
  2557. return DDERR_INVALIDPARAMS;
  2558. }
  2559. }
  2560. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2561. {
  2562. D3D_ERR( "Exception encountered validating parameters" );
  2563. return DDERR_INVALIDPARAMS;
  2564. }
  2565. if (!hMatrix)
  2566. {
  2567. D3D_ERR("NULL hMatrix passed.");
  2568. return (DDERR_INVALIDPARAMS);
  2569. }
  2570. memset(lpdmMatrix, 0, sizeof(D3DMATRIX));
  2571. servRet = D3DHAL_MatrixGetData(this, hMatrix, lpdmMatrix);
  2572. if (servRet != D3D_OK)
  2573. {
  2574. D3D_ERR("Could not get matrix");
  2575. return (DDERR_INVALIDPARAMS);
  2576. }
  2577. return (D3D_OK);
  2578. }
  2579. #undef DPF_MODNAME
  2580. #define DPF_MODNAME "Direct3DDevice::DeleteMatrix"
  2581. HRESULT D3DAPI DIRECT3DDEVICEI::DeleteMatrix(D3DMATRIXHANDLE hMatrix)
  2582. {
  2583. HRESULT servRet;
  2584. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2585. /*
  2586. * validate parms
  2587. */
  2588. TRY
  2589. {
  2590. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2591. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2592. return DDERR_INVALIDOBJECT;
  2593. }
  2594. }
  2595. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2596. {
  2597. D3D_ERR( "Exception encountered validating parameters" );
  2598. return DDERR_INVALIDPARAMS;
  2599. }
  2600. if (!hMatrix) {
  2601. D3D_ERR("invalid D3DMATRIXHANDLE");
  2602. return DDERR_INVALIDPARAMS;
  2603. }
  2604. servRet = D3DHAL_MatrixDestroy(this, hMatrix);
  2605. if (servRet != D3D_OK)
  2606. {
  2607. D3D_ERR("Could not delete matrix");
  2608. return (DDERR_INVALIDPARAMS);
  2609. }
  2610. return (D3D_OK);
  2611. }
  2612. #undef DPF_MODNAME
  2613. #define DPF_MODNAME "Direct3DDevice::BeginScene"
  2614. HRESULT D3DAPI DIRECT3DDEVICEI::BeginScene()
  2615. {
  2616. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2617. /*
  2618. * validate parms
  2619. */
  2620. TRY
  2621. {
  2622. if (!VALID_DIRECT3DDEVICE_PTR(this)) {
  2623. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2624. return DDERR_INVALIDOBJECT;
  2625. }
  2626. }
  2627. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2628. {
  2629. D3D_ERR( "Exception encountered validating parameters" );
  2630. return DDERR_INVALIDPARAMS;
  2631. }
  2632. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)
  2633. {
  2634. D3D_ERR("BeginScene, already in scene.");
  2635. return (D3DERR_SCENE_IN_SCENE);
  2636. }
  2637. // Check if we lost surfaces or rtarget / zbuffer was locked
  2638. HRESULT servRet = this->CheckSurfaces();
  2639. if (servRet != D3D_OK)
  2640. {
  2641. // If we lost surfaces
  2642. if (servRet == DDERR_SURFACELOST)
  2643. {
  2644. // Even if the app restores the rendertargets and z buffer, it
  2645. // doesn't know anything about vidmem execute buffers or
  2646. // managed texture surfaces in vidmem. So, we need to do
  2647. // this on our own. We first check if it is safe to restore
  2648. // surfaces. If not, we fail in the usual way. Else, we
  2649. // do the restore. Note that we will fail *only* if the
  2650. // app calls BeginScene at the wrong time.
  2651. servRet = this->lpDirect3DI->lpDD4->TestCooperativeLevel();
  2652. if (servRet == DD_OK)
  2653. {
  2654. // Everything must be evicted otherwise Restore might not work
  2655. // as there might be new surface allocated, in fact, we should
  2656. // post a flag in Device so that Texture manage stop calling
  2657. // CreateSurface() if this flag is indicating TestCooperativeLevel()
  2658. // failed, however, even we added those, the EvictTextures below
  2659. // is still needed but not this critical--kanqiu
  2660. this->lpDirect3DI->lpTextureManager->EvictTextures();
  2661. servRet = this->lpDirect3DI->lpDD4->RestoreAllSurfaces();
  2662. if (servRet != DD_OK)
  2663. return D3DERR_SCENE_BEGIN_FAILED;
  2664. }
  2665. else
  2666. return DDERR_SURFACELOST;
  2667. }
  2668. else
  2669. {
  2670. // Render target and / or the z buffer was locked
  2671. return servRet;
  2672. }
  2673. }
  2674. servRet = D3DHAL_SceneCapture(this, TRUE);
  2675. if (servRet != D3D_OK && servRet != DDERR_NOTFOUND)
  2676. {
  2677. D3D_ERR("Could not BeginScene.");
  2678. return D3DERR_SCENE_BEGIN_FAILED;
  2679. }
  2680. this->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_INSCENE;
  2681. if (lpD3DHALGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR)
  2682. {
  2683. lpDirect3DI->lpTextureManager->TimeStamp();
  2684. }
  2685. return (D3D_OK);
  2686. }
  2687. #undef DPF_MODNAME
  2688. #define DPF_MODNAME "Direct3DDevice::EndScene"
  2689. HRESULT D3DAPI DIRECT3DDEVICEI::EndScene()
  2690. {
  2691. HRESULT servRet;
  2692. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2693. /*
  2694. * validate parms
  2695. */
  2696. TRY
  2697. {
  2698. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2699. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2700. return DDERR_INVALIDOBJECT;
  2701. }
  2702. }
  2703. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2704. {
  2705. D3D_ERR( "Exception encountered validating parameters" );
  2706. return DDERR_INVALIDPARAMS;
  2707. }
  2708. if (!(this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)) {
  2709. D3D_ERR("EndScene, not in scene.");
  2710. return (D3DERR_SCENE_NOT_IN_SCENE);
  2711. }
  2712. this->dwHintFlags &= ~D3DDEVBOOL_HINTFLAGS_INSCENE;
  2713. if (IS_DX7HAL_DEVICE(this))
  2714. {
  2715. // must set the token before FlushStates()
  2716. SetRenderStateI((D3DRENDERSTATETYPE)D3DRENDERSTATE_SCENECAPTURE, FALSE);
  2717. }
  2718. servRet = FlushStates(); //time to flush DrawPrimitives
  2719. if (servRet != D3D_OK)
  2720. {
  2721. D3D_ERR("Could not Flush commands in EndScene!");
  2722. return (D3DERR_SCENE_END_FAILED);
  2723. }
  2724. if (!IS_DX7HAL_DEVICE(this))
  2725. {
  2726. servRet = D3DHAL_SceneCapture(this, FALSE);
  2727. if (servRet != D3D_OK && servRet != DDERR_NOTFOUND)
  2728. {
  2729. DPF(0, "(ERROR) Direct3DDevice::EndScene: Could not EndScene. Returning %d", servRet);
  2730. return (D3DERR_SCENE_END_FAILED);
  2731. }
  2732. }
  2733. // Did we lose any surfaces during this scene ?
  2734. if (this->dwFEFlags & D3DFE_LOSTSURFACES)
  2735. {
  2736. D3D_INFO(3, "reporting DDERR_SURFACELOST in EndScene");
  2737. this->dwFEFlags &= ~D3DFE_LOSTSURFACES;
  2738. return DDERR_SURFACELOST;
  2739. }
  2740. return (D3D_OK);
  2741. }
  2742. #undef DPF_MODNAME
  2743. #define DPF_MODNAME "Direct3DDevice::GetDirect3D"
  2744. HRESULT D3DAPI DIRECT3DDEVICEI::GetDirect3D(LPDIRECT3D* lplpD3D)
  2745. {
  2746. LPDIRECT3D3 lpD3D3;
  2747. HRESULT ret;
  2748. ret = GetDirect3D(&lpD3D3);
  2749. if (ret == D3D_OK)
  2750. {
  2751. // *lplpD3D = dynamic_cast<LPDIRECT3D>(lpD3D3); // This is possible using RTTI
  2752. *lplpD3D = static_cast<LPDIRECT3D>(static_cast<LPDIRECT3DI>(lpD3D3)); // This is safe even using static_cast
  2753. }
  2754. return ret;
  2755. }
  2756. HRESULT D3DAPI DIRECT3DDEVICEI::GetDirect3D(LPDIRECT3D2* lplpD3D)
  2757. {
  2758. LPDIRECT3D3 lpD3D3;
  2759. HRESULT ret;
  2760. ret = GetDirect3D(&lpD3D3);
  2761. if (ret == D3D_OK)
  2762. {
  2763. // *lplpD3D = dynamic_cast<LPDIRECT3D>(lpD3D3); // This is possible using RTTI
  2764. *lplpD3D = static_cast<LPDIRECT3D2>(static_cast<LPDIRECT3DI>(lpD3D3)); // This is safe even using static_cast
  2765. }
  2766. return ret;
  2767. }
  2768. HRESULT D3DAPI DIRECT3DDEVICEI::GetDirect3D(LPDIRECT3D3* lplpD3D)
  2769. {
  2770. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2771. /*
  2772. * validate parms
  2773. */
  2774. TRY
  2775. {
  2776. if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
  2777. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2778. return DDERR_INVALIDOBJECT;
  2779. }
  2780. if (!VALID_OUTPTR(lplpD3D)) {
  2781. D3D_ERR( "Invalid Direct3D pointer pointer" );
  2782. return DDERR_INVALIDPARAMS;
  2783. }
  2784. }
  2785. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  2786. {
  2787. D3D_ERR( "Exception encountered validating parameters" );
  2788. return DDERR_INVALIDPARAMS;
  2789. }
  2790. *lplpD3D = (LPDIRECT3D3) this->lpDirect3DI;
  2791. (*lplpD3D)->AddRef();
  2792. return (D3D_OK);
  2793. }
  2794. void
  2795. D3DDeviceDescConvert(LPD3DDEVICEDESC lpOut,
  2796. LPD3DDEVICEDESC_V1 lpV1,
  2797. LPD3DHAL_D3DEXTENDEDCAPS lpExt)
  2798. {
  2799. if(lpV1!=NULL)
  2800. memcpy(lpOut, lpV1, D3DDEVICEDESCSIZE_V1);
  2801. if (lpExt)
  2802. {
  2803. // DX5
  2804. lpOut->dwSize = D3DDEVICEDESCSIZE;
  2805. lpOut->dwMinTextureWidth = lpExt->dwMinTextureWidth;
  2806. lpOut->dwMaxTextureWidth = lpExt->dwMaxTextureWidth;
  2807. lpOut->dwMinTextureHeight = lpExt->dwMinTextureHeight;
  2808. lpOut->dwMaxTextureHeight = lpExt->dwMaxTextureHeight;
  2809. lpOut->dwMinStippleWidth = lpExt->dwMinStippleWidth;
  2810. lpOut->dwMaxStippleWidth = lpExt->dwMaxStippleWidth;
  2811. lpOut->dwMinStippleHeight = lpExt->dwMinStippleHeight;
  2812. lpOut->dwMaxStippleHeight = lpExt->dwMaxStippleHeight;
  2813. // DX6
  2814. lpOut->dwMaxTextureRepeat = lpExt->dwMaxTextureRepeat;
  2815. lpOut->dwMaxTextureAspectRatio = lpExt->dwMaxTextureAspectRatio;
  2816. lpOut->dwMaxAnisotropy = lpExt->dwMaxAnisotropy;
  2817. lpOut->dvGuardBandLeft = lpExt->dvGuardBandLeft;
  2818. lpOut->dvGuardBandTop = lpExt->dvGuardBandTop;
  2819. lpOut->dvGuardBandRight = lpExt->dvGuardBandRight;
  2820. lpOut->dvGuardBandBottom = lpExt->dvGuardBandBottom;
  2821. lpOut->dvExtentsAdjust = lpExt->dvExtentsAdjust;
  2822. lpOut->dwStencilCaps = lpExt->dwStencilCaps;
  2823. lpOut->dwFVFCaps = lpExt->dwFVFCaps;
  2824. lpOut->dwTextureOpCaps = lpExt->dwTextureOpCaps;
  2825. lpOut->wMaxTextureBlendStages = lpExt->wMaxTextureBlendStages;
  2826. lpOut->wMaxSimultaneousTextures = lpExt->wMaxSimultaneousTextures;
  2827. }
  2828. }
  2829. //---------------------------------------------------------------------
  2830. #undef DPF_MODNAME
  2831. #define DPF_MODNAME "DIRECT3DDEVICEI::CheckSurfaces"
  2832. HRESULT DIRECT3DDEVICEI::CheckSurfaces()
  2833. {
  2834. if(this->lpDirect3DI->lpTextureManager->CheckIfLost())
  2835. {
  2836. D3D_ERR("Managed Textures lost");
  2837. return DDERR_SURFACELOST;
  2838. }
  2839. if ( ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSTarget)->lpLcl->lpGbl->dwUsageCount ||
  2840. (this->lpDDSZBuffer && ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSZBuffer)->lpLcl->lpGbl->dwUsageCount) )
  2841. {
  2842. D3D_ERR("Render target or Z buffer locked");
  2843. return DDERR_SURFACEBUSY;
  2844. }
  2845. if ( ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSTarget)->lpLcl->dwFlags & DDRAWISURF_INVALID )\
  2846. {
  2847. D3D_ERR("Render target buffer lost");
  2848. return DDERR_SURFACELOST;
  2849. }
  2850. if ( this->lpDDSZBuffer && ( ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSZBuffer)->lpLcl->dwFlags & DDRAWISURF_INVALID ) )
  2851. {
  2852. D3D_ERR("Z buffer lost");
  2853. return DDERR_SURFACELOST;
  2854. }
  2855. return D3D_OK;
  2856. }