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.

3333 lines
124 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. *@@END_MSINTERNAL
  12. *
  13. ***************************************************************************/
  14. #include "pch.cpp"
  15. #pragma hdrstop
  16. /*
  17. * Create an api for the Direct3DDevice object
  18. */
  19. extern "C" {
  20. #define this _this
  21. #include "ddrawpr.h"
  22. #undef this
  23. }
  24. #include "commdrv.hpp"
  25. #include "drawprim.hpp"
  26. //#ifdef DEBUG_PIPELINE
  27. #include "testprov.h"
  28. //#endif //DEBUG_PIPELINE
  29. #ifdef PROFILE4
  30. #include <icecap.h>
  31. #endif
  32. #ifdef PROFILE
  33. #include <icapexp.h>
  34. #endif
  35. // Remove DDraw's type unsafe definition and replace with our C++ friendly def
  36. #ifdef VALIDEX_CODE_PTR
  37. #undef VALIDEX_CODE_PTR
  38. #endif
  39. #define VALIDEX_CODE_PTR( ptr ) \
  40. (!IsBadCodePtr( (FARPROC) ptr ) )
  41. #undef DPF_MODNAME
  42. #define DPF_MODNAME "Direct3DDevice"
  43. // DX3, DX5, DX6, DX7, TL
  44. #define MAX_DRIVERMODELS_SUPPORTED 5
  45. #define D3DDRVMODEL_DX3 0x00000001
  46. #define D3DDRVMODEL_DX5 0x00000002
  47. #define D3DDRVMODEL_DX6 0x00000003
  48. #define D3DDRVMODEL_DX7 0x00000004
  49. #define D3DDRVMODEL_TL 0x00000005
  50. extern BOOL isMMXprocessor(void);
  51. extern BOOL IsValidD3DDeviceGuid(REFCLSID riid);
  52. extern void setIdentity(D3DMATRIXI * m);
  53. extern DWORD dwCPUFeatures;
  54. #ifdef _X86_
  55. extern HRESULT D3DAPI katmai_FEContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs);
  56. extern HRESULT D3DAPI wlmt_FEContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs);
  57. extern LPD3DFE_CONTEXTCREATE px3DContextCreate;
  58. #endif
  59. BOOL D3DI_isHALValid(LPD3DHAL_CALLBACKS halTable)
  60. {
  61. if(halTable==NULL) {
  62. D3D_WARN(0, "HAL callbacks is NULL. HAL will not be enumerated.");
  63. return FALSE;
  64. }
  65. if (halTable->dwSize != D3DHAL_SIZE_V1) {
  66. D3D_WARN(0, "HAL callbacks invalid - size = %d, wanted %d. HAL will not be enumerated.",
  67. halTable->dwSize, D3DHAL_SIZE_V1);
  68. return FALSE;
  69. }
  70. if (halTable->dwReserved ||
  71. halTable->dwReserved0 ||
  72. halTable->dwReserved1 ||
  73. halTable->dwReserved2 ||
  74. halTable->dwReserved3 ||
  75. halTable->dwReserved4 ||
  76. halTable->dwReserved5 ||
  77. halTable->dwReserved6 ||
  78. halTable->dwReserved7 ||
  79. halTable->dwReserved8 ||
  80. halTable->dwReserved9 ||
  81. halTable->lpReserved10 ||
  82. halTable->lpReserved11 ||
  83. halTable->lpReserved12 ||
  84. halTable->lpReserved13 ||
  85. halTable->lpReserved14 ||
  86. halTable->lpReserved15 ||
  87. halTable->lpReserved16 ||
  88. halTable->lpReserved17 ||
  89. halTable->lpReserved18 ||
  90. halTable->lpReserved19 ||
  91. halTable->lpReserved20 ||
  92. halTable->lpReserved21) {
  93. D3D_WARN(0, "HAL callbacks invalid - has non-zero reserved fields, HAL will not be enumerated.");
  94. return FALSE;
  95. }
  96. return TRUE;
  97. }
  98. // This is a list of all rstates that UpdateInternalState does some
  99. // work other than updating this->rstates[] array. This is used to
  100. // do a quick bitwise check to see if this rstate is trivial or not.
  101. const D3DRENDERSTATETYPE rsList[] = {
  102. D3DRENDERSTATE_FOGENABLE,
  103. D3DRENDERSTATE_SPECULARENABLE,
  104. D3DRENDERSTATE_RANGEFOGENABLE,
  105. D3DRENDERSTATE_FOGDENSITY,
  106. D3DRENDERSTATE_FOGSTART,
  107. D3DRENDERSTATE_FOGEND,
  108. D3DRENDERSTATE_WRAP0,
  109. D3DRENDERSTATE_WRAP1,
  110. D3DRENDERSTATE_WRAP2,
  111. D3DRENDERSTATE_WRAP3,
  112. D3DRENDERSTATE_WRAP4,
  113. D3DRENDERSTATE_WRAP5,
  114. D3DRENDERSTATE_WRAP6,
  115. D3DRENDERSTATE_WRAP7,
  116. D3DRENDERSTATE_CLIPPING,
  117. D3DRENDERSTATE_LIGHTING,
  118. D3DRENDERSTATE_EXTENTS,
  119. D3DRENDERSTATE_AMBIENT,
  120. D3DRENDERSTATE_FOGVERTEXMODE,
  121. D3DRENDERSTATE_COLORVERTEX,
  122. D3DRENDERSTATE_LOCALVIEWER,
  123. D3DRENDERSTATE_NORMALIZENORMALS,
  124. D3DRENDERSTATE_COLORKEYBLENDENABLE,
  125. D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,
  126. D3DRENDERSTATE_SPECULARMATERIALSOURCE,
  127. D3DRENDERSTATE_AMBIENTMATERIALSOURCE,
  128. D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,
  129. D3DRENDERSTATE_VERTEXBLEND,
  130. D3DRENDERSTATE_CLIPPLANEENABLE,
  131. D3DRENDERSTATE_SHADEMODE,
  132. // Retired renderstates to be filtered with DPF error and INVALID return
  133. // NOTE: everything listed here is also assumed to appear in rsListRetired
  134. D3DRENDERSTATE_TEXTUREHANDLE,
  135. D3DRENDERSTATE_TEXTUREADDRESS,
  136. D3DRENDERSTATE_WRAPU,
  137. D3DRENDERSTATE_WRAPV,
  138. D3DRENDERSTATE_MONOENABLE,
  139. D3DRENDERSTATE_ROP2,
  140. D3DRENDERSTATE_PLANEMASK,
  141. D3DRENDERSTATE_TEXTUREMAG,
  142. D3DRENDERSTATE_TEXTUREMIN,
  143. D3DRENDERSTATE_TEXTUREMAPBLEND,
  144. D3DRENDERSTATE_SUBPIXEL,
  145. D3DRENDERSTATE_SUBPIXELX,
  146. D3DRENDERSTATE_STIPPLEENABLE,
  147. D3DRENDERSTATE_BORDERCOLOR,
  148. D3DRENDERSTATE_TEXTUREADDRESSU,
  149. D3DRENDERSTATE_TEXTUREADDRESSV,
  150. D3DRENDERSTATE_MIPMAPLODBIAS,
  151. D3DRENDERSTATE_ANISOTROPY,
  152. D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT,
  153. D3DRENDERSTATE_STIPPLEPATTERN00,
  154. D3DRENDERSTATE_STIPPLEPATTERN01,
  155. D3DRENDERSTATE_STIPPLEPATTERN02,
  156. D3DRENDERSTATE_STIPPLEPATTERN03,
  157. D3DRENDERSTATE_STIPPLEPATTERN04,
  158. D3DRENDERSTATE_STIPPLEPATTERN05,
  159. D3DRENDERSTATE_STIPPLEPATTERN06,
  160. D3DRENDERSTATE_STIPPLEPATTERN07,
  161. D3DRENDERSTATE_STIPPLEPATTERN08,
  162. D3DRENDERSTATE_STIPPLEPATTERN09,
  163. D3DRENDERSTATE_STIPPLEPATTERN10,
  164. D3DRENDERSTATE_STIPPLEPATTERN11,
  165. D3DRENDERSTATE_STIPPLEPATTERN12,
  166. D3DRENDERSTATE_STIPPLEPATTERN13,
  167. D3DRENDERSTATE_STIPPLEPATTERN14,
  168. D3DRENDERSTATE_STIPPLEPATTERN15,
  169. D3DRENDERSTATE_STIPPLEPATTERN16,
  170. D3DRENDERSTATE_STIPPLEPATTERN17,
  171. D3DRENDERSTATE_STIPPLEPATTERN18,
  172. D3DRENDERSTATE_STIPPLEPATTERN19,
  173. D3DRENDERSTATE_STIPPLEPATTERN20,
  174. D3DRENDERSTATE_STIPPLEPATTERN21,
  175. D3DRENDERSTATE_STIPPLEPATTERN22,
  176. D3DRENDERSTATE_STIPPLEPATTERN23,
  177. D3DRENDERSTATE_STIPPLEPATTERN24,
  178. D3DRENDERSTATE_STIPPLEPATTERN25,
  179. D3DRENDERSTATE_STIPPLEPATTERN26,
  180. D3DRENDERSTATE_STIPPLEPATTERN27,
  181. D3DRENDERSTATE_STIPPLEPATTERN28,
  182. D3DRENDERSTATE_STIPPLEPATTERN29,
  183. D3DRENDERSTATE_STIPPLEPATTERN30,
  184. D3DRENDERSTATE_STIPPLEPATTERN31,
  185. };
  186. // list of retired renderstates - need to make sure these are
  187. // filtered and never get from app directly to driver
  188. const D3DRENDERSTATETYPE rsListRetired[] = {
  189. D3DRENDERSTATE_TEXTUREHANDLE,
  190. D3DRENDERSTATE_TEXTUREADDRESS,
  191. D3DRENDERSTATE_WRAPU,
  192. D3DRENDERSTATE_WRAPV,
  193. D3DRENDERSTATE_MONOENABLE,
  194. D3DRENDERSTATE_ROP2,
  195. D3DRENDERSTATE_PLANEMASK,
  196. D3DRENDERSTATE_TEXTUREMAG,
  197. D3DRENDERSTATE_TEXTUREMIN,
  198. D3DRENDERSTATE_TEXTUREMAPBLEND,
  199. D3DRENDERSTATE_SUBPIXEL,
  200. D3DRENDERSTATE_SUBPIXELX,
  201. D3DRENDERSTATE_STIPPLEENABLE,
  202. D3DRENDERSTATE_BORDERCOLOR,
  203. D3DRENDERSTATE_TEXTUREADDRESSU,
  204. D3DRENDERSTATE_TEXTUREADDRESSV,
  205. D3DRENDERSTATE_MIPMAPLODBIAS,
  206. D3DRENDERSTATE_ANISOTROPY,
  207. D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT,
  208. D3DRENDERSTATE_STIPPLEPATTERN00,
  209. D3DRENDERSTATE_STIPPLEPATTERN01,
  210. D3DRENDERSTATE_STIPPLEPATTERN02,
  211. D3DRENDERSTATE_STIPPLEPATTERN03,
  212. D3DRENDERSTATE_STIPPLEPATTERN04,
  213. D3DRENDERSTATE_STIPPLEPATTERN05,
  214. D3DRENDERSTATE_STIPPLEPATTERN06,
  215. D3DRENDERSTATE_STIPPLEPATTERN07,
  216. D3DRENDERSTATE_STIPPLEPATTERN08,
  217. D3DRENDERSTATE_STIPPLEPATTERN09,
  218. D3DRENDERSTATE_STIPPLEPATTERN10,
  219. D3DRENDERSTATE_STIPPLEPATTERN11,
  220. D3DRENDERSTATE_STIPPLEPATTERN12,
  221. D3DRENDERSTATE_STIPPLEPATTERN13,
  222. D3DRENDERSTATE_STIPPLEPATTERN14,
  223. D3DRENDERSTATE_STIPPLEPATTERN15,
  224. D3DRENDERSTATE_STIPPLEPATTERN16,
  225. D3DRENDERSTATE_STIPPLEPATTERN17,
  226. D3DRENDERSTATE_STIPPLEPATTERN18,
  227. D3DRENDERSTATE_STIPPLEPATTERN19,
  228. D3DRENDERSTATE_STIPPLEPATTERN20,
  229. D3DRENDERSTATE_STIPPLEPATTERN21,
  230. D3DRENDERSTATE_STIPPLEPATTERN22,
  231. D3DRENDERSTATE_STIPPLEPATTERN23,
  232. D3DRENDERSTATE_STIPPLEPATTERN24,
  233. D3DRENDERSTATE_STIPPLEPATTERN25,
  234. D3DRENDERSTATE_STIPPLEPATTERN26,
  235. D3DRENDERSTATE_STIPPLEPATTERN27,
  236. D3DRENDERSTATE_STIPPLEPATTERN28,
  237. D3DRENDERSTATE_STIPPLEPATTERN29,
  238. D3DRENDERSTATE_STIPPLEPATTERN30,
  239. D3DRENDERSTATE_STIPPLEPATTERN31,
  240. };
  241. //---------------------------------------------------------------------
  242. DIRECT3DDEVICEI::DIRECT3DDEVICEI()
  243. {
  244. m_rsMax = D3DRENDERSTATE_CLIPPING;
  245. m_tssMax = D3DTSS_TEXTURETRANSFORMFLAGS;
  246. }
  247. //---------------------------------------------------------------------
  248. HRESULT DIRECT3DDEVICEI::stateInitialize(BOOL bZEnable)
  249. {
  250. D3DLINEPATTERN defLPat;
  251. HRESULT ret;
  252. float tmpval;
  253. DWORD i;
  254. // Initialize the bit array indicating the rstates needing non-trivial
  255. // work.
  256. for (i=0; i < sizeof(rsList) / sizeof(D3DRENDERSTATETYPE); ++i)
  257. rsVec[rsList[i] >> D3D_RSVEC_SHIFT] |= 1 << (rsList[i] & D3D_RSVEC_MASK);
  258. // Initialize the bit array indicating the retired rstates
  259. for (i=0; i < sizeof(rsListRetired) / sizeof(D3DRENDERSTATETYPE); ++i)
  260. rsVecRetired[rsListRetired[i] >> D3D_RSVEC_SHIFT] |= 1 << (rsListRetired[i] & D3D_RSVEC_MASK);
  261. // Obviate SetRenderState filtering 'redundant' render state settings
  262. // since this is the init step.
  263. memset( this->rstates, 0xff, sizeof(DWORD)*D3D_MAXRENDERSTATES);
  264. this->rstates[D3DRENDERSTATE_PLANEMASK] = 0;
  265. this->rstates[D3DRENDERSTATE_STENCILMASK] = 0;
  266. this->rstates[D3DRENDERSTATE_STENCILWRITEMASK] = 0;
  267. this->rstates[D3DRENDERSTATE_TEXTUREFACTOR] = 0;
  268. SetRenderStateInternal( D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE);
  269. SetRenderStateInternal( D3DRENDERSTATE_SPECULARENABLE, FALSE);
  270. SetRenderStateInternal( D3DRENDERSTATE_ZENABLE, bZEnable);
  271. SetRenderStateInternal( D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID);
  272. SetRenderStateInternal( D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
  273. defLPat.wRepeatFactor = 0;
  274. defLPat.wLinePattern = 0;
  275. SetRenderStateInternal( D3DRENDERSTATE_LINEPATTERN, *((LPDWORD)&defLPat)); /* 10 */
  276. /*
  277. ((LPD3DSTATE)lpPointer)->drstRenderStateType =
  278. (D3DRENDERSTATETYPE)D3DRENDERSTATE_LINEPATTERN;
  279. memcpy(&(((LPD3DSTATE)lpPointer)->dwArg[0]), &defLPat, sizeof(DWORD));
  280. lpPointer = (void *)(((LPD3DSTATE)lpPointer) + 1);*/
  281. SetRenderStateInternal( D3DRENDERSTATE_ZWRITEENABLE, TRUE);
  282. SetRenderStateInternal( D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
  283. SetRenderStateInternal( D3DRENDERSTATE_LASTPIXEL, TRUE);
  284. SetRenderStateInternal( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
  285. SetRenderStateInternal( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO);
  286. SetRenderStateInternal( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW); /* 21 */
  287. SetRenderStateInternal( D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
  288. SetRenderStateInternal( D3DRENDERSTATE_ALPHAREF, 0);
  289. SetRenderStateInternal( D3DRENDERSTATE_ALPHAFUNC, D3DCMP_ALWAYS);
  290. SetRenderStateInternal( D3DRENDERSTATE_DITHERENABLE, FALSE);
  291. SetRenderStateInternal( D3DRENDERSTATE_FOGENABLE, FALSE);
  292. SetRenderStateInternal( D3DRENDERSTATE_ZVISIBLE, FALSE);
  293. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEDALPHA, FALSE);
  294. SetRenderStateInternal( D3DRENDERSTATE_FOGCOLOR, 0);
  295. SetRenderStateInternal( D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
  296. tmpval = 0.0f;
  297. SetRenderStateInternal( D3DRENDERSTATE_FOGSTART, *((DWORD *)&tmpval));
  298. tmpval = 1.0f;
  299. SetRenderStateInternal( D3DRENDERSTATE_FOGEND, *((DWORD *)&tmpval));
  300. tmpval = 1.0f;
  301. SetRenderStateInternal( D3DRENDERSTATE_FOGDENSITY, *((DWORD *)&tmpval));
  302. SetRenderStateInternal( D3DRENDERSTATE_COLORKEYENABLE, FALSE);
  303. SetRenderStateInternal( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
  304. SetRenderStateInternal( D3DRENDERSTATE_ZBIAS, 0);
  305. SetRenderStateInternal( D3DRENDERSTATE_RANGEFOGENABLE, FALSE);
  306. if (deviceType < D3DDEVTYPE_DX7HAL)
  307. {
  308. // send retired renderstate init's to pre-DX7 HALs only
  309. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEENABLE, FALSE);
  310. SetRenderStateInternal( D3DRENDERSTATE_MONOENABLE, FALSE);
  311. SetRenderStateInternal( D3DRENDERSTATE_ROP2, R2_COPYPEN);
  312. SetRenderStateInternal( D3DRENDERSTATE_PLANEMASK, (DWORD)~0);
  313. SetRenderStateInternal( D3DRENDERSTATE_WRAPU, FALSE);
  314. SetRenderStateInternal( D3DRENDERSTATE_WRAPV, FALSE);
  315. SetRenderStateInternal( D3DRENDERSTATE_ANTIALIAS, FALSE);
  316. SetRenderStateInternal( D3DRENDERSTATE_SUBPIXEL, FALSE); /* 30 */
  317. SetRenderStateInternal( D3DRENDERSTATE_SUBPIXELX, FALSE);
  318. SetRenderStateInternal( D3DRENDERSTATE_EDGEANTIALIAS, FALSE);
  319. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN00, 0);
  320. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN01, 0); /* 40 */
  321. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN02, 0);
  322. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN03, 0);
  323. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN04, 0);
  324. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN05, 0);
  325. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN06, 0);
  326. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN07, 0);
  327. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN08, 0);
  328. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN09, 0);
  329. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN10, 0);
  330. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN11, 0); /* 50 */
  331. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN12, 0);
  332. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN13, 0);
  333. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN14, 0);
  334. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN15, 0);
  335. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN16, 0);
  336. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN17, 0);
  337. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN18, 0);
  338. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN19, 0);
  339. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN20, 0);
  340. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN21, 0); /* 60 */
  341. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN22, 0);
  342. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN23, 0);
  343. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN24, 0);
  344. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN25, 0);
  345. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN26, 0);
  346. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN27, 0);
  347. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN28, 0);
  348. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN29, 0);
  349. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN30, 0);
  350. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN31, 0); /* 70 */
  351. }
  352. // init stencil states to something reasonable
  353. // stencil enable is OFF by default since stenciling rasterizers will be
  354. // faster with it disabled, even if stencil states are benign
  355. SetRenderStateInternal( D3DRENDERSTATE_STENCILENABLE, FALSE);
  356. SetRenderStateInternal( D3DRENDERSTATE_STENCILFAIL, D3DSTENCILOP_KEEP);
  357. SetRenderStateInternal( D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_KEEP);
  358. SetRenderStateInternal( D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_KEEP);
  359. SetRenderStateInternal( D3DRENDERSTATE_STENCILFUNC, D3DCMP_ALWAYS);
  360. SetRenderStateInternal( D3DRENDERSTATE_STENCILREF, 0);
  361. SetRenderStateInternal( D3DRENDERSTATE_STENCILMASK, 0xFFFFFFFF);
  362. SetRenderStateInternal( D3DRENDERSTATE_STENCILWRITEMASK,0xFFFFFFFF);
  363. // don't forget about texturefactor (like we did in DX6.0...)
  364. SetRenderStateInternal( D3DRENDERSTATE_TEXTUREFACTOR, 0xFFFFFFFF);
  365. for (i = 0; i < 8; i++)
  366. {
  367. SetRenderStateInternal( (D3DRENDERSTATETYPE)
  368. (D3DRENDERSTATE_WRAPBIAS + i), FALSE );
  369. }
  370. for (i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
  371. {
  372. lpD3DMappedTexI[i] = NULL;
  373. lpD3DMappedBlock[i] = NULL;
  374. }
  375. m_dwStageDirty = 0;
  376. // Obviate SetTextureStageState/Settexture filtering 'redundant' render state
  377. // settings since this is the init step.
  378. memset( this->tsstates, 0xff, sizeof(DWORD)*D3DHAL_TSS_MAXSTAGES*D3DHAL_TSS_STATESPERSTAGE );
  379. for (i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
  380. {
  381. SetTexture(i, NULL);
  382. if(i == 0)
  383. SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_MODULATE);
  384. else
  385. SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
  386. SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  387. SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
  388. if(i == 0)
  389. SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  390. else
  391. SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  392. SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  393. SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  394. SetTextureStageState(i, D3DTSS_BUMPENVMAT00, 0);
  395. SetTextureStageState(i, D3DTSS_BUMPENVMAT01, 0);
  396. SetTextureStageState(i, D3DTSS_BUMPENVMAT10, 0);
  397. SetTextureStageState(i, D3DTSS_BUMPENVMAT11, 0);
  398. SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, 0);
  399. SetTextureStageState(i, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
  400. SetTextureStageState(i, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  401. SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  402. SetTextureStageState(i, D3DTSS_BORDERCOLOR, 0x00000000);
  403. SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTFG_POINT);
  404. SetTextureStageState(i, D3DTSS_MINFILTER, D3DTFN_POINT);
  405. SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTFP_NONE);
  406. SetTextureStageState(i, D3DTSS_MIPMAPLODBIAS, 0);
  407. SetTextureStageState(i, D3DTSS_MAXMIPLEVEL, 0);
  408. SetTextureStageState(i, D3DTSS_MAXANISOTROPY, 1);
  409. SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, 0);
  410. SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, 0);
  411. SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  412. }
  413. #ifdef WIN95
  414. // Force a mapping if old HAL
  415. if(deviceType < D3DDEVTYPE_DP2HAL)
  416. {
  417. SetRenderStateInternal( D3DRENDERSTATE_TEXTUREHANDLE, (DWORD)NULL);
  418. static_cast<CDirect3DDeviceIHW*>(this)->MapTSSToRS();
  419. }
  420. #endif
  421. SetRenderStateInternal(D3DRENDERSTATE_AMBIENT, 0);
  422. SetRenderStateInternal(D3DRENDERSTATE_COLORVERTEX, TRUE);
  423. SetRenderStateInternal(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE);
  424. SetRenderStateInternal(D3DRENDERSTATE_CLIPPING, TRUE);
  425. SetRenderStateInternal(D3DRENDERSTATE_LIGHTING, TRUE);
  426. SetRenderStateInternal(D3DRENDERSTATE_EXTENTS, FALSE);
  427. SetRenderStateInternal(D3DRENDERSTATE_NORMALIZENORMALS, FALSE);
  428. SetRenderStateInternal(D3DRENDERSTATE_LOCALVIEWER, TRUE);
  429. SetRenderStateInternal(D3DRENDERSTATE_COLORKEYBLENDENABLE, FALSE);
  430. SetRenderStateInternal(D3DRENDERSTATE_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
  431. SetRenderStateInternal(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
  432. SetRenderStateInternal(D3DRENDERSTATE_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
  433. SetRenderStateInternal(D3DRENDERSTATE_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
  434. SetRenderStateInternal(D3DRENDERSTATE_VERTEXBLEND, D3DVBLEND_DISABLE);
  435. SetRenderStateInternal(D3DRENDERSTATE_CLIPPLANEENABLE, 0);
  436. // If we have created any textures prior to creating this device, then
  437. // let the driver know their priorities.
  438. if(DDCAPS2_CANMANAGETEXTURE & ((LPDDRAWI_DIRECTDRAW_INT)lpDirect3DI->lpDD)->lpLcl->lpGbl->ddCaps.dwCaps2)
  439. {
  440. LPDIRECT3DTEXTUREI lpTexI = LIST_FIRST(&lpDirect3DI->textures);
  441. while(lpTexI)
  442. {
  443. // If the texture is managed (by the driver)
  444. if(DDSCAPS2_TEXTUREMANAGE & ((LPDDRAWI_DDRAWSURFACE_INT)(lpTexI->lpDDS))->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2)
  445. {
  446. ret = lpTexI->SetPriority(lpTexI->m_dwPriority);
  447. if(ret != D3D_OK)
  448. {
  449. D3D_ERR("SetPriority failed in device initialize.");
  450. return ret;
  451. }
  452. ret = lpTexI->SetLOD(lpTexI->m_dwLOD);
  453. if(ret != D3D_OK)
  454. {
  455. D3D_ERR("SetLOD failed in device initialize.");
  456. return ret;
  457. }
  458. }
  459. lpTexI = LIST_NEXT(lpTexI, m_List);
  460. }
  461. }
  462. return(D3D_OK);
  463. }
  464. DWORD BitDepthToDDBD(int bpp)
  465. {
  466. switch(bpp)
  467. {
  468. case 1:
  469. return DDBD_1;
  470. case 2:
  471. return DDBD_2;
  472. case 4:
  473. return DDBD_4;
  474. case 8:
  475. return DDBD_8;
  476. case 16:
  477. return DDBD_16;
  478. case 24:
  479. return DDBD_24;
  480. case 32:
  481. return DDBD_32;
  482. default:
  483. D3D_ERR("Invalid bit depth");
  484. return 0;
  485. }
  486. }
  487. HRESULT DIRECT3DDEVICEI::checkDeviceSurface(LPDIRECTDRAWSURFACE lpDDS, LPDIRECTDRAWSURFACE lpZbuffer, LPGUID pGuid)
  488. {
  489. D3DDEVICEDESC7 Desc;
  490. DDPIXELFORMAT surfPF;
  491. DDSCAPS surfCaps;
  492. HRESULT ret;
  493. DWORD bpp;
  494. /* Get caps bits - check whether device and surface are:
  495. - video/system memory and depth compatible */
  496. if (FAILED(ret = lpDDS->GetCaps(&surfCaps))) {
  497. D3D_ERR("Failed to get render-target surface caps");
  498. return(ret);
  499. }
  500. memset(&surfPF, 0, sizeof(DDPIXELFORMAT));
  501. surfPF.dwSize = sizeof(DDPIXELFORMAT);
  502. if (FAILED(ret = lpDDS->GetPixelFormat(&surfPF))) {
  503. D3D_ERR("Failed to get render-target surface pixel format");
  504. return(ret);
  505. }
  506. if (IS_HW_DEVICE(this)) {
  507. /* I'm taking this as evidence that its running on hardware - therefore
  508. the surface should be in video memory */
  509. D3D_INFO(3, "Hardware device being used");
  510. if (!(surfCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) {
  511. D3D_ERR("Render-target surface not in video memory for hw device");
  512. return(D3DERR_SURFACENOTINVIDMEM);
  513. }
  514. }
  515. /* A surface can only have one bit depth - whereas a device can support
  516. multiple bit depths */
  517. if (surfPF.dwFlags & DDPF_RGB) {
  518. D3D_INFO(3, "Render-target surface is RGB");
  519. bpp = BitDepthToDDBD(surfPF.dwRGBBitCount);
  520. if (!bpp) {
  521. D3D_ERR("Bogus render-target surface pixel depth");
  522. return(DDERR_INVALIDPIXELFORMAT);
  523. }
  524. if((surfPF.dwRGBBitCount<16) && (IsEqualIID(*pGuid, IID_IDirect3DRefDevice) || IsEqualIID(*pGuid, IID_IDirect3DNullDevice))) {
  525. // this is actually subsumed by the following test, but whatever
  526. D3D_ERR("Reference rasterizer and null device dont support render targets with bitdepth < 16");
  527. return(DDERR_INVALIDPIXELFORMAT);
  528. }
  529. if (!(bpp & this->d3dDevDesc.dwDeviceRenderBitDepth)) {
  530. D3D_ERR("Render-target surface bitdepth is not supported by this device");
  531. return(DDERR_INVALIDPIXELFORMAT);
  532. }
  533. }
  534. if(lpZbuffer==NULL)
  535. return D3D_OK;
  536. memset(&surfPF, 0, sizeof(DDPIXELFORMAT));
  537. surfPF.dwSize = sizeof(DDPIXELFORMAT);
  538. if (FAILED(ret = lpZbuffer->GetPixelFormat(&surfPF))) {
  539. D3D_ERR("Failed to get zbuffer pixel format");
  540. return(ret);
  541. }
  542. if (FAILED(ret = lpZbuffer->GetCaps(&surfCaps))) {
  543. D3D_ERR("Failed to get Zbuffer caps");
  544. return(ret);
  545. }
  546. if (IS_HW_DEVICE(this)) {
  547. if (!(surfCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) {
  548. D3D_ERR("Zbuffer not in video memory for hw device");
  549. return(D3DERR_ZBUFF_NEEDS_VIDEOMEMORY);
  550. }
  551. D3D_INFO(3, "Hw device, zbuffer in video memory");
  552. } else {
  553. if (!(surfCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) {
  554. D3D_ERR("Zbuffer not in system memory for HEL device");
  555. return(D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY);
  556. }
  557. D3D_INFO(3, "Hel device, zbuffer in system memory");
  558. // have to hack in a check to make sure ramp isn't used with stencil zbuffer
  559. // cant do this validation until device creation time (instead of at zbuffer creation in
  560. // ddhel.c) because rgb vs. ramp isn't known until now
  561. if(IsEqualIID(*pGuid, IID_IDirect3DRampDevice)) {
  562. if(surfPF.dwFlags & DDPF_STENCILBUFFER) {
  563. D3D_ERR("Z-Buffer with stencil is invalid with RAMP software rasterizer");
  564. return DDERR_INVALIDPARAMS;
  565. }
  566. }
  567. }
  568. if (surfPF.dwFlags & DDPF_ZBUFFER) {
  569. bpp = BitDepthToDDBD(surfPF.dwZBufferBitDepth);
  570. if (!bpp) {
  571. D3D_ERR("Bogus Zbuffer surface pixel depth");
  572. return(DDERR_INVALIDPIXELFORMAT);
  573. }
  574. }
  575. return(D3D_OK);
  576. }
  577. /*
  578. * Initialisation - class part and device part
  579. */
  580. /*
  581. * Generic class part initialisation
  582. */
  583. HRESULT InitDeviceI(LPDIRECT3DDEVICEI lpDevI, LPDIRECT3DI lpD3DI)
  584. {
  585. LPDDRAWI_DIRECTDRAW_GBL lpDDI;
  586. HRESULT error;
  587. D3DDEVICEDESC7 dummyDesc;
  588. lpDDI = ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl;
  589. //
  590. // Retrieve HAL information from provider.
  591. //
  592. if (IS_HW_DEVICE(lpDevI))
  593. error = lpDevI->pHalProv->GetCaps(lpDDI,
  594. &lpDevI->d3dDevDesc,
  595. &dummyDesc,
  596. 4);
  597. else
  598. error = lpDevI->pHalProv->GetCaps(lpDDI,
  599. &dummyDesc,
  600. &lpDevI->d3dDevDesc,
  601. 4);
  602. if (error != S_OK)
  603. {
  604. return (error);
  605. }
  606. // Insert the GUID
  607. memcpy(&lpDevI->d3dDevDesc.deviceGUID, &lpDevI->guid, sizeof(GUID));
  608. if( lpDevI->d3dDevDesc.wMaxVertexBlendMatrices == 1 )
  609. lpDevI->d3dDevDesc.wMaxVertexBlendMatrices = 0;
  610. //
  611. // Fix up the caps for non-T&L devices
  612. // That use out front-end
  613. //
  614. if( IsEqualIID(lpDevI->guid, IID_IDirect3DHALDevice) ||
  615. IsEqualIID(lpDevI->guid, IID_IDirect3DRGBDevice) )
  616. {
  617. lpDevI->d3dDevDesc.dwMaxActiveLights = 0xffffffff;
  618. lpDevI->d3dDevDesc.wMaxVertexBlendMatrices = 4;
  619. lpDevI->d3dDevDesc.wMaxUserClipPlanes = __MAXUSERCLIPPLANES;
  620. lpDevI->d3dDevDesc.dwVertexProcessingCaps = D3DVTXPCAPS_ALL;
  621. }
  622. D3DHALPROVIDER_INTERFACEDATA HalProviderIData;
  623. memset(&HalProviderIData,0,sizeof(HalProviderIData));
  624. HalProviderIData.dwSize = sizeof(HalProviderIData);
  625. if ((error = lpDevI->pHalProv->GetInterface(lpDDI,
  626. &HalProviderIData,
  627. 4)) != S_OK)
  628. {
  629. return error;
  630. }
  631. // interface data for <=DX5 HAL
  632. lpDevI->lpD3DHALGlobalDriverData = HalProviderIData.pGlobalData;
  633. lpDevI->lpD3DExtendedCaps = HalProviderIData.pExtCaps;
  634. lpDevI->lpD3DHALCallbacks = HalProviderIData.pCallbacks;
  635. lpDevI->lpD3DHALCallbacks2 = HalProviderIData.pCallbacks2;
  636. // interface data for DX6 HAL
  637. lpDevI->lpD3DHALCallbacks3 = HalProviderIData.pCallbacks3;
  638. lpDevI->pfnRastService = HalProviderIData.pfnRastService;
  639. lpDevI->dwHintFlags = 0;
  640. // This is available in all DX7+ drivers and is used by GetInfo API
  641. // call.
  642. lpDevI->pfnGetDriverState = HalProviderIData.pfnGetDriverState;
  643. // Zero out 8 bpp render target caps for real hardware.
  644. if (IS_HW_DEVICE(lpDevI))
  645. {
  646. lpDevI->lpD3DHALGlobalDriverData->hwCaps.dwDeviceRenderBitDepth &=
  647. (~DDBD_8);
  648. }
  649. if (!D3DI_isHALValid(lpDevI->lpD3DHALCallbacks))
  650. {
  651. return D3DERR_INITFAILED;
  652. }
  653. if (lpDevI->lpD3DExtendedCaps && lpDevI->lpD3DExtendedCaps->dwFVFCaps)
  654. {
  655. lpDevI->dwMaxTextureIndices =
  656. lpDevI->lpD3DExtendedCaps->dwFVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK;
  657. lpDevI->dwMaxTextureBlendStages =
  658. lpDevI->lpD3DExtendedCaps->wMaxTextureBlendStages;
  659. lpDevI->dwDeviceFlags |= D3DDEV_FVF;
  660. if (lpDevI->lpD3DExtendedCaps->dwFVFCaps & D3DFVFCAPS_DONOTSTRIPELEMENTS)
  661. lpDevI->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS;
  662. DWORD value;
  663. if ((
  664. #ifdef WIN95
  665. lpDevI->dwDebugFlags & D3DDEBUG_DISABLEDP ||
  666. lpDevI->dwDebugFlags & D3DDEBUG_DISABLEDP2 ||
  667. #endif // WIN95
  668. (GetD3DRegValue(REG_DWORD, "DisableFVF", &value, 4) &&
  669. value != 0)) &&
  670. FVF_DRIVERSUPPORTED(lpDevI))
  671. {
  672. lpDevI->dwMaxTextureIndices = 1;
  673. lpDevI->dwDeviceFlags &= ~D3DDEV_FVF;
  674. lpDevI->dwDebugFlags |= D3DDEBUG_DISABLEFVF;
  675. }
  676. if ((GetD3DRegValue(REG_DWORD, "DisableStripFVF", &value, 4) &&
  677. value != 0))
  678. {
  679. lpDevI->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS;
  680. }
  681. }
  682. else
  683. {
  684. lpDevI->dwMaxTextureIndices = 1;
  685. lpDevI->dwMaxTextureBlendStages = 1;
  686. }
  687. lpDevI->transform.dwMaxUserClipPlanes =
  688. lpDevI->d3dDevDesc.wMaxUserClipPlanes;
  689. lpDevI->dwFEFlags |= D3DFE_FRONTEND_DIRTY;
  690. #if DBG
  691. lpDevI->dwCaller=0;
  692. memset(lpDevI->dwPrimitiveType,0,sizeof(lpDevI->dwPrimitiveType));
  693. memset(lpDevI->dwVertexType1,0,sizeof(lpDevI->dwVertexType1));
  694. memset(lpDevI->dwVertexType2,0,sizeof(lpDevI->dwVertexType2));
  695. #endif
  696. return D3D_OK;
  697. }
  698. HRESULT D3DMallocBucket(LPDIRECT3DI lpD3DI, LPD3DBUCKET *lplpBucket)
  699. {
  700. if (lpD3DI->lpFreeList == NULL ){
  701. if (lpD3DI->lpFreeList == NULL )
  702. {
  703. LPD3DBUCKET lpBufferList;
  704. LPVOID lpBuffer;
  705. int i;
  706. *lplpBucket=NULL;
  707. if (D3DMalloc(&lpBuffer, D3DBUCKETBUFFERSIZE*sizeof(D3DBUCKET)) != D3D_OK)
  708. return DDERR_OUTOFMEMORY;
  709. D3D_INFO(9, "D3DMallocBucket %d Bytes allocated for %d free Buckets",
  710. D3DBUCKETBUFFERSIZE*sizeof(D3DBUCKET),D3DBUCKETBUFFERSIZE-1);
  711. lpBufferList=(LPD3DBUCKET)lpBuffer;
  712. for (i=0;i<D3DBUCKETBUFFERSIZE-2;i++)
  713. lpBufferList[i].next=&lpBufferList[i+1];
  714. lpBufferList[D3DBUCKETBUFFERSIZE-2].next=NULL;
  715. lpD3DI->lpFreeList=(LPD3DBUCKET)lpBuffer; //new free list
  716. lpBufferList[D3DBUCKETBUFFERSIZE-1].next=lpD3DI->lpBufferList;//add to lpBufferList
  717. lpBufferList[D3DBUCKETBUFFERSIZE-1].lpBuffer=lpBuffer;
  718. lpD3DI->lpBufferList=&lpBufferList[D3DBUCKETBUFFERSIZE-1];
  719. }
  720. }
  721. *lplpBucket=lpD3DI->lpFreeList;
  722. lpD3DI->lpFreeList=lpD3DI->lpFreeList->next;
  723. return D3D_OK;
  724. }
  725. void D3DFreeBucket(LPDIRECT3DI lpD3DI, LPD3DBUCKET lpBucket)
  726. {
  727. lpBucket->next=lpD3DI->lpFreeList;
  728. lpD3DI->lpFreeList=lpBucket;
  729. }
  730. void DIRECT3DDEVICEI::CleanupTextures()
  731. {
  732. /*
  733. * free up all textures created by this object - this also frees up Textures
  734. * We need to do this backwards because we cannot have a texture bound to
  735. * stage i + 1 when there is a texture bound to stage i.
  736. */
  737. for (int i = D3DHAL_TSS_MAXSTAGES - 1; i >= 0; --i)
  738. {
  739. if (lpD3DMappedTexI[i])
  740. {
  741. lpD3DMappedTexI[i]->Release();
  742. lpD3DMappedTexI[i] = NULL;
  743. lpD3DMappedBlock[i] = NULL;
  744. }
  745. }
  746. // The following code can result in D3DHAL_TextureDestroy() being called.
  747. // This BATCHES NEW INSTRUCTIONS in the instruction stream. So we must
  748. // make sure that at this point, the device is still able to accept
  749. // instructions.
  750. while (LIST_FIRST(&this->texBlocks)) {
  751. LPD3DI_TEXTUREBLOCK tBlock = LIST_FIRST(&this->texBlocks);
  752. D3DI_RemoveTextureHandle(tBlock);
  753. // Remove from device
  754. LIST_DELETE(tBlock, devList);
  755. // Remove from texture
  756. LIST_DELETE(tBlock, list);
  757. D3DFree(tBlock);
  758. }
  759. FlushStates();
  760. }
  761. /*
  762. * Generic device part destroy
  763. */
  764. DIRECT3DDEVICEI::~DIRECT3DDEVICEI()
  765. {
  766. LPDIRECTDRAWSURFACE lpDDS=NULL, lpDDSZ=NULL;
  767. LPDIRECTDRAWSURFACE7 lpDDS_DDS7=NULL;
  768. LPDIRECTDRAWPALETTE lpDDPal=NULL;
  769. /* Clear flags that could prohibit cleanup */
  770. this->dwHintFlags &= ~(D3DDEVBOOL_HINTFLAGS_INSCENE);
  771. // Hold pointers into ddraw object for release after driver is destroyed
  772. lpDDSZ = this->lpDDSZBuffer;
  773. lpDDPal = this->lpDDPalTarget;
  774. lpDDS_DDS7 = this->lpDDSTarget_DDS7;
  775. // this indicates that the device need no longer be flushed when Locking, Blting
  776. // or GetDC'ing from the previous rendertarget
  777. if (this->lpDDSTarget)
  778. ((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSTarget)->lpLcl->lpSurfMore->qwBatch.QuadPart = 0;
  779. // this indicates that the device need no longer be flushed when Locking, Blting
  780. // or GetDC'ing from the previous zbuffer
  781. if (this->lpDDSZBuffer)
  782. ((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSZBuffer)->lpLcl->lpSurfMore->qwBatch.QuadPart = 0;
  783. if (pGeometryFuncs != &GeometryFuncsGuaranteed)
  784. delete pGeometryFuncs;
  785. D3DFE_Destroy(this);
  786. if (this->lpDirect3DI)
  787. UnhookFromD3D();
  788. if (this->lpwDPBufferAlloced)
  789. D3DFree(this->lpwDPBufferAlloced);
  790. if (this->pHalProv != NULL)
  791. {
  792. this->pHalProv->Release();
  793. }
  794. if (this->hDllProv != NULL)
  795. {
  796. FreeLibrary(this->hDllProv);
  797. }
  798. // Free the rstates that was allocated
  799. if(!(IS_HW_DEVICE(this) && IS_DP2HAL_DEVICE(this)))
  800. {
  801. delete rstates;
  802. }
  803. if (m_pStateSets)
  804. delete m_pStateSets;
  805. if (lpDDS)
  806. lpDDS->Release();
  807. if (lpDDSZ)
  808. lpDDSZ->Release();
  809. if (lpDDPal)
  810. lpDDPal->Release();
  811. if (lpDDS_DDS7)
  812. lpDDS_DDS7->Release();
  813. D3DFree(clrRects);
  814. }
  815. HRESULT DIRECT3DDEVICEI::HookToD3D(LPDIRECT3DI lpD3DI)
  816. {
  817. LIST_INSERT_ROOT(&lpD3DI->devices, this, list);
  818. this->lpDirect3DI = lpD3DI;
  819. this->lpDirect3DI->AddRef(); // Since we hold a pointer to Direct3D
  820. lpD3DI->numDevs++;
  821. return (D3D_OK);
  822. }
  823. HRESULT DIRECT3DDEVICEI::UnhookFromD3D()
  824. {
  825. LIST_DELETE(this, list);
  826. this->lpDirect3DI->numDevs--;
  827. this->lpDirect3DI->Release(); // Release our AddRef
  828. this->lpDirect3DI = NULL;
  829. return (D3D_OK);
  830. }
  831. /*
  832. * Create a device.
  833. *
  834. * NOTE: Radical modifications to support the aggregatable device
  835. * interface (so devices can be queried off DirectDraw surfaces):
  836. *
  837. * 1) This call is no longer a member of the Direct3D device interface.
  838. * It is now an API function exported from the Direct3D DLL. Its
  839. * a hidden API function - only DirectDraw will ever invoke it.
  840. *
  841. * 2) This call is, in effect, the class factory for Direct3DDevice
  842. * objects. This function will be invoked to create the aggregated
  843. * device object hanging off the DirectDraw surface.
  844. *
  845. * NOTE: So the Direct3DDevice knows which DirectDraw surface is
  846. * its rendering target this function is passed an interface pointer
  847. * for that DirectDraw surface. I suspect this blows a nice big
  848. * hole in the COM model as the DirectDraw surface is also the
  849. * owning interface of the device and I don't think aggregated
  850. * objects should know about thier owning interfaces. However, to
  851. * make this thing work this is what we have to do.
  852. *
  853. * EXTRA BIG NOTE: Because of the above don't take a reference to
  854. * the DirectDraw surface passed in. If you do you will get a circular
  855. * reference and the bloody thing will never die. When aggregated
  856. * the device interface's lifetime is entirely defined by the
  857. * lifetime of its owning interface (the DirectDraw surface) so the
  858. * DirectDraw surface can never go away before the texture.
  859. *
  860. * EXTRA EXTRA BIG NOTE: No device description is passed in any more.
  861. * The only things that can get passed in are things that DirectDraw
  862. * knows about (which does not include stuff like dither and color
  863. * model). Therefore, any input parameters must come in via a
  864. * different IID for the device. The data returned by the device
  865. * description must now be retrieved by another call.
  866. */
  867. #undef DPF_MODNAME
  868. #define DPF_MODNAME "Direct3DCreateDevice"
  869. HRESULT WINAPI Direct3DCreateDevice(REFCLSID riid,
  870. LPUNKNOWN lpDirect3D,
  871. LPDIRECTDRAWSURFACE lpDDSTarget,
  872. LPUNKNOWN* lplpD3DDevice,
  873. IUnknown* pUnkOuter)
  874. {
  875. LPDIRECT3DI lpD3DI;
  876. LPDIRECT3DDEVICEI pd3ddev;
  877. D3DCOLORMODEL cm = D3DCOLOR_MONO;
  878. HRESULT ret = D3D_OK;
  879. HKEY hKey = (HKEY) NULL;
  880. bool bDisableST = false;
  881. WORD wDriverStyle = MAX_DRIVERMODELS_SUPPORTED;
  882. #if _D3D_FORCEDOUBLE
  883. bool bForceDouble = true;
  884. #endif //_D3D_FORCEDOUBLE
  885. /* No need to validate params as they are passed to us by DirectDraw */
  886. /* CreateDevice member of IDirect3D2 will cause this function to be called
  887. * from within Direct3D. The parameters from the application level must be
  888. * validated. Need a way to validate the surface pointer from outside DDraw.
  889. */
  890. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  891. if( ! VALID_PTR_PTR( lplpD3DDevice) )
  892. {
  893. D3D_ERR( "Invalid ptr to device pointer in Direct3DCreateDevice" );
  894. return DDERR_INVALIDPARAMS;
  895. }
  896. if(!IsValidD3DDeviceGuid(riid))
  897. {
  898. D3D_ERR( "Unrecognized Device GUID!");
  899. return DDERR_INVALIDPARAMS;
  900. }
  901. *lplpD3DDevice = NULL;
  902. // Might be safer to use dynamic_cast<> if RTTI is enabled
  903. lpD3DI = reinterpret_cast<CDirect3DUnk*>(lpDirect3D)->pD3DI;
  904. if (IsEqualIID(riid, IID_IDirect3DMMXDevice) && !isMMXprocessor()) {
  905. D3D_ERR("Can't create MMX Device on non-MMX machine");
  906. return DDERR_INVALIDPARAMS;
  907. }
  908. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey) )
  909. {
  910. DWORD dwType;
  911. DWORD dwValue;
  912. DWORD dwSize = 4;
  913. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "DriverStyle", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  914. dwType == REG_DWORD &&
  915. dwValue != 0)
  916. {
  917. // Win64 compiler will scream here!!
  918. wDriverStyle = (WORD)dwValue;
  919. if (wDriverStyle > MAX_DRIVERMODELS_SUPPORTED)
  920. wDriverStyle = MAX_DRIVERMODELS_SUPPORTED;
  921. }
  922. D3D_INFO(2,"DriverStyle: %d",wDriverStyle);
  923. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "DisableST", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  924. dwType == REG_DWORD &&
  925. dwValue != 0)
  926. {
  927. bDisableST = true;
  928. }
  929. #if _D3D_FORCEDOUBLE
  930. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "ForceDouble", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  931. dwType == REG_DWORD &&
  932. dwValue == 0)
  933. {
  934. bForceDouble = false;
  935. }
  936. D3D_INFO(2,"ForceDouble: %d",bForceDouble);
  937. #endif //_D3D_FORCEDOUBLE
  938. RegCloseKey( hKey );
  939. }
  940. // Now create the appropriate device based on the wDriverStyle settings
  941. //---------------------------------------------------------------------
  942. // HKEY_LOCAL_MACHINE\Software\Microsoft\Direct3D\DriverStyle
  943. // In DX7 this registry key replaces the host of keys we had before like
  944. // DisableDP, DisableDP2 etc. This stuff is for testing purpose only.
  945. // It is more like a hint, in that, if the requested driver type is
  946. // available, it is used otherwise the latest available driver is used
  947. // The following is the meanings for this dword:
  948. //
  949. // Value: Driver-type:
  950. // 0x0 Latest available
  951. // 0x1 DeviceHW (DX3)
  952. // 0x2 DeviceDP (DX5)
  953. // 0x3 DeviceDP2 (DX6)
  954. // 0x4 DeviceDX7 (DX7)
  955. // 0x5 DeviceTL (DX7+T&L)
  956. //
  957. // The following are the various cases we need to consider:
  958. // 1) NT Hardware: 3 and above are considered legal
  959. // 2) W9x Hardware: All of the above are legal
  960. // 3) Reference: 2 and above
  961. // 4) Software: 3 till 4 (no TL)
  962. //---------------------------------------------------------------------
  963. if (IsEqualIID(riid, IID_IDirect3DTnLHalDevice))
  964. {
  965. // For T&L hal guid, we ignore the wDriverStyle hint
  966. // set in the registry
  967. if (DDGBL(lpD3DI)->lpD3DGlobalDriverData &&
  968. (DDGBL(lpD3DI)->lpD3DGlobalDriverData->hwCaps.dwDevCaps &
  969. D3DDEVCAPS_HWTRANSFORMANDLIGHT))
  970. {
  971. wDriverStyle = D3DDRVMODEL_TL;
  972. }
  973. else // fail device creation
  974. {
  975. wDriverStyle = 0;
  976. }
  977. D3D_INFO(1,"TnLHalDevice Driver Style %x",wDriverStyle);
  978. }
  979. else if (IsEqualIID(riid, IID_IDirect3DHALDevice))
  980. {
  981. WORD wDriverCaps = 0;
  982. WORD wLatestDDI=0;
  983. //
  984. // 1) Determine what styles of DDIs the driver is capable of
  985. //
  986. // DX7 ?
  987. if (DDGBL(lpD3DI)->lpDDCBtmp &&
  988. DDGBL(lpD3DI)->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState)
  989. {
  990. wDriverCaps |= (1 << D3DDRVMODEL_DX7);
  991. if (wLatestDDI==0)
  992. wLatestDDI = D3DDRVMODEL_DX7;
  993. }
  994. // DX6 ?
  995. if (DDGBL(lpD3DI)->lpD3DHALCallbacks3 &&
  996. DDGBL(lpD3DI)->lpD3DHALCallbacks3->DrawPrimitives2)
  997. {
  998. wDriverCaps |= (1 << D3DDRVMODEL_DX6);
  999. if (wLatestDDI==0)
  1000. wLatestDDI = D3DDRVMODEL_DX6;
  1001. }
  1002. #ifdef WIN95
  1003. // DX5 ?
  1004. if (DDGBL(lpD3DI)->lpD3DHALCallbacks2 &&
  1005. DDGBL(lpD3DI)->lpD3DHALCallbacks2->DrawOnePrimitive)
  1006. {
  1007. wDriverCaps |= (1 << D3DDRVMODEL_DX5);
  1008. if (wLatestDDI==0)
  1009. wLatestDDI = D3DDRVMODEL_DX5;
  1010. }
  1011. // DX3 ?
  1012. if (DDGBL(lpD3DI)->lpD3DHALCallbacks &&
  1013. DDGBL(lpD3DI)->lpD3DHALCallbacks->RenderPrimitive)
  1014. {
  1015. wDriverCaps |= (1 << D3DDRVMODEL_DX3);
  1016. if (wLatestDDI==0)
  1017. wLatestDDI = D3DDRVMODEL_DX3;
  1018. }
  1019. #endif //WIN95
  1020. //
  1021. // 2) Verify if the requested driver is supported
  1022. //
  1023. if (wDriverCaps == 0)
  1024. {
  1025. wDriverStyle = 0; // nothing supported so fail
  1026. }
  1027. else if (!(wDriverCaps & (1 << wDriverStyle)))
  1028. {
  1029. // use the latest available if not specified or
  1030. // incorrectly specified or specified but not available
  1031. wDriverStyle = wLatestDDI;
  1032. }
  1033. D3D_INFO(1,"HalDevice Driver Style %x",wDriverStyle);
  1034. }
  1035. // Reference Device
  1036. else if (IsEqualIID(riid, IID_IDirect3DRefDevice))
  1037. {
  1038. // By default choose TL device for RefRast in DX7
  1039. if (wDriverStyle < D3DDRVMODEL_DX5 || wDriverStyle > D3DDRVMODEL_TL)
  1040. {
  1041. // Refrast is capable of DX7+T&L
  1042. wDriverStyle = D3DDRVMODEL_TL;
  1043. }
  1044. }
  1045. // Software Rasterizers
  1046. else
  1047. {
  1048. // Ignore driver style for everything except the reference rasterizer
  1049. wDriverStyle = D3DDRVMODEL_DX6;
  1050. }
  1051. // Note: If wDriverStyle == 0x0 here, driver creation will fail
  1052. // Something must have been chosen by now
  1053. switch (wDriverStyle)
  1054. {
  1055. #ifdef WIN95
  1056. case D3DDRVMODEL_DX3:
  1057. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIHW());
  1058. break;
  1059. case D3DDRVMODEL_DX5:
  1060. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP());
  1061. break;
  1062. #endif //WIN95
  1063. case D3DDRVMODEL_DX6:
  1064. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP2());
  1065. break;
  1066. case D3DDRVMODEL_DX7:
  1067. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDevice7());
  1068. break;
  1069. case D3DDRVMODEL_TL:
  1070. pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceTL());
  1071. break;
  1072. default:
  1073. D3D_ERR("Runtime doesnt support requested/installed driver");
  1074. // Change this return value ?
  1075. return (DDERR_OUTOFMEMORY);
  1076. }
  1077. if (!pd3ddev) {
  1078. D3D_ERR("Failed to allocate space for D3DDevice. Quitting.");
  1079. return (DDERR_OUTOFMEMORY);
  1080. }
  1081. // If we have lost managed textures, we need to cleanup
  1082. // since CheckSurfaces() would fail which would cause
  1083. // FlushStates() to fail, which would result in the
  1084. // current batch being abandoned (along with any device initialization)
  1085. if(lpD3DI->lpTextureManager->CheckIfLost())
  1086. {
  1087. D3D_INFO(2, "Found lost managed textures. Evicting...");
  1088. lpD3DI->lpTextureManager->EvictTextures();
  1089. }
  1090. ret = pd3ddev->Init(riid, lpD3DI, lpDDSTarget, pUnkOuter, lplpD3DDevice);
  1091. if (ret!=D3D_OK)
  1092. {
  1093. delete pd3ddev;
  1094. D3D_ERR("Failed to intilialize D3DDevice");
  1095. return ret;
  1096. }
  1097. if (bDisableST)
  1098. pd3ddev->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_MULTITHREADED;
  1099. #ifdef _X86_
  1100. if (!(((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->dwLocalFlags & DDRAWILCL_FPUPRESERVE) &&
  1101. IS_DP2HAL_DEVICE(pd3ddev))
  1102. {
  1103. pd3ddev->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_FPUSETUP;
  1104. WORD wSave, wTemp;
  1105. __asm {
  1106. fstcw wSave
  1107. mov ax, wSave
  1108. and ax, not 300h ;; single mode
  1109. or ax, 3fh ;; disable all exceptions
  1110. and ax, not 0C00h ;; round to nearest mode
  1111. mov wTemp, ax
  1112. fldcw wTemp
  1113. }
  1114. }
  1115. #if _D3D_FORCEDOUBLE
  1116. if (bForceDouble && (pd3ddev->deviceType <= D3DDEVTYPE_DPHAL))
  1117. {
  1118. pd3ddev->dwDebugFlags |= D3DDEBUG_FORCEDOUBLE;
  1119. }
  1120. else
  1121. {
  1122. pd3ddev->dwDebugFlags &= ~D3DDEBUG_FORCEDOUBLE;
  1123. }
  1124. #endif //_D3D_FORCEDOUBLE
  1125. #endif
  1126. return (ret);
  1127. }
  1128. HRESULT DIRECT3DDEVICEI::Init(REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS,
  1129. IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice)
  1130. {
  1131. DDSCAPS ddscaps;
  1132. DDSURFACEDESC ddsd;
  1133. HRESULT ret, ddrval;
  1134. LPDIRECTDRAWSURFACE lpDDSZ=NULL;
  1135. LPDIRECTDRAWPALETTE lpDDPal=NULL;
  1136. LPGUID pGuid;
  1137. DDSCAPS surfCaps;
  1138. m_qwBatch = 1;
  1139. this->dwVIDIn = 0;
  1140. this->refCnt = 1;
  1141. pD3DMappedTexI = (LPVOID*)(this->lpD3DMappedTexI);
  1142. /* Single threaded or Multi threaded app ? */
  1143. if (((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->dwLocalFlags & DDRAWILCL_MULTITHREADED)
  1144. this->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_MULTITHREADED;
  1145. /*
  1146. * Initialise textures
  1147. */
  1148. LIST_INITIALIZE(&this->texBlocks);
  1149. this->dwVertexBase = 0;
  1150. pGeometryFuncs = &GeometryFuncsGuaranteed;
  1151. /*-----------------------------------------------------------------------------------------
  1152. * Up till now we have done the easy part of the initialization. This is the stuff that
  1153. * cannot fail. It initializes the object so that the destructor can be safely called if
  1154. * any of the further initialization does not succeed.
  1155. *---------------------------------------------------------------------------------------*/
  1156. /*
  1157. * Ensure the riid is one we understand.
  1158. *
  1159. * Query the registry.
  1160. */
  1161. pGuid = (GUID *)&riid;
  1162. #if DBG
  1163. if (IsEqualIID(*pGuid, IID_IDirect3DTnLHalDevice))
  1164. {
  1165. D3D_INFO(0, "======================= TL-Hal device selected");
  1166. }
  1167. if (IsEqualIID(*pGuid, IID_IDirect3DRGBDevice))
  1168. {
  1169. D3D_INFO(0, "======================= RGB device selected");
  1170. }
  1171. if (IsEqualIID(*pGuid, IID_IDirect3DHALDevice))
  1172. {
  1173. D3D_INFO(0, "======================= HAL device selected");
  1174. }
  1175. if (IsEqualIID(*pGuid, IID_IDirect3DRefDevice))
  1176. {
  1177. D3D_INFO(0, "======================= Reference Rasterizer device selected");
  1178. }
  1179. if (IsEqualIID(*pGuid, IID_IDirect3DNullDevice))
  1180. {
  1181. D3D_INFO(0, "======================= Null device selected");
  1182. }
  1183. #endif
  1184. // set up flag to use MMX when requested RGB
  1185. BOOL bUseMMXAsRGBDevice = FALSE;
  1186. if (IsEqualIID(*pGuid, IID_IDirect3DRGBDevice) && isMMXprocessor())
  1187. {
  1188. bUseMMXAsRGBDevice = TRUE;
  1189. // read reg key to override use of MMX for RGB
  1190. HKEY hKey = (HKEY) NULL;
  1191. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH, &hKey) )
  1192. {
  1193. DWORD dwType;
  1194. DWORD dwValue;
  1195. DWORD dwSize = 4;
  1196. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "UseMMXForRGB", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  1197. dwType == REG_DWORD &&
  1198. dwValue == 0)
  1199. {
  1200. bUseMMXAsRGBDevice = FALSE;
  1201. }
  1202. RegCloseKey( hKey );
  1203. }
  1204. if (bUseMMXAsRGBDevice)
  1205. {
  1206. D3D_INFO(0, " using MMX in RGB device");
  1207. }
  1208. }
  1209. if (IsEqualIID(*pGuid, IID_IDirect3DRGBDevice) &&
  1210. isMMXprocessor())
  1211. {
  1212. // Check for whether this app is one of the Intel ones
  1213. // that want the MMX rasterizer
  1214. LPDDRAWI_DIRECTDRAW_LCL lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl;
  1215. // 0x4 corresponds to the "Intel app that wants MMX"
  1216. // flag defined in ddrawpr.h
  1217. if ( lpDDLcl->dwAppHackFlags & 0x4 )
  1218. {
  1219. pGuid = (GUID *)&IID_IDirect3DMMXDevice;
  1220. }
  1221. }
  1222. /*
  1223. * Check if the 3D cap is set on the surface.
  1224. */
  1225. memset(&ddsd, 0, sizeof ddsd);
  1226. ddsd.dwSize = sizeof ddsd;
  1227. ddrval = lpDDS->GetSurfaceDesc(&ddsd);
  1228. if (ddrval != DD_OK) {
  1229. D3D_ERR("Failed to get surface description of device's surface.");
  1230. return (ddrval);
  1231. }
  1232. if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)) {
  1233. D3D_ERR("**** The DDSCAPS_3DDEVICE is not set on this surface.");
  1234. D3D_ERR("**** You need to add DDSCAPS_3DDEVICE to ddsCaps.dwCaps");
  1235. D3D_ERR("**** when creating the surface.");
  1236. return (DDERR_INVALIDCAPS);
  1237. }
  1238. if (ddsd.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) {
  1239. D3D_ERR("**** DDSCAPS_ZBUFFER is set on this surface.");
  1240. D3D_ERR("**** Rendering into Z buffer surfaces is not");
  1241. D3D_ERR("**** currently supported by Direct3D.");
  1242. return (DDERR_INVALIDCAPS);
  1243. }
  1244. if (ddsd.dwWidth > 2048 || ddsd.dwHeight > 2048)
  1245. {
  1246. D3D_ERR("**** Surface too large - must be <= 2048 in width & height.");
  1247. return (DDERR_INVALIDOBJECT);
  1248. }
  1249. /* Check for palette... */
  1250. ret = lpDDS->GetPalette(&lpDDPal);
  1251. if ((ret != DD_OK) && (ret != DDERR_NOPALETTEATTACHED))
  1252. {
  1253. /*
  1254. * NOTE: Again, not an error (yet) if there is no palette attached.
  1255. * But if there is palette and we can't get at it for some reason
  1256. * - fail.
  1257. */
  1258. D3D_ERR("Supplied DirectDraw Palette is invalid - can't create device");
  1259. return (DDERR_INVALIDPARAMS);
  1260. }
  1261. /*
  1262. * We're going to check now whether we should have got a palette.
  1263. */
  1264. if (ret == DDERR_NOPALETTEATTACHED) {
  1265. if (ddsd.ddpfPixelFormat.dwRGBBitCount < 16) {
  1266. D3D_ERR("No palette supplied for palettized surface - can't create device");
  1267. return (DDERR_NOPALETTEATTACHED);
  1268. }
  1269. }
  1270. this->lpDDPalTarget = lpDDPal;
  1271. // Check for ZBuffer
  1272. memset(&surfCaps, 0, sizeof(DDSCAPS));
  1273. surfCaps.dwCaps = DDSCAPS_ZBUFFER;
  1274. if (FAILED(ret = lpDDS->GetAttachedSurface(&surfCaps, &lpDDSZ))) {
  1275. if (ret != DDERR_NOTFOUND) {
  1276. D3D_ERR("Failed GetAttachedSurface for ZBuffer");
  1277. goto handle_err;
  1278. }
  1279. D3D_INFO(2, "No zbuffer is attached to rendertarget surface (which is OK)");
  1280. }
  1281. this->lpDDSZBuffer = lpDDSZ;
  1282. this->guid = *pGuid;
  1283. // Try to get a HAL provider for this driver (may need to use MMX guid if
  1284. // using MMX for RGB requested device)
  1285. ret = GetSwHalProvider(
  1286. bUseMMXAsRGBDevice ? IID_IDirect3DMMXAsRGBDevice : riid,
  1287. &this->pHalProv, &this->hDllProv);
  1288. if (ret == S_OK)
  1289. {
  1290. // Got a software provider.
  1291. }
  1292. else if (ret == E_NOINTERFACE &&
  1293. ((ret = GetHwHalProvider(riid, &this->pHalProv,
  1294. &this->hDllProv,
  1295. ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl)) == S_OK))
  1296. {
  1297. // Got a hardware provider.
  1298. }
  1299. else
  1300. {
  1301. if( IsEqualIID(riid, IID_IDirect3DHALDevice) ||
  1302. IsEqualIID(riid, IID_IDirect3DTnLHalDevice)) {
  1303. D3D_ERR("Requested HAL Device non-existent or invalid");
  1304. } else {
  1305. D3D_ERR("Unable to get D3D Device provider for requested GUID");
  1306. }
  1307. goto handle_err;
  1308. }
  1309. {
  1310. // Initialize test HAL provider to drop HAL calls (sort of a Null device)
  1311. //
  1312. DWORD value = 0;
  1313. if (GetD3DRegValue(REG_DWORD, "DisableRendering", &value, sizeof(DWORD)) &&
  1314. value != 0)
  1315. {
  1316. ret = GetTestHalProvider(
  1317. riid, ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl,
  1318. &this->pHalProv, this->pHalProv, 0);
  1319. if (ret != D3D_OK)
  1320. {
  1321. D3D_ERR("Unable to set up 'DisableRendering' mode");
  1322. goto handle_err;
  1323. }
  1324. }
  1325. }
  1326. // Initialise general DEVICEI information.
  1327. if ((ret = InitDeviceI(this, lpD3DI)) != D3D_OK)
  1328. {
  1329. D3D_ERR("Failed to initialise device");
  1330. goto handle_err;
  1331. }
  1332. // Check the surface and device to see if they're compatible
  1333. if (FAILED(ret = checkDeviceSurface(lpDDS,lpDDSZ,pGuid))) {
  1334. D3D_ERR("Device and surface aren't compatible");
  1335. goto handle_err;
  1336. }
  1337. // Create front-end support structures.
  1338. // ATTENTION - We probably want to avoid doing this if the driver
  1339. // does its own front end. Software fallbacks complicate the issue,
  1340. // though.
  1341. ret = D3DFE_Create(this, lpD3DI->lpDD, lpD3DI->lpDD7, lpDDS, lpDDSZ, lpDDPal);
  1342. if (ret != D3D_OK)
  1343. {
  1344. D3D_ERR("Failed to create front-end data-structures.");
  1345. goto handle_err;
  1346. }
  1347. // Figure out place for rstates
  1348. if (IS_HW_DEVICE(this) && IS_DP2HAL_DEVICE(this))
  1349. {
  1350. // In case of HW DP2 HAL we reuse the kernel allocated
  1351. // memory for RStates since we need the driver to update
  1352. // it
  1353. rstates = (LPDWORD)lpwDPBuffer;
  1354. }
  1355. else
  1356. {
  1357. // In all other cases we simply allocate memory for rstates
  1358. rstates = new DWORD[D3D_MAXRENDERSTATES];
  1359. }
  1360. D3DFE_PROCESSVERTICES::lpdwRStates = this->rstates;
  1361. // Check if we have a processor specific implementation available
  1362. // only use if DisablePSGP is not in registry or set to zero
  1363. DWORD value;
  1364. if (!GetD3DRegValue(REG_DWORD, "DisablePSGP", &value, sizeof(DWORD)))
  1365. {
  1366. value = 0;
  1367. }
  1368. #ifdef _X86_
  1369. if (value != 1)
  1370. {
  1371. if ( dwCPUFeatures & D3DCPU_X3D && value != 2)
  1372. pfnFEContextCreate = px3DContextCreate;
  1373. else if ( dwCPUFeatures & D3DCPU_WLMT )
  1374. pfnFEContextCreate = wlmt_FEContextCreate;
  1375. else if ( dwCPUFeatures & D3DCPU_SSE )
  1376. pfnFEContextCreate = katmai_FEContextCreate;
  1377. if (pfnFEContextCreate)
  1378. {
  1379. D3D_INFO(0, "PSGP enabled for device");
  1380. // Ask the PV implementation to create a device specific "context"
  1381. LPD3DFE_PVFUNCS pOptGeoFuncs = pGeometryFuncs;
  1382. ret = pfnFEContextCreate(dwDeviceFlags, &pOptGeoFuncs);
  1383. if ((ret == D3D_OK) && pOptGeoFuncs)
  1384. {
  1385. D3D_INFO(2, "using PSGP");
  1386. pGeometryFuncs = pOptGeoFuncs;
  1387. }
  1388. }
  1389. }
  1390. #endif // _X86_
  1391. /*
  1392. * put this device in the list of those owned by the Direct3D object
  1393. */
  1394. ret = HookToD3D(lpD3DI);
  1395. if (ret != D3D_OK)
  1396. {
  1397. D3D_ERR("Failed to associate device with Direct3D");
  1398. goto handle_err;
  1399. }
  1400. {
  1401. if (HVbuf.Grow((__INIT_VERTEX_NUMBER*2)*sizeof(D3DFE_CLIPCODE)) != DD_OK)
  1402. {
  1403. D3D_ERR( "Out of memory in DeviceCreate (HVBuf)" );
  1404. ret = DDERR_OUTOFMEMORY;
  1405. goto handle_err;
  1406. }
  1407. ret = this->ClipperState.clipBuf.Grow
  1408. (this, MAX_CLIP_VERTICES*__MAX_VERTEX_SIZE);
  1409. if (ret != D3D_OK)
  1410. {
  1411. D3D_ERR( "Out of memory in DeviceCreate (ClipBuf)" );
  1412. ret = DDERR_OUTOFMEMORY;
  1413. goto handle_err;
  1414. }
  1415. ret = this->ClipperState.clipBufPrim.Grow
  1416. (this, MAX_CLIP_TRIANGLES*sizeof(D3DTRIANGLE));
  1417. if (ret != D3D_OK)
  1418. {
  1419. D3D_ERR( "Out of memory in DeviceCreate (ClipBufPrim)" );
  1420. ret = DDERR_OUTOFMEMORY;
  1421. goto handle_err;
  1422. }
  1423. }
  1424. // this indicates that the device should always be flushed when Locking, Blting
  1425. // or GetDC'ing a rendertarget
  1426. ((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl->lpSurfMore->qwBatch.QuadPart = _UI64_MAX;
  1427. // this indicates that the device should always be flushed when Locking, Blting
  1428. // or GetDC'ing a zbuffer
  1429. if (lpDDSZ)
  1430. {
  1431. ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSZ)->lpLcl->lpSurfMore->qwBatch.QuadPart = _UI64_MAX;
  1432. }
  1433. /* Set the initial render state of the device */
  1434. if (FAILED(ret = stateInitialize(lpDDSZ!=NULL)))
  1435. {
  1436. D3D_ERR("Failed to set initial state for device");
  1437. goto handle_err;
  1438. }
  1439. // Setup the viewport
  1440. m_Viewport.dwX = 0;
  1441. m_Viewport.dwY = 0;
  1442. m_Viewport.dwWidth = ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wWidth;
  1443. m_Viewport.dwHeight = ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpGbl->wHeight;
  1444. m_Viewport.dvMinZ = (D3DVALUE)0;
  1445. m_Viewport.dvMaxZ = (D3DVALUE)1;
  1446. if (FAILED(this->SetViewport(&m_Viewport)))
  1447. goto handle_err;
  1448. // Setup lights
  1449. m_dwNumLights = 8;
  1450. m_pLights = new DIRECT3DLIGHTI[8];
  1451. LIST_INITIALIZE(&m_ActiveLights);
  1452. // Setup material
  1453. memset(&this->lighting.material, 0, sizeof(this->lighting.material));
  1454. // Setup set states
  1455. m_pStateSets = new CStateSets;
  1456. if (m_pStateSets == NULL)
  1457. return DDERR_OUTOFMEMORY;
  1458. m_pStateSets->Init(this->dwFEFlags);
  1459. #ifdef PROFILE4
  1460. m_dwProfStart = m_dwProfStop = 0;
  1461. GetD3DRegValue(REG_DWORD, "ProfileStartFrame", &m_dwProfStart, 4);
  1462. GetD3DRegValue(REG_DWORD, "ProfileStopFrame", &m_dwProfStop, 4);
  1463. #endif
  1464. #ifdef PROFILE
  1465. m_dwProfStart = m_dwProfStop = 0;
  1466. GetD3DRegValue(REG_DWORD, "ProfileStartFrame", &m_dwProfStart, 4);
  1467. GetD3DRegValue(REG_DWORD, "ProfileStopFrame", &m_dwProfStop, 4);
  1468. #endif
  1469. #ifdef VTABLE_HACK
  1470. // Copy with vtable
  1471. lpVtbl = *((LPVOID**)this);
  1472. memcpy(newVtbl, lpVtbl, sizeof(PVOID)*D3D_NUM_VIRTUAL_FUNCTIONS);
  1473. // Point to the new one
  1474. *((LPVOID*)this) = (LPVOID)newVtbl;
  1475. // Set vtable hack for PreLoad() if single threaded and not software
  1476. if (!IS_MT_DEVICE(this) && (this->dwFEFlags & D3DFE_REALHAL))
  1477. {
  1478. VtblPreLoadFast();
  1479. }
  1480. #endif // VTABLE_HACK
  1481. /*
  1482. * NOTE: We don't return the actual device interface. We
  1483. * return the device's special IUnknown interface which
  1484. * will be used in a QueryInterface to get the actual
  1485. * Direct3D device interface.
  1486. */
  1487. *lplpD3DDevice = static_cast<LPUNKNOWN>(this);
  1488. return (D3D_OK);
  1489. handle_err:
  1490. // might be able to simplify if this fn and not D3DFE_Create sets this->lpDDSZBuffer/this->lpDDPalette
  1491. if(lpDDSZ!=NULL) {
  1492. lpDDSZ->Release(); // release the reference GetAttachedSurface created
  1493. this->lpDDSZBuffer=NULL; // make sure the device destructor doesn't try to re-release this
  1494. // I'd let device destructor handle this, but errors can occur before D3DFE_Create is called
  1495. }
  1496. if(lpDDPal!=NULL) {
  1497. lpDDPal->Release(); // release the reference GetPalette created
  1498. this->lpDDPalTarget=NULL; // make sure the device destructor doesn't try to re-release this
  1499. }
  1500. D3D_ERR("Device creation failed!!");
  1501. return(ret);
  1502. }
  1503. HRESULT D3DAPI DIRECT3DDEVICEI::GetCaps(LPD3DDEVICEDESC7 lpD3DDevDesc)
  1504. {
  1505. HRESULT ret;
  1506. ret = D3D_OK;
  1507. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1508. if (!VALID_DIRECT3DDEVICE_PTR(this))
  1509. {
  1510. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1511. return DDERR_INVALIDOBJECT;
  1512. }
  1513. if (!VALID_D3DDEVICEDESC7_PTR(lpD3DDevDesc))
  1514. {
  1515. D3D_ERR( "Invalid D3DDEVICEDESC7 pointer" );
  1516. return DDERR_INVALIDPARAMS;
  1517. }
  1518. memcpy(lpD3DDevDesc, &this->d3dDevDesc, sizeof( D3DDEVICEDESC7 ));
  1519. return (ret);
  1520. }
  1521. #undef DPF_MODNAME
  1522. #define DPF_MODNAME "Direct3DDevice::EnumTextureFormats"
  1523. HRESULT D3DAPI DIRECT3DDEVICEI::EnumTextureFormats(
  1524. LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
  1525. LPVOID lpContext)
  1526. {
  1527. HRESULT ret, userRet;
  1528. LPDDSURFACEDESC lpDescs, lpRetDescs;
  1529. DWORD num_descs;
  1530. DWORD i;
  1531. try
  1532. {
  1533. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1534. ret = D3D_OK;
  1535. if (!VALID_DIRECT3DDEVICE_PTR(this))
  1536. {
  1537. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1538. return DDERR_INVALIDOBJECT;
  1539. }
  1540. if (!VALIDEX_CODE_PTR(lpEnumCallback))
  1541. {
  1542. D3D_ERR( "Invalid callback pointer" );
  1543. return DDERR_INVALIDPARAMS;
  1544. }
  1545. LPDDRAWI_DIRECTDRAW_LCL lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)(this->lpDD))->lpLcl;
  1546. BOOL bFourCCAppHack =
  1547. (lpDDLcl->dwAppHackFlags & DDRAW_APPCOMPAT_TEXENUMDX7FOURCC)?1:0;
  1548. D3D_INFO(3, "APPCOMPAT_TEXENUMDX7FOURCC: %d",bFourCCAppHack);
  1549. num_descs = this->lpD3DHALGlobalDriverData->dwNumTextureFormats;
  1550. lpDescs = this->lpD3DHALGlobalDriverData->lpTextureFormats;
  1551. if (!num_descs)
  1552. {
  1553. D3D_ERR("no texture formats supported");
  1554. return (D3DERR_TEXTURE_NO_SUPPORT);
  1555. }
  1556. if (D3DMalloc((void**)&lpRetDescs, sizeof(DDSURFACEDESC) * num_descs) != D3D_OK)
  1557. {
  1558. D3D_ERR("failed to alloc space for return descriptions");
  1559. return (DDERR_OUTOFMEMORY);
  1560. }
  1561. memcpy(lpRetDescs, lpDescs, sizeof(DDSURFACEDESC) * num_descs);
  1562. userRet = D3DENUMRET_OK;
  1563. for (i = 0; i < num_descs && userRet == D3DENUMRET_OK; i++) {
  1564. // Filter out any DX8 formats
  1565. if (lpRetDescs[i].ddpfPixelFormat.dwFlags & DDPF_D3DFORMAT)
  1566. {
  1567. continue;
  1568. }
  1569. // Filter out non-DXTn FourCCs if apphack set
  1570. if ( bFourCCAppHack && (lpRetDescs[i].ddpfPixelFormat.dwFlags == DDPF_FOURCC) )
  1571. {
  1572. if ( (lpRetDescs[i].ddpfPixelFormat.dwFourCC != MAKEFOURCC('D', 'X', 'T', '1')) &&
  1573. (lpRetDescs[i].ddpfPixelFormat.dwFourCC != MAKEFOURCC('D', 'X', 'T', '2')) &&
  1574. (lpRetDescs[i].ddpfPixelFormat.dwFourCC != MAKEFOURCC('D', 'X', 'T', '3')) &&
  1575. (lpRetDescs[i].ddpfPixelFormat.dwFourCC != MAKEFOURCC('D', 'X', 'T', '4')) &&
  1576. (lpRetDescs[i].ddpfPixelFormat.dwFourCC != MAKEFOURCC('D', 'X', 'T', '5')) )
  1577. {
  1578. D3D_INFO(3, "EnumTextureFormats: filtering non-DXT FourCC format <%08x>",
  1579. lpRetDescs[i].ddpfPixelFormat.dwFourCC);
  1580. continue;
  1581. }
  1582. }
  1583. userRet = (*lpEnumCallback)(&(lpRetDescs[i].ddpfPixelFormat), lpContext);
  1584. }
  1585. D3DFree(lpRetDescs);
  1586. return (D3D_OK);
  1587. }
  1588. catch (HRESULT ret)
  1589. {
  1590. return ret;
  1591. }
  1592. }
  1593. #if COLLECTSTATS
  1594. #undef DPF_MODNAME
  1595. #define DPF_MODNAME "Direct3DDevice::ResetStats"
  1596. void DIRECT3DDEVICEI::ResetTexStats()
  1597. {
  1598. this->lpDirect3DI->ResetTexStats();
  1599. memset(&m_texstats, 0, sizeof(D3DDEVINFO_TEXTURING));
  1600. }
  1601. #endif
  1602. #undef DPF_MODNAME
  1603. #define DPF_MODNAME "Direct3DDevice::BeginScene"
  1604. HRESULT D3DAPI DIRECT3DDEVICEI::BeginScene()
  1605. {
  1606. #ifdef PROFILE4
  1607. static DWORD dwFrameCount = 0;
  1608. #endif
  1609. #ifdef PROFILE
  1610. static DWORD dwFrameCount = 0;
  1611. #endif
  1612. try
  1613. {
  1614. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1615. if (!VALID_DIRECT3DDEVICE_PTR(this))
  1616. {
  1617. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1618. return DDERR_INVALIDOBJECT;
  1619. }
  1620. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)
  1621. {
  1622. D3D_ERR("BeginScene, already in scene.");
  1623. return (D3DERR_SCENE_IN_SCENE);
  1624. }
  1625. // Check if we lost surfaces or rtarget / zbuffer was locked
  1626. HRESULT servRet = this->CheckSurfaces();
  1627. if (servRet != D3D_OK)
  1628. {
  1629. // If we lost surfaces
  1630. if (servRet == DDERR_SURFACELOST)
  1631. {
  1632. // Even if the app restores the rendertargets and z buffer, it
  1633. // doesn't know anything about vidmem execute buffers or
  1634. // managed texture surfaces in vidmem. So, we need to do
  1635. // this on our own. We first check if it is safe to restore
  1636. // surfaces. If not, we fail in the usual way. Else, we
  1637. // do the restore. Note that we will fail *only* if the
  1638. // app calls BeginScene at the wrong time.
  1639. servRet = this->lpDirect3DI->lpDD7->TestCooperativeLevel();
  1640. if (servRet == DD_OK)
  1641. {
  1642. // Everything must be evicted otherwise Restore might not work
  1643. // as there might be new surface allocated, in fact, we should
  1644. // post a flag in Device so that Texture manage stop calling
  1645. // CreateSurface() if this flag is indicating TestCooperativeLevel()
  1646. // failed, however, even we added those, the EvictTextures below
  1647. // is still needed but not this critical--kanqiu
  1648. this->lpDirect3DI->lpTextureManager->EvictTextures();
  1649. if(IS_DP2HAL_DEVICE(this))
  1650. {
  1651. // We just bother restoring our internal vertex and command buffers
  1652. // It is upto the app to restore all surfaces that IT allocated.
  1653. // (managed textures are taken care of by the preceding evict)
  1654. CDirect3DDeviceIDP2 *dp2dev = static_cast<CDirect3DDeviceIDP2*>(this);
  1655. servRet = dp2dev->TLVbuf_GetDDS()->Restore();
  1656. if (servRet != DD_OK)
  1657. return D3DERR_SCENE_BEGIN_FAILED;
  1658. servRet = dp2dev->lpDDSCB1->Restore();
  1659. if (servRet != DD_OK)
  1660. return D3DERR_SCENE_BEGIN_FAILED;
  1661. // If TLVbuf was really lost
  1662. if (dp2dev->TLVbuf_GetVBI()->position.lpvData == 0)
  1663. {
  1664. DPF(10, "Need to reallocate TLVbuf");
  1665. // Reallocate TLVbuf of the orig size in the same memory location as before
  1666. dp2dev->TLVbuf_base = 0;
  1667. DWORD origSize = dp2dev->TLVbuf_size;
  1668. dp2dev->TLVbuf_size = 0;
  1669. if (dp2dev->TLVbuf_Grow(origSize, (this->dwDeviceFlags & D3DDEV_TLVBUFWRITEONLY) != 0) != DD_OK)
  1670. {
  1671. D3D_ERR( "Out of memory in BeginScene (TLVbuf)" );
  1672. return DDERR_OUTOFMEMORY;
  1673. }
  1674. }
  1675. // Release current VB since it could be app created and app might want
  1676. // to get rid of it due to the mode change.
  1677. if (dp2dev->lpDP2CurrBatchVBI)
  1678. {
  1679. dp2dev->lpDP2CurrBatchVBI->lpDevIBatched = NULL;
  1680. dp2dev->lpDP2CurrBatchVBI->Release();
  1681. }
  1682. dp2dev->lpDP2CurrBatchVBI = dp2dev->TLVbuf_GetVBI();
  1683. dp2dev->lpDP2CurrBatchVBI->AddRef();
  1684. dp2dev->dp2data.lpDDVertex = DDSLCL(dp2dev->TLVbuf_GetDDS());
  1685. dp2dev->dp2data.dwVertexLength = 0;
  1686. #ifdef VTABLE_HACK
  1687. dp2dev->VtblDrawPrimitiveDefault();
  1688. dp2dev->VtblDrawPrimitiveVBDefault();
  1689. dp2dev->VtblDrawIndexedPrimitiveDefault();
  1690. dp2dev->VtblDrawIndexedPrimitiveVBDefault();
  1691. #endif
  1692. }
  1693. servRet = this->CheckSurfaces();
  1694. if(servRet != D3D_OK)
  1695. return servRet;
  1696. this->dwFEFlags &= ~D3DFE_LOSTSURFACES;
  1697. }
  1698. else
  1699. return DDERR_SURFACELOST;
  1700. }
  1701. else
  1702. {
  1703. // Render target and / or the z buffer was locked
  1704. return servRet;
  1705. }
  1706. }
  1707. else
  1708. {
  1709. // We need to check if TLVbuf was lost. The app could have restored
  1710. // all surfaces and thus we might not know by check TCL. However the
  1711. // BreakLock function would have been called on the VB and the position.lpvData
  1712. // would be set to NULL. We check this to detect that the TLVbuf was lost.
  1713. if (IS_DP2HAL_DEVICE(this))
  1714. {
  1715. CDirect3DDeviceIDP2 *dp2dev = static_cast<CDirect3DDeviceIDP2*>(this);
  1716. // If the lock was broken
  1717. if (dp2dev->TLVbuf_GetVBI()->position.lpvData == 0)
  1718. {
  1719. DPF(10, "Broken lock on TLVbuf. Need to reallocate");
  1720. // Reallocate TLVbuf of the orig size in the same memory location as before
  1721. dp2dev->TLVbuf_base = 0;
  1722. DWORD origSize = dp2dev->TLVbuf_size;
  1723. dp2dev->TLVbuf_size = 0;
  1724. if (dp2dev->TLVbuf_Grow(origSize, (this->dwDeviceFlags & D3DDEV_TLVBUFWRITEONLY) != 0) != DD_OK)
  1725. {
  1726. D3D_ERR( "Out of memory in BeginScene (TLVbuf)" );
  1727. return DDERR_OUTOFMEMORY;
  1728. }
  1729. }
  1730. }
  1731. }
  1732. if (IS_DX7HAL_DEVICE(this))
  1733. {
  1734. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  1735. {
  1736. D3D_ERR("Cannot be recording state macros when calling BeginScene");
  1737. return (D3DERR_SCENE_END_FAILED);
  1738. }
  1739. servRet = SetRenderStateI((D3DRENDERSTATETYPE)D3DRENDERSTATE_SCENECAPTURE, TRUE);
  1740. }
  1741. else
  1742. servRet = D3DHAL_SceneCapture(this, TRUE);
  1743. if (servRet != D3D_OK && servRet != DDERR_NOTFOUND)
  1744. {
  1745. D3D_ERR("Could not BeginScene.");
  1746. return D3DERR_SCENE_BEGIN_FAILED;
  1747. }
  1748. #ifdef PROFILE4
  1749. if (++dwFrameCount == m_dwProfStart)
  1750. {
  1751. OutputDebugString("Direct3D IM 7.0: Started Profiling...\n");
  1752. StartProfile(PROFILE_THREADLEVEL, PROFILE_CURRENTID);
  1753. }
  1754. else if (dwFrameCount == m_dwProfStop)
  1755. {
  1756. StopProfile(PROFILE_THREADLEVEL, PROFILE_CURRENTID);
  1757. OutputDebugString("Direct3D IM 7.0: Stopped Profiling.\n");
  1758. }
  1759. #endif
  1760. #ifdef PROFILE
  1761. if (++dwFrameCount == m_dwProfStart)
  1762. {
  1763. OutputDebugString("Direct3D IM 7.0: Started Profiling...\n");
  1764. StartCAP();
  1765. }
  1766. else if (dwFrameCount == m_dwProfStop)
  1767. {
  1768. StopCAP();
  1769. OutputDebugString("Direct3D IM 7.0: Stopped Profiling.\n");
  1770. }
  1771. #endif
  1772. // So that currently bound textures get scene stamped
  1773. m_dwStageDirty = (1ul << this->dwMaxTextureBlendStages) - 1ul;
  1774. this->dwFEFlags |= D3DFE_NEED_TEXTURE_UPDATE;
  1775. #if COLLECTSTATS
  1776. this->lpDirect3DI->lpTextureManager->ResetStatCounters();
  1777. this->ResetTexStats();
  1778. #endif
  1779. this->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_INSCENE;
  1780. return (D3D_OK);
  1781. }
  1782. catch (HRESULT ret)
  1783. {
  1784. return ret;
  1785. }
  1786. }
  1787. #if COLLECTSTATS
  1788. #undef DPF_MODNAME
  1789. #define DPF_MODNAME "Direct3DDevice::DisplayStats"
  1790. void DIRECT3DDEVICEI::DisplayStats()
  1791. {
  1792. HDC hDC;
  1793. if(SUCCEEDED(this->lpDDSTarget_DDS7->GetDC(&hDC)))
  1794. {
  1795. HFONT hOldFont = (HFONT)SelectObject(hDC, this->lpDirect3DI->m_hFont);
  1796. SetTextColor(hDC, RGB(255,255,0));
  1797. SetBkMode(hDC, TRANSPARENT);
  1798. D3DDEVINFO_TEXTUREMANAGER stats;
  1799. GetInfo(D3DDEVINFOID_TEXTUREMANAGER, &stats, sizeof(D3DDEVINFO_TEXTUREMANAGER));
  1800. char str[256];
  1801. int x = STATS_FONT_SIZE, y = STATS_FONT_SIZE, len;
  1802. len = sprintf(str, "Texture Cache Management Statistics");
  1803. TextOut( hDC, x, y, str, len );
  1804. y += STATS_FONT_SIZE;
  1805. len = sprintf(str, "-----------------------------------");
  1806. TextOut( hDC, x, y, str, len );
  1807. y += STATS_FONT_SIZE;
  1808. len = sprintf(str, "Thrashing : %s", stats.bThrashing ? "Yes" : "No");
  1809. TextOut( hDC, x, y, str, len );
  1810. y += STATS_FONT_SIZE;
  1811. len = sprintf(str, "Downloaded : %d bytes", stats.dwApproxBytesDownloaded);
  1812. TextOut( hDC, x, y, str, len );
  1813. y += STATS_FONT_SIZE;
  1814. len = sprintf(str, "Evicts : %d", stats.dwNumEvicts);
  1815. TextOut( hDC, x, y, str, len );
  1816. y += STATS_FONT_SIZE;
  1817. len = sprintf(str, "Creates : %d", stats.dwNumVidCreates);
  1818. TextOut( hDC, x, y, str, len );
  1819. y += STATS_FONT_SIZE;
  1820. len = sprintf(str, "Textures used : %d", stats.dwNumTexturesUsed);
  1821. TextOut( hDC, x, y, str, len );
  1822. y += STATS_FONT_SIZE;
  1823. len = sprintf(str, "Hit rate : %d%%", stats.dwNumTexturesUsed != 0 ? ((stats.dwNumUsedTexInVid * 100) / stats.dwNumTexturesUsed) : 0);
  1824. TextOut( hDC, x, y, str, len );
  1825. y += STATS_FONT_SIZE;
  1826. len = sprintf(str, "Working set : %d (%d bytes)", stats.dwWorkingSet, stats.dwWorkingSetBytes);
  1827. TextOut( hDC, x, y, str, len );
  1828. y += STATS_FONT_SIZE;
  1829. len = sprintf(str, "Total managed : %d (%d bytes)", stats.dwTotalManaged, stats.dwTotalBytes);
  1830. TextOut( hDC, x, y, str, len );
  1831. D3DDEVINFO_TEXTURING texstats;
  1832. GetInfo(D3DDEVINFOID_TEXTURING, &texstats, sizeof(D3DDEVINFO_TEXTURING));
  1833. y += STATS_FONT_SIZE * 2;
  1834. len = sprintf(str, "Texturing Statistics");
  1835. TextOut( hDC, x, y, str, len );
  1836. y += STATS_FONT_SIZE;
  1837. len = sprintf(str, "--------------------");
  1838. TextOut( hDC, x, y, str, len );
  1839. y += STATS_FONT_SIZE;
  1840. len = sprintf(str, "Loads : %d (%d bytes)", texstats.dwNumLoads, texstats.dwApproxBytesLoaded);
  1841. TextOut( hDC, x, y, str, len );
  1842. y += STATS_FONT_SIZE;
  1843. len = sprintf(str, "PreLoads : %d", texstats.dwNumPreLoads);
  1844. TextOut( hDC, x, y, str, len );
  1845. y += STATS_FONT_SIZE;
  1846. len = sprintf(str, "SetTextures : %d", texstats.dwNumSet);
  1847. TextOut( hDC, x, y, str, len );
  1848. y += STATS_FONT_SIZE;
  1849. len = sprintf(str, "Creates : %d", texstats.dwNumCreates);
  1850. TextOut( hDC, x, y, str, len );
  1851. y += STATS_FONT_SIZE;
  1852. len = sprintf(str, "Destroys : %d", texstats.dwNumDestroys);
  1853. TextOut( hDC, x, y, str, len );
  1854. y += STATS_FONT_SIZE;
  1855. len = sprintf(str, "SetPriorities : %d", texstats.dwNumSetPriorities);
  1856. TextOut( hDC, x, y, str, len );
  1857. y += STATS_FONT_SIZE;
  1858. len = sprintf(str, "SetLODs : %d", texstats.dwNumSetLODs);
  1859. TextOut( hDC, x, y, str, len );
  1860. y += STATS_FONT_SIZE;
  1861. len = sprintf(str, "Locks : %d", texstats.dwNumLocks);
  1862. TextOut( hDC, x, y, str, len );
  1863. y += STATS_FONT_SIZE;
  1864. len = sprintf(str, "GetDCs : %d", texstats.dwNumGetDCs);
  1865. TextOut( hDC, x, y, str, len );
  1866. SelectObject(hDC, hOldFont);
  1867. this->lpDDSTarget_DDS7->ReleaseDC(hDC);
  1868. }
  1869. }
  1870. #endif
  1871. #undef DPF_MODNAME
  1872. #define DPF_MODNAME "Direct3DDevice::EndScene"
  1873. HRESULT D3DAPI DIRECT3DDEVICEI::EndScene()
  1874. {
  1875. HRESULT servRet;
  1876. try
  1877. {
  1878. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  1879. if (!VALID_DIRECT3DDEVICE_PTR(this))
  1880. {
  1881. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1882. return DDERR_INVALIDOBJECT;
  1883. }
  1884. if (!(this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)) {
  1885. D3D_ERR("EndScene, not in scene.");
  1886. return (D3DERR_SCENE_NOT_IN_SCENE);
  1887. }
  1888. this->dwHintFlags &= ~D3DDEVBOOL_HINTFLAGS_INSCENE;
  1889. if (IS_DX7HAL_DEVICE(this))
  1890. {
  1891. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  1892. {
  1893. D3D_ERR("Cannot be recording state macros when calling EndScene");
  1894. return (D3DERR_SCENE_END_FAILED);
  1895. }
  1896. servRet = SetRenderStateI((D3DRENDERSTATETYPE)D3DRENDERSTATE_SCENECAPTURE, FALSE);
  1897. if (servRet != D3D_OK)
  1898. {
  1899. D3D_ERR("Could not send EndScene to Driver!");
  1900. return (D3DERR_SCENE_END_FAILED);
  1901. }
  1902. servRet = FlushStates(); //time to flush DrawPrimitives
  1903. }
  1904. else
  1905. {
  1906. servRet = FlushStates(); //time to flush DrawPrimitives
  1907. if (servRet != D3D_OK)
  1908. {
  1909. D3D_ERR("Could not Flush commands in EndScene!");
  1910. return (D3DERR_SCENE_END_FAILED);
  1911. }
  1912. servRet = D3DHAL_SceneCapture(this, FALSE);
  1913. }
  1914. if (servRet != D3D_OK && servRet != DDERR_NOTFOUND)
  1915. {
  1916. DPF(0, "(ERROR) Direct3DDevice::EndScene: Could not EndScene. Returning %08lx", servRet);
  1917. return (D3DERR_SCENE_END_FAILED);
  1918. }
  1919. // Did we lose any surfaces during this scene ?
  1920. if (this->dwFEFlags & D3DFE_LOSTSURFACES)
  1921. {
  1922. D3D_INFO(3, "reporting DDERR_SURFACELOST in EndScene");
  1923. this->dwFEFlags &= ~D3DFE_LOSTSURFACES;
  1924. return DDERR_SURFACELOST;
  1925. }
  1926. // Update the scene count in texman
  1927. lpDirect3DI->lpTextureManager->SceneStamp();
  1928. // Clear num TLVbuf changes per frame
  1929. if (IS_DP2HAL_DEVICE(this))
  1930. {
  1931. CDirect3DDeviceIDP2* dev = static_cast<CDirect3DDeviceIDP2*>(this);
  1932. dev->dwTLVbufChanges = 0;
  1933. }
  1934. #if COLLECTSTATS
  1935. // Display stats if they have been enabled via regkey
  1936. if(this->lpDirect3DI->m_hFont != 0)
  1937. {
  1938. DisplayStats();
  1939. }
  1940. #endif
  1941. return (D3D_OK);
  1942. }
  1943. catch (HRESULT ret)
  1944. {
  1945. return ret;
  1946. }
  1947. }
  1948. void
  1949. D3DDeviceDescConvert(LPD3DDEVICEDESC7 lpOut,
  1950. LPD3DDEVICEDESC_V1 lpV1,
  1951. LPD3DHAL_D3DEXTENDEDCAPS lpExt)
  1952. {
  1953. if( lpV1 )
  1954. {
  1955. lpOut->dwDevCaps = lpV1->dwDevCaps;
  1956. lpOut->dpcLineCaps = lpV1->dpcLineCaps;
  1957. lpOut->dpcTriCaps = lpV1->dpcTriCaps;
  1958. lpOut->dwDeviceRenderBitDepth = lpV1->dwDeviceRenderBitDepth;
  1959. lpOut->dwDeviceZBufferBitDepth = lpV1->dwDeviceZBufferBitDepth;
  1960. }
  1961. if (lpExt)
  1962. {
  1963. // DX5
  1964. lpOut->dwMinTextureWidth = lpExt->dwMinTextureWidth;
  1965. lpOut->dwMaxTextureWidth = lpExt->dwMaxTextureWidth;
  1966. lpOut->dwMinTextureHeight = lpExt->dwMinTextureHeight;
  1967. lpOut->dwMaxTextureHeight = lpExt->dwMaxTextureHeight;
  1968. // DX6
  1969. lpOut->dwMaxTextureRepeat = lpExt->dwMaxTextureRepeat;
  1970. lpOut->dwMaxTextureAspectRatio = lpExt->dwMaxTextureAspectRatio;
  1971. lpOut->dwMaxAnisotropy = lpExt->dwMaxAnisotropy;
  1972. lpOut->dvGuardBandLeft = lpExt->dvGuardBandLeft;
  1973. lpOut->dvGuardBandTop = lpExt->dvGuardBandTop;
  1974. lpOut->dvGuardBandRight = lpExt->dvGuardBandRight;
  1975. lpOut->dvGuardBandBottom = lpExt->dvGuardBandBottom;
  1976. lpOut->dvExtentsAdjust = lpExt->dvExtentsAdjust;
  1977. lpOut->dwStencilCaps = lpExt->dwStencilCaps;
  1978. lpOut->dwFVFCaps = lpExt->dwFVFCaps;
  1979. lpOut->dwTextureOpCaps = lpExt->dwTextureOpCaps;
  1980. lpOut->wMaxTextureBlendStages = lpExt->wMaxTextureBlendStages;
  1981. lpOut->wMaxSimultaneousTextures = lpExt->wMaxSimultaneousTextures;
  1982. // DX7
  1983. lpOut->dwMaxActiveLights = lpExt->dwMaxActiveLights;
  1984. lpOut->dvMaxVertexW = lpExt->dvMaxVertexW;
  1985. lpOut->wMaxUserClipPlanes = lpExt->wMaxUserClipPlanes;
  1986. lpOut->wMaxVertexBlendMatrices = lpExt->wMaxVertexBlendMatrices;
  1987. lpOut->dwVertexProcessingCaps = lpExt->dwVertexProcessingCaps;
  1988. lpOut->dwReserved1 = lpExt->dwReserved1;
  1989. lpOut->dwReserved2 = lpExt->dwReserved2;
  1990. lpOut->dwReserved3 = lpExt->dwReserved3;
  1991. lpOut->dwReserved4 = lpExt->dwReserved4;
  1992. }
  1993. }
  1994. //---------------------------------------------------------------------
  1995. #undef DPF_MODNAME
  1996. #define DPF_MODNAME "DIRECT3DDEVICEI::CheckSurfaces"
  1997. HRESULT DIRECT3DDEVICEI::CheckSurfaces()
  1998. {
  1999. if(this->lpDirect3DI->lpTextureManager->CheckIfLost())
  2000. {
  2001. D3D_ERR("Managed Textures lost");
  2002. return DDERR_SURFACELOST;
  2003. }
  2004. if ( ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSTarget)->lpLcl->lpGbl->dwUsageCount ||
  2005. (this->lpDDSZBuffer && ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSZBuffer)->lpLcl->lpGbl->dwUsageCount) )
  2006. {
  2007. D3D_ERR("Render target or Z buffer locked");
  2008. return DDERR_SURFACEBUSY;
  2009. }
  2010. if ( ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSTarget)->lpLcl->dwFlags & DDRAWISURF_INVALID )\
  2011. {
  2012. D3D_ERR("Render target buffer lost");
  2013. return DDERR_SURFACELOST;
  2014. }
  2015. if ( this->lpDDSZBuffer && ( ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSZBuffer)->lpLcl->dwFlags & DDRAWISURF_INVALID ) )
  2016. {
  2017. D3D_ERR("Z buffer lost");
  2018. return DDERR_SURFACELOST;
  2019. }
  2020. return D3D_OK;
  2021. }
  2022. //---------------------------------------------------------------------
  2023. #undef DPF_MODNAME
  2024. #define DPF_MODNAME "DIRECT3DDEVICEI::GetDirect3D"
  2025. HRESULT D3DAPI DIRECT3DDEVICEI::GetDirect3D(LPDIRECT3D7 *lplpD3D)
  2026. {
  2027. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2028. if (!VALID_DIRECT3DDEVICE_PTR(this))
  2029. {
  2030. D3D_ERR( "Invalid Direct3DDevice pointer" );
  2031. return DDERR_INVALIDOBJECT;
  2032. }
  2033. if (!VALID_OUTPTR(lplpD3D))
  2034. {
  2035. D3D_ERR( "Invalid Direct3D pointer pointer" );
  2036. return DDERR_INVALIDPARAMS;
  2037. }
  2038. *lplpD3D = (LPDIRECT3D7) this->lpDirect3DI;
  2039. (*lplpD3D)->AddRef();
  2040. return (D3D_OK);
  2041. }
  2042. //---------------------------------------------------------------------
  2043. #undef DPF_MODNAME
  2044. #define DPF_MODNAME "DIRECT3DDEVICEI::HookTexture"
  2045. LPD3DI_TEXTUREBLOCK DIRECT3DDEVICEI::HookTexture(LPDIRECT3DTEXTUREI lpD3DText)
  2046. {
  2047. LPD3DI_TEXTUREBLOCK nBlock;
  2048. if (D3DMalloc((void**)&nBlock, sizeof(D3DI_TEXTUREBLOCK)) != D3D_OK)
  2049. {
  2050. D3D_ERR("failed to allocate space for texture block");
  2051. return NULL;
  2052. }
  2053. nBlock->lpDevI = this;
  2054. nBlock->lpD3DTextureI = lpD3DText;
  2055. nBlock->hTex = 0; // initialized to be zero
  2056. LIST_INSERT_ROOT(&lpD3DText->blocks, nBlock, list);
  2057. LIST_INSERT_ROOT(&texBlocks, nBlock, devList);
  2058. return nBlock;
  2059. }
  2060. //---------------------------------------------------------------------
  2061. #undef DPF_MODNAME
  2062. #define DPF_MODNAME "DIRECT3DDEVICEI::D3DI_FindTextureBlock"
  2063. LPD3DI_TEXTUREBLOCK DIRECT3DDEVICEI::D3DI_FindTextureBlock(LPDIRECT3DTEXTUREI lpTex)
  2064. {
  2065. LPD3DI_TEXTUREBLOCK tBlock;
  2066. tBlock = LIST_FIRST(&lpTex->blocks);
  2067. while (tBlock) {
  2068. // return match for Texture(2) only (not Texture3)
  2069. if (tBlock->lpDevI == this) {
  2070. return tBlock;
  2071. }
  2072. tBlock = LIST_NEXT(tBlock,list);
  2073. }
  2074. return NULL;
  2075. }
  2076. //---------------------------------------------------------------------
  2077. #undef DPF_MODNAME
  2078. #define DPF_MODNAME "DIRECT3DDEVICEI::GetTextureDDIHandle"
  2079. HRESULT DIRECT3DDEVICEI::GetTextureDDIHandle(LPDIRECT3DTEXTUREI lpTexI,
  2080. LPD3DI_TEXTUREBLOCK* lplpBlock)
  2081. {
  2082. HRESULT ret;
  2083. LPD3DI_TEXTUREBLOCK lpBlock=*lplpBlock; //in case has the pointer
  2084. DDASSERT(lpTexI);
  2085. /*
  2086. * Find out if we've used this device before.
  2087. */
  2088. if (!lpBlock)
  2089. {
  2090. lpBlock = D3DI_FindTextureBlock(lpTexI);
  2091. if (!lpBlock)
  2092. {
  2093. /*
  2094. * Put this device in the list of those owned by the
  2095. * Direct3DDevice object
  2096. */
  2097. lpBlock=HookTexture(lpTexI);
  2098. if (!lpBlock)
  2099. {
  2100. D3D_ERR("failed to associate texture with device");
  2101. return DDERR_OUTOFMEMORY;
  2102. }
  2103. }
  2104. *lplpBlock = lpBlock;
  2105. }
  2106. if (!lpBlock->hTex)
  2107. {
  2108. if (lpTexI->D3DManaged())
  2109. {
  2110. if(!lpTexI->InVidmem()) // This check covers the case when hTex is zero,
  2111. // but there ALREADY IS a vidmem copy don't
  2112. // create another one. This case arises when
  2113. // InvalidateHandles() is called by SetRenderTarget.
  2114. {
  2115. ret = lpDirect3DI->lpTextureManager->allocNode(lpTexI, this);
  2116. if (D3D_OK != ret)
  2117. {
  2118. D3D_ERR("Failed to create video memory surface");
  2119. return ret;
  2120. }
  2121. }
  2122. lpDirect3DI->lpTextureManager->TimeStamp(lpTexI);
  2123. }
  2124. CLockD3DST lockObject(this, DPF_MODNAME, REMIND(""));
  2125. if (D3D_OK != (ret=D3DHAL_TextureCreate(this, &lpBlock->hTex, (LPDIRECTDRAWSURFACE)&(lpTexI->DDS1Tex))))
  2126. return ret;
  2127. }
  2128. else
  2129. {
  2130. if(lpTexI->D3DManaged())
  2131. lpDirect3DI->lpTextureManager->TimeStamp(lpTexI);
  2132. }
  2133. DDASSERT(lpBlock->hTex);
  2134. return D3D_OK;
  2135. }
  2136. #if COLLECTSTATS
  2137. #undef DPF_MODNAME
  2138. #define DPF_MODNAME "BytesDownloaded"
  2139. DWORD BytesDownloaded(LPDDRAWI_DDRAWSURFACE_LCL lpLcl, LPRECT lpRect)
  2140. {
  2141. DWORD bytes;
  2142. if( (lpLcl->dwFlags & DDRAWISURF_HASPIXELFORMAT) &&
  2143. (lpLcl->lpGbl->ddpfSurface.dwFlags & DDPF_FOURCC) )
  2144. {
  2145. switch (lpLcl->lpGbl->ddpfSurface.dwFourCC)
  2146. {
  2147. case FOURCC_DXT1:
  2148. case FOURCC_DXT2:
  2149. case FOURCC_DXT3:
  2150. case FOURCC_DXT4:
  2151. case FOURCC_DXT5:
  2152. if(lpRect == NULL)
  2153. {
  2154. bytes = lpLcl->lpGbl->dwLinearSize;
  2155. }
  2156. else
  2157. {
  2158. bytes = (DWORD)(lpLcl->lpGbl->dwLinearSize * (double((lpRect->right - lpRect->left) * (lpRect->bottom - lpRect->top)) /
  2159. double(lpLcl->lpGbl->wWidth * lpLcl->lpGbl->wHeight)));
  2160. }
  2161. return lpLcl->lpSurfMore->dwMipMapCount == 0 ? bytes : (DWORD)(bytes * ((1. - pow(.25, lpLcl->lpSurfMore->dwMipMapCount)) / .75));
  2162. }
  2163. }
  2164. if(lpRect == NULL)
  2165. {
  2166. bytes = lpLcl->lpGbl->lPitch * lpLcl->lpGbl->wHeight;
  2167. }
  2168. else
  2169. {
  2170. bytes = (DWORD)(lpLcl->lpGbl->lPitch * lpLcl->lpGbl->wHeight *
  2171. (double((lpRect->right - lpRect->left) * (lpRect->bottom - lpRect->top)) /
  2172. double(lpLcl->lpGbl->wWidth * lpLcl->lpGbl->wHeight)));
  2173. }
  2174. return lpLcl->lpSurfMore->dwMipMapCount == 0 ? bytes : (DWORD)(bytes * ((1. - pow(.25, lpLcl->lpSurfMore->dwMipMapCount)) / .75));
  2175. }
  2176. #endif
  2177. //---------------------------------------------------------------------
  2178. #undef DPF_MODNAME
  2179. #define DPF_MODNAME "DIRECT3DDEVICEI::PreLoad"
  2180. HRESULT D3DAPI DIRECT3DDEVICEI::PreLoad(LPDIRECTDRAWSURFACE7 lpSrc)
  2181. {
  2182. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  2183. // Release in the destructor
  2184. if(!(this->dwFEFlags & D3DFE_REALHAL))
  2185. {
  2186. D3D_WARN(2, "PreLoad called on a software device");
  2187. return D3D_OK;
  2188. }
  2189. return PreLoadFast(lpSrc);
  2190. }
  2191. //---------------------------------------------------------------------
  2192. #undef DPF_MODNAME
  2193. #define DPF_MODNAME "DIRECT3DDEVICEI::PreLoadFast"
  2194. HRESULT D3DAPI DIRECT3DDEVICEI::PreLoadFast(LPDIRECTDRAWSURFACE7 lpSrc)
  2195. {
  2196. #if DBG
  2197. if (!VALID_DIRECT3DDEVICE_PTR(this))
  2198. {
  2199. D3D_ERR( "Invalid DIRECT3DDEVICE7 pointer" );
  2200. return DDERR_INVALIDOBJECT;
  2201. }
  2202. if (!VALID_DDSURF_PTR(lpSrc))
  2203. {
  2204. D3D_ERR( "Invalid DIRECTDRAWSURFACE7 source pointer" );
  2205. return DDERR_INVALIDOBJECT;
  2206. }
  2207. if(!IsToplevel(((LPDDRAWI_DDRAWSURFACE_INT)lpSrc)->lpLcl))
  2208. {
  2209. D3D_ERR( "Cannot PreLoad a mipmap sublevel or a cubemap subface" );
  2210. return DDERR_INVALIDPARAMS;
  2211. }
  2212. #endif
  2213. LPDIRECT3DTEXTUREI this_src = reinterpret_cast<LPDIRECT3DTEXTUREI>(((LPDDRAWI_DDRAWSURFACE_INT)lpSrc)->lpLcl->lpSurfMore->lpTex);
  2214. #if DBG
  2215. if (this_src == NULL)
  2216. {
  2217. D3D_ERR( "Not a texture" );
  2218. return DDERR_INVALIDPARAMS;
  2219. }
  2220. #endif
  2221. #if COLLECTSTATS
  2222. this->IncNumPreLoads();
  2223. #endif
  2224. try
  2225. {
  2226. HRESULT ddrval = D3D_OK;
  2227. if (!this_src->D3DManaged())
  2228. {
  2229. #if DBG
  2230. // Make sure that texture is driver managed
  2231. if(!(DDSCAPS2_TEXTUREMANAGE & ((LPDDRAWI_DDRAWSURFACE_INT)(this_src->lpDDS))->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2))
  2232. {
  2233. D3D_ERR( "Cannot PreLoad unmanaged textures" );
  2234. return DDERR_INVALIDPARAMS;
  2235. }
  2236. #endif
  2237. if(this->lpDirect3DI->numDevs > 1)
  2238. {
  2239. D3D_WARN(2, "Multiple devices used. Calling Flush");
  2240. ddrval = this->lpDirect3DI->FlushDevicesExcept(this); // to avoid sync problems
  2241. if(ddrval != D3D_OK)
  2242. {
  2243. D3D_ERR("Error flushing devices");
  2244. return ddrval;
  2245. }
  2246. }
  2247. POINT p = {0, 0};
  2248. RECTL r = {0, 0, 0, 0};
  2249. DDASSERT(IS_DX7HAL_DEVICE(this));
  2250. ddrval = static_cast<CDirect3DDevice7*>(this)->TexBltI(NULL, ((LPDDRAWI_DDRAWSURFACE_INT)(this_src->lpDDS))->lpLcl, &p, &r, 0);
  2251. if(ddrval != D3D_OK)
  2252. {
  2253. DPF_ERR("Error inserting TexBlt instruction in batch");
  2254. return ddrval;
  2255. }
  2256. if(this->lpDirect3DI->numDevs > 1)
  2257. {
  2258. ddrval = FlushStates(); // to avoid sync problems
  2259. if(ddrval != D3D_OK)
  2260. {
  2261. D3D_ERR("Error flushing device");
  2262. return ddrval;
  2263. }
  2264. }
  2265. else
  2266. {
  2267. BatchTexture(((LPDDRAWI_DDRAWSURFACE_INT)(this_src->lpDDS))->lpLcl);
  2268. }
  2269. }
  2270. else if (this_src->InVidmem())
  2271. {
  2272. if (this_src->bDirty)
  2273. {
  2274. // 0xFFFFFFFF is equivalent to ALL_FACES, but in addition indicates to CopySurface
  2275. // that this is a sysmem -> vidmem transfer.
  2276. ddrval = CopySurface(this_src->lpDDS,NULL,this_src->lpDDSSys,NULL,0xFFFFFFFF);
  2277. if (DD_OK == ddrval)
  2278. {
  2279. this_src->bDirty=FALSE;
  2280. D3D_INFO(4,"Load: Dirty texture updated");
  2281. }
  2282. }
  2283. #if COLLECTSTATS
  2284. this->lpDirect3DI->lpTextureManager->IncNumTexturesSet();
  2285. this->lpDirect3DI->lpTextureManager->IncNumSetTexInVid();
  2286. #endif
  2287. }
  2288. else
  2289. {
  2290. if(IS_DX7HAL_DEVICE(this))
  2291. {
  2292. D3DTEXTUREHANDLE hTex;
  2293. ddrval = static_cast<CDirect3DDevice7*>(this)->GetTextureDDIHandle(this_src, &hTex);
  2294. }
  2295. else
  2296. {
  2297. LPD3DI_TEXTUREBLOCK lpBlock = NULL;
  2298. ddrval = GetTextureDDIHandle(this_src, &lpBlock);
  2299. }
  2300. #if COLLECTSTATS
  2301. this->lpDirect3DI->lpTextureManager->IncNumTexturesSet();
  2302. #endif
  2303. }
  2304. return ddrval;
  2305. }
  2306. catch (HRESULT ret)
  2307. {
  2308. return ret;
  2309. }
  2310. }
  2311. //---------------------------------------------------------------------
  2312. #undef DPF_MODNAME
  2313. #define DPF_MODNAME "DIRECT3DDEVICEI::Load"
  2314. HRESULT D3DAPI DIRECT3DDEVICEI::Load(LPDIRECTDRAWSURFACE7 lpDest, LPPOINT lpDestPoint,
  2315. LPDIRECTDRAWSURFACE7 lpSrc, LPRECT lpSrcRect, DWORD dwFlags)
  2316. {
  2317. LPDIRECT3DTEXTUREI this_src, this_dst;
  2318. HRESULT ddrval = D3D_OK;
  2319. LPDIRECTDRAWSURFACE7 lpDDSSrc, lpDDSDst;
  2320. try
  2321. {
  2322. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock (can't take MT since code accesses DDraw surf global)
  2323. // Release in the destructor
  2324. #if DBG
  2325. // validate args
  2326. if(lpDestPoint != NULL && lpSrcRect == NULL)
  2327. {
  2328. D3D_ERR( "Cannot have NULL src rect and non-NULL dest" );
  2329. return DDERR_INVALIDPARAMS;
  2330. }
  2331. if(lpDestPoint != NULL)
  2332. {
  2333. if(!VALID_GDIPOINT_PTR(lpDestPoint))
  2334. {
  2335. D3D_ERR( "Invalid POINT pointer" );
  2336. return DDERR_INVALIDOBJECT;
  2337. }
  2338. }
  2339. if(lpSrcRect != NULL)
  2340. {
  2341. if(!VALID_GDIRECT_PTR(lpSrcRect))
  2342. {
  2343. D3D_ERR( "Invalid RECT pointer" );
  2344. return DDERR_INVALIDOBJECT;
  2345. }
  2346. }
  2347. if(dwFlags & (~DDSCAPS2_CUBEMAP_ALLFACES))
  2348. {
  2349. D3D_ERR( "Invalid flags" );
  2350. return DDERR_INVALIDPARAMS;
  2351. }
  2352. if (!VALID_DIRECT3DDEVICE_PTR(this))
  2353. {
  2354. D3D_ERR( "Invalid DIRECT3DDEVICE7 pointer" );
  2355. return DDERR_INVALIDOBJECT;
  2356. }
  2357. if (!VALID_DDSURF_PTR(lpDest))
  2358. {
  2359. D3D_ERR( "Invalid DIRECTDRAWSURFACE7 dest pointer" );
  2360. return DDERR_INVALIDOBJECT;
  2361. }
  2362. if(!IsToplevel(((LPDDRAWI_DDRAWSURFACE_INT)lpDest)->lpLcl))
  2363. {
  2364. D3D_ERR( "Cannot Load to a mipmap sublevel or a cubemap subface" );
  2365. return DDERR_INVALIDPARAMS;
  2366. }
  2367. #endif
  2368. this_dst = reinterpret_cast<LPDIRECT3DTEXTUREI>(((LPDDRAWI_DDRAWSURFACE_INT)lpDest)->lpLcl->lpSurfMore->lpTex);
  2369. #if DBG
  2370. if(this_dst == NULL)
  2371. {
  2372. D3D_ERR( "Destination surface not a texture" );
  2373. return DDERR_INVALIDPARAMS;
  2374. }
  2375. if (!VALID_DDSURF_PTR(lpSrc))
  2376. {
  2377. D3D_ERR( "Invalid DIRECTDRAWSURFACE7 source pointer" );
  2378. return DDERR_INVALIDOBJECT;
  2379. }
  2380. if(!IsToplevel(((LPDDRAWI_DDRAWSURFACE_INT)lpSrc)->lpLcl))
  2381. {
  2382. D3D_ERR( "Cannot Load from a mipmap sublevel or a cubemap subface" );
  2383. return DDERR_INVALIDPARAMS;
  2384. }
  2385. #endif
  2386. this_src = reinterpret_cast<LPDIRECT3DTEXTUREI>(((LPDDRAWI_DDRAWSURFACE_INT)lpSrc)->lpLcl->lpSurfMore->lpTex);
  2387. #if DBG
  2388. if(this_src == NULL)
  2389. {
  2390. D3D_ERR( "Source surface not a texture" );
  2391. return DDERR_INVALIDPARAMS;
  2392. }
  2393. #endif
  2394. #if COLLECTSTATS
  2395. this->IncNumLoads();
  2396. #endif
  2397. if(this_src->D3DManaged())
  2398. lpDDSSrc = this_src->lpDDSSys;
  2399. else
  2400. lpDDSSrc = this_src->lpDDS;
  2401. RECT destRect, *lpDestRect;
  2402. if(lpDestPoint)
  2403. {
  2404. if(IsRectEmpty(lpSrcRect))
  2405. {
  2406. D3D_ERR( "Source rectangle is empty" );
  2407. return DDERR_INVALIDPARAMS;
  2408. }
  2409. WORD &width = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSSrc)->lpLcl->lpGbl->wWidth;
  2410. WORD &height = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSSrc)->lpLcl->lpGbl->wHeight;
  2411. if(lpSrcRect->left < 0 ||
  2412. lpSrcRect->left >= width ||
  2413. lpSrcRect->top < 0 ||
  2414. lpSrcRect->top >= height ||
  2415. lpSrcRect->right <= 0 ||
  2416. lpSrcRect->right > width ||
  2417. lpSrcRect->bottom <= 0 ||
  2418. lpSrcRect->bottom > height)
  2419. {
  2420. D3D_ERR( "Rectangle outside source texture" );
  2421. return DDERR_INVALIDPARAMS;
  2422. }
  2423. destRect.left = lpDestPoint->x;
  2424. destRect.top = lpDestPoint->y;
  2425. destRect.right = lpDestPoint->x + (lpSrcRect->right - lpSrcRect->left);
  2426. destRect.bottom = lpDestPoint->y + (lpSrcRect->bottom - lpSrcRect->top);
  2427. lpDestRect = &destRect;
  2428. if(lpDestRect->left < 0 ||
  2429. lpDestRect->left >= width ||
  2430. lpDestRect->top < 0 ||
  2431. lpDestRect->top >= height ||
  2432. lpDestRect->right <= 0 ||
  2433. lpDestRect->right > width ||
  2434. lpDestRect->bottom <= 0 ||
  2435. lpDestRect->bottom > height)
  2436. {
  2437. D3D_ERR( "Rectangle outside destination texture" );
  2438. return DDERR_INVALIDPARAMS;
  2439. }
  2440. }
  2441. else
  2442. {
  2443. if(lpSrcRect)
  2444. {
  2445. if(IsRectEmpty(lpSrcRect))
  2446. {
  2447. D3D_ERR( "Source rectangle is empty" );
  2448. return DDERR_INVALIDPARAMS;
  2449. }
  2450. WORD &width = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSSrc)->lpLcl->lpGbl->wWidth;
  2451. WORD &height = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSSrc)->lpLcl->lpGbl->wHeight;
  2452. if(lpSrcRect->left < 0 ||
  2453. lpSrcRect->left >= width ||
  2454. lpSrcRect->top < 0 ||
  2455. lpSrcRect->top >= height ||
  2456. lpSrcRect->right <= 0 ||
  2457. lpSrcRect->right > width ||
  2458. lpSrcRect->bottom <= 0 ||
  2459. lpSrcRect->bottom > height)
  2460. {
  2461. D3D_ERR( "Source rectangle outside texture" );
  2462. return DDERR_INVALIDPARAMS;
  2463. }
  2464. destRect = *lpSrcRect;
  2465. lpDestRect = &destRect;
  2466. }
  2467. else
  2468. {
  2469. lpDestRect = NULL;
  2470. }
  2471. }
  2472. if(this_dst->D3DManaged())
  2473. lpDDSDst = this_dst->lpDDSSys;
  2474. else
  2475. lpDDSDst = this_dst->lpDDS;
  2476. ddrval = CopySurface(lpDDSDst, lpDestRect, lpDDSSrc, lpSrcRect, dwFlags);
  2477. return ddrval;
  2478. }
  2479. catch (HRESULT ret)
  2480. {
  2481. return ret;
  2482. }
  2483. }
  2484. #undef DPF_MODNAME
  2485. #define DPF_MODNAME "DIRECT3DDEVICEI::CanDoTexBlt"
  2486. bool DIRECT3DDEVICEI::CanDoTexBlt(LPDDRAWI_DDRAWSURFACE_LCL lpDDSSrcSubFace_lcl,
  2487. LPDDRAWI_DDRAWSURFACE_LCL lpDDSDstSubFace_lcl)
  2488. {
  2489. return false;
  2490. }
  2491. #undef DPF_MODNAME
  2492. #define DPF_MODNAME "DIRECT3DDEVICEI::CopySurface"
  2493. HRESULT DIRECT3DDEVICEI::CopySurface(LPDIRECTDRAWSURFACE7 lpDDSDst,
  2494. LPRECT lpDestRect,
  2495. LPDIRECTDRAWSURFACE7 lpDDSSrc,
  2496. LPRECT lpSrcRect,
  2497. DWORD dwFlags)
  2498. {
  2499. DDRAWI_DDRAWSURFACE_INT DDSSrcSubFace, DDSDstSubFace;
  2500. DDSSrcSubFace.lpVtbl = DDSDstSubFace.lpVtbl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSSrc)->lpVtbl;
  2501. DDSDstSubFace.lpLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSDst)->lpLcl;
  2502. DDSSrcSubFace.lpLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSSrc)->lpLcl;
  2503. LPDIRECTDRAWSURFACE7 lpDDSSrcSubFace = reinterpret_cast<LPDIRECTDRAWSURFACE7>(&DDSSrcSubFace);
  2504. LPDIRECTDRAWSURFACE7 lpDDSDstSubFace = reinterpret_cast<LPDIRECTDRAWSURFACE7>(&DDSDstSubFace);
  2505. CCubemapIter cmsrc(DDSSrcSubFace.lpLcl), cmdst(DDSDstSubFace.lpLcl);
  2506. while(true)
  2507. {
  2508. DDSSrcSubFace.lpLcl = cmsrc();
  2509. DDSDstSubFace.lpLcl = cmdst();
  2510. DWORD face = DDSSrcSubFace.lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
  2511. if(face != (DDSDstSubFace.lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES))
  2512. {
  2513. D3D_ERR("Destination texture has different cubemap faces than source");
  2514. return DDERR_INVALIDPARAMS;
  2515. }
  2516. if(face == 0 || (DDSSrcSubFace.lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & dwFlags))
  2517. {
  2518. HRESULT ddrval = D3D_OK;
  2519. DWORD psize = 0;
  2520. if (DDSDstSubFace.lpLcl->lpDDPalette)
  2521. {
  2522. if(DDSSrcSubFace.lpLcl->lpDDPalette)
  2523. {
  2524. const DWORD paltype = DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED2 | DDPF_PALETTEINDEXED1;
  2525. if((PixelFormat(DDSDstSubFace.lpLcl).dwFlags & paltype) != (PixelFormat(DDSSrcSubFace.lpLcl).dwFlags & paltype))
  2526. {
  2527. D3D_ERR("Src texture is has a different type of palette than dest");
  2528. return DDERR_INVALIDPARAMS;
  2529. }
  2530. switch(PixelFormat(DDSDstSubFace.lpLcl).dwFlags & paltype)
  2531. {
  2532. case DDPF_PALETTEINDEXED1:
  2533. psize = 2;
  2534. break;
  2535. case DDPF_PALETTEINDEXED2:
  2536. psize = 4;
  2537. break;
  2538. case DDPF_PALETTEINDEXED4:
  2539. psize = 16;
  2540. break;
  2541. case DDPF_PALETTEINDEXED8:
  2542. psize = 256;
  2543. break;
  2544. default:
  2545. D3D_ERR("Paletted texture format not supported");
  2546. return E_NOTIMPL;
  2547. }
  2548. ddrval = (reinterpret_cast<LPDIRECTDRAWPALETTE>(DDSDstSubFace.lpLcl->lpDDPalette))->SetEntries(0, 0, psize, DDSSrcSubFace.lpLcl->lpDDPalette->lpLcl->lpGbl->lpColorTable);
  2549. if (ddrval != DD_OK)
  2550. {
  2551. D3D_ERR("Failed to set palette entries in dest texture");
  2552. return ddrval;
  2553. }
  2554. }
  2555. else
  2556. {
  2557. D3D_WARN(2, "Destination texture has palette, but source has none");
  2558. }
  2559. }
  2560. /* Copy color keys */
  2561. if(DDSSrcSubFace.lpLcl->dwFlags & DDRAWISURF_HASCKEYDESTBLT)
  2562. lpDDSDstSubFace->SetColorKey(DDCKEY_DESTBLT, &DDSSrcSubFace.lpLcl->ddckCKDestBlt);
  2563. else if(DDSDstSubFace.lpLcl->dwFlags & DDRAWISURF_HASCKEYDESTBLT)
  2564. lpDDSDstSubFace->SetColorKey(DDCKEY_DESTBLT, NULL);
  2565. if(DDSSrcSubFace.lpLcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT)
  2566. lpDDSDstSubFace->SetColorKey(DDCKEY_SRCBLT, &DDSSrcSubFace.lpLcl->ddckCKSrcBlt);
  2567. else if(DDSDstSubFace.lpLcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT)
  2568. lpDDSDstSubFace->SetColorKey(DDCKEY_SRCBLT, NULL);
  2569. DDRAWI_DDRAWSURFACE_INT DDSSrcSubMip, DDSDstSubMip;
  2570. DDSSrcSubMip.lpVtbl = DDSDstSubMip.lpVtbl = DDSSrcSubFace.lpVtbl;
  2571. DDSDstSubMip.lpLcl = DDSDstSubFace.lpLcl;
  2572. DDSSrcSubMip.lpLcl = DDSSrcSubFace.lpLcl;
  2573. LPDIRECTDRAWSURFACE7 lpDDSSrcSubMip = reinterpret_cast<LPDIRECTDRAWSURFACE7>(&DDSSrcSubMip);
  2574. LPDIRECTDRAWSURFACE7 lpDDSDstSubMip = reinterpret_cast<LPDIRECTDRAWSURFACE7>(&DDSDstSubMip);
  2575. RECT SrcRct, DstRct, *lpSrcRct, *lpDstRct;
  2576. if(lpSrcRect)
  2577. {
  2578. SrcRct = *lpSrcRect;
  2579. lpSrcRct = &SrcRct;
  2580. }
  2581. else
  2582. lpSrcRct = NULL;
  2583. if(lpDestRect)
  2584. {
  2585. DstRct = *lpDestRect;
  2586. lpDstRct = &DstRct;
  2587. }
  2588. else
  2589. lpDstRct = NULL;
  2590. CMipmapIter mmsrc(DDSSrcSubMip.lpLcl), mmdst(DDSDstSubMip.lpLcl);
  2591. unsigned srcmipoff = 0;
  2592. while(mmsrc()->lpGbl->wHeight != mmdst()->lpGbl->wHeight || mmsrc()->lpGbl->wWidth != mmdst()->lpGbl->wWidth)
  2593. {
  2594. //
  2595. // _COMPUTE_NEXT_LOD_RECT - Computes rectangle (in place) for next smaller LOD in mip
  2596. // chain. Top & left are divided by two, which effectively rounds down (via truncation).
  2597. // Bottom & right are incremented prior to truncated-division, which will round up.
  2598. // Result is guaranteed to be at least 1x1 in size.
  2599. //
  2600. #define _COMPUTE_NEXT_LOD_RECT( m_pRct ) \
  2601. { \
  2602. (m_pRct)->left >>= 1; \
  2603. (m_pRct)->top >>= 1; \
  2604. DWORD right = ((m_pRct)->right +1) >> 1; \
  2605. DWORD bottom = ((m_pRct)->bottom+1) >> 1; \
  2606. (m_pRct)->right = ((right - (m_pRct)->left) < 1) ? ((m_pRct)->left+1) : (right); \
  2607. (m_pRct)->bottom = ((bottom - (m_pRct)->top ) < 1) ? ((m_pRct)->top +1) : (bottom); \
  2608. }
  2609. if(lpSrcRct)
  2610. {
  2611. _COMPUTE_NEXT_LOD_RECT(lpSrcRct)
  2612. }
  2613. if(lpDstRct)
  2614. {
  2615. _COMPUTE_NEXT_LOD_RECT(lpDstRct)
  2616. }
  2617. ++srcmipoff;
  2618. ++mmsrc;
  2619. if(mmsrc == 0)
  2620. {
  2621. D3D_ERR("Size mismatch between source and destination textures");
  2622. return DDERR_INVALIDPARAMS;
  2623. }
  2624. }
  2625. DWORD dstmipcnt = DDSDstSubMip.lpLcl->lpSurfMore->dwMipMapCount == 0 ? 1 : DDSDstSubMip.lpLcl->lpSurfMore->dwMipMapCount;
  2626. DWORD srcmipcnt = DDSSrcSubMip.lpLcl->lpSurfMore->dwMipMapCount == 0 ? 1 : DDSSrcSubMip.lpLcl->lpSurfMore->dwMipMapCount;
  2627. if(dstmipcnt != (srcmipcnt - srcmipoff))
  2628. {
  2629. if(dstmipcnt > (srcmipcnt - srcmipoff))
  2630. {
  2631. D3D_ERR("Destination texture has more mipmap levels than source");
  2632. return DDERR_INVALIDPARAMS;
  2633. }
  2634. else
  2635. D3D_INFO(3, "Destination texture has fewer mipmap levels than source");
  2636. }
  2637. #if COLLECTSTATS
  2638. if(dwFlags == 0xFFFFFFFF) // texman CopySurface
  2639. this->lpDirect3DI->lpTextureManager->IncBytesDownloaded(DDSDstSubMip.lpLcl, lpDstRct);
  2640. else
  2641. this->IncBytesDownloaded(DDSDstSubMip.lpLcl, lpDstRct);
  2642. #endif
  2643. if(this->lpDirect3DI->numDevs == 1 && CanDoTexBlt(DDSSrcSubFace.lpLcl, DDSDstSubFace.lpLcl))
  2644. {
  2645. bool doblt = true;
  2646. LPREGIONLIST lpRegionList = DDSSrcSubFace.lpLcl->lpSurfMore->lpRegionList;
  2647. if(dwFlags == 0xFFFFFFFF) // 0xFFFFFFFF indicates that we
  2648. // are loading from sysmem to vidmem
  2649. // and the regionlist should be used
  2650. {
  2651. if(lpRegionList->rdh.nCount == 0)
  2652. {
  2653. doblt = false;
  2654. }
  2655. else
  2656. {
  2657. if(lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  2658. {
  2659. if(DDSSrcSubFace.lpLcl->lpGbl->dwUsageCount > 0
  2660. || DDSDstSubFace.lpLcl->lpGbl->dwUsageCount > 0)
  2661. {
  2662. D3D_ERR("Surfaces locked");
  2663. return DDERR_SURFACEBUSY;
  2664. }
  2665. for(unsigned i = 0; i < lpRegionList->rdh.nCount; ++i)
  2666. {
  2667. POINT p;
  2668. p.x = lpRegionList->rect[i].left;
  2669. p.y = lpRegionList->rect[i].top;
  2670. ddrval = static_cast<CDirect3DDevice7*>(this)->TexBltI(DDSDstSubFace.lpLcl,
  2671. DDSSrcSubFace.lpLcl,
  2672. &p, &lpRegionList->rect[i], 0);
  2673. if(ddrval != D3D_OK)
  2674. {
  2675. DPF_ERR("Error inserting TexBlt instruction in batch");
  2676. return ddrval;
  2677. }
  2678. }
  2679. BatchTexture(DDSDstSubFace.lpLcl);
  2680. BatchTexture(DDSSrcSubFace.lpLcl);
  2681. doblt = false;
  2682. }
  2683. lpRegionList->rdh.nCount = 0;
  2684. lpRegionList->rdh.nRgnSize = 0;
  2685. lpRegionList->rdh.rcBound.left = LONG_MAX;
  2686. lpRegionList->rdh.rcBound.right = 0;
  2687. lpRegionList->rdh.rcBound.top = LONG_MAX;
  2688. lpRegionList->rdh.rcBound.bottom = 0;
  2689. }
  2690. }
  2691. if(doblt)
  2692. {
  2693. if(DDSSrcSubFace.lpLcl->lpGbl->dwUsageCount > 0
  2694. || DDSDstSubFace.lpLcl->lpGbl->dwUsageCount > 0)
  2695. {
  2696. D3D_ERR("Surfaces locked");
  2697. return DDERR_SURFACEBUSY;
  2698. }
  2699. POINT p;
  2700. if(lpDstRct)
  2701. {
  2702. p.x = lpDstRct->left;
  2703. p.y = lpDstRct->top;
  2704. }
  2705. else
  2706. {
  2707. p.x = 0;
  2708. p.y = 0;
  2709. }
  2710. RECTL r;
  2711. if(lpSrcRct)
  2712. {
  2713. r = *((LPRECTL)lpSrcRct);
  2714. }
  2715. else
  2716. {
  2717. r.bottom = DDSSrcSubFace.lpLcl->lpGbl->wHeight;
  2718. r.left = 0;
  2719. r.right = DDSSrcSubFace.lpLcl->lpGbl->wWidth;
  2720. r.top = 0;
  2721. }
  2722. ddrval = static_cast<CDirect3DDevice7*>(this)->TexBltI(DDSDstSubFace.lpLcl,
  2723. DDSSrcSubFace.lpLcl,
  2724. &p, &r, 0);
  2725. if(ddrval != D3D_OK)
  2726. {
  2727. DPF_ERR("Error inserting TexBlt instruction in batch");
  2728. return ddrval;
  2729. }
  2730. BatchTexture(DDSDstSubFace.lpLcl);
  2731. BatchTexture(DDSSrcSubFace.lpLcl);
  2732. if(IsD3DManaged(DDSDstSubFace.lpLcl))
  2733. {
  2734. MarkDirty(DDSDstSubFace.lpLcl);
  2735. LPREGIONLIST lpRegionList = DDSDstSubFace.lpLcl->lpSurfMore->lpRegionList;
  2736. if(lpDstRct)
  2737. {
  2738. if(lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  2739. {
  2740. lpRegionList->rect[(lpRegionList->rdh.nCount)++] = *((LPRECTL)lpDstRct);
  2741. lpRegionList->rdh.nRgnSize += sizeof(RECT);
  2742. if(lpDstRct->left < lpRegionList->rdh.rcBound.left)
  2743. lpRegionList->rdh.rcBound.left = lpDstRct->left;
  2744. if(lpDstRct->right > lpRegionList->rdh.rcBound.right)
  2745. lpRegionList->rdh.rcBound.right = lpDstRct->right;
  2746. if(lpDstRct->top < lpRegionList->rdh.rcBound.top)
  2747. lpRegionList->rdh.rcBound.top = lpDstRct->top;
  2748. if(lpDstRct->bottom > lpRegionList->rdh.rcBound.bottom)
  2749. lpRegionList->rdh.rcBound.bottom = lpDstRct->bottom;
  2750. }
  2751. }
  2752. else
  2753. {
  2754. /* Mark everything dirty */
  2755. lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
  2756. }
  2757. }
  2758. }
  2759. }
  2760. else
  2761. {
  2762. do
  2763. {
  2764. DDSSrcSubMip.lpLcl = mmsrc();
  2765. DDSDstSubMip.lpLcl = mmdst();
  2766. bool doblt = true;
  2767. LPREGIONLIST lpRegionList = DDSSrcSubMip.lpLcl->lpSurfMore->lpRegionList;
  2768. if(dwFlags == 0xFFFFFFFF) // 0xFFFFFFFF indicates that we
  2769. // are loading from sysmem to vidmem
  2770. // and the regionlist should be used.
  2771. {
  2772. if(lpRegionList->rdh.nCount == 0)
  2773. {
  2774. doblt = false;
  2775. }
  2776. else if(lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  2777. {
  2778. if(lpClipper->SetClipList((LPRGNDATA)lpRegionList, 0) != DD_OK)
  2779. {
  2780. D3D_ERR("Failed to set clip list");
  2781. }
  2782. if(lpDDSDstSubMip->SetClipper(lpClipper) != DD_OK)
  2783. {
  2784. D3D_ERR("Failed to detach the clipper");
  2785. }
  2786. }
  2787. }
  2788. if(doblt)
  2789. {
  2790. ddrval = lpDDSDstSubMip->Blt(lpDstRct, lpDDSSrcSubMip, lpSrcRct, DDBLT_WAIT, NULL);
  2791. }
  2792. if(dwFlags == 0xFFFFFFFF)
  2793. {
  2794. if(lpRegionList->rdh.nCount)
  2795. {
  2796. if(lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  2797. {
  2798. if(lpDDSDstSubMip->SetClipper(NULL) != DD_OK)
  2799. {
  2800. D3D_ERR("Failed to detach the clipper");
  2801. }
  2802. }
  2803. lpRegionList->rdh.nCount = 0;
  2804. lpRegionList->rdh.nRgnSize = 0;
  2805. lpRegionList->rdh.rcBound.left = LONG_MAX;
  2806. lpRegionList->rdh.rcBound.right = 0;
  2807. lpRegionList->rdh.rcBound.top = LONG_MAX;
  2808. lpRegionList->rdh.rcBound.bottom = 0;
  2809. }
  2810. }
  2811. if (ddrval == E_NOTIMPL && (psize == 16 || psize == 4 || psize == 2))
  2812. {
  2813. DDSURFACEDESC2 ddsd_s, ddsd_d;
  2814. LPBYTE psrc, pdst;
  2815. DWORD i;
  2816. DWORD dwBytesPerLine;
  2817. memset(&ddsd_s, 0, sizeof ddsd_s);
  2818. memset(&ddsd_d, 0, sizeof ddsd_d);
  2819. ddsd_s.dwSize = ddsd_d.dwSize = sizeof(ddsd_s);
  2820. // ATTENTION: implement subrect locks and copy correctly.
  2821. if ((ddrval = lpDDSSrcSubMip->Lock(NULL, &ddsd_s, DDLOCK_WAIT, NULL)) != DD_OK)
  2822. {
  2823. if((ddrval == DDERR_SURFACELOST) && (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE))
  2824. {
  2825. this->dwFEFlags |= D3DFE_LOSTSURFACES;
  2826. ddrval = DD_OK;
  2827. }
  2828. else
  2829. {
  2830. D3D_ERR("Failed to lock src texture");
  2831. }
  2832. return ddrval;
  2833. }
  2834. if ((ddrval = lpDDSDstSubMip->Lock(NULL, &ddsd_d, DDLOCK_WAIT, NULL)) != DD_OK)
  2835. {
  2836. lpDDSSrcSubMip->Unlock(NULL);
  2837. if((ddrval == DDERR_SURFACELOST) && (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE))
  2838. {
  2839. this->dwFEFlags |= D3DFE_LOSTSURFACES;
  2840. ddrval = DD_OK;
  2841. }
  2842. else
  2843. {
  2844. D3D_ERR("Failed to lock dst texture");
  2845. }
  2846. return ddrval;
  2847. }
  2848. switch (psize)
  2849. {
  2850. case 16: dwBytesPerLine = (ddsd_s.dwWidth + 1) / 2; break;
  2851. case 4: dwBytesPerLine = (ddsd_s.dwWidth + 3) / 4; break;
  2852. case 2: dwBytesPerLine = (ddsd_s.dwWidth + 7) / 8; break;
  2853. }
  2854. psrc = (LPBYTE)ddsd_s.lpSurface;
  2855. pdst = (LPBYTE)ddsd_d.lpSurface;
  2856. for (i = 0; i < ddsd_s.dwHeight; i++) {
  2857. memcpy( pdst, psrc, dwBytesPerLine );
  2858. psrc += ddsd_s.lPitch;
  2859. pdst += ddsd_d.lPitch;
  2860. }
  2861. lpDDSSrcSubMip->Unlock(NULL);
  2862. lpDDSDstSubMip->Unlock(NULL);
  2863. }
  2864. else if (ddrval != DD_OK)
  2865. {
  2866. if((ddrval == DDERR_SURFACELOST) && (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE))
  2867. {
  2868. this->dwFEFlags |= D3DFE_LOSTSURFACES;
  2869. ddrval = DD_OK;
  2870. }
  2871. else
  2872. {
  2873. D3D_ERR("Blt failure");
  2874. }
  2875. return ddrval;
  2876. }
  2877. if(lpSrcRct)
  2878. {
  2879. _COMPUTE_NEXT_LOD_RECT(lpSrcRct)
  2880. }
  2881. if(lpDstRct)
  2882. {
  2883. _COMPUTE_NEXT_LOD_RECT(lpDstRct)
  2884. }
  2885. ++mmsrc;
  2886. ++mmdst;
  2887. }
  2888. while(mmsrc != 0 && mmdst != 0);
  2889. }
  2890. }
  2891. ++cmsrc;
  2892. if(cmsrc == 0)
  2893. {
  2894. break; // out of outer loop
  2895. }
  2896. ++cmdst;
  2897. if(cmdst == 0)
  2898. {
  2899. D3D_ERR("Destination texture has different cubemap faces than source");
  2900. return DDERR_INVALIDPARAMS;
  2901. }
  2902. }
  2903. return D3D_OK;
  2904. }
  2905. #undef DPF_MODNAME
  2906. #define DPF_MODNAME "DIRECT3DDEVICEI::VerifyTextureCaps"
  2907. HRESULT DIRECT3DDEVICEI::VerifyTextureCaps(LPDIRECT3DTEXTUREI lpTexI)
  2908. {
  2909. DWORD texcap;
  2910. WORD width, height;
  2911. LPDDRAWI_DDRAWSURFACE_INT lpDDS;
  2912. if(lpTexI->D3DManaged())
  2913. lpDDS = (LPDDRAWI_DDRAWSURFACE_INT)(lpTexI->lpDDSSys);
  2914. else
  2915. lpDDS = (LPDDRAWI_DDRAWSURFACE_INT)(lpTexI->lpDDS);
  2916. /*
  2917. * Are we palettized?
  2918. */
  2919. LPDDPIXELFORMAT pPF = &PixelFormat(lpDDS->lpLcl);
  2920. if ( (pPF->dwFlags & DDPF_PALETTEINDEXED1) ||
  2921. (pPF->dwFlags & DDPF_PALETTEINDEXED2) ||
  2922. (pPF->dwFlags & DDPF_PALETTEINDEXED4) ||
  2923. (pPF->dwFlags & DDPF_PALETTEINDEXED8) )
  2924. {
  2925. if(lpDDS->lpLcl->lpDDPalette == NULL)
  2926. {
  2927. D3D_ERR("No palette attached to a palettized texture");
  2928. return DDERR_NOPALETTEATTACHED;
  2929. }
  2930. }
  2931. /* first verify the dimensions */
  2932. texcap = this->d3dDevDesc.dpcTriCaps.dwTextureCaps;
  2933. width = lpDDS->lpLcl->lpGbl->wWidth;
  2934. height = lpDDS->lpLcl->lpGbl->wHeight;
  2935. if (texcap & D3DPTEXTURECAPS_POW2)
  2936. {
  2937. if (width & (width - 1)) // Clear the right most set bit
  2938. {
  2939. if (texcap & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
  2940. {
  2941. D3D_INFO( 3, "Texture width not a power of two");
  2942. D3D_INFO( 3, " with D3DPTEXTURECAPS_NONPOW2CONDITIONAL");
  2943. }
  2944. else
  2945. {
  2946. D3D_ERR("Texture width not a power of two");
  2947. return D3DERR_TEXTURE_BADSIZE;
  2948. }
  2949. }
  2950. if (height & (height - 1)) // Clear the right most set bit
  2951. {
  2952. if (texcap & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
  2953. {
  2954. D3D_INFO( 3, "Texture height not a power of two");
  2955. D3D_INFO( 3, " with D3DPTEXTURECAPS_NONPOW2CONDITIONAL");
  2956. }
  2957. else
  2958. {
  2959. D3D_ERR("Texture height not a power of two");
  2960. return D3DERR_TEXTURE_BADSIZE;
  2961. }
  2962. }
  2963. }
  2964. if (texcap & D3DPTEXTURECAPS_SQUAREONLY)
  2965. {
  2966. if (width != height)
  2967. {
  2968. D3D_ERR("Texture not square");
  2969. return D3DERR_TEXTURE_BADSIZE;
  2970. }
  2971. }
  2972. return D3D_OK;
  2973. }
  2974. #if COLLECTSTATS
  2975. #undef DPF_MODNAME
  2976. #define DPF_MODNAME "Direct3DDevice::GetTexStats"
  2977. void DIRECT3DDEVICEI::GetTexStats(LPD3DDEVINFO_TEXTURING pStats)
  2978. {
  2979. lpDirect3DI->GetTexStats(&m_texstats);
  2980. *pStats = m_texstats;
  2981. }
  2982. #endif
  2983. #undef DPF_MODNAME
  2984. #define DPF_MODNAME "Direct3DDevice::GetInfoInternal"
  2985. BOOL DIRECT3DDEVICEI::GetInfoInternal(DWORD dwDevInfoID, LPVOID pDevInfoStruct, DWORD dwSize)
  2986. {
  2987. switch(dwDevInfoID)
  2988. {
  2989. #if COLLECTSTATS
  2990. case D3DDEVINFOID_D3DTEXTUREMANAGER:
  2991. if(dwSize < sizeof(D3DDEVINFO_TEXTUREMANAGER))
  2992. {
  2993. D3D_ERR( "Invalid size" );
  2994. throw DDERR_INVALIDPARAMS;
  2995. }
  2996. lpDirect3DI->lpTextureManager->GetStats((LPD3DDEVINFO_TEXTUREMANAGER)pDevInfoStruct);
  2997. break;
  2998. case D3DDEVINFOID_TEXTURING:
  2999. if(dwSize < sizeof(D3DDEVINFO_TEXTURING))
  3000. {
  3001. D3D_ERR( "Invalid size" );
  3002. throw DDERR_INVALIDPARAMS;
  3003. }
  3004. this->GetTexStats((LPD3DDEVINFO_TEXTURING)pDevInfoStruct);
  3005. break;
  3006. #else
  3007. case D3DDEVINFOID_D3DTEXTUREMANAGER:
  3008. case D3DDEVINFOID_TEXTURING:
  3009. D3D_WARN( 0, "Stats not collected in this build" );
  3010. memset(pDevInfoStruct, 0, dwSize);
  3011. throw S_FALSE;
  3012. #endif
  3013. default:
  3014. return FALSE;
  3015. }
  3016. return TRUE;
  3017. }
  3018. #undef DPF_MODNAME
  3019. #define DPF_MODNAME "Direct3DDevice::GetInfo"
  3020. HRESULT D3DAPI DIRECT3DDEVICEI::GetInfo(DWORD dwDevInfoID, LPVOID pDevInfoStruct, DWORD dwSize)
  3021. {
  3022. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  3023. // Release in the destructor
  3024. if (!VALID_DIRECT3DDEVICE_PTR(this))
  3025. {
  3026. D3D_ERR( "Invalid DIRECT3DDEVICE7 pointer" );
  3027. return DDERR_INVALIDOBJECT;
  3028. }
  3029. if (dwSize == 0 || !VALID_D3DDEVINFOSTRUCT_PTR(pDevInfoStruct, dwSize))
  3030. {
  3031. D3D_ERR( "Invalid structure pointer or size" );
  3032. return DDERR_INVALIDOBJECT;
  3033. }
  3034. memset(pDevInfoStruct, 0, dwSize);
  3035. #if DBG
  3036. if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)
  3037. {
  3038. D3D_WARN( 2, "GetInfo called within a scene" );
  3039. }
  3040. #endif
  3041. try
  3042. {
  3043. switch(dwDevInfoID)
  3044. {
  3045. #if COLLECTSTATS
  3046. case D3DDEVINFOID_TEXTUREMANAGER:
  3047. lpDirect3DI->lpTextureManager->GetStats((LPD3DDEVINFO_TEXTUREMANAGER)pDevInfoStruct);
  3048. return D3D_OK;
  3049. #else
  3050. case D3DDEVINFOID_TEXTUREMANAGER:
  3051. D3D_WARN( 0, "Stats not collected in this build" );
  3052. return S_FALSE;
  3053. #endif
  3054. default:
  3055. if(GetInfoInternal(dwDevInfoID, pDevInfoStruct, dwSize))
  3056. return D3D_OK;
  3057. }
  3058. D3D_WARN( 1, "Device information query unsupported" );
  3059. return E_FAIL;
  3060. }
  3061. catch(HRESULT hr)
  3062. {
  3063. memset(pDevInfoStruct, 0, dwSize);
  3064. return hr;
  3065. }
  3066. }