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.

1497 lines
49 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 "drawprim.hpp"
  25. #include "fe.h"
  26. #include "enum.hpp"
  27. //#define APIPROF
  28. #ifdef APIPROF
  29. #include "apiprof.cpp"
  30. #endif //APIPROF
  31. #if defined(PROFILE4)
  32. #include <icecap.h>
  33. #elif defined(PROFILE)
  34. #include <icapexp.h>
  35. #endif
  36. // Remove DDraw's type unsafe definition and replace with our C++ friendly def
  37. #ifdef VALIDEX_CODE_PTR
  38. #undef VALIDEX_CODE_PTR
  39. #endif
  40. #define VALIDEX_CODE_PTR( ptr ) \
  41. (!IsBadCodePtr( (FARPROC) ptr ) )
  42. #undef DPF_MODNAME
  43. #define DPF_MODNAME "Direct3DDevice"
  44. extern void setIdentity(D3DMATRIXI * m);
  45. #ifndef PROFILE4
  46. #ifdef _X86_
  47. extern HRESULT D3DAPI katmai_FEContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs);
  48. extern HRESULT D3DAPI wlmt_FEContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs);
  49. extern HRESULT D3DAPI x3DContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs);
  50. #endif
  51. #endif
  52. #ifdef _X86_
  53. extern BOOL IsWin95();
  54. #endif
  55. extern HINSTANCE hMsGeometryDLL;
  56. // This is a list of all rstates that UpdateInternalState does some
  57. // work other than updating this->rstates[] array. This is used to
  58. // do a quick bitwise check to see if this rstate is trivial or not.
  59. const D3DRENDERSTATETYPE rsList[] = {
  60. // renderstates that either need runtime attention or that cannot be sent
  61. // to legacy drivers
  62. D3DRENDERSTATE_FOGENABLE,
  63. D3DRENDERSTATE_SPECULARENABLE,
  64. D3DRENDERSTATE_RANGEFOGENABLE,
  65. D3DRENDERSTATE_FOGDENSITY,
  66. D3DRENDERSTATE_FOGSTART,
  67. D3DRENDERSTATE_FOGEND,
  68. D3DRENDERSTATE_WRAP0,
  69. D3DRENDERSTATE_WRAP1,
  70. D3DRENDERSTATE_WRAP2,
  71. D3DRENDERSTATE_WRAP3,
  72. D3DRENDERSTATE_WRAP4,
  73. D3DRENDERSTATE_WRAP5,
  74. D3DRENDERSTATE_WRAP6,
  75. D3DRENDERSTATE_WRAP7,
  76. D3DRENDERSTATE_CLIPPING,
  77. D3DRENDERSTATE_LIGHTING,
  78. D3DRENDERSTATE_AMBIENT,
  79. D3DRENDERSTATE_FOGVERTEXMODE,
  80. D3DRENDERSTATE_COLORVERTEX,
  81. D3DRENDERSTATE_LOCALVIEWER,
  82. D3DRENDERSTATE_NORMALIZENORMALS,
  83. D3DRENDERSTATE_COLORKEYBLENDENABLE,
  84. D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,
  85. D3DRENDERSTATE_SPECULARMATERIALSOURCE,
  86. D3DRENDERSTATE_AMBIENTMATERIALSOURCE,
  87. D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,
  88. D3DRENDERSTATE_VERTEXBLEND,
  89. D3DRENDERSTATE_CLIPPLANEENABLE,
  90. D3DRENDERSTATE_SHADEMODE,
  91. D3DRS_SOFTWAREVERTEXPROCESSING,
  92. D3DRS_POINTSIZE,
  93. D3DRS_POINTSIZE_MIN,
  94. D3DRS_POINTSPRITEENABLE,
  95. D3DRS_POINTSCALEENABLE,
  96. D3DRS_POINTSCALE_A,
  97. D3DRS_POINTSCALE_B,
  98. D3DRS_POINTSCALE_C,
  99. D3DRS_MULTISAMPLEANTIALIAS,
  100. D3DRS_MULTISAMPLEMASK,
  101. D3DRS_PATCHEDGESTYLE,
  102. D3DRS_PATCHSEGMENTS,
  103. D3DRS_DEBUGMONITORTOKEN,
  104. D3DRS_POINTSIZE_MAX,
  105. D3DRS_INDEXEDVERTEXBLENDENABLE,
  106. D3DRS_COLORWRITEENABLE,
  107. D3DRS_TWEENFACTOR,
  108. D3DRS_DEBUGMONITORTOKEN,
  109. D3DRS_BLENDOP,
  110. D3DRS_PATCHSEGMENTS,
  111. // Retired renderstates to be filtered with DPF error and INVALID return
  112. // NOTE: everything listed here is also assumed to appear in rsListRetired
  113. D3DRENDERSTATE_TEXTUREHANDLE,
  114. D3DRENDERSTATE_TEXTUREADDRESS,
  115. D3DRENDERSTATE_WRAPU,
  116. D3DRENDERSTATE_WRAPV,
  117. D3DRENDERSTATE_MONOENABLE,
  118. D3DRENDERSTATE_ROP2,
  119. D3DRENDERSTATE_PLANEMASK,
  120. D3DRENDERSTATE_TEXTUREMAG,
  121. D3DRENDERSTATE_TEXTUREMIN,
  122. D3DRENDERSTATE_TEXTUREMAPBLEND,
  123. D3DRENDERSTATE_SUBPIXEL,
  124. D3DRENDERSTATE_SUBPIXELX,
  125. D3DRENDERSTATE_STIPPLEENABLE,
  126. D3DRENDERSTATE_BORDERCOLOR,
  127. D3DRENDERSTATE_TEXTUREADDRESSU,
  128. D3DRENDERSTATE_TEXTUREADDRESSV,
  129. D3DRENDERSTATE_MIPMAPLODBIAS,
  130. D3DRENDERSTATE_ANISOTROPY,
  131. D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT,
  132. D3DRENDERSTATE_STIPPLEPATTERN00,
  133. D3DRENDERSTATE_STIPPLEPATTERN01,
  134. D3DRENDERSTATE_STIPPLEPATTERN02,
  135. D3DRENDERSTATE_STIPPLEPATTERN03,
  136. D3DRENDERSTATE_STIPPLEPATTERN04,
  137. D3DRENDERSTATE_STIPPLEPATTERN05,
  138. D3DRENDERSTATE_STIPPLEPATTERN06,
  139. D3DRENDERSTATE_STIPPLEPATTERN07,
  140. D3DRENDERSTATE_STIPPLEPATTERN08,
  141. D3DRENDERSTATE_STIPPLEPATTERN09,
  142. D3DRENDERSTATE_STIPPLEPATTERN10,
  143. D3DRENDERSTATE_STIPPLEPATTERN11,
  144. D3DRENDERSTATE_STIPPLEPATTERN12,
  145. D3DRENDERSTATE_STIPPLEPATTERN13,
  146. D3DRENDERSTATE_STIPPLEPATTERN14,
  147. D3DRENDERSTATE_STIPPLEPATTERN15,
  148. D3DRENDERSTATE_STIPPLEPATTERN16,
  149. D3DRENDERSTATE_STIPPLEPATTERN17,
  150. D3DRENDERSTATE_STIPPLEPATTERN18,
  151. D3DRENDERSTATE_STIPPLEPATTERN19,
  152. D3DRENDERSTATE_STIPPLEPATTERN20,
  153. D3DRENDERSTATE_STIPPLEPATTERN21,
  154. D3DRENDERSTATE_STIPPLEPATTERN22,
  155. D3DRENDERSTATE_STIPPLEPATTERN23,
  156. D3DRENDERSTATE_STIPPLEPATTERN24,
  157. D3DRENDERSTATE_STIPPLEPATTERN25,
  158. D3DRENDERSTATE_STIPPLEPATTERN26,
  159. D3DRENDERSTATE_STIPPLEPATTERN27,
  160. D3DRENDERSTATE_STIPPLEPATTERN28,
  161. D3DRENDERSTATE_STIPPLEPATTERN29,
  162. D3DRENDERSTATE_STIPPLEPATTERN30,
  163. D3DRENDERSTATE_STIPPLEPATTERN31,
  164. // newly retired for DX8
  165. D3DRENDERSTATE_ANTIALIAS,
  166. D3DRENDERSTATE_TEXTUREPERSPECTIVE,
  167. D3DRENDERSTATE_COLORKEYENABLE,
  168. D3DRENDERSTATE_COLORKEYBLENDENABLE,
  169. D3DRENDERSTATE_STIPPLEDALPHA,
  170. };
  171. // list of retired renderstates - need to make sure these are
  172. // filtered and never get from app directly to driver
  173. const D3DRENDERSTATETYPE rsListRetired[] = {
  174. D3DRENDERSTATE_TEXTUREHANDLE,
  175. D3DRENDERSTATE_TEXTUREADDRESS,
  176. D3DRENDERSTATE_WRAPU,
  177. D3DRENDERSTATE_WRAPV,
  178. D3DRENDERSTATE_MONOENABLE,
  179. D3DRENDERSTATE_ROP2,
  180. D3DRENDERSTATE_PLANEMASK,
  181. D3DRENDERSTATE_TEXTUREMAG,
  182. D3DRENDERSTATE_TEXTUREMIN,
  183. D3DRENDERSTATE_TEXTUREMAPBLEND,
  184. D3DRENDERSTATE_SUBPIXEL,
  185. D3DRENDERSTATE_SUBPIXELX,
  186. D3DRENDERSTATE_STIPPLEENABLE,
  187. D3DRENDERSTATE_BORDERCOLOR,
  188. D3DRENDERSTATE_TEXTUREADDRESSU,
  189. D3DRENDERSTATE_TEXTUREADDRESSV,
  190. D3DRENDERSTATE_MIPMAPLODBIAS,
  191. D3DRENDERSTATE_ANISOTROPY,
  192. D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT,
  193. D3DRENDERSTATE_STIPPLEPATTERN00,
  194. D3DRENDERSTATE_STIPPLEPATTERN01,
  195. D3DRENDERSTATE_STIPPLEPATTERN02,
  196. D3DRENDERSTATE_STIPPLEPATTERN03,
  197. D3DRENDERSTATE_STIPPLEPATTERN04,
  198. D3DRENDERSTATE_STIPPLEPATTERN05,
  199. D3DRENDERSTATE_STIPPLEPATTERN06,
  200. D3DRENDERSTATE_STIPPLEPATTERN07,
  201. D3DRENDERSTATE_STIPPLEPATTERN08,
  202. D3DRENDERSTATE_STIPPLEPATTERN09,
  203. D3DRENDERSTATE_STIPPLEPATTERN10,
  204. D3DRENDERSTATE_STIPPLEPATTERN11,
  205. D3DRENDERSTATE_STIPPLEPATTERN12,
  206. D3DRENDERSTATE_STIPPLEPATTERN13,
  207. D3DRENDERSTATE_STIPPLEPATTERN14,
  208. D3DRENDERSTATE_STIPPLEPATTERN15,
  209. D3DRENDERSTATE_STIPPLEPATTERN16,
  210. D3DRENDERSTATE_STIPPLEPATTERN17,
  211. D3DRENDERSTATE_STIPPLEPATTERN18,
  212. D3DRENDERSTATE_STIPPLEPATTERN19,
  213. D3DRENDERSTATE_STIPPLEPATTERN20,
  214. D3DRENDERSTATE_STIPPLEPATTERN21,
  215. D3DRENDERSTATE_STIPPLEPATTERN22,
  216. D3DRENDERSTATE_STIPPLEPATTERN23,
  217. D3DRENDERSTATE_STIPPLEPATTERN24,
  218. D3DRENDERSTATE_STIPPLEPATTERN25,
  219. D3DRENDERSTATE_STIPPLEPATTERN26,
  220. D3DRENDERSTATE_STIPPLEPATTERN27,
  221. D3DRENDERSTATE_STIPPLEPATTERN28,
  222. D3DRENDERSTATE_STIPPLEPATTERN29,
  223. D3DRENDERSTATE_STIPPLEPATTERN30,
  224. D3DRENDERSTATE_STIPPLEPATTERN31,
  225. // newly retired for DX8
  226. D3DRENDERSTATE_ANTIALIAS,
  227. D3DRENDERSTATE_TEXTUREPERSPECTIVE,
  228. D3DRENDERSTATE_COLORKEYENABLE,
  229. D3DRENDERSTATE_COLORKEYBLENDENABLE,
  230. D3DRENDERSTATE_STIPPLEDALPHA,
  231. };
  232. /////////////////////////////////////////////////////////////////////////////
  233. // //
  234. // CD3DHal //
  235. // //
  236. /////////////////////////////////////////////////////////////////////////////
  237. //---------------------------------------------------------------------
  238. CD3DHal::CD3DHal()
  239. {
  240. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  241. // DO NOT PUT INITIALIZATION IN THE CONSTRUCTOR.
  242. // Put it in Init() instead. This is because the device can be
  243. // "Destroy()ed" and "Init()ed" anytime via Reset. In this
  244. // situation, the constructor is never called. (snene 01/00)
  245. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  246. }
  247. //---------------------------------------------------------------------
  248. #undef DPF_MODNAME
  249. #define DPF_MODNAME "CD3DHal::StateInitialize"
  250. void CD3DHal::StateInitialize(BOOL bZEnable)
  251. {
  252. DWORD i,j;
  253. // Initialize the bit array indicating the rstates needing non-trivial
  254. // work.
  255. for (i=0; i < sizeof(rsList) / sizeof(D3DRENDERSTATETYPE); ++i)
  256. rsVec.SetBit(rsList[i]);
  257. // Initialize the bit array indicating the retired rstates
  258. for (i=0; i < sizeof(rsListRetired) / sizeof(D3DRENDERSTATETYPE); ++i)
  259. rsVecRetired.SetBit(rsListRetired[i]);
  260. // Initialize the bit array indicating the vertex processing only rstates
  261. for (i=0; i < sizeof(rsVertexProcessingList) / sizeof(D3DRENDERSTATETYPE); ++i)
  262. rsVertexProcessingOnly.SetBit(rsVertexProcessingList[i]);
  263. // Obviate Set(Render;TextureStage)State filtering 'redundant' device state settings
  264. // since this is the init step.
  265. // memset( this->rstates, 0xff, sizeof(DWORD)*D3D_MAXRENDERSTATES);
  266. for (i=0; i<D3D_MAXRENDERSTATES; i++)
  267. this->rstates[i] = 0xbaadcafe;
  268. // memset( this->tsstates, 0xff, sizeof(DWORD)*D3DHAL_TSS_MAXSTAGES*D3DHAL_TSS_STATESPERSTAGE );
  269. for (j=0; j<D3DHAL_TSS_MAXSTAGES; j++)
  270. for (i=0; i<D3DHAL_TSS_STATESPERSTAGE; i++)
  271. this->tsstates[j][i] = 0xbaadcafe;
  272. CD3DBase::StateInitialize(bZEnable);
  273. if (GetDDIType() < D3DDDITYPE_DX8)
  274. {
  275. SetRenderStateInternal(D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE);
  276. SetRenderStateInternal(D3DRENDERSTATE_COLORKEYENABLE, FALSE);
  277. SetRenderStateInternal(D3DRENDERSTATE_COLORKEYBLENDENABLE, FALSE);
  278. SetRenderStateInternal(D3DRENDERSTATE_STIPPLEDALPHA, FALSE);
  279. }
  280. if (GetDDIType() < D3DDDITYPE_DX7)
  281. {
  282. // send retired renderstate init's to pre-DX7 HALs only
  283. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEENABLE, FALSE);
  284. SetRenderStateInternal( D3DRENDERSTATE_MONOENABLE, FALSE);
  285. SetRenderStateInternal( D3DRENDERSTATE_ROP2, R2_COPYPEN);
  286. SetRenderStateInternal( D3DRENDERSTATE_PLANEMASK, (DWORD)~0);
  287. SetRenderStateInternal( D3DRENDERSTATE_WRAPU, FALSE);
  288. SetRenderStateInternal( D3DRENDERSTATE_WRAPV, FALSE);
  289. SetRenderStateInternal( D3DRENDERSTATE_ANTIALIAS, FALSE);
  290. SetRenderStateInternal( D3DRENDERSTATE_SUBPIXEL, FALSE); /* 30 */
  291. SetRenderStateInternal( D3DRENDERSTATE_SUBPIXELX, FALSE);
  292. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN00, 0);
  293. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN01, 0); /* 40 */
  294. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN02, 0);
  295. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN03, 0);
  296. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN04, 0);
  297. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN05, 0);
  298. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN06, 0);
  299. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN07, 0);
  300. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN08, 0);
  301. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN09, 0);
  302. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN10, 0);
  303. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN11, 0); /* 50 */
  304. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN12, 0);
  305. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN13, 0);
  306. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN14, 0);
  307. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN15, 0);
  308. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN16, 0);
  309. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN17, 0);
  310. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN18, 0);
  311. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN19, 0);
  312. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN20, 0);
  313. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN21, 0); /* 60 */
  314. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN22, 0);
  315. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN23, 0);
  316. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN24, 0);
  317. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN25, 0);
  318. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN26, 0);
  319. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN27, 0);
  320. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN28, 0);
  321. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN29, 0);
  322. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN30, 0);
  323. SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN31, 0); /* 70 */
  324. }
  325. if( BehaviorFlags() & D3DCREATE_SOFTWARE_VERTEXPROCESSING )
  326. {
  327. SwitchVertexProcessingMode(TRUE);
  328. rstates[D3DRS_SOFTWAREVERTEXPROCESSING] = TRUE;
  329. }
  330. else if( BehaviorFlags() & D3DCREATE_HARDWARE_VERTEXPROCESSING )
  331. {
  332. SwitchVertexProcessingMode(FALSE);
  333. rstates[D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE;
  334. }
  335. else if( BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING )
  336. {
  337. SetRenderStateInternal( D3DRS_SOFTWAREVERTEXPROCESSING, 0);
  338. }
  339. else
  340. {
  341. D3D_INFO( 0, "No Vertex Processing behavior specified, assuming software" );
  342. SwitchVertexProcessingMode(TRUE);
  343. rstates[D3DRS_SOFTWAREVERTEXPROCESSING] = TRUE;
  344. }
  345. }
  346. /*
  347. * Initialisation - class part and device part
  348. */
  349. //---------------------------------------------------------------------
  350. HRESULT CD3DHal::D3DFE_Create()
  351. {
  352. DDSURFACEDESC ddsd;
  353. HRESULT hr;
  354. const D3DCAPS8 *pCaps = GetD3DCaps();
  355. if (m_pDDI->GetDDIType() < D3DDDITYPE_DX7)
  356. {
  357. m_dwRuntimeFlags |= D3DRT_ONLY2FLOATSPERTEXTURE;
  358. }
  359. else
  360. if (m_pDDI->GetDDIType() < D3DDDITYPE_DX8)
  361. {
  362. // Some drivers (G200, G400) cannot handle more than 2 floats in
  363. // texture coordinates, even they are supposed to. We set the
  364. // runtime bit to mark such drivers and compute output FVF for vertex
  365. // shaders accordingly
  366. if (!(pCaps->TextureCaps & D3DPTEXTURECAPS_PROJECTED ||
  367. pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP))
  368. {
  369. m_dwRuntimeFlags |= D3DRT_ONLY2FLOATSPERTEXTURE;
  370. }
  371. }
  372. if (!(pCaps->TextureCaps & D3DPTEXTURECAPS_PROJECTED))
  373. m_dwRuntimeFlags |= D3DRT_EMULATEPROJECTEDTEXTURE;
  374. if (pCaps && pCaps->FVFCaps)
  375. {
  376. this->m_pv->dwMaxTextureIndices =
  377. pCaps->FVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK;
  378. if (pCaps->FVFCaps & D3DFVFCAPS_DONOTSTRIPELEMENTS)
  379. this->m_pv->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS;
  380. DWORD value;
  381. if ((GetD3DRegValue(REG_DWORD, "DisableStripFVF", &value, 4) &&
  382. value != 0))
  383. {
  384. this->m_pv->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS;
  385. }
  386. }
  387. else
  388. {
  389. this->m_pv->dwMaxTextureIndices = 1;
  390. }
  391. this->dwFEFlags |= D3DFE_FRONTEND_DIRTY;
  392. #if DBG
  393. this->dwCaller=0;
  394. memset(this->dwPrimitiveType,0,sizeof(this->dwPrimitiveType));
  395. memset(this->dwVertexType1,0,sizeof(this->dwVertexType1));
  396. memset(this->dwVertexType2,0,sizeof(this->dwVertexType2));
  397. #endif
  398. // True for software rendering
  399. m_dwNumStreams = __NUMSTREAMS;
  400. m_dwMaxUserClipPlanes = __MAXUSERCLIPPLANES;
  401. this->m_pv->dwClipMaskOffScreen = 0xFFFFFFFF;
  402. if (pCaps != NULL)
  403. {
  404. if (pCaps->GuardBandLeft != 0.0f ||
  405. pCaps->GuardBandRight != 0.0f ||
  406. pCaps->GuardBandTop != 0.0f ||
  407. pCaps->GuardBandBottom != 0.0f)
  408. {
  409. this->m_pv->dwDeviceFlags |= D3DDEV_GUARDBAND;
  410. this->m_pv->dwClipMaskOffScreen = ~__D3DCS_INGUARDBAND;
  411. DWORD v;
  412. if (GetD3DRegValue(REG_DWORD, "DisableGB", &v, 4) &&
  413. v != 0)
  414. {
  415. this->m_pv->dwDeviceFlags &= ~D3DDEV_GUARDBAND;
  416. this->m_pv->dwClipMaskOffScreen = 0xFFFFFFFF;
  417. }
  418. #if DBG
  419. // Try to get test values for the guard band
  420. char value[80];
  421. if (GetD3DRegValue(REG_SZ, "GuardBandLeft", &value, 80) &&
  422. value[0] != 0)
  423. sscanf(value, "%f", &pCaps->GuardBandLeft);
  424. if (GetD3DRegValue(REG_SZ, "GuardBandRight", &value, 80) &&
  425. value[0] != 0)
  426. sscanf(value, "%f", &pCaps->GuardBandRight);
  427. if (GetD3DRegValue(REG_SZ, "GuardBandTop", &value, 80) &&
  428. value[0] != 0)
  429. sscanf(value, "%f", &pCaps->GuardBandTop);
  430. if (GetD3DRegValue(REG_SZ, "GuardBandBottom", &value, 80) &&
  431. value[0] != 0)
  432. sscanf(value, "%f", &pCaps->GuardBandBottom);
  433. #endif // DBG
  434. }
  435. }
  436. LIST_INITIALIZE(&this->specular_tables);
  437. this->specular_table = NULL;
  438. this->lightVertexFuncTable = &lightVertexTable;
  439. m_pv->lighting.activeLights = NULL;
  440. this->m_ClipStatus.ClipUnion = 0;
  441. this->m_ClipStatus.ClipIntersection = ~0;
  442. m_pv->pDDI = m_pDDI;
  443. return S_OK;
  444. }
  445. void CD3DHal::D3DFE_Destroy()
  446. {
  447. // Destroy lighting data
  448. SpecularTable *spec;
  449. SpecularTable *spec_next;
  450. for (spec = LIST_FIRST(&this->specular_tables); spec; spec = spec_next)
  451. {
  452. spec_next = LIST_NEXT(spec,list);
  453. D3DFree(spec);
  454. }
  455. LIST_INITIALIZE(&specular_tables);
  456. delete m_pLightArray;
  457. m_pLightArray = NULL;
  458. delete m_pv;
  459. m_pv = NULL;
  460. delete m_pConvObj;
  461. m_pConvObj = NULL;
  462. if (m_clrRects)
  463. {
  464. D3DFree(m_clrRects);
  465. m_clrRects = NULL;
  466. }
  467. }
  468. /*
  469. * Generic device part destroy
  470. */
  471. CD3DHal::~CD3DHal()
  472. {
  473. Destroy();
  474. }
  475. void
  476. CD3DHal::Destroy()
  477. {
  478. try // Since Destroy() can be called directly by fw
  479. {
  480. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  481. // MUST CLEANUP AND RELEASE CURRENTLY SET TEXTURES BEFORE
  482. // DOING ANY OTHER WORK, else we will get into situations
  483. // where we are calling FlushStates or batching DDI tokens.
  484. CleanupTextures();
  485. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  486. /* Clear flags that could prohibit cleanup */
  487. m_dwHintFlags &= ~(D3DDEVBOOL_HINTFLAGS_INSCENE);
  488. // Destroy vertex shaders. We need to delete vertex shaders completely
  489. // to preserve behavior for DX8.0 apps. For DX8.1 apps we delete only
  490. // PSGP part of a vertex shader. The rest will be used to re-create
  491. // the shader during Reset()
  492. if (m_pVShaderArray != NULL)
  493. {
  494. UINT size = m_pVShaderArray->GetSize();
  495. for (UINT i=0; i < size; i++)
  496. {
  497. UINT Handle = m_pVShaderArray->HandleFromIndex(i);
  498. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(Handle);
  499. if (pShader)
  500. {
  501. if (Enum()->GetAppSdkVersion() == D3D_SDK_VERSION_DX8)
  502. {
  503. m_pVShaderArray->ReleaseHandle(Handle, TRUE);
  504. }
  505. else
  506. {
  507. // We need to delete PSGP shader object before deleting
  508. // D3DFE_PROCESSVERTICES object, because AMD has keeps a
  509. // pointer to it inside the code object
  510. if (pShader->m_dwFlags & CVShader::SOFTWARE)
  511. {
  512. delete pShader->m_pCode;
  513. pShader->m_pCode = NULL;
  514. }
  515. }
  516. }
  517. }
  518. }
  519. // Destroy pixel shaders for DX8.0 apps to preserve trhe original behavior
  520. if (m_pPShaderArray != NULL)
  521. {
  522. UINT size = m_pPShaderArray->GetSize();
  523. for (UINT i=0; i < size; i++)
  524. {
  525. UINT Handle = m_pPShaderArray->HandleFromIndex(i);
  526. CPShader* pShader = (CPShader*)m_pPShaderArray->GetObject(Handle);
  527. if (pShader)
  528. {
  529. if (Enum()->GetAppSdkVersion() == D3D_SDK_VERSION_DX8)
  530. {
  531. m_pPShaderArray->ReleaseHandle(Handle, TRUE);
  532. }
  533. }
  534. }
  535. }
  536. if (m_pv)
  537. {
  538. if ( 0 != m_pv->pGeometryFuncs &&
  539. (LPVOID)m_pv->pGeometryFuncs != (LPVOID)GeometryFuncsGuaranteed)
  540. {
  541. delete m_pv->pGeometryFuncs;
  542. m_pv->pGeometryFuncs = 0;
  543. }
  544. if ( 0 != GeometryFuncsGuaranteed)
  545. {
  546. delete GeometryFuncsGuaranteed;
  547. GeometryFuncsGuaranteed = 0;
  548. m_pv->pGeometryFuncs = 0;
  549. }
  550. }
  551. this->D3DFE_Destroy();
  552. if ( 0 != rstates)
  553. {
  554. delete[] rstates;
  555. rstates = 0;
  556. }
  557. delete pMatrixDirtyForDDI;
  558. pMatrixDirtyForDDI = NULL;
  559. CD3DBase::Destroy();
  560. }
  561. catch(HRESULT ret)
  562. {
  563. DPF_ERR("There was some error when Reset()ing the device; as a result some resources may not be freed.");
  564. }
  565. }
  566. /*
  567. * Create a device.
  568. *
  569. * This method
  570. * implements the CreateDevice method of the CEnum object. (The CEnum
  571. * object exposes the IDirect3D8 interface which supports enumeration
  572. * etc.)
  573. *
  574. */
  575. #undef DPF_MODNAME
  576. #define DPF_MODNAME "CEnum::CreateDevice"
  577. STDMETHODIMP CEnum::CreateDevice(
  578. UINT iAdapter,
  579. D3DDEVTYPE DeviceType,
  580. HWND hwndFocusWindow,
  581. DWORD dwFlags,
  582. D3DPRESENT_PARAMETERS *pPresentationParams,
  583. IDirect3DDevice8 **ppNewInterface)
  584. {
  585. API_ENTER(this);
  586. PD3D8_DEVICEDATA pDD;
  587. LPD3DBASE pd3ddev;
  588. HRESULT ret = D3D_OK;
  589. VOID* pInit = NULL;
  590. if (!VALID_PTR_PTR(ppNewInterface))
  591. {
  592. DPF_ERR("Invalid IDirect3DDevice8* pointer, CreateDevice fails");
  593. return D3DERR_INVALIDCALL;
  594. }
  595. // Zero out out parameters
  596. *ppNewInterface = NULL;
  597. if (!VALID_PTR(pPresentationParams, sizeof(D3DPRESENT_PARAMETERS)))
  598. {
  599. DPF_ERR("Invalid D3DPRESENT_PARAMETERS pointer, CreateDevice fails");
  600. return D3DERR_INVALIDCALL;
  601. }
  602. // Check that fullscreen parameters are correct
  603. if (pPresentationParams->Windowed)
  604. {
  605. if (pPresentationParams->FullScreen_RefreshRateInHz != 0)
  606. {
  607. DPF_ERR("FullScreen_RefreshRateInHz must be zero for windowed mode. CreateDevice fails.");
  608. return D3DERR_INVALIDCALL;
  609. }
  610. if (pPresentationParams->FullScreen_PresentationInterval != 0)
  611. {
  612. DPF_ERR("FullScreen_PresentationInterval must be zero for windowed mode. CreateDevice fails.");
  613. return D3DERR_INVALIDCALL;
  614. }
  615. }
  616. else
  617. {
  618. DWORD interval = pPresentationParams->FullScreen_PresentationInterval;
  619. switch (interval)
  620. {
  621. case D3DPRESENT_INTERVAL_DEFAULT:
  622. case D3DPRESENT_INTERVAL_ONE:
  623. case D3DPRESENT_INTERVAL_TWO:
  624. case D3DPRESENT_INTERVAL_THREE:
  625. case D3DPRESENT_INTERVAL_FOUR:
  626. case D3DPRESENT_INTERVAL_IMMEDIATE:
  627. break;
  628. default:
  629. DPF_ERR("Invalid value for FullScreen_PresentationInterval. CreateDevice Fails.");
  630. return D3DERR_INVALIDCALL;
  631. }
  632. }
  633. if (pPresentationParams->BackBufferFormat == D3DFMT_UNKNOWN)
  634. {
  635. DPF_ERR("Invalid backbuffer format specified. CreateDevice fails.");
  636. return D3DERR_INVALIDCALL;
  637. }
  638. if (pPresentationParams->Flags & ~D3DPRESENTFLAG_LOCKABLE_BACKBUFFER)
  639. {
  640. DPF_ERR("Invalid flag for Flags. CreateDevice fails.");
  641. return D3DERR_INVALIDCALL;
  642. }
  643. // Validate the HWNDs that we are given
  644. if (hwndFocusWindow && !IsWindow(hwndFocusWindow))
  645. {
  646. DPF_ERR("Invalid HWND specified for hwndFocusWindow, CreateDevice fails");
  647. return D3DERR_INVALIDCALL;
  648. }
  649. if (pPresentationParams->hDeviceWindow && !IsWindow(pPresentationParams->hDeviceWindow))
  650. {
  651. DPF_ERR("Invalid HWND specified for PresentationParams.hDeviceWindow. CreateDevice fails.");
  652. return D3DERR_INVALIDCALL;
  653. }
  654. // Make sure that we are given a focus window or a device window
  655. if (NULL == hwndFocusWindow)
  656. {
  657. if (!pPresentationParams->Windowed)
  658. {
  659. DPF_ERR("Fullscreen CreateDevice must specify Focus window");
  660. return D3DERR_INVALIDCALL;
  661. }
  662. else
  663. if (NULL == pPresentationParams->hDeviceWindow)
  664. {
  665. DPF_ERR("Neither hDeviceWindow nor Focus window specified. CreateDevice Failed.");
  666. return D3DERR_INVALIDCALL;
  667. }
  668. }
  669. if (iAdapter >= m_cAdapter)
  670. {
  671. DPF_ERR("Invalid iAdapter parameter passed to CreateDevice");
  672. return D3DERR_INVALIDCALL;
  673. }
  674. if (dwFlags & ~VALID_D3DCREATE_FLAGS)
  675. {
  676. DPF_ERR("Invalid BehaviorFlags passed to CreateDevice");
  677. return D3DERR_INVALIDCALL;
  678. }
  679. // Check that exactly one of the vertex processing flags is set
  680. DWORD dwVertexProcessingFlags = dwFlags & (D3DCREATE_HARDWARE_VERTEXPROCESSING |
  681. D3DCREATE_SOFTWARE_VERTEXPROCESSING |
  682. D3DCREATE_MIXED_VERTEXPROCESSING);
  683. if (dwVertexProcessingFlags != D3DCREATE_HARDWARE_VERTEXPROCESSING &&
  684. dwVertexProcessingFlags != D3DCREATE_SOFTWARE_VERTEXPROCESSING &&
  685. dwVertexProcessingFlags != D3DCREATE_MIXED_VERTEXPROCESSING)
  686. {
  687. DPF_ERR("Invalid Flags parameter to CreateDevice: Exactly One of the"
  688. " following must be set: D3DCREATE_HARDWARE_VERTEXPROCESSING,"
  689. " D3DCREATE_SOFTWARE_VERTEXPROCESSING or"
  690. " D3DCREATE_MIXED_VERTEXPROCESSING");
  691. return D3DERR_INVALIDCALL;
  692. }
  693. if (DeviceType == D3DDEVTYPE_SW)
  694. {
  695. pInit = m_pSwInitFunction;
  696. if (pInit == NULL)
  697. {
  698. D3D_ERR("App specified D3DDEVTYPE_SW without first registering a software device. CreateDevice Failed.");
  699. return D3DERR_INVALIDCALL;
  700. }
  701. GetSwCaps(iAdapter);
  702. }
  703. else if (DeviceType == D3DDEVTYPE_REF)
  704. {
  705. GetRefCaps(iAdapter);
  706. }
  707. ret = InternalDirectDrawCreate(&pDD,
  708. &m_AdapterInfo[iAdapter],
  709. DeviceType,
  710. pInit,
  711. GetUnknown16(iAdapter),
  712. m_AdapterInfo[iAdapter].HALCaps.pGDD8SupportedFormatOps,
  713. m_AdapterInfo[iAdapter].HALCaps.GDD8NumSupportedFormatOps);
  714. if( FAILED(ret) )
  715. {
  716. D3D_ERR("Failed to create DirectDraw. CreateDevice Failed.");
  717. return ret;
  718. }
  719. if((dwFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) != 0)
  720. {
  721. if((dwFlags & D3DCREATE_PUREDEVICE) != 0)
  722. {
  723. D3D_ERR("Pure device cannot perform software processing. CreateDevice Failed.");
  724. InternalDirectDrawRelease(pDD);
  725. return D3DERR_INVALIDCALL;
  726. }
  727. }
  728. else if((dwFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0)
  729. {
  730. if((pDD->DriverData.D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  731. == 0)
  732. {
  733. D3D_ERR("Device cannot perform hardware processing");
  734. InternalDirectDrawRelease(pDD);
  735. return D3DERR_INVALIDCALL;
  736. }
  737. }
  738. else if((dwFlags & D3DCREATE_MIXED_VERTEXPROCESSING) != 0)
  739. {
  740. if((pDD->DriverData.D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  741. (dwFlags & D3DCREATE_PUREDEVICE) != 0)
  742. {
  743. D3D_ERR("Device cannot perform mixed processing because driver cannot do hardware T&L. CreateDevice Failed.");
  744. InternalDirectDrawRelease(pDD);
  745. return D3DERR_INVALIDCALL;
  746. }
  747. }
  748. else
  749. {
  750. if((dwFlags & D3DCREATE_PUREDEVICE) != 0)
  751. {
  752. if((pDD->DriverData.D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE) == 0)
  753. {
  754. D3D_ERR("Hardware should be capable of creating a pure device");
  755. InternalDirectDrawRelease(pDD);
  756. return D3DERR_INVALIDCALL;
  757. }
  758. }
  759. else
  760. {
  761. D3D_ERR("Must specify software, hardware or mixed vertex processing");
  762. InternalDirectDrawRelease(pDD);
  763. return D3DERR_INVALIDCALL;
  764. }
  765. }
  766. switch (DeviceType)
  767. {
  768. case D3DDEVTYPE_SW:
  769. case D3DDEVTYPE_REF:
  770. case D3DDEVTYPE_HAL:
  771. if (dwFlags & D3DCREATE_PUREDEVICE)
  772. {
  773. pd3ddev = new CD3DBase();
  774. }
  775. else
  776. {
  777. pd3ddev = static_cast<LPD3DBASE>(new CD3DHal());
  778. }
  779. break;
  780. default:
  781. D3D_ERR("Unrecognized or unsupported DeviceType. CreateDevice Failed.");
  782. InternalDirectDrawRelease(pDD);
  783. return D3DERR_INVALIDCALL;
  784. }
  785. if (!pd3ddev)
  786. {
  787. D3D_ERR("Failed to allocate space for the device object. CreateDevice Failed.");
  788. InternalDirectDrawRelease(pDD);
  789. return (E_OUTOFMEMORY);
  790. }
  791. #if DBG
  792. {
  793. char DevTypeMsg[256];
  794. _snprintf( DevTypeMsg, 256, "=======================" );
  795. switch( DeviceType )
  796. {
  797. case D3DDEVTYPE_HAL:
  798. _snprintf( DevTypeMsg, 256, "%s Hal", DevTypeMsg );
  799. break;
  800. case D3DDEVTYPE_SW:
  801. _snprintf( DevTypeMsg, 256, "%s Pluggable SW", DevTypeMsg );
  802. break;
  803. case D3DDEVTYPE_REF:
  804. _snprintf( DevTypeMsg, 256, "%s Reference", DevTypeMsg );
  805. break;
  806. default:
  807. _snprintf( DevTypeMsg, 256, "%s Unknown", DevTypeMsg );
  808. break;
  809. }
  810. if (dwFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING)
  811. {
  812. _snprintf( DevTypeMsg, 256, "%s HWVP", DevTypeMsg );
  813. }
  814. else if (dwFlags & D3DCREATE_MIXED_VERTEXPROCESSING)
  815. {
  816. _snprintf( DevTypeMsg, 256, "%s MixedVP", DevTypeMsg );
  817. }
  818. else if (dwFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
  819. {
  820. _snprintf( DevTypeMsg, 256, "%s SWVP", DevTypeMsg );
  821. }
  822. if (dwFlags & D3DCREATE_PUREDEVICE)
  823. {
  824. _snprintf( DevTypeMsg, 256, "%s Pure", DevTypeMsg );
  825. }
  826. _snprintf( DevTypeMsg, 256, "%s device selected", DevTypeMsg );
  827. D3D_INFO( 0, DevTypeMsg );
  828. }
  829. #endif
  830. //
  831. // FW's Init
  832. //
  833. ret = static_cast<CBaseDevice*>(pd3ddev)->Init(
  834. pDD,
  835. DeviceType,
  836. hwndFocusWindow,
  837. dwFlags,
  838. pPresentationParams,
  839. iAdapter,
  840. this);
  841. if (FAILED(ret))
  842. {
  843. D3D_ERR("Failed to initialize Framework Device. CreateDevice Failed.");
  844. delete pd3ddev;
  845. return ret;
  846. }
  847. // We try and create a dummy vidmem vertexbuffer. If this doesn't
  848. // succeed, we just turn off vidmem VBs. This is to work around
  849. // the Rage 128 driver that reports DDERR_OUTOFVIDEOMEMORY even
  850. // though it simply doesn't support vidmem VBs
  851. if(!IS_DX8HAL_DEVICE(pd3ddev))
  852. {
  853. #ifdef WIN95
  854. //ON 9x we probe to see if the driver can do vidmem VBs...
  855. CVertexBuffer *pVertexBuffer;
  856. ret = CVertexBuffer::CreateDriverVertexBuffer(pd3ddev,
  857. 1024,
  858. D3DFVF_TLVERTEX,
  859. D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP,
  860. D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_LOCK,
  861. D3DPOOL_DEFAULT,
  862. D3DPOOL_DEFAULT,
  863. REF_INTERNAL,
  864. &pVertexBuffer);
  865. if(FAILED(ret))
  866. {
  867. if(pd3ddev->VBFailOversDisabled())
  868. {
  869. DPF_ERR("Cannot create Vidmem vertex buffer. Will ***NOT*** failover to Sysmem.");
  870. return ret;
  871. }
  872. DPF(1,"Driver doesnt support VidMemVBs which is fine");
  873. }
  874. else
  875. {
  876. // Get rid of the vb
  877. pVertexBuffer->DecrementUseCount();
  878. pd3ddev->EnableVidmemVBs();
  879. }
  880. #else //WIN95
  881. //On NT we require the drivers to tell us (by setting D3DDEVCAPS_HWVERTEXBUFFER)
  882. //Turn off DX7 driver VBs on NT if asked to do so...
  883. DWORD value;
  884. if ((GetD3DRegValue(REG_DWORD, "DisableVidMemVBs", &value, 4) != 0) &&
  885. (value != 0))
  886. {
  887. pd3ddev->DisableVidmemVBs();
  888. }
  889. #endif //!WIN95
  890. }
  891. ret = pd3ddev->Init();
  892. if (ret != D3D_OK)
  893. {
  894. delete pd3ddev;
  895. D3D_ERR("Failed to initialize D3DDevice. CreateDevice Failed.");
  896. return ret;
  897. }
  898. // Looks like everything is in order
  899. *ppNewInterface = static_cast<IDirect3DDevice8*>(pd3ddev);
  900. #ifdef APIPROF
  901. CApiProfileDevice* profile = new CApiProfileDevice;
  902. if (profile)
  903. {
  904. if (profile->Init() == D3D_OK)
  905. {
  906. profile->SetDevice(*ppNewInterface);
  907. *ppNewInterface = static_cast<IDirect3DDevice8*>(profile);
  908. }
  909. else
  910. {
  911. delete profile;
  912. }
  913. }
  914. #endif // APIPROF
  915. return S_OK;
  916. }
  917. #ifdef _X86_
  918. // --------------------------------------------------------------------------
  919. // Detect 3D extensions
  920. // --------------------------------------------------------------------------
  921. BOOL _asm_isX3D()
  922. {
  923. DWORD retval = 0;
  924. _asm
  925. {
  926. pushad ; CPUID trashes lots - save everything
  927. mov eax,80000000h ; Check for extended CPUID support
  928. ;;; We need to upgrade our compiler
  929. ;;; CPUID == 0f,a2
  930. _emit 0x0f
  931. _emit 0xa2
  932. cmp eax,80000001h ; Jump if no extended CPUID
  933. jb short done ;
  934. mov eax,80000001h ; Check for feature
  935. ;;; CPUID == 0f,a2
  936. _emit 0x0f
  937. _emit 0xa2
  938. xor eax,eax ;
  939. test edx,80000000h ;
  940. setnz al ;
  941. mov retval,eax ;
  942. done:
  943. popad ; Restore everything
  944. };
  945. return retval;
  946. }
  947. static BOOL isX3Dprocessor(void)
  948. {
  949. __try
  950. {
  951. if( _asm_isX3D() )
  952. {
  953. return TRUE;
  954. }
  955. }
  956. __except(GetExceptionCode() == STATUS_ILLEGAL_INSTRUCTION ?
  957. EXCEPTION_EXECUTE_HANDLER :
  958. EXCEPTION_CONTINUE_SEARCH)
  959. {
  960. }
  961. return FALSE;
  962. }
  963. //---------------------------------------------------------------------
  964. // Detects Intel SSE processor
  965. //
  966. #pragma optimize("", off)
  967. #define CPUID _asm _emit 0x0f _asm _emit 0xa2
  968. #define SSE_PRESENT 0x02000000 // bit number 25
  969. #define WNI_PRESENT 0x04000000 // bit number 26
  970. DWORD IsIntelSSEProcessor(void)
  971. {
  972. DWORD retval = 0;
  973. DWORD RegisterEAX;
  974. DWORD RegisterEDX;
  975. char VendorId[12];
  976. const char IntelId[13]="GenuineIntel";
  977. __try
  978. {
  979. _asm {
  980. xor eax,eax
  981. CPUID
  982. mov RegisterEAX, eax
  983. mov dword ptr VendorId, ebx
  984. mov dword ptr VendorId+4, edx
  985. mov dword ptr VendorId+8, ecx
  986. }
  987. } __except (1)
  988. {
  989. return retval;
  990. }
  991. // make sure EAX is > 0 which means the chip
  992. // supports a value >=1. 1 = chip info
  993. if (RegisterEAX == 0)
  994. return retval;
  995. // this CPUID can't fail if the above test passed
  996. __asm {
  997. mov eax,1
  998. CPUID
  999. mov RegisterEAX,eax
  1000. mov RegisterEDX,edx
  1001. }
  1002. if (RegisterEDX & SSE_PRESENT) {
  1003. retval |= D3DCPU_SSE;
  1004. }
  1005. if (RegisterEDX & WNI_PRESENT) {
  1006. retval |= D3DCPU_WLMT;
  1007. }
  1008. return retval;
  1009. }
  1010. #pragma optimize("", on)
  1011. // IsProcessorFeatureAvailable() is supported only by WINNT. For other OS
  1012. // we emulate it
  1013. #ifdef WINNT
  1014. static BOOL D3DIsProcessorFeaturePresent(UINT feature)
  1015. {
  1016. switch (feature)
  1017. {
  1018. // WINNT does not recognize Willamette processor when we use
  1019. // PF_XMMI64_INSTRUCTIONS_AVAILABLE, so use our detection instead
  1020. case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
  1021. {
  1022. DWORD flags = IsIntelSSEProcessor();
  1023. return flags & D3DCPU_WLMT;
  1024. }
  1025. default: return IsProcessorFeaturePresent(feature);
  1026. }
  1027. }
  1028. #else
  1029. #define PF_XMMI_INSTRUCTIONS_AVAILABLE 6
  1030. #define PF_3DNOW_INSTRUCTIONS_AVAILABLE 7
  1031. #define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10
  1032. static BOOL D3DIsProcessorFeaturePresent(UINT feature)
  1033. {
  1034. switch (feature)
  1035. {
  1036. case PF_XMMI_INSTRUCTIONS_AVAILABLE:
  1037. {
  1038. if (IsWin95())
  1039. return FALSE;
  1040. DWORD flags = IsIntelSSEProcessor();
  1041. return flags & D3DCPU_SSE;
  1042. }
  1043. case PF_3DNOW_INSTRUCTIONS_AVAILABLE: return isX3Dprocessor();
  1044. case PF_XMMI64_INSTRUCTIONS_AVAILABLE:
  1045. {
  1046. if (IsWin95())
  1047. return FALSE;
  1048. DWORD flags = IsIntelSSEProcessor();
  1049. return flags & D3DCPU_WLMT;
  1050. }
  1051. default: return FALSE;
  1052. }
  1053. }
  1054. #endif // WINNT
  1055. #endif // _X86_
  1056. //------------------------------------------------------------------------------
  1057. #undef DPF_MODNAME
  1058. #define DPF_MODNAME "CD3DHal::InitDevice"
  1059. HRESULT
  1060. CD3DHal::InitDevice()
  1061. {
  1062. HRESULT ret;
  1063. // Initialize values so we don't crash at shutdown
  1064. this->GeometryFuncsGuaranteed = NULL;
  1065. this->rstates = NULL;
  1066. m_pLightArray = NULL;
  1067. m_pv = NULL;
  1068. m_pCurrentShader = NULL;
  1069. m_pConvObj = NULL;
  1070. pMatrixDirtyForDDI = NULL;
  1071. m_clrRects = NULL;
  1072. m_clrCount = 0;
  1073. m_pv = new D3DFE_PROCESSVERTICES;
  1074. if (m_pv == NULL)
  1075. {
  1076. D3D_ERR("Could not allocate the FE/PSGP data structure (D3DFE_PROCESSVERTICES).");
  1077. return E_OUTOFMEMORY;
  1078. }
  1079. m_pv->pGeometryFuncs = NULL;
  1080. ret = CD3DBase::InitDevice();
  1081. if (ret != D3D_OK)
  1082. {
  1083. D3D_ERR("Failed to initialize CD3DBase.");
  1084. return(ret);
  1085. }
  1086. pMatrixDirtyForDDI = new CPackedBitArray;
  1087. if( pMatrixDirtyForDDI == NULL )
  1088. {
  1089. D3D_ERR("Could not allocate memory for internal data structure pMatrixDirtyForDDI.");
  1090. return E_OUTOFMEMORY;
  1091. }
  1092. if (FAILED(rsVec.Init(D3D_MAXRENDERSTATES)) ||
  1093. FAILED(rsVecRetired.Init(D3D_MAXRENDERSTATES)) ||
  1094. FAILED(rsVertexProcessingOnly.Init(D3D_MAXRENDERSTATES)) ||
  1095. FAILED(pMatrixDirtyForDDI->Init(D3D_MAXTRANSFORMSTATES)))
  1096. {
  1097. D3D_ERR("Could not allocate memory for renderstate processing bit vectors");
  1098. return E_OUTOFMEMORY;
  1099. }
  1100. m_pLightArray = new CHandleArray;
  1101. if (m_pLightArray == NULL)
  1102. {
  1103. D3D_ERR("Could not allocate memory for internal data structure m_pLightArray");
  1104. return E_OUTOFMEMORY;
  1105. }
  1106. dwFEFlags = 0;
  1107. // Initialize FEFlags content that depends on DDI type
  1108. if ( (GetDDIType() == D3DDDITYPE_DX7TL) ||
  1109. (GetDDIType() == D3DDDITYPE_DX8TL) )
  1110. dwFEFlags |= D3DFE_TLHAL;
  1111. // Since this is HAL, initialize it to use the software pipeline
  1112. // this will be turned off when the SW/HW renderstate is set.
  1113. m_pv->dwVIDIn = 0;
  1114. m_pv->pD3DMappedTexI = (LPVOID*)(m_lpD3DMappedTexI);
  1115. /*-------------------------------------------------------------------------
  1116. * Up till now we have done the easy part of the initialization. This is
  1117. * the stuff that cannot fail. It initializes the object so that the
  1118. * destructor can be safely called if any of the further initialization
  1119. * does not succeed.
  1120. *-----------------------------------------------------------------------*/
  1121. this->GeometryFuncsGuaranteed = new D3DFE_PVFUNCSI;
  1122. if (this->GeometryFuncsGuaranteed == NULL)
  1123. {
  1124. D3D_ERR("Could not allocate memory for internal data structure GeometryFuncsGuaranteed");
  1125. return E_OUTOFMEMORY;
  1126. }
  1127. // Software constant register buffer must handle all constants, provided by
  1128. // hardware, to make Set/Get constants possible
  1129. this->GeometryFuncsGuaranteed->m_VertexVM.Init(GetD3DCaps()->MaxVertexShaderConst);
  1130. m_pv->pGeometryFuncs = (LPD3DFE_PVFUNCS)GeometryFuncsGuaranteed;
  1131. if (this->GeometryFuncsGuaranteed == NULL)
  1132. {
  1133. D3D_ERR("Could not allocate memory for FE/PSGP function table.");
  1134. return D3DERR_INVALIDCALL;
  1135. }
  1136. // set up flag to use MMX when requested RGB
  1137. BOOL bUseMMXAsRGBDevice = FALSE;
  1138. D3DSURFACE_DESC desc = this->RenderTarget()->InternalGetDesc();
  1139. /*
  1140. * Check if the 3D cap is set on the surface.
  1141. */
  1142. if ((desc.Usage & D3DUSAGE_RENDERTARGET) == 0)
  1143. {
  1144. D3D_ERR("**** The D3DUSAGE_RENDERTARGET is not set on this surface.");
  1145. D3D_ERR("**** You need to add D3DUSAGE_RENDERTARGET to the Usage parameter");
  1146. D3D_ERR("**** when creating the surface.");
  1147. return (D3DERR_INVALIDCALL);
  1148. }
  1149. // Create front-end support structures.
  1150. ret = this->D3DFE_Create();
  1151. if (ret != D3D_OK)
  1152. {
  1153. D3D_ERR("Failed to create front-end data-structures.");
  1154. goto handle_err;
  1155. }
  1156. // In all other cases we simply allocate memory for rstates
  1157. rstates = new DWORD[D3D_MAXRENDERSTATES];
  1158. m_pv->lpdwRStates = this->rstates;
  1159. #ifndef PROFILE4
  1160. #ifdef _X86_
  1161. if ((ULONG_PTR)&m_pv->view & 0xF)
  1162. {
  1163. char s[256];
  1164. sprintf(s, "0%xh \n", (ULONG_PTR)&m_pv->view);
  1165. OutputDebugString("INTERNAL ERROR:View matrix in D3DFE_PROCESSVERTICES structure must be aligned to 16 bytes\n");
  1166. OutputDebugString(s);
  1167. ret = D3DERR_INVALIDCALL;
  1168. goto handle_err;
  1169. }
  1170. // Check if we have a processor specific implementation available
  1171. // only use if DisablePSGP is not in registry or set to zero
  1172. DWORD value;
  1173. if (!GetD3DRegValue(REG_DWORD, "DisablePSGP", &value, sizeof(DWORD)))
  1174. {
  1175. value = 0;
  1176. }
  1177. // value =
  1178. // 0 - PSGP enabled
  1179. // 1 - PSGP disabled
  1180. // 2 - X3D PSGP disabled
  1181. if (value != 1)
  1182. {
  1183. // Ask the PV implementation to create a device specific "context"
  1184. LPD3DFE_PVFUNCS pOptGeoFuncs = m_pv->pGeometryFuncs;
  1185. // TODO (bug 40438): Remove DLL interface for final
  1186. // Try to use PSGP DLL first
  1187. if (pfnFEContextCreate)
  1188. {
  1189. ret = pfnFEContextCreate(m_pv->dwDeviceFlags, &pOptGeoFuncs);
  1190. if ((ret == D3D_OK) && pOptGeoFuncs)
  1191. {
  1192. D3D_INFO(0, "Using PSGP DLL");
  1193. m_pv->pGeometryFuncs = pOptGeoFuncs;
  1194. goto l_chosen;
  1195. }
  1196. }
  1197. if (D3DIsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE) &&
  1198. value != 2)
  1199. {
  1200. ret = x3DContextCreate(m_pv->dwDeviceFlags, &pOptGeoFuncs);
  1201. if (ret == S_OK && pOptGeoFuncs)
  1202. {
  1203. D3D_INFO(0, "Using X3D PSGP");
  1204. m_pv->pGeometryFuncs = pOptGeoFuncs;
  1205. goto l_chosen;
  1206. }
  1207. }
  1208. if (D3DIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE))
  1209. {
  1210. ret = wlmt_FEContextCreate(m_pv->dwDeviceFlags, &pOptGeoFuncs);
  1211. if (ret == S_OK && pOptGeoFuncs)
  1212. {
  1213. D3D_INFO(0, "Using WLMT PSGP");
  1214. m_pv->pGeometryFuncs = pOptGeoFuncs;
  1215. goto l_chosen;
  1216. }
  1217. }
  1218. if (D3DIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE))
  1219. {
  1220. ret = katmai_FEContextCreate(m_pv->dwDeviceFlags, &pOptGeoFuncs);
  1221. if (ret == S_OK && pOptGeoFuncs)
  1222. {
  1223. D3D_INFO(0, "Using P3 PSGP");
  1224. m_pv->pGeometryFuncs = pOptGeoFuncs;
  1225. goto l_chosen;
  1226. }
  1227. }
  1228. l_chosen:;
  1229. }
  1230. #endif // _X86_
  1231. #endif // PROFILE4
  1232. {
  1233. if (HVbuf.Grow((__INIT_VERTEX_NUMBER*2)*sizeof(D3DFE_CLIPCODE)) != DD_OK)
  1234. {
  1235. D3D_ERR( "Could not allocate memory for internal buffer HVBuf" );
  1236. ret = E_OUTOFMEMORY;
  1237. goto handle_err;
  1238. }
  1239. }
  1240. // Setup lights
  1241. if( FAILED( m_pLightArray->Grow( 8 ) ) )
  1242. {
  1243. D3D_ERR( "Could not allocate memory for the light array" );
  1244. ret = E_OUTOFMEMORY;
  1245. goto handle_err;
  1246. }
  1247. LIST_INITIALIZE(&m_ActiveLights);
  1248. // Setup material
  1249. memset(&m_pv->lighting.material, 0, sizeof(m_pv->lighting.material));
  1250. // Set viewport to update front-end data
  1251. SetViewportI(&m_Viewport);
  1252. m_pv->PointSizeMax = GetD3DCaps()->MaxPointSize;
  1253. {
  1254. DWORD EmulatePointSprites = 1;
  1255. GetD3DRegValue(REG_DWORD, "EmulatePointSprites", &EmulatePointSprites, sizeof(DWORD));
  1256. if ((m_pv->PointSizeMax == 0 || !(GetD3DCaps()->FVFCaps & D3DFVFCAPS_PSIZE)) &&
  1257. EmulatePointSprites)
  1258. {
  1259. m_dwRuntimeFlags |= D3DRT_DOPOINTSPRITEEMULATION;
  1260. if (m_pv->PointSizeMax == 0)
  1261. m_pv->PointSizeMax = __MAX_POINT_SIZE;
  1262. else
  1263. m_dwRuntimeFlags |= D3DRT_SUPPORTSPOINTSPRITES;
  1264. }
  1265. }
  1266. m_pfnPrepareToDraw = NULL;
  1267. return (D3D_OK);
  1268. handle_err:
  1269. return(ret);
  1270. }
  1271. //---------------------------------------------------------------------
  1272. DWORD
  1273. ProcessRects(CD3DHal* pDevI, DWORD dwCount, CONST D3DRECT* rects)
  1274. {
  1275. RECT vwport;
  1276. DWORD i,j;
  1277. /*
  1278. * Rip through the rects and validate that they
  1279. * are within the viewport.
  1280. */
  1281. if (dwCount == 0 && rects == NULL)
  1282. {
  1283. dwCount = 1;
  1284. }
  1285. #if DBG
  1286. else if (rects == NULL)
  1287. {
  1288. D3D_ERR("The rects parameter is NULL.");
  1289. throw D3DERR_INVALIDCALL;
  1290. }
  1291. #endif
  1292. if (dwCount > pDevI->m_clrCount)
  1293. {
  1294. LPD3DRECT newRects;
  1295. if (D3D_OK == D3DMalloc((void**)&newRects, dwCount * sizeof(D3DRECT)))
  1296. {
  1297. memcpy((void*)newRects,(void*)pDevI->m_clrRects,
  1298. pDevI->m_clrCount* sizeof(D3DRECT));
  1299. D3DFree((LPVOID)pDevI->m_clrRects);
  1300. pDevI->m_clrRects = newRects;
  1301. }
  1302. else
  1303. {
  1304. pDevI->m_clrCount = 0;
  1305. D3DFree((LPVOID)pDevI->m_clrRects);
  1306. pDevI->m_clrRects = NULL;
  1307. D3D_ERR("failed to allocate space for rects");
  1308. throw E_OUTOFMEMORY;
  1309. }
  1310. }
  1311. pDevI->m_clrCount = dwCount;
  1312. // If nothing is specified, assume the viewport needs to be cleared
  1313. if (!rects)
  1314. {
  1315. pDevI->m_clrRects[0].x1 = pDevI->m_Viewport.X;
  1316. pDevI->m_clrRects[0].y1 = pDevI->m_Viewport.Y;
  1317. pDevI->m_clrRects[0].x2 = pDevI->m_Viewport.X + pDevI->m_Viewport.Width;
  1318. pDevI->m_clrRects[0].y2 = pDevI->m_Viewport.Y + pDevI->m_Viewport.Height;
  1319. return 1;
  1320. }
  1321. else
  1322. {
  1323. vwport.left = pDevI->m_Viewport.X;
  1324. vwport.top = pDevI->m_Viewport.Y;
  1325. vwport.right = pDevI->m_Viewport.X + pDevI->m_Viewport.Width;
  1326. vwport.bottom = pDevI->m_Viewport.Y + pDevI->m_Viewport.Height;
  1327. j=0;
  1328. for (i = 0; i < dwCount; i++)
  1329. {
  1330. if (IntersectRect((LPRECT)(pDevI->m_clrRects + j), &vwport, (LPRECT)(rects + i)))
  1331. j++;
  1332. }
  1333. return j;
  1334. }
  1335. }
  1336. //---------------------------------------------------------------------
  1337. #undef DPF_MODNAME
  1338. #define DPF_MODNAME "CD3DHal::ClearI"
  1339. void
  1340. CD3DHal::ClearI(DWORD dwCount,
  1341. CONST D3DRECT* rects,
  1342. DWORD dwFlags,
  1343. D3DCOLOR dwColor,
  1344. D3DVALUE dvZ,
  1345. DWORD dwStencil)
  1346. {
  1347. dwCount = ProcessRects(this, dwCount, rects);
  1348. // Device should never receive 0 count, because for Pure device this
  1349. // means "clear whole viewport"
  1350. if (dwCount != 0)
  1351. {
  1352. // Call DDI specific Clear routine
  1353. m_pDDI->Clear(dwFlags, dwCount, m_clrRects, dwColor, dvZ, dwStencil);
  1354. }
  1355. }