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.

572 lines
16 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dlld3d.cpp
  6. * Content: Direct3D startup
  7. *@@BEGIN_MSINTERNAL
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 05/11/95 stevela Initial rev with this header.
  13. * 21/11/95 colinmc Added Direct3D interface ID.
  14. * 07/12/95 stevela Merged Colin's changes.
  15. * 10/12/95 stevela Removed AGGREGATE_D3D.
  16. * 02/03/96 colinmc Minor build fix.
  17. *@@END_MSINTERNAL
  18. *
  19. ***************************************************************************/
  20. #include "pch.cpp"
  21. #pragma hdrstop
  22. /*
  23. * Define the Direct3D IIDs.
  24. */
  25. #undef DPF_MODNAME
  26. #define DPF_MODNAME "Direct3D Startup"
  27. DPF_DECLARE(Direct3D);
  28. #ifdef WIN95
  29. LPVOID lpWin16Lock;
  30. #endif
  31. DWORD dwD3DTriBatchSize, dwTriBatchSize, dwLineBatchSize;
  32. DWORD dwHWBufferSize, dwHWMaxTris, dwHWFewVertices;
  33. HINSTANCE hGeometryDLL;
  34. LPD3DFE_CONTEXTCREATE pfnFEContextCreate;
  35. char szCPUString[13];
  36. DWORD dwCPUFamily, dwCPUFeatures;
  37. #ifdef _X86_
  38. extern BOOL isX3Dprocessor(void);
  39. #endif
  40. void SetMostRecentApp(void);
  41. #ifndef WIN95 // and Win98, WinME
  42. //---------------------------------------------------------------------
  43. BOOL bVBSwapEnabled = TRUE, bVBSwapWorkaround = FALSE;
  44. void SetVBSwapStatus(void)
  45. {
  46. OSVERSIONINFOEX osvi;
  47. ZeroMemory(&osvi, sizeof(osvi));
  48. osvi.dwOSVersionInfoSize = sizeof(osvi);
  49. if (!GetVersionEx((LPOSVERSIONINFO)&osvi))
  50. {
  51. D3D_INFO(1,"GetVersionEx failed - turning off VB swapping");
  52. bVBSwapEnabled = FALSE;
  53. return;
  54. }
  55. if ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId )
  56. {
  57. if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) // Check if Win2K Gold (2195)
  58. {
  59. if (osvi.wServicePackMajor == 0) // No service pack
  60. {
  61. D3D_INFO(1, "Win2K Gold detected - turning off VB swapping");
  62. bVBSwapEnabled = FALSE;
  63. }
  64. else
  65. {
  66. D3D_INFO(1, "Win2K SP1 or above detected - enabling VB swap workaround");
  67. bVBSwapEnabled = FALSE;
  68. bVBSwapWorkaround = TRUE;
  69. }
  70. }
  71. else // Whistler and above
  72. {
  73. /* ASSUMPTION: NO WORKAROUND NEEDED */
  74. }
  75. }
  76. else
  77. {
  78. // Should never get here
  79. DPF_ERR("OS Detection failed - turning off VB swapping");
  80. bVBSwapEnabled = FALSE;
  81. return;
  82. }
  83. }
  84. #endif // WIN95
  85. #ifdef _X86_
  86. // --------------------------------------------------------------------------
  87. // Here's a routine helps us determine if we should try MMX or not
  88. // --------------------------------------------------------------------------
  89. BOOL _asm_isMMX()
  90. {
  91. DWORD retval;
  92. _asm
  93. {
  94. xor eax,eax ; Clear out eax for return value
  95. pushad ; CPUID trashes lots - save everything
  96. mov eax,1 ; Check for MMX support
  97. ;;; We need to upgrade our compiler
  98. ;;; CPUID == 0f,a2
  99. _emit 0x0f
  100. _emit 0xa2
  101. test edx,00800000h ; Set flags before restoring registers
  102. popad ; Restore everything
  103. setnz al ; Set return value
  104. mov retval, eax
  105. };
  106. return retval;
  107. }
  108. #endif
  109. static int isMMX = -1;
  110. BOOL
  111. isMMXprocessor(void)
  112. {
  113. HKEY hKey;
  114. if ( RegOpenKey( HKEY_LOCAL_MACHINE,
  115. RESPATH_D3D,
  116. &hKey) == ERROR_SUCCESS)
  117. {
  118. DWORD dwType;
  119. DWORD dwValue;
  120. DWORD dwSize = 4;
  121. if ( RegQueryValueEx( hKey, "DisableMMX", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) == ERROR_SUCCESS &&
  122. dwType == REG_DWORD &&
  123. dwValue != 0)
  124. {
  125. RegCloseKey( hKey );
  126. isMMX = 0;
  127. return FALSE;
  128. }
  129. RegCloseKey( hKey );
  130. }
  131. if (isMMX < 0)
  132. {
  133. isMMX = FALSE;
  134. #ifdef _X86_
  135. D3D_WARN(0, "Executing processor detection code (benign first-chance exception possible)" );
  136. #ifndef WIN95
  137. {
  138. // GetSystemInfo is not broken on WinNT.
  139. SYSTEM_INFO si;
  140. GetSystemInfo(&si);
  141. if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL &&
  142. si.wProcessorLevel >= 5)
  143. {
  144. #endif
  145. __try
  146. {
  147. if( _asm_isMMX() )
  148. {
  149. // Emit an emms instruction.
  150. // This file needs to compile for non-Pentium
  151. // processors
  152. // so we can't use use inline asm since we're in the
  153. // wrong
  154. // processor mode.
  155. __asm __emit 0xf;
  156. __asm __emit 0x77;
  157. isMMX = TRUE;
  158. D3D_INFO(0, "MMX detected");
  159. }
  160. }
  161. __except(GetExceptionCode() == STATUS_ILLEGAL_INSTRUCTION ?
  162. EXCEPTION_EXECUTE_HANDLER :
  163. EXCEPTION_CONTINUE_SEARCH)
  164. {
  165. }
  166. #ifndef WIN95
  167. }
  168. }
  169. #endif
  170. #endif
  171. }
  172. return isMMX;
  173. }
  174. #ifdef _X86_
  175. //---------------------------------------------------------------------
  176. // Detects Intel SSE processor
  177. //
  178. #pragma optimize("", off)
  179. #define CPUID _asm _emit 0x0f _asm _emit 0xa2
  180. #define SSE_PRESENT 0x02000000 // bit number 25
  181. #define WNI_PRESENT 0x04000000 // bit number 26
  182. DWORD IsIntelSSEProcessor(void)
  183. {
  184. DWORD retval = 0;
  185. DWORD RegisterEAX;
  186. DWORD RegisterEDX;
  187. char VendorId[12];
  188. __try
  189. {
  190. _asm {
  191. xor eax,eax
  192. CPUID
  193. mov RegisterEAX, eax
  194. mov dword ptr VendorId, ebx
  195. mov dword ptr VendorId+4, edx
  196. mov dword ptr VendorId+8, ecx
  197. }
  198. } __except (1)
  199. {
  200. return retval;
  201. }
  202. // make sure EAX is > 0 which means the chip
  203. // supports a value >=1. 1 = chip info
  204. if (RegisterEAX == 0)
  205. return retval;
  206. // this CPUID can't fail if the above test passed
  207. __asm {
  208. mov eax,1
  209. CPUID
  210. mov RegisterEAX,eax
  211. mov RegisterEDX,edx
  212. }
  213. if (RegisterEDX & SSE_PRESENT) {
  214. retval |= D3DCPU_SSE;
  215. }
  216. if (RegisterEDX & WNI_PRESENT) {
  217. retval |= D3DCPU_WLMT;
  218. }
  219. return retval;
  220. }
  221. #pragma optimize("", on)
  222. #ifdef WIN95 // and Win98...
  223. //---------------------------------------------------------------------
  224. BOOL
  225. IsWin95(void)
  226. {
  227. OSVERSIONINFO osvi;
  228. ZeroMemory(&osvi, sizeof(osvi));
  229. osvi.dwOSVersionInfoSize = sizeof(osvi);
  230. if (!GetVersionEx(&osvi))
  231. {
  232. D3D_INFO(1,"GetVersionEx failed - assuming Win95");
  233. return TRUE;
  234. }
  235. if ( VER_PLATFORM_WIN32_WINDOWS == osvi.dwPlatformId )
  236. {
  237. if( ( osvi.dwMajorVersion > 4UL ) ||
  238. ( ( osvi.dwMajorVersion == 4UL ) &&
  239. ( osvi.dwMinorVersion >= 10UL ) &&
  240. ( LOWORD( osvi.dwBuildNumber ) >= 1373 ) ) )
  241. {
  242. // is Win98
  243. D3D_INFO(2,"Detected Win98");
  244. return FALSE;
  245. }
  246. else
  247. {
  248. // is Win95
  249. D3D_INFO(2,"Detected Win95");
  250. return TRUE;
  251. }
  252. }
  253. else if ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId )
  254. {
  255. D3D_INFO(2,"Detected WinNT");
  256. return FALSE;
  257. }
  258. D3D_INFO(2,"OS Detection failed");
  259. return TRUE;
  260. }
  261. #endif // WIN95
  262. //---------------------------------------------------------------------
  263. //
  264. // void GetProcessorFamily(LPDWORD lpdwFamily);
  265. //
  266. // Passes back 3, 4, 5, 6 for 386, 486, Pentium, PPro class machines
  267. //
  268. #pragma optimize("", off)
  269. void
  270. GetProcessorFamily(LPDWORD lpdwFamily, LPDWORD lpdwCPUFeatures)
  271. {
  272. SYSTEM_INFO si;
  273. __int64 start, end, freq;
  274. int flags,family;
  275. int time;
  276. int clocks;
  277. DWORD oldclass;
  278. HANDLE hprocess;
  279. // guilty until proven otherwise
  280. *lpdwCPUFeatures = D3DCPU_BLOCKINGREAD;
  281. if ( isMMXprocessor() )
  282. {
  283. *lpdwCPUFeatures |= D3DCPU_MMX;
  284. }
  285. ZeroMemory(&si, sizeof(si));
  286. GetSystemInfo(&si);
  287. //Set the family. If wProcessorLevel is not specified, dig it out of dwProcessorType
  288. //Because wProcessor level is not implemented on Win95
  289. if (si.wProcessorLevel)
  290. {
  291. *lpdwFamily=si.wProcessorLevel;
  292. }
  293. else
  294. {
  295. //Ok, we're on Win95
  296. switch (si.dwProcessorType)
  297. {
  298. case PROCESSOR_INTEL_386:
  299. *lpdwFamily=3;
  300. break;
  301. case PROCESSOR_INTEL_486:
  302. *lpdwFamily=4;
  303. break;
  304. default:
  305. *lpdwFamily=0;
  306. break;
  307. }
  308. }
  309. //
  310. // make sure this is a INTEL Pentium (or clone) or higher.
  311. //
  312. if (si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL)
  313. return;
  314. if (si.dwProcessorType < PROCESSOR_INTEL_PENTIUM)
  315. return;
  316. //
  317. // see if this chip supports rdtsc before using it.
  318. //
  319. __try
  320. {
  321. _asm
  322. {
  323. xor eax,eax
  324. _emit 00fh ;; CPUID
  325. _emit 0a2h
  326. mov dword ptr szCPUString,ebx
  327. mov dword ptr szCPUString+8,ecx
  328. mov dword ptr szCPUString+4,edx
  329. mov byte ptr szCPUString+12,0
  330. mov eax,1
  331. _emit 00Fh ;; CPUID
  332. _emit 0A2h
  333. mov flags,edx
  334. mov family,eax
  335. }
  336. }
  337. __except(1)
  338. {
  339. flags = 0;
  340. }
  341. //check for support of CPUID and fail
  342. if (!(flags & 0x10))
  343. return;
  344. // fcomi and FPU features both set
  345. if ( (flags&(1<<15)) && (flags & (1<<0)) )
  346. {
  347. D3D_INFO(2, "Pentium Pro CPU features (fcomi, cmov) detected");
  348. *lpdwCPUFeatures |= D3DCPU_FCOMICMOV;
  349. }
  350. //If we don't have a family, set it now
  351. //Family is bits 11:8 of eax from CPU, with eax=1
  352. if (!(*lpdwFamily))
  353. {
  354. *lpdwFamily=(family& 0x0F00) >> 8;
  355. }
  356. // not aware of any non-Intel processors w/non blocking reads
  357. if ( (! strcmp(szCPUString, "GenuineIntel")) &&
  358. *lpdwFamily > 5)
  359. {
  360. *lpdwCPUFeatures &= ~D3DCPU_BLOCKINGREAD;
  361. }
  362. if ( isX3Dprocessor() )
  363. {
  364. D3D_INFO(2, "X3D Processor detected for PSGP");
  365. *lpdwCPUFeatures |= D3DCPU_X3D;
  366. }
  367. DWORD retval = IsIntelSSEProcessor();
  368. if (retval & D3DCPU_SSE)
  369. {
  370. D3D_INFO(2, "Streaming SIMD Extensions detected for PSGP");
  371. *lpdwCPUFeatures |= D3DCPU_SSE;
  372. }
  373. if (retval & D3DCPU_WLMT)
  374. {
  375. D3D_INFO(2, "Streaming SIMD Extensions 2 detected for PSGP");
  376. *lpdwCPUFeatures |= D3DCPU_WLMT;
  377. }
  378. return;
  379. }
  380. #pragma optimize("", on)
  381. #endif // _X86_
  382. BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
  383. {
  384. HKEY hKey;
  385. LONG lRet;
  386. DWORD dwType, dwSize = sizeof(dwHWFewVertices);
  387. char filename[_MAX_PATH];
  388. switch( ul_reason_for_call ) {
  389. case DLL_PROCESS_ATTACH:
  390. DisableThreadLibraryCalls( hModule );
  391. DPFINIT();
  392. MemInit();
  393. #ifdef WIN95
  394. GetpWin16Lock(&lpWin16Lock);
  395. #endif
  396. #ifdef _X86_
  397. GetProcessorFamily(&dwCPUFamily, &dwCPUFeatures);
  398. D3D_INFO(3, "dwCPUFamily = %d, dwCPUFeatures = %d", dwCPUFamily, dwCPUFeatures);
  399. D3D_INFO(3, "szCPUString = %s", szCPUString);
  400. #endif
  401. #ifdef WIN95 // and Win98...
  402. // SSE (aka Katmai) does not work on Win95, so see if we are on Win95 and disable
  403. //
  404. {
  405. BOOL bIsWin95 = IsWin95();
  406. if (bIsWin95)
  407. {
  408. dwCPUFeatures &= ~(D3DCPU_SSE | D3DCPU_WLMT);
  409. }
  410. }
  411. // We need to workaround VB problems on Win2K
  412. #else
  413. SetVBSwapStatus();
  414. #endif
  415. // Unfounded default value. 128*40 (vertex+D3DTRIANGLE struct)=5K
  416. // The assumption is that the primary cache hasn't got much better
  417. // to do than contain the vertex and index data.
  418. dwD3DTriBatchSize = 80;
  419. // Work item: do something more intelligent here than assume that
  420. // MMX-enabled processors have twice as much primary cache.
  421. if ( isMMXprocessor() )
  422. dwD3DTriBatchSize *= 2;
  423. dwTriBatchSize = (dwD3DTriBatchSize * 4) / 3;
  424. dwLineBatchSize = dwD3DTriBatchSize * 2;
  425. dwHWBufferSize = dwD3DTriBatchSize * (sizeof(D3DTLVERTEX) + sizeof(D3DTRIANGLE));
  426. dwHWMaxTris = dwD3DTriBatchSize;
  427. lRet = RegOpenKey( HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey );
  428. if ( lRet == ERROR_SUCCESS )
  429. {
  430. lRet = RegQueryValueEx(hKey,
  431. "FewVertices",
  432. NULL,
  433. &dwType,
  434. (LPBYTE) &dwHWFewVertices,
  435. &dwSize);
  436. if (lRet != ERROR_SUCCESS ||
  437. dwType != REG_DWORD ||
  438. dwHWFewVertices < 4 ||
  439. dwHWFewVertices > 128)
  440. dwHWFewVertices = 24;
  441. #ifdef __D3D_PSGP_DLL__
  442. dwSize = sizeof(filename);
  443. lRet = RegQueryValueEx(hKey,
  444. "GeometryDriver",
  445. NULL,
  446. &dwType,
  447. (LPBYTE) filename,
  448. &dwSize);
  449. if (lRet == ERROR_SUCCESS && dwType == REG_SZ)
  450. {
  451. hGeometryDLL = LoadLibrary(filename);
  452. if (hGeometryDLL)
  453. {
  454. pfnFEContextCreate = (LPD3DFE_CONTEXTCREATE) GetProcAddress(hGeometryDLL, "FEContextCreate");
  455. }
  456. }
  457. #endif //__D3D_PSGP_DLL__
  458. RegCloseKey( hKey );
  459. }
  460. else
  461. {
  462. dwHWFewVertices = 24;
  463. }
  464. // Set the app name to reg.
  465. SetMostRecentApp();
  466. break;
  467. case DLL_PROCESS_DETACH:
  468. MemFini();
  469. if (NULL != hGeometryDLL)
  470. FreeLibrary(hGeometryDLL);
  471. break;
  472. default:
  473. ;
  474. }
  475. return TRUE;
  476. }
  477. // --------------------------------------------------------------------------
  478. // This function is called at process attach time to put the name of current
  479. // app to registry.
  480. // --------------------------------------------------------------------------
  481. void SetMostRecentApp(void)
  482. {
  483. char fname[_MAX_PATH];
  484. char name[_MAX_PATH];
  485. int i;
  486. HKEY hKey;
  487. HANDLE hFile;
  488. // Find out what process we are dealing with
  489. hFile = GetModuleHandle( NULL );
  490. GetModuleFileName( (HINSTANCE)hFile, fname, sizeof( fname ) );
  491. DPF( 3, "full name = %s", fname );
  492. i = strlen( fname )-1;
  493. while( i >=0 && fname[i] != '\\' )
  494. {
  495. i--;
  496. }
  497. i++;
  498. strcpy( name, &fname[i] );
  499. DPF( 3, "name = %s", name );
  500. // Now write the name into some known place
  501. if( !RegCreateKey( HKEY_LOCAL_MACHINE,
  502. RESPATH_D3D "\\" REGSTR_KEY_LASTAPP, &hKey ) )
  503. {
  504. RegSetValueEx(hKey, REGSTR_VAL_DDRAW_NAME, 0, REG_SZ, (LPBYTE)name, strlen(name)+1);
  505. RegCloseKey(hKey);
  506. }
  507. }